* copy vendor drop to trunk
[lab.git] / Dev / utvpn / utvpn-unix-v101-7101-public / src / Cedar / Hub.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 // Hub.c\r
79 // 仮想 HUB モジュール\r
80 \r
81 #include "CedarPch.h"\r
82 \r
83 static UCHAR broadcast[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};\r
84 \r
85 // 現在サポートされている管理オプションの一覧とデフォルト値\r
86 // 名前は 63 文字以内にすること\r
87 ADMIN_OPTION admin_options[] =\r
88 {\r
89         {"allow_hub_admin_change_option", 0},\r
90         {"max_users", 0},\r
91         {"max_multilogins_per_user", 0},\r
92         {"max_groups", 0},\r
93         {"max_accesslists", 0},\r
94         {"max_sessions_client_bridge_apply", 0},\r
95         {"max_sessions", 0},\r
96         {"max_sessions_client", 0},\r
97         {"max_sessions_bridge", 0},\r
98         {"max_bitrates_download", 0},\r
99         {"max_bitrates_upload", 0},\r
100         {"deny_empty_password", 0},\r
101         {"deny_bridge", 0},\r
102         {"deny_routing", 0},\r
103         {"deny_qos", 0},\r
104         {"deny_change_user_password", 0},\r
105         {"no_change_users", 0},\r
106         {"no_change_groups", 0},\r
107         {"no_securenat", 0},\r
108         {"no_securenat_enablenat", 0},\r
109         {"no_securenat_enabledhcp", 0},\r
110         {"no_cascade", 0},\r
111         {"no_online", 0},\r
112         {"no_offline", 0},\r
113         {"no_change_log_config", 0},\r
114         {"no_disconnect_session", 0},\r
115         {"no_delete_iptable", 0},\r
116         {"no_delete_mactable", 0},\r
117         {"no_enum_session", 0},\r
118         {"no_query_session", 0},\r
119         {"no_change_admin_password", 0},\r
120         {"no_change_log_switch_type", 0},\r
121         {"no_change_access_list", 0},\r
122         {"no_change_access_control_list", 0},\r
123         {"no_change_cert_list", 0},\r
124         {"no_change_crl_list", 0},\r
125         {"no_read_log_file", 0},\r
126         {"deny_hub_admin_change_ext_option", 0},\r
127         {"no_delay_jitter_packet_loss", 0},\r
128         {"no_change_msg", 0},\r
129 };\r
130 \r
131 UINT num_admin_options = sizeof(admin_options) / sizeof(ADMIN_OPTION);\r
132 \r
133 // 指定されたメッセージが URL 文字列かどうか取得\r
134 bool IsURLMsg(wchar_t *str, char *url, UINT url_size)\r
135 {\r
136         UNI_TOKEN_LIST *t;\r
137         bool ret = false;\r
138         UINT i;\r
139         UINT n = 0;\r
140         // 引数チェック\r
141         if (str == NULL)\r
142         {\r
143                 return false;\r
144         }\r
145 \r
146         t = UniParseToken(str, L"\r\n");\r
147 \r
148         for (i = 0;i < t->NumTokens;i++)\r
149         {\r
150                 wchar_t *str = t->Token[i];\r
151 \r
152                 if (IsEmptyUniStr(str) == false)\r
153                 {\r
154                         n++;\r
155 \r
156                         UniTrim(str);\r
157 \r
158                         if (n == 1)\r
159                         {\r
160                                 if (UniStartWith(str, L"http://") ||\r
161                                         UniStartWith(str, L"https://") ||\r
162                                         UniStartWith(str, L"ftp://"))\r
163                                 {\r
164                                         ret = true;\r
165 \r
166                                         UniToStr(url, url_size, str);\r
167                                 }\r
168                         }\r
169                 }\r
170         }\r
171 \r
172         if (n != 1)\r
173         {\r
174                 ret = false;\r
175         }\r
176 \r
177         UniFreeToken(t);\r
178 \r
179         return ret;\r
180 }\r
181 \r
182 // RPC_ADMIN_OPTION からデータを取得\r
183 UINT GetHubAdminOptionData(RPC_ADMIN_OPTION *ao, char *name)\r
184 {\r
185         UINT i;\r
186         // 引数チェック\r
187         if (ao == NULL || name == NULL)\r
188         {\r
189                 return INFINITE;\r
190         }\r
191 \r
192         for (i = 0;i < ao->NumItem;i++)\r
193         {\r
194                 ADMIN_OPTION *a = &ao->Items[i];\r
195 \r
196                 if (StrCmpi(a->Name, name) == 0)\r
197                 {\r
198                         return a->Value;\r
199                 }\r
200         }\r
201 \r
202         return INFINITE;\r
203 }\r
204 void GetHubAdminOptionDataAndSet(RPC_ADMIN_OPTION *ao, char *name, UINT *dest)\r
205 {\r
206         UINT value;\r
207         // 引数チェック\r
208         if (ao == NULL || name == NULL || dest == NULL)\r
209         {\r
210                 return;\r
211         }\r
212 \r
213         value = GetHubAdminOptionData(ao, name);\r
214         if (value == INFINITE)\r
215         {\r
216                 return;\r
217         }\r
218 \r
219         *dest = value;\r
220 }\r
221 \r
222 // データをもとに HUB_OPTION の内容を設定\r
223 void DataToHubOptionStruct(HUB_OPTION *o, RPC_ADMIN_OPTION *ao)\r
224 {\r
225         // 引数チェック\r
226         if (o == NULL || ao == NULL)\r
227         {\r
228                 return;\r
229         }\r
230 \r
231         GetHubAdminOptionDataAndSet(ao, "NoAddressPollingIPv4", &o->NoArpPolling);\r
232         GetHubAdminOptionDataAndSet(ao, "NoAddressPollingIPv6", &o->NoIPv6AddrPolling);\r
233         GetHubAdminOptionDataAndSet(ao, "NoIpTable", &o->NoIpTable);\r
234         GetHubAdminOptionDataAndSet(ao, "NoMacAddressLog", &o->NoMacAddressLog);\r
235         GetHubAdminOptionDataAndSet(ao, "ManageOnlyPrivateIP", &o->ManageOnlyPrivateIP);\r
236         GetHubAdminOptionDataAndSet(ao, "ManageOnlyLocalUnicastIPv6", &o->ManageOnlyLocalUnicastIPv6);\r
237         GetHubAdminOptionDataAndSet(ao, "DisableIPParsing", &o->DisableIPParsing);\r
238         GetHubAdminOptionDataAndSet(ao, "YieldAfterStorePacket", &o->YieldAfterStorePacket);\r
239         GetHubAdminOptionDataAndSet(ao, "NoSpinLockForPacketDelay", &o->NoSpinLockForPacketDelay);\r
240         GetHubAdminOptionDataAndSet(ao, "BroadcastStormDetectionThreshold", &o->BroadcastStormDetectionThreshold);\r
241         GetHubAdminOptionDataAndSet(ao, "ClientMinimumRequiredBuild", &o->ClientMinimumRequiredBuild);\r
242         GetHubAdminOptionDataAndSet(ao, "FilterPPPoE", &o->FilterPPPoE);\r
243         GetHubAdminOptionDataAndSet(ao, "FilterOSPF", &o->FilterOSPF);\r
244         GetHubAdminOptionDataAndSet(ao, "FilterIPv4", &o->FilterIPv4);\r
245         GetHubAdminOptionDataAndSet(ao, "FilterIPv6", &o->FilterIPv6);\r
246         GetHubAdminOptionDataAndSet(ao, "FilterNonIP", &o->FilterNonIP);\r
247         GetHubAdminOptionDataAndSet(ao, "NoIPv4PacketLog", &o->NoIPv4PacketLog);\r
248         GetHubAdminOptionDataAndSet(ao, "NoIPv6PacketLog", &o->NoIPv6PacketLog);\r
249         GetHubAdminOptionDataAndSet(ao, "FilterBPDU", &o->FilterBPDU);\r
250         GetHubAdminOptionDataAndSet(ao, "NoIPv6DefaultRouterInRAWhenIPv6", &o->NoIPv6DefaultRouterInRAWhenIPv6);\r
251         GetHubAdminOptionDataAndSet(ao, "NoLookBPDUBridgeId", &o->NoLookBPDUBridgeId);\r
252         GetHubAdminOptionDataAndSet(ao, "NoManageVlanId", &o->NoManageVlanId);\r
253         GetHubAdminOptionDataAndSet(ao, "VlanTypeId", &o->VlanTypeId);\r
254         GetHubAdminOptionDataAndSet(ao, "FixForDLinkBPDU", &o->FixForDLinkBPDU);\r
255         GetHubAdminOptionDataAndSet(ao, "RequiredClientId", &o->RequiredClientId);\r
256 }\r
257 \r
258 // HUB_OPTION の内容をデータに変換\r
259 void HubOptionStructToData(RPC_ADMIN_OPTION *ao, HUB_OPTION *o, char *hub_name)\r
260 {\r
261         LIST *aol;\r
262         UINT i;\r
263         // 引数チェック\r
264         if (ao == NULL || o == NULL || hub_name == NULL)\r
265         {\r
266                 return;\r
267         }\r
268 \r
269         aol = NewListFast(NULL);\r
270 \r
271         Add(aol, NewAdminOption("NoAddressPollingIPv4", o->NoArpPolling));\r
272         Add(aol, NewAdminOption("NoAddressPollingIPv6", o->NoIPv6AddrPolling));\r
273         Add(aol, NewAdminOption("NoIpTable", o->NoIpTable));\r
274         Add(aol, NewAdminOption("NoMacAddressLog", o->NoMacAddressLog));\r
275         Add(aol, NewAdminOption("ManageOnlyPrivateIP", o->ManageOnlyPrivateIP));\r
276         Add(aol, NewAdminOption("ManageOnlyLocalUnicastIPv6", o->ManageOnlyLocalUnicastIPv6));\r
277         Add(aol, NewAdminOption("DisableIPParsing", o->DisableIPParsing));\r
278         Add(aol, NewAdminOption("YieldAfterStorePacket", o->YieldAfterStorePacket));\r
279         Add(aol, NewAdminOption("NoSpinLockForPacketDelay", o->NoSpinLockForPacketDelay));\r
280         Add(aol, NewAdminOption("BroadcastStormDetectionThreshold", o->BroadcastStormDetectionThreshold));\r
281         Add(aol, NewAdminOption("ClientMinimumRequiredBuild", o->ClientMinimumRequiredBuild));\r
282         Add(aol, NewAdminOption("FilterPPPoE", o->FilterPPPoE));\r
283         Add(aol, NewAdminOption("FilterOSPF", o->FilterOSPF));\r
284         Add(aol, NewAdminOption("FilterIPv4", o->FilterIPv4));\r
285         Add(aol, NewAdminOption("FilterIPv6", o->FilterIPv6));\r
286         Add(aol, NewAdminOption("FilterNonIP", o->FilterNonIP));\r
287         Add(aol, NewAdminOption("NoIPv4PacketLog", o->NoIPv4PacketLog));\r
288         Add(aol, NewAdminOption("NoIPv6PacketLog", o->NoIPv6PacketLog));\r
289         Add(aol, NewAdminOption("FilterBPDU", o->FilterBPDU));\r
290         Add(aol, NewAdminOption("NoIPv6DefaultRouterInRAWhenIPv6", o->NoIPv6DefaultRouterInRAWhenIPv6));\r
291         Add(aol, NewAdminOption("NoLookBPDUBridgeId", o->NoLookBPDUBridgeId));\r
292         Add(aol, NewAdminOption("NoManageVlanId", o->NoManageVlanId));\r
293         Add(aol, NewAdminOption("VlanTypeId", o->VlanTypeId));\r
294         Add(aol, NewAdminOption("FixForDLinkBPDU", o->FixForDLinkBPDU));\r
295         Add(aol, NewAdminOption("RequiredClientId", o->RequiredClientId));\r
296 \r
297         Zero(ao, sizeof(RPC_ADMIN_OPTION));\r
298 \r
299         StrCpy(ao->HubName, sizeof(ao->HubName), hub_name);\r
300 \r
301         ao->NumItem = LIST_NUM(aol);\r
302         ao->Items = ZeroMalloc(sizeof(ADMIN_OPTION) * ao->NumItem);\r
303 \r
304         for (i = 0;i < LIST_NUM(aol);i++)\r
305         {\r
306                 ADMIN_OPTION *a = LIST_DATA(aol, i);\r
307 \r
308                 Copy(&ao->Items[i], a, sizeof(ADMIN_OPTION));\r
309 \r
310                 Free(a);\r
311         }\r
312 \r
313         ReleaseList(aol);\r
314 }\r
315 \r
316 // 新しい ADMIN OPTION の作成\r
317 ADMIN_OPTION *NewAdminOption(char *name, UINT value)\r
318 {\r
319         ADMIN_OPTION *a;\r
320         // 引数チェック\r
321         if (name == NULL)\r
322         {\r
323                 return NULL;\r
324         }\r
325 \r
326         a = ZeroMalloc(sizeof(ADMIN_OPTION));\r
327         StrCpy(a->Name, sizeof(a->Name), name);\r
328         a->Value = value;\r
329 \r
330         return a;\r
331 }\r
332 \r
333 // AC リストのクローン\r
334 LIST *CloneAcList(LIST *o)\r
335 {\r
336         LIST *ret;\r
337         // 引数チェック\r
338         if (o == NULL)\r
339         {\r
340                 return NULL;\r
341         }\r
342 \r
343         ret = NewAcList();\r
344         SetAcList(ret, o);\r
345 \r
346         return ret;\r
347 }\r
348 \r
349 // AC リストをすべてセットする\r
350 void SetAcList(LIST *o, LIST *src)\r
351 {\r
352         UINT i;\r
353         // 引数チェック\r
354         if (o == NULL || src == NULL)\r
355         {\r
356                 return;\r
357         }\r
358 \r
359         DelAllAc(o);\r
360 \r
361         for (i = 0;i < LIST_NUM(src);i++)\r
362         {\r
363                 AC *ac = LIST_DATA(src, i);\r
364 \r
365                 AddAc(o, ac);\r
366         }\r
367 }\r
368 \r
369 // AC リストからすべての AC を削除する\r
370 void DelAllAc(LIST *o)\r
371 {\r
372         UINT i;\r
373         // 引数チェック\r
374         if (o == NULL)\r
375         {\r
376                 return;\r
377         }\r
378 \r
379         for (i = 0;i < LIST_NUM(o);i++)\r
380         {\r
381                 AC *ac = LIST_DATA(o, i);\r
382 \r
383                 Free(ac);\r
384         }\r
385 \r
386         DeleteAll(o);\r
387 }\r
388 \r
389 // AC リストを解放する\r
390 void FreeAcList(LIST *o)\r
391 {\r
392         UINT i;\r
393         // 引数チェック\r
394         if (o == NULL)\r
395         {\r
396                 return;\r
397         }\r
398 \r
399         for (i = 0;i < LIST_NUM(o);i++)\r
400         {\r
401                 AC *ac = LIST_DATA(o, i);\r
402 \r
403                 Free(ac);\r
404         }\r
405 \r
406         ReleaseList(o);\r
407 }\r
408 \r
409 // AC の内容を示す文字列を生成する\r
410 char *GenerateAcStr(AC *ac)\r
411 {\r
412         char tmp[MAX_SIZE];\r
413         char ip[64], mask[64];\r
414 \r
415         if (ac == NULL)\r
416         {\r
417                 return NULL;\r
418         }\r
419 \r
420         IPToStr(ip, sizeof(ip), &ac->IpAddress);\r
421         MaskToStr(mask, sizeof(mask), &ac->SubnetMask);\r
422 \r
423         if (ac->Masked == false)\r
424         {\r
425                 Format(tmp, sizeof(tmp), "%s", ip);\r
426         }\r
427         else\r
428         {\r
429                 Format(tmp, sizeof(tmp), "%s/%s", ip, mask);\r
430         }\r
431 \r
432         return CopyStr(tmp);\r
433 }\r
434 \r
435 // AC の設定\r
436 void SetAc(LIST *o, UINT id, AC *ac)\r
437 {\r
438         // 引数チェック\r
439         if (o == NULL || id == 0 || ac == NULL)\r
440         {\r
441                 return;\r
442         }\r
443 \r
444         if (DelAc(o, id))\r
445         {\r
446                 AddAc(o, ac);\r
447         }\r
448 }\r
449 \r
450 // AC の取得\r
451 AC *GetAc(LIST *o, UINT id)\r
452 {\r
453         UINT i;\r
454         // 引数チェック\r
455         if (o == NULL || id == 0)\r
456         {\r
457                 return NULL;\r
458         }\r
459 \r
460         for (i = 0;i < LIST_NUM(o);i++)\r
461         {\r
462                 AC *ac = LIST_DATA(o, i);\r
463 \r
464                 if (ac->Id == id)\r
465                 {\r
466                         return Clone(ac, sizeof(AC));\r
467                 }\r
468         }\r
469 \r
470         return NULL;\r
471 }\r
472 \r
473 // AC の削除\r
474 bool DelAc(LIST *o, UINT id)\r
475 {\r
476         UINT i;\r
477         // 引数チェック\r
478         if (o == NULL || id == 0)\r
479         {\r
480                 return false;\r
481         }\r
482 \r
483         for (i = 0;i < LIST_NUM(o);i++)\r
484         {\r
485                 AC *ac = LIST_DATA(o, i);\r
486 \r
487                 if (ac->Id == id)\r
488                 {\r
489                         if (Delete(o, ac))\r
490                         {\r
491                                 Free(ac);\r
492 \r
493                                 NormalizeAcList(o);\r
494 \r
495                                 return true;\r
496                         }\r
497                 }\r
498         }\r
499 \r
500         return false;\r
501 }\r
502 \r
503 // AC の追加\r
504 void AddAc(LIST *o, AC *ac)\r
505 {\r
506         // 引数チェック\r
507         if (o == NULL || ac == NULL)\r
508         {\r
509                 return;\r
510         }\r
511 \r
512         if (LIST_NUM(o) < MAX_HUB_ACS)\r
513         {\r
514                 Insert(o, Clone(ac, sizeof(AC)));\r
515 \r
516                 NormalizeAcList(o);\r
517         }\r
518 }\r
519 \r
520 // AC リストを正規化する\r
521 void NormalizeAcList(LIST *o)\r
522 {\r
523         UINT i;\r
524         // 引数チェック\r
525         if (o == NULL)\r
526         {\r
527                 return;\r
528         }\r
529 \r
530         for (i = 0;i < LIST_NUM(o);i++)\r
531         {\r
532                 AC *ac = LIST_DATA(o, i);\r
533 \r
534                 if (IsIP6(&ac->IpAddress))\r
535                 {\r
536                         ac->IpAddress.ipv6_scope_id = 0;\r
537                 }\r
538 \r
539                 ac->Id = (i + 1);\r
540         }\r
541 }\r
542 \r
543 // 新しい AC リストの作成\r
544 LIST *NewAcList()\r
545 {\r
546         return NewList(CmpAc);\r
547 }\r
548 \r
549 // AC 比較\r
550 int CmpAc(void *p1, void *p2)\r
551 {\r
552         AC *a1, *a2;\r
553         if (p1 == NULL || p2 == NULL)\r
554         {\r
555                 return 0;\r
556         }\r
557         a1 = *(AC **)p1;\r
558         a2 = *(AC **)p2;\r
559         if (a1 == NULL || a2 == NULL)\r
560         {\r
561                 return 0;\r
562         }\r
563         if (a1->Priority > a2->Priority)\r
564         {\r
565                 return 1;\r
566         }\r
567         else if (a1->Priority < a2->Priority)\r
568         {\r
569                 return -1;\r
570         }\r
571         else if (a1->Deny > a2->Deny)\r
572         {\r
573                 return 1;\r
574         }\r
575         else if (a1->Deny < a2->Deny)\r
576         {\r
577                 return -1;\r
578         }\r
579         else\r
580         {\r
581                 return 0;\r
582         }\r
583 }\r
584 \r
585 // CRL のコピー\r
586 CRL *CopyCrl(CRL *crl)\r
587 {\r
588         CRL *ret;\r
589         // 引数チェック\r
590         if (crl == NULL)\r
591         {\r
592                 return NULL;\r
593         }\r
594 \r
595         ret = ZeroMalloc(sizeof(CRL));\r
596 \r
597         if (crl->Serial != NULL)\r
598         {\r
599                 ret->Serial = NewXSerial(crl->Serial->data, crl->Serial->size);\r
600         }\r
601 \r
602         ret->Name = CopyName(crl->Name);\r
603 \r
604         Copy(ret->DigestMD5, crl->DigestMD5, MD5_SIZE);\r
605         Copy(ret->DigestSHA1, crl->DigestSHA1, SHA1_SIZE);\r
606 \r
607         return ret;\r
608 }\r
609 \r
610 // CRL の解放\r
611 void FreeCrl(CRL *crl)\r
612 {\r
613         // 引数チェック\r
614         if (crl == NULL)\r
615         {\r
616                 return;\r
617         }\r
618 \r
619         if (crl->Serial != NULL)\r
620         {\r
621                 FreeXSerial(crl->Serial);\r
622         }\r
623 \r
624         if (crl->Name != NULL)\r
625         {\r
626                 FreeName(crl->Name);\r
627         }\r
628 \r
629         Free(crl);\r
630 }\r
631 \r
632 // 仮想 HUB の CRL リストを検索して証明書が無効化されていないかどうか調べる\r
633 bool IsValidCertInHub(HUB *h, X *x)\r
634 {\r
635         bool ret;\r
636         // 引数チェック\r
637         if (h == NULL || x == NULL)\r
638         {\r
639                 return false;\r
640         }\r
641 \r
642         if (h->HubDb == NULL)\r
643         {\r
644                 return false;\r
645         }\r
646 \r
647         if (IsXRevoked(x))\r
648         {\r
649                 // ファイルに保存されている CRL によって無効化されている\r
650                 return false;\r
651         }\r
652 \r
653         LockList(h->HubDb->CrlList);\r
654         {\r
655                 ret = IsCertMatchCrlList(x, h->HubDb->CrlList);\r
656         }\r
657         UnlockList(h->HubDb->CrlList);\r
658 \r
659         if (ret)\r
660         {\r
661                 // 一致するので無効である\r
662                 return false;\r
663         }\r
664 \r
665         // 一致しなかったので有効である\r
666         return true;\r
667 }\r
668 \r
669 // CRL リストに証明書が一致するかどうか検索\r
670 bool IsCertMatchCrlList(X *x, LIST *o)\r
671 {\r
672         UINT i;\r
673         // 引数チェック\r
674         if (x == NULL || o == NULL)\r
675         {\r
676                 return false;\r
677         }\r
678 \r
679         for (i = 0;i < LIST_NUM(o);i++)\r
680         {\r
681                 CRL *crl = LIST_DATA(o, i);\r
682 \r
683                 if (IsCertMatchCrl(x, crl))\r
684                 {\r
685                         return true;\r
686                 }\r
687         }\r
688 \r
689         return false;\r
690 }\r
691 \r
692 // CRL を示す文字列に変換する\r
693 wchar_t *GenerateCrlStr(CRL *crl)\r
694 {\r
695         wchar_t tmp[2048];\r
696         // 引数チェック\r
697         if (crl == NULL)\r
698         {\r
699                 return NULL;\r
700         }\r
701 \r
702         UniStrCpy(tmp, sizeof(tmp), L"");\r
703 \r
704         if (crl->Name != NULL)\r
705         {\r
706                 // 名前情報\r
707                 wchar_t name[MAX_SIZE];\r
708 \r
709                 UniStrCat(tmp, sizeof(tmp), L"Subject=\"");\r
710 \r
711                 GetAllNameFromName(name, sizeof(name), crl->Name);\r
712                 UniStrCat(tmp, sizeof(tmp), name);\r
713                 UniStrCat(tmp, sizeof(tmp), L"\", ");\r
714         }\r
715 \r
716         if (crl->Serial != NULL)\r
717         {\r
718                 // シリアル情報\r
719                 char str[128];\r
720                 wchar_t uni[128];\r
721 \r
722                 BinToStrEx(str, sizeof(str), crl->Serial->data, crl->Serial->size);\r
723                 StrToUni(uni, sizeof(uni), str);\r
724                 UniStrCat(tmp, sizeof(tmp), L"Serial=\"");\r
725                 UniStrCat(tmp, sizeof(tmp), uni);\r
726                 UniStrCat(tmp, sizeof(tmp), L"\", ");\r
727         }\r
728 \r
729         if (IsZero(crl->DigestMD5, MD5_SIZE) == false)\r
730         {\r
731                 // MD5\r
732                 char str[128];\r
733                 wchar_t uni[128];\r
734 \r
735                 BinToStrEx(str, sizeof(str), crl->DigestMD5, MD5_SIZE);\r
736                 StrToUni(uni, sizeof(uni), str);\r
737                 UniStrCat(tmp, sizeof(tmp), L"MD5=\"");\r
738                 UniStrCat(tmp, sizeof(tmp), uni);\r
739                 UniStrCat(tmp, sizeof(tmp), L"\", ");\r
740         }\r
741 \r
742         if (IsZero(crl->DigestSHA1, SHA1_SIZE) == false)\r
743         {\r
744                 // MD5\r
745                 char str[128];\r
746                 wchar_t uni[128];\r
747 \r
748                 BinToStrEx(str, sizeof(str), crl->DigestSHA1, SHA1_SIZE);\r
749                 StrToUni(uni, sizeof(uni), str);\r
750                 UniStrCat(tmp, sizeof(tmp), L"SHA1=\"");\r
751                 UniStrCat(tmp, sizeof(tmp), uni);\r
752                 UniStrCat(tmp, sizeof(tmp), L"\", ");\r
753         }\r
754 \r
755         if (UniEndWith(tmp, L", "))\r
756         {\r
757                 tmp[UniStrLen(tmp) - 2] = 0;\r
758         }\r
759 \r
760         return CopyUniStr(tmp);\r
761 }\r
762 \r
763 // 証明書無効リストエントリに一致するかどうか検査する\r
764 bool IsCertMatchCrl(X *x, CRL *crl)\r
765 {\r
766         // このあたりは急いで実装したのでコードがあまり美しくない。\r
767         bool b = true;\r
768         // 引数チェック\r
769         if (x == NULL || crl == NULL)\r
770         {\r
771                 return false;\r
772         }\r
773 \r
774         if (crl->Serial != NULL)\r
775         {\r
776                 // CRL にシリアル番号が定義されている場合\r
777                 if (x->serial == NULL || CompareXSerial(x->serial, crl->Serial) == false)\r
778                 {\r
779                         // シリアル番号不一致\r
780                         b = false;\r
781                 }\r
782         }\r
783 \r
784         if (IsZero(crl->DigestMD5, sizeof(crl->DigestMD5)) == false)\r
785         {\r
786                 UCHAR test[MD5_SIZE];\r
787                 // CRL に DigestMD5 が定義されている場合\r
788                 GetXDigest(x, test, false);\r
789 \r
790                 if (Cmp(test, crl->DigestMD5, MD5_SIZE) != 0)\r
791                 {\r
792                         b = false;\r
793                 }\r
794         }\r
795 \r
796         if (IsZero(crl->DigestSHA1, sizeof(crl->DigestSHA1)) == false)\r
797         {\r
798                 UCHAR test[SHA1_SIZE];\r
799                 // CRL に DigestSHA1 が定義されている場合\r
800                 GetXDigest(x, test, true);\r
801 \r
802                 if (Cmp(test, crl->DigestSHA1, SHA1_SIZE) != 0)\r
803                 {\r
804                         b = false;\r
805                 }\r
806         }\r
807 \r
808         if (crl->Name != NULL)\r
809         {\r
810                 // CRL に名前が定義されている場合\r
811                 NAME *xn, *cn;\r
812                 xn = x->subject_name;\r
813                 cn = crl->Name;\r
814 \r
815                 if (cn->CommonName != NULL && (UniIsEmptyStr(cn->CommonName) == false))\r
816                 {\r
817                         if (xn->CommonName == NULL || UniSoftStrCmp(xn->CommonName, cn->CommonName) != 0)\r
818                         {\r
819                                 // CommonName 不一致\r
820                                 b = false;\r
821                         }\r
822                 }\r
823 \r
824                 if (cn->Organization != NULL && (UniIsEmptyStr(cn->Organization) == false))\r
825                 {\r
826                         if (xn->Organization == NULL || UniSoftStrCmp(xn->Organization, cn->Organization) != 0)\r
827                         {\r
828                                 // Organization 不一致\r
829                                 b = false;\r
830                         }\r
831                 }\r
832 \r
833                 if (cn->Unit != NULL && (UniIsEmptyStr(cn->Unit) == false))\r
834                 {\r
835                         if (xn->Unit == NULL || UniSoftStrCmp(xn->Unit, cn->Unit) != 0)\r
836                         {\r
837                                 // Unit不一致\r
838                                 b = false;\r
839                         }\r
840                 }\r
841 \r
842                 if (cn->Country != NULL && (UniIsEmptyStr(cn->Country) == false))\r
843                 {\r
844                         if (xn->Country == NULL || UniSoftStrCmp(xn->Country, cn->Country) != 0)\r
845                         {\r
846                                 // Country 不一致\r
847                                 b = false;\r
848                         }\r
849                 }\r
850 \r
851                 if (cn->State != NULL && (UniIsEmptyStr(cn->State) == false))\r
852                 {\r
853                         if (xn->State == NULL || UniSoftStrCmp(xn->State, cn->State) != 0)\r
854                         {\r
855                                 // State 不一致\r
856                                 b = false;\r
857                         }\r
858                 }\r
859 \r
860                 if (cn->Local != NULL && (UniIsEmptyStr(cn->Local) == false))\r
861                 {\r
862                         if (xn->Local == NULL || UniSoftStrCmp(xn->Local, cn->Local) != 0)\r
863                         {\r
864                                 // Local 不一致\r
865                                 b = false;\r
866                         }\r
867                 }\r
868         }\r
869 \r
870         return b;\r
871 }\r
872 \r
873 // 管理オプションのヘルプ文字列を取得する\r
874 wchar_t *GetHubAdminOptionHelpString(char *name)\r
875 {\r
876         char tmp[MAX_SIZE];\r
877         wchar_t *ret;\r
878         // 引数チェック\r
879         if (name == NULL)\r
880         {\r
881                 return L"";\r
882         }\r
883 \r
884         Format(tmp, sizeof(tmp), "HUB_AO_%s", name);\r
885 \r
886         ret = _UU(tmp);\r
887         if (UniIsEmptyStr(ret))\r
888         {\r
889                 ret = _UU("HUB_AO_UNKNOWN");\r
890         }\r
891 \r
892         return ret;\r
893 }\r
894 \r
895 // 仮想 HUB にデフォルトの管理オプションを追加する\r
896 void AddHubAdminOptionsDefaults(HUB *h, bool lock)\r
897 {\r
898         UINT i;\r
899         // 引数チェック\r
900         if (h == NULL)\r
901         {\r
902                 return;\r
903         }\r
904 \r
905         if (lock)\r
906         {\r
907                 LockList(h->AdminOptionList);\r
908         }\r
909 \r
910         for (i = 0;i < num_admin_options;i++)\r
911         {\r
912                 ADMIN_OPTION *e = &admin_options[i];\r
913                 ADMIN_OPTION t, *r;\r
914 \r
915                 Zero(&t, sizeof(t));\r
916                 StrCpy(t.Name, sizeof(t.Name), e->Name);\r
917 \r
918                 r = Search(h->AdminOptionList, &t);\r
919                 if (r == NULL)\r
920                 {\r
921                         ADMIN_OPTION *a = ZeroMalloc(sizeof(ADMIN_OPTION));\r
922 \r
923                         StrCpy(a->Name, sizeof(a->Name), e->Name);\r
924                         a->Value = e->Value;\r
925 \r
926                         Insert(h->AdminOptionList, a);\r
927                 }\r
928         }\r
929 \r
930         if (lock)\r
931         {\r
932                 UnlockList(h->AdminOptionList);\r
933         }\r
934 }\r
935 \r
936 // 仮想 HUB のすべての管理オプションの削除\r
937 void DeleteAllHubAdminOption(HUB *h, bool lock)\r
938 {\r
939         UINT i;\r
940         // 引数チェック\r
941         if (h == NULL)\r
942         {\r
943                 return;\r
944         }\r
945 \r
946         if (lock)\r
947         {\r
948                 LockList(h->AdminOptionList);\r
949         }\r
950 \r
951         for (i = 0;i < LIST_NUM(h->AdminOptionList);i++)\r
952         {\r
953                 Free(LIST_DATA(h->AdminOptionList, i));\r
954         }\r
955 \r
956         DeleteAll(h->AdminOptionList);\r
957 \r
958         if (lock)\r
959         {\r
960                 UnlockList(h->AdminOptionList);\r
961         }\r
962 }\r
963 \r
964 // 仮想 HUB の管理オプションの取得\r
965 UINT GetHubAdminOptionEx(HUB *h, char *name, UINT default_value)\r
966 {\r
967         UINT ret = default_value;\r
968         // 引数チェック\r
969         if (h == NULL || name == NULL)\r
970         {\r
971                 return 0;\r
972         }\r
973 \r
974         LockList(h->AdminOptionList);\r
975         {\r
976                 ADMIN_OPTION *a, t;\r
977 \r
978                 Zero(&t, sizeof(t));\r
979                 StrCpy(t.Name, sizeof(t.Name), name);\r
980                 Trim(t.Name);\r
981 \r
982                 a = Search(h->AdminOptionList, &t);\r
983 \r
984                 if (a != NULL)\r
985                 {\r
986                         ret = a->Value;\r
987                 }\r
988         }\r
989         UnlockList(h->AdminOptionList);\r
990 \r
991         return ret;\r
992 }\r
993 UINT GetHubAdminOption(HUB *h, char *name)\r
994 {\r
995         return GetHubAdminOptionEx(h, name, 0);\r
996 }\r
997 \r
998 // 管理オプション\r
999 int CompareAdminOption(void *p1, void *p2)\r
1000 {\r
1001         ADMIN_OPTION *a1, *a2;\r
1002         if (p1 == NULL || p2 == NULL)\r
1003         {\r
1004                 return 0;\r
1005         }\r
1006         a1 = *(ADMIN_OPTION **)p1;\r
1007         a2 = *(ADMIN_OPTION **)p2;\r
1008         if (a1 == NULL || a2 == NULL)\r
1009         {\r
1010                 return 0;\r
1011         }\r
1012         return StrCmpi(a1->Name, a2->Name);\r
1013 }\r
1014 \r
1015 // 番犬開始\r
1016 void StartHubWatchDog(HUB *h)\r
1017 {\r
1018         THREAD *t;\r
1019         // 引数チェック\r
1020         if (h == NULL)\r
1021         {\r
1022                 return;\r
1023         }\r
1024 \r
1025         h->HaltWatchDog = false;\r
1026         h->WatchDogEvent = NewEvent();\r
1027 \r
1028         t = NewThread(HubWatchDogThread, h);\r
1029         WaitThreadInit(t);\r
1030         ReleaseThread(t);\r
1031 }\r
1032 \r
1033 // 番犬停止\r
1034 void StopHubWatchDog(HUB *h)\r
1035 {\r
1036         // 引数チェック\r
1037         if (h == NULL)\r
1038         {\r
1039                 return;\r
1040         }\r
1041 \r
1042         h->HaltWatchDog = true;\r
1043         Set(h->WatchDogEvent);\r
1044 \r
1045         WaitThread(h->WatchDogThread, INFINITE);\r
1046         ReleaseThread(h->WatchDogThread);\r
1047         h->WatchDogThread = NULL;\r
1048         h->HaltWatchDog = false;\r
1049 \r
1050         ReleaseEvent(h->WatchDogEvent);\r
1051         h->WatchDogEvent = NULL;\r
1052 }\r
1053 \r
1054 // 番犬スレッド\r
1055 void HubWatchDogThread(THREAD *t, void *param)\r
1056 {\r
1057         UINT num_packets_v4 = 0;\r
1058         UINT num_packets_v6 = 0;\r
1059         HUB *hub;\r
1060         // 引数チェック\r
1061         if (t == NULL || param == NULL)\r
1062         {\r
1063                 return;\r
1064         }\r
1065 \r
1066         hub = (HUB *)param;\r
1067 \r
1068         hub->WatchDogThread = t;\r
1069         AddRef(t->ref);\r
1070 \r
1071         NoticeThreadInit(t);\r
1072 \r
1073         while (true)\r
1074         {\r
1075                 LIST *o;\r
1076                 LIST *o2;\r
1077                 UINT i, num;\r
1078                 UINT interval;\r
1079                 UINT wait_time = 100;\r
1080                 if (hub->HaltWatchDog)\r
1081                 {\r
1082                         break;\r
1083                 }\r
1084 \r
1085                 o = NewListFast(NULL);\r
1086                 o2 = NewListFast(NULL);\r
1087 \r
1088                 // ARP パケットの送信\r
1089                 LockList(hub->IpTable);\r
1090                 {\r
1091                         num = LIST_NUM(hub->IpTable);\r
1092                         for (i = 0;i < LIST_NUM(hub->IpTable);i++)\r
1093                         {\r
1094                                 IP_TABLE_ENTRY *e = LIST_DATA(hub->IpTable, i);\r
1095 \r
1096                                 if ((e->UpdatedTime + (UINT64)(IP_TABLE_EXPIRE_TIME)) > Tick64())\r
1097                                 {\r
1098                                         if (e->MacAddress[0] != 0xff || e->MacAddress[1] != 0xff || e->MacAddress[2] != 0xff ||\r
1099                                                 e->MacAddress[3] != 0xff || e->MacAddress[4] != 0xff || e->MacAddress[5] != 0xff)\r
1100                                         {\r
1101                                                 if (hub->Option != NULL && hub->Option->NoArpPolling == false)\r
1102                                                 {\r
1103                                                         if (IsIP4(&e->Ip))\r
1104                                                         {\r
1105                                                                 // IPv4\r
1106                                                                 MAC_HEADER *mac = ZeroMalloc(sizeof(MAC_HEADER) + sizeof(ARPV4_HEADER));\r
1107                                                                 ARPV4_HEADER *p = (ARPV4_HEADER *)(((UCHAR *)mac) + sizeof(MAC_HEADER));\r
1108 \r
1109                                                                 Copy(mac->DestAddress, e->MacAddress, 6);\r
1110                                                                 Copy(mac->SrcAddress, hub->HubMacAddr, 6);\r
1111                                                                 mac->Protocol = Endian16(MAC_PROTO_ARPV4);\r
1112 \r
1113                                                                 p->HardwareType = Endian16(ARP_HARDWARE_TYPE_ETHERNET);\r
1114                                                                 p->ProtocolType = Endian16(MAC_PROTO_IPV4);\r
1115                                                                 p->HardwareSize = 6;\r
1116                                                                 p->ProtocolSize = 4;\r
1117                                                                 p->Operation = Endian16(ARP_OPERATION_REQUEST);\r
1118                                                                 Copy(p->SrcAddress, hub->HubMacAddr, 6);\r
1119                                                                 p->SrcIP = IPToUINT(&hub->HubIp);\r
1120                                                                 p->TargetAddress[0] =\r
1121                                                                         p->TargetAddress[1] =\r
1122                                                                         p->TargetAddress[2] =\r
1123                                                                         p->TargetAddress[3] =\r
1124                                                                         p->TargetAddress[4] =\r
1125                                                                         p->TargetAddress[5] = 0x00;\r
1126                                                                 p->TargetIP = IPToUINT(&e->Ip);\r
1127                                                                 Insert(o, mac);\r
1128                                                         }\r
1129                                                 }\r
1130 \r
1131                                                 if (hub->Option != NULL && hub->Option->NoIPv6AddrPolling == false)\r
1132                                                 {\r
1133                                                         if (IsIP6(&e->Ip))\r
1134                                                         {\r
1135                                                                 // IPv6\r
1136                                                                 BUF *buf;\r
1137                                                                 IPV6_ADDR ip6addr;\r
1138 \r
1139                                                                 if (IPToIPv6Addr(&ip6addr, &e->Ip))\r
1140                                                                 {\r
1141                                                                         buf = BuildICMPv6NeighborSoliciation(&hub->HubIpV6,\r
1142                                                                                 &ip6addr,\r
1143                                                                                 hub->HubMacAddr, ++hub->HubIP6Id);\r
1144 \r
1145                                                                         if (buf != NULL)\r
1146                                                                         {\r
1147                                                                                 BUF *buf2 = NewBuf();\r
1148                                                                                 MAC_HEADER mac;\r
1149 \r
1150                                                                                 Zero(&mac, sizeof(mac));\r
1151 \r
1152                                                                                 Copy(mac.DestAddress, e->MacAddress, 6);\r
1153                                                                                 Copy(mac.SrcAddress, hub->HubMacAddr, 6);\r
1154                                                                                 mac.Protocol = Endian16(MAC_PROTO_IPV6);\r
1155 \r
1156                                                                                 WriteBuf(buf2, &mac, sizeof(MAC_HEADER));\r
1157 \r
1158                                                                                 WriteBuf(buf2, buf->Buf, buf->Size);\r
1159 \r
1160                                                                                 FreeBuf(buf);\r
1161 \r
1162                                                                                 Insert(o2, buf2);\r
1163                                                                         }\r
1164                                                                 }\r
1165                                                         }\r
1166                                                 }\r
1167                                         }\r
1168                                 }\r
1169                         }\r
1170                 }\r
1171                 UnlockList(hub->IpTable);\r
1172 \r
1173                 if ((LIST_NUM(o) + LIST_NUM(o2)) != 0)\r
1174                 {\r
1175                         interval = HUB_ARP_SEND_INTERVAL / (LIST_NUM(o) + LIST_NUM(o2));\r
1176                 }\r
1177                 else\r
1178                 {\r
1179                         interval = HUB_ARP_SEND_INTERVAL;\r
1180                 }\r
1181 \r
1182                 for (i = 0;i < LIST_NUM(o);i++)\r
1183                 {\r
1184                         PKT *packet;\r
1185                         void *p = LIST_DATA(o, i);\r
1186 \r
1187                         Wait(hub->WatchDogEvent, interval);\r
1188                         if (hub->HaltWatchDog)\r
1189                         {\r
1190                                 for (;i < LIST_NUM(o);i++)\r
1191                                 {\r
1192                                         Free(LIST_DATA(o, i));\r
1193                                 }\r
1194                                 ReleaseList(o);\r
1195 \r
1196                                 for (i = 0;i < LIST_NUM(o2);i++)\r
1197                                 {\r
1198                                         FreeBuf(LIST_DATA(o2, i));\r
1199                                 }\r
1200                                 ReleaseList(o2);\r
1201                                 goto ESCAPE;\r
1202                         }\r
1203 \r
1204                         packet = ParsePacket((UCHAR *)p, sizeof(MAC_HEADER) + sizeof(ARPV4_HEADER));\r
1205                         if (packet != NULL)\r
1206                         {\r
1207                                 StorePacket(hub, NULL, packet);\r
1208                                 num_packets_v4++;\r
1209                         }\r
1210                         else\r
1211                         {\r
1212                                 Free(p);\r
1213                         }\r
1214                 }\r
1215 \r
1216                 for (i = 0;i < LIST_NUM(o2);i++)\r
1217                 {\r
1218                         PKT *packet;\r
1219                         BUF *buf = LIST_DATA(o2, i);\r
1220 \r
1221                         Wait(hub->WatchDogEvent, interval);\r
1222                         if (hub->HaltWatchDog)\r
1223                         {\r
1224                                 ReleaseList(o);\r
1225 \r
1226                                 for (;i < LIST_NUM(o2);i++)\r
1227                                 {\r
1228                                         FreeBuf(LIST_DATA(o2, i));\r
1229                                 }\r
1230                                 ReleaseList(o2);\r
1231                                 goto ESCAPE;\r
1232                         }\r
1233 \r
1234                         packet = ParsePacket(buf->Buf, buf->Size);\r
1235                         if (packet != NULL)\r
1236                         {\r
1237                                 StorePacket(hub, NULL, packet);\r
1238                                 num_packets_v6++;\r
1239                         }\r
1240                         else\r
1241                         {\r
1242                                 Free(buf->Buf);\r
1243                         }\r
1244 \r
1245                         Free(buf);\r
1246                 }\r
1247 \r
1248                 ReleaseList(o);\r
1249                 ReleaseList(o2);\r
1250 \r
1251                 if (num == 0)\r
1252                 {\r
1253                         wait_time = HUB_ARP_SEND_INTERVAL;\r
1254                 }\r
1255 \r
1256                 Wait(hub->WatchDogEvent, wait_time);\r
1257         }\r
1258 ESCAPE:\r
1259         return;\r
1260 }\r
1261 \r
1262 // SecureNAT を有効/無効に設定する\r
1263 void EnableSecureNAT(HUB *h, bool enable)\r
1264 {\r
1265         EnableSecureNATEx(h, enable, false);\r
1266 }\r
1267 void EnableSecureNATEx(HUB *h, bool enable, bool no_change)\r
1268 {\r
1269         bool for_cluster = false;\r
1270         // 引数チェック\r
1271         if (h == NULL)\r
1272         {\r
1273                 return;\r
1274         }\r
1275 \r
1276         if (h->Cedar->Server != NULL && h->Cedar->Server->ServerType == SERVER_TYPE_FARM_CONTROLLER)\r
1277         {\r
1278                 if (h->Type == HUB_TYPE_FARM_DYNAMIC)\r
1279                 {\r
1280                         for_cluster = true;\r
1281                 }\r
1282         }\r
1283 \r
1284         Lock(h->lock_online);\r
1285         {\r
1286                 if (no_change == false)\r
1287                 {\r
1288                         h->EnableSecureNAT = enable;\r
1289                 }\r
1290 \r
1291                 if (h->EnableSecureNAT == false)\r
1292                 {\r
1293 STOP:\r
1294                         // すでに開始している場合は停止する\r
1295                         if (h->SecureNAT != NULL)\r
1296                         {\r
1297                                 SnFreeSecureNAT(h->SecureNAT);\r
1298                                 h->SecureNAT = NULL;\r
1299                         }\r
1300                 }\r
1301                 else\r
1302                 {\r
1303                         if (for_cluster)\r
1304                         {\r
1305                                 if ((h->SecureNAT != NULL && LIST_NUM(h->SessionList) <= 1) ||\r
1306                                         (h->SecureNAT == NULL && LIST_NUM(h->SessionList) == 0))\r
1307                                 {\r
1308                                         // 開始モードだが、ダイナミック仮想 HUB で他にセッションが無い場合\r
1309                                         // は停止する\r
1310                                         goto STOP;\r
1311                                 }\r
1312                         }\r
1313 \r
1314                         // まだ開始していない場合で HUB がオンラインの場合は開始する\r
1315                         if (h->SecureNAT == NULL && h->Offline == false)\r
1316                         {\r
1317                                 h->SecureNAT = SnNewSecureNAT(h, h->SecureNATOption);\r
1318                         }\r
1319                 }\r
1320         }\r
1321         Unlock(h->lock_online);\r
1322 }\r
1323 \r
1324 // アクセスリストを文字列に変換する\r
1325 void GetAccessListStr(char *str, UINT size, ACCESS *a)\r
1326 {\r
1327         char tmp[MAX_SIZE];\r
1328         char tmp1[MAX_SIZE];\r
1329         char tmp2[MAX_SIZE];\r
1330         bool l3 = false;\r
1331         bool asterisk = false;\r
1332         // 引数チェック\r
1333         if (str == NULL || a == NULL)\r
1334         {\r
1335                 return;\r
1336         }\r
1337 \r
1338         StrCpy(str, size, "");\r
1339 \r
1340         if (a->IsIPv6 == false)\r
1341         {\r
1342                 if (a->SrcIpAddress != 0 || a->SrcSubnetMask != 0)\r
1343                 {\r
1344                         IPToStr32(tmp1, sizeof(tmp1), a->SrcIpAddress);\r
1345                         MaskToStr32(tmp2, sizeof(tmp2), a->SrcSubnetMask);\r
1346                         Format(tmp, sizeof(tmp), "SrcIPv4=%s/%s, ", tmp1, tmp2);\r
1347                         StrCat(str, size, tmp);\r
1348 \r
1349                         l3 = true;\r
1350                 }\r
1351 \r
1352                 if (a->DestIpAddress != 0 || a->DestSubnetMask != 0)\r
1353                 {\r
1354                         IPToStr32(tmp1, sizeof(tmp1), a->DestIpAddress);\r
1355                         MaskToStr32(tmp2, sizeof(tmp2), a->DestSubnetMask);\r
1356                         Format(tmp, sizeof(tmp), "DstIPv4=%s/%s, ", tmp1, tmp2);\r
1357                         StrCat(str, size, tmp);\r
1358 \r
1359                         l3 = true;\r
1360                 }\r
1361         }\r
1362         else\r
1363         {\r
1364                 if (IsZeroIP6Addr(&a->SrcIpAddress6) == false || IsZeroIP6Addr(&a->SrcSubnetMask6) == false)\r
1365                 {\r
1366                         IP6AddrToStr(tmp1, sizeof(tmp1), &a->SrcIpAddress6);\r
1367                         Mask6AddrToStr(tmp2, sizeof(tmp2), &a->SrcSubnetMask6);\r
1368                         Format(tmp, sizeof(tmp), "SrcIPv6=%s/%s, ", tmp1, tmp2);\r
1369                         StrCat(str, size, tmp);\r
1370 \r
1371                         l3 = true;\r
1372                 }\r
1373 \r
1374                 if (IsZeroIP6Addr(&a->DestIpAddress6) == false || IsZeroIP6Addr(&a->DestSubnetMask6) == false)\r
1375                 {\r
1376                         IP6AddrToStr(tmp1, sizeof(tmp1), &a->DestIpAddress6);\r
1377                         Mask6AddrToStr(tmp2, sizeof(tmp2), &a->DestSubnetMask6);\r
1378                         Format(tmp, sizeof(tmp), "DstIPv6=%s/%s, ", tmp1, tmp2);\r
1379                         StrCat(str, size, tmp);\r
1380 \r
1381                         l3 = true;\r
1382                 }\r
1383         }\r
1384 \r
1385         if (a->Protocol != 0)\r
1386         {\r
1387                 StrCpy(tmp1, sizeof(tmp1), "");\r
1388                 switch (a->Protocol)\r
1389                 {\r
1390                 case 1:\r
1391                         StrCpy(tmp1, sizeof(tmp1), "ICMPv4");\r
1392                         break;\r
1393                 case 3:\r
1394                         StrCpy(tmp1, sizeof(tmp1), "GGP");\r
1395                         break;\r
1396                 case 6:\r
1397                         StrCpy(tmp1, sizeof(tmp1), "TCP");\r
1398                         break;\r
1399                 case 8:\r
1400                         StrCpy(tmp1, sizeof(tmp1), "EGP");\r
1401                         break;\r
1402                 case 12:\r
1403                         StrCpy(tmp1, sizeof(tmp1), "PUP");\r
1404                         break;\r
1405                 case 17:\r
1406                         StrCpy(tmp1, sizeof(tmp1), "UDP");\r
1407                         break;\r
1408                 case 20:\r
1409                         StrCpy(tmp1, sizeof(tmp1), "HMP");\r
1410                         break;\r
1411                 case 22:\r
1412                         StrCpy(tmp1, sizeof(tmp1), "XNS-IDP");\r
1413                         break;\r
1414                 case 27:\r
1415                         StrCpy(tmp1, sizeof(tmp1), "RDP");\r
1416                         break;\r
1417                 case 58:\r
1418                         StrCpy(tmp1, sizeof(tmp1), "ICMPv6");\r
1419                         break;\r
1420                 case 66:\r
1421                         StrCpy(tmp1, sizeof(tmp1), "RVD");\r
1422                         break;\r
1423                 }\r
1424                 Format(tmp, sizeof(tmp), "Protocol=%s(%u), ", tmp1, a->Protocol);\r
1425                 StrCat(str, size, tmp);\r
1426 \r
1427                 l3 = true;\r
1428         }\r
1429 \r
1430         if (a->SrcPortStart != 0)\r
1431         {\r
1432                 if (a->SrcPortEnd == a->SrcPortStart)\r
1433                 {\r
1434                         Format(tmp, sizeof(tmp), "SrcPort=%u, ", a->SrcPortStart);\r
1435                         StrCat(str, size, tmp);\r
1436                 }\r
1437                 else\r
1438                 {\r
1439                         Format(tmp, sizeof(tmp), "SrcPort=%u-%u, ", a->SrcPortStart, a->SrcPortEnd);\r
1440                         StrCat(str, size, tmp);\r
1441                 }\r
1442 \r
1443                 l3 = true;\r
1444         }\r
1445 \r
1446         if (a->DestPortStart != 0)\r
1447         {\r
1448                 if (a->DestPortEnd == a->DestPortStart)\r
1449                 {\r
1450                         Format(tmp, sizeof(tmp), "DstPort=%u, ", a->DestPortStart);\r
1451                         StrCat(str, size, tmp);\r
1452                 }\r
1453                 else\r
1454                 {\r
1455                         Format(tmp, sizeof(tmp), "DstPort=%u-%u, ", a->DestPortStart, a->DestPortEnd);\r
1456                         StrCat(str, size, tmp);\r
1457                 }\r
1458 \r
1459                 l3 = true;\r
1460         }\r
1461 \r
1462         if (StrLen(a->SrcUsername) != 0)\r
1463         {\r
1464                 Format(tmp, sizeof(tmp), "SrcUser=%s, ", a->SrcUsername);\r
1465                 StrCat(str, size, tmp);\r
1466         }\r
1467 \r
1468         if (StrLen(a->DestUsername) != 0)\r
1469         {\r
1470                 Format(tmp, sizeof(tmp), "DstUser=%s, ", a->DestUsername);\r
1471                 StrCat(str, size, tmp);\r
1472         }\r
1473 \r
1474         if (a->CheckSrcMac != false)\r
1475         {\r
1476                 char mac[MAX_SIZE], mask[MAX_SIZE];\r
1477                 MacToStr(mac, sizeof(mac), a->SrcMacAddress);\r
1478                 MacToStr(mask, sizeof(mask), a->SrcMacMask);\r
1479                 Format(tmp, sizeof(tmp), "SrcMac=%s/%s, ", mac, mask);\r
1480                 StrCat(str, size, tmp);\r
1481         }\r
1482         if (a->CheckDstMac != false)\r
1483         {\r
1484                 char mac[MAX_SIZE], mask[MAX_SIZE];\r
1485                 MacToStr(mac, sizeof(mac), a->DstMacAddress);\r
1486                 MacToStr(mask, sizeof(mask), a->DstMacMask);\r
1487                 Format(tmp, sizeof(tmp), "DstMac=%s/%s, ", mac, mask);\r
1488                 StrCat(str, size, tmp);\r
1489         }\r
1490 \r
1491         if (a->CheckTcpState)\r
1492         {\r
1493                 if(a->Established)\r
1494                 {\r
1495                         StrCat(str, size, "Established, ");\r
1496                 }\r
1497                 else\r
1498                 {\r
1499                         StrCat(str, size, "Unestablished, ");\r
1500                 }\r
1501 \r
1502                 l3 = true;\r
1503         }\r
1504 \r
1505         if (a->Discard == false)\r
1506         {\r
1507                 if (a->Delay >= 1)\r
1508                 {\r
1509                         Format(tmp, sizeof(tmp), "Delay=%u, ", a->Delay);\r
1510                         StrCat(str, size, tmp);\r
1511                 }\r
1512 \r
1513                 if (a->Jitter >= 1)\r
1514                 {\r
1515                         Format(tmp, sizeof(tmp), "Jitter=%u, ", a->Jitter);\r
1516                         StrCat(str, size, tmp);\r
1517                 }\r
1518 \r
1519                 if (a->Loss >= 1)\r
1520                 {\r
1521                         Format(tmp, sizeof(tmp), "Loss=%u, " , a->Loss);\r
1522                         StrCat(str, size, tmp);\r
1523                 }\r
1524         }\r
1525 \r
1526         if (StrLen(str) == 0)\r
1527         {\r
1528                 asterisk = true;\r
1529         }\r
1530 \r
1531         if (l3)\r
1532         {\r
1533                 if (a->IsIPv6)\r
1534                 {\r
1535                         StrCatLeft(str, size, "(ipv6) ");\r
1536                 }\r
1537                 else\r
1538                 {\r
1539                         StrCatLeft(str, size, "(ipv4) ");\r
1540                 }\r
1541         }\r
1542         else\r
1543         {\r
1544                 StrCatLeft(str, size, "(ether) ");\r
1545         }\r
1546 \r
1547         if (EndWith(str, ", "))\r
1548         {\r
1549                 str[StrLen(str) - 2] = 0;\r
1550         }\r
1551 \r
1552         if (asterisk)\r
1553         {\r
1554                 StrCat(str, size, "*");\r
1555         }\r
1556 }\r
1557 \r
1558 // パケットをアクセスリストによってマスクすることができるかどうか判定する\r
1559 bool IsPacketMaskedByAccessList(SESSION *s, PKT *p, ACCESS *a, UINT dest_username, UINT dest_groupname)\r
1560 {\r
1561         UINT src_username;\r
1562         UINT src_groupname;\r
1563         HUB_PA *pa;\r
1564         IPV4_HEADER *ip = NULL;\r
1565         IPV6_HEADER *ip6 = NULL;\r
1566         bool is_ipv4_packet = false;\r
1567         bool is_ipv6_packet = false;\r
1568         // 引数チェック\r
1569         if (s == NULL || p == NULL || a == NULL)\r
1570         {\r
1571                 return false;\r
1572         }\r
1573         if (a->Active == false)\r
1574         {\r
1575                 // アクセスリストは無効\r
1576                 return false;\r
1577         }\r
1578 \r
1579         pa = (HUB_PA *)s->PacketAdapter->Param;\r
1580 \r
1581         // 送信元のユーザー名ハッシュ\r
1582         src_username = pa->UsernameHash;\r
1583         src_groupname = pa->GroupnameHash;\r
1584 \r
1585         // 送信元・宛先 MAC アドレスの判定\r
1586         if (a->CheckSrcMac != false)\r
1587         {\r
1588                 UINT i;\r
1589                 for (i = 0; i < 6; i++)\r
1590                 {\r
1591                         if((a->SrcMacAddress[i] & a->SrcMacMask[i]) != (a->SrcMacMask[i] & p->MacAddressSrc[i]))\r
1592                         {\r
1593                                 return false;\r
1594                         }\r
1595                 }\r
1596         }\r
1597 \r
1598         if (a->CheckDstMac != false)\r
1599         {\r
1600                 UINT i;\r
1601                 for (i = 0; i < 6; i++)\r
1602                 {\r
1603                         if ((a->DstMacAddress[i] & a->DstMacMask[i]) != (a->DstMacMask[i] & p->MacAddressDest[i]))\r
1604                         {\r
1605                                 return false;\r
1606                         }\r
1607                 }\r
1608         }\r
1609 \r
1610         // 送信元ユーザー名 / グループ名のチェック\r
1611         if (a->SrcUsernameHash != 0)\r
1612         {\r
1613                 if ((a->SrcUsernameHash != src_username) && (a->SrcUsernameHash != src_groupname))\r
1614                 {\r
1615                         return false;\r
1616                 }\r
1617         }\r
1618 \r
1619         // 宛先ユーザー名 / グループ名のチェック\r
1620         if (a->DestUsernameHash != 0)\r
1621         {\r
1622                 if ((a->DestUsernameHash != dest_username) && (a->DestUsernameHash != dest_groupname))\r
1623                 {\r
1624                         return false;\r
1625                 }\r
1626         }\r
1627 \r
1628         // IP パケットの判定\r
1629         if (p->TypeL3 != L3_IPV4)\r
1630         {\r
1631                 is_ipv4_packet = false;\r
1632         }\r
1633         else\r
1634         {\r
1635                 is_ipv4_packet = true;\r
1636         }\r
1637 \r
1638         if (p->TypeL3 != L3_IPV6)\r
1639         {\r
1640                 is_ipv6_packet = false;\r
1641         }\r
1642         else\r
1643         {\r
1644                 is_ipv6_packet = true;\r
1645         }\r
1646 \r
1647         if (is_ipv4_packet)\r
1648         {\r
1649                 ip = p->L3.IPv4Header;\r
1650         }\r
1651 \r
1652         if (is_ipv6_packet)\r
1653         {\r
1654                 ip6 = p->L3.IPv6Header;\r
1655         }\r
1656 \r
1657         if (a->IsIPv6 == false)\r
1658         {\r
1659                 // IPv4\r
1660 \r
1661                 // 送信元 IP アドレスのチェック\r
1662                 if (a->SrcIpAddress != 0 || a->SrcSubnetMask != 0)\r
1663                 {\r
1664                         if (is_ipv4_packet == false)\r
1665                         {\r
1666                                 if (p->TypeL3 == L3_ARPV4)\r
1667                                 {\r
1668                                         bool arp_match = false;\r
1669                                         if (p->L3.ARPv4Header->HardwareSize == 6 &&\r
1670                                                 Endian16(p->L3.ARPv4Header->HardwareType) == ARP_HARDWARE_TYPE_ETHERNET &&\r
1671                                                 p->L3.ARPv4Header->ProtocolSize == 4 &&\r
1672                                                 Endian16(p->L3.ARPv4Header->ProtocolType) == 0x0800)\r
1673                                         {\r
1674                                                 UINT uint_ip = p->L3.ARPv4Header->SrcIP;\r
1675 \r
1676                                                 if (uint_ip != 0 && uint_ip != 0xffffffff && !(IsHubIpAddress32(uint_ip) && IsHubMacAddress(p->MacAddressSrc)))\r
1677                                                 {\r
1678                                                         if ((uint_ip & a->SrcSubnetMask) != (a->SrcIpAddress & a->SrcSubnetMask))\r
1679                                                         {\r
1680                                                         }\r
1681                                                         else\r
1682                                                         {\r
1683                                                                 arp_match = true;\r
1684                                                         }\r
1685                                                 }\r
1686                                         }\r
1687 \r
1688                                         if (arp_match == false)\r
1689                                         {\r
1690                                                 return false;\r
1691                                         }\r
1692                                 }\r
1693                                 else\r
1694                                 {\r
1695                                         return false;\r
1696                                 }\r
1697                         }\r
1698                         else\r
1699                         {\r
1700                                 if ((ip->SrcIP & a->SrcSubnetMask) != (a->SrcIpAddress & a->SrcSubnetMask))\r
1701                                 {\r
1702                                         return false;\r
1703                                 }\r
1704                         }\r
1705                 }\r
1706 \r
1707                 // 宛先 IP アドレスのチェック\r
1708                 if (a->DestIpAddress != 0 || a->DestSubnetMask != 0)\r
1709                 {\r
1710                         if (is_ipv4_packet == false)\r
1711                         {\r
1712                                 if (p->TypeL3 == L3_ARPV4)\r
1713                                 {\r
1714                                         bool arp_match = false;\r
1715                                         if (p->L3.ARPv4Header->HardwareSize == 6 &&\r
1716                                                 Endian16(p->L3.ARPv4Header->HardwareType) == ARP_HARDWARE_TYPE_ETHERNET &&\r
1717                                                 p->L3.ARPv4Header->ProtocolSize == 4 &&\r
1718                                                 Endian16(p->L3.ARPv4Header->ProtocolType) == 0x0800)\r
1719                                         {\r
1720                                                 UINT uint_ip = p->L3.ARPv4Header->TargetIP;\r
1721 \r
1722                                                 if (uint_ip != 0 && uint_ip != 0xffffffff && !(IsHubIpAddress32(uint_ip) && IsHubMacAddress(p->MacAddressSrc)))\r
1723                                                 {\r
1724                                                         if ((uint_ip & a->DestSubnetMask) != (a->DestIpAddress & a->DestSubnetMask))\r
1725                                                         {\r
1726                                                         }\r
1727                                                         else\r
1728                                                         {\r
1729                                                                 arp_match = true;\r
1730                                                         }\r
1731                                                 }\r
1732                                         }\r
1733 \r
1734                                         if (arp_match == false)\r
1735                                         {\r
1736                                                 return false;\r
1737                                         }\r
1738                                 }\r
1739                                 else\r
1740                                 {\r
1741                                         return false;\r
1742                                 }\r
1743                         }\r
1744                         else\r
1745                         {\r
1746                                 if ((ip->DstIP & a->DestSubnetMask) != (a->DestIpAddress & a->DestSubnetMask))\r
1747                                 {\r
1748                                         return false;\r
1749                                 }\r
1750                         }\r
1751                 }\r
1752         }\r
1753         else\r
1754         {\r
1755                 // IPv6\r
1756 \r
1757                 // 送信元 IP アドレスのチェック\r
1758                 if (IsZeroIP6Addr(&a->SrcIpAddress6) == false ||\r
1759                         IsZeroIP6Addr(&a->SrcSubnetMask6) == false)\r
1760                 {\r
1761                         if (is_ipv6_packet == false)\r
1762                         {\r
1763                                 return false;\r
1764                         }\r
1765                         else\r
1766                         {\r
1767                                 IP a_ip, a_subnet, p_ip;\r
1768                                 IP and1, and2;\r
1769 \r
1770                                 IPv6AddrToIP(&a_ip, &a->SrcIpAddress6);\r
1771                                 IPv6AddrToIP(&a_subnet, &a->SrcSubnetMask6);\r
1772                                 IPv6AddrToIP(&p_ip, &ip6->SrcAddress);\r
1773 \r
1774                                 IPAnd6(&and1, &a_ip, &a_subnet);\r
1775                                 IPAnd6(&and2, &p_ip, &a_subnet);\r
1776 \r
1777                                 if (CmpIpAddr(&and1, &and2) != 0)\r
1778                                 {\r
1779                                         return false;\r
1780                                 }\r
1781                         }\r
1782                 }\r
1783 \r
1784                 // 宛先 IP アドレスのチェック\r
1785                 if (IsZeroIP6Addr(&a->DestIpAddress6) == false ||\r
1786                         IsZeroIP6Addr(&a->DestSubnetMask6) == false)\r
1787                 {\r
1788                         if (is_ipv6_packet == false)\r
1789                         {\r
1790                                 return false;\r
1791                         }\r
1792                         else\r
1793                         {\r
1794                                 IP a_ip, a_subnet, p_ip;\r
1795                                 IP and1, and2;\r
1796 \r
1797                                 IPv6AddrToIP(&a_ip, &a->DestIpAddress6);\r
1798                                 IPv6AddrToIP(&a_subnet, &a->DestSubnetMask6);\r
1799                                 IPv6AddrToIP(&p_ip, &ip6->DestAddress);\r
1800 \r
1801                                 IPAnd6(&and1, &a_ip, &a_subnet);\r
1802                                 IPAnd6(&and2, &p_ip, &a_subnet);\r
1803 \r
1804                                 if (CmpIpAddr(&and1, &and2) != 0)\r
1805                                 {\r
1806                                         return false;\r
1807                                 }\r
1808                         }\r
1809                 }\r
1810         }\r
1811 \r
1812         // IPv4 でも IPv6 でもないパケットはマッチさせない。\r
1813         if(is_ipv4_packet == false && is_ipv6_packet==false){\r
1814                 return false;\r
1815         }\r
1816 \r
1817         // プロトコル番号のチェック\r
1818         if (a->Protocol != 0)\r
1819         {\r
1820                 if (a->IsIPv6 == false)\r
1821                 {\r
1822                         if (is_ipv4_packet == false)\r
1823                         {\r
1824                                 return false;\r
1825                         }\r
1826                         else\r
1827                         {\r
1828                                 if (ip->Protocol != a->Protocol)\r
1829                                 {\r
1830                                         return false;\r
1831                                 }\r
1832                         }\r
1833                 }\r
1834                 else\r
1835                 {\r
1836                         if (is_ipv6_packet == false)\r
1837                         {\r
1838                                 return false;\r
1839                         }\r
1840                         else\r
1841                         {\r
1842                                 if (p->IPv6HeaderPacketInfo.Protocol != a->Protocol)\r
1843                                 {\r
1844                                         return false;\r
1845                                 }\r
1846                         }\r
1847                 }\r
1848         }\r
1849 \r
1850         // ポート番号のチェック\r
1851         if (a->SrcPortStart != 0 || a->DestPortStart != 0 ||\r
1852                 a->SrcPortEnd != 0 || a->DestPortEnd != 0)\r
1853         {\r
1854                 if ((a->IsIPv6 == false && is_ipv4_packet == false) ||\r
1855                         (a->IsIPv6 && is_ipv6_packet == false))\r
1856                 {\r
1857                         return false;\r
1858                 }\r
1859                 else\r
1860                 {\r
1861                         if (p->TypeL4 == L4_TCP)\r
1862                         {\r
1863                                 TCP_HEADER *tcp = p->L4.TCPHeader;\r
1864                                 // 送信元ポートのチェック\r
1865                                 if (a->SrcPortStart != 0 || a->SrcPortEnd != 0)\r
1866                                 {\r
1867                                         UINT src_port = Endian16(tcp->SrcPort);\r
1868                                         if (src_port < a->SrcPortStart || src_port > a->SrcPortEnd)\r
1869                                         {\r
1870                                                 return false;\r
1871                                         }\r
1872                                 }\r
1873 \r
1874                                 // 宛先ポート番号のチェック\r
1875                                 if (a->DestPortStart != 0 || a->DestPortEnd != 0)\r
1876                                 {\r
1877                                         UINT dest_port = Endian16(tcp->DstPort);\r
1878                                         if (dest_port < a->DestPortStart || dest_port > a->DestPortEnd)\r
1879                                         {\r
1880                                                 return false;\r
1881                                         }\r
1882                                 }\r
1883                         }\r
1884                         else if (p->TypeL4 == L4_UDP)\r
1885                         {\r
1886                                 UDP_HEADER *udp = p->L4.UDPHeader;\r
1887                                 // 送信元ポートのチェック\r
1888                                 if (a->SrcPortStart != 0 || a->SrcPortEnd != 0)\r
1889                                 {\r
1890                                         UINT src_port = Endian16(udp->SrcPort);\r
1891                                         if (src_port < a->SrcPortStart || src_port > a->SrcPortEnd)\r
1892                                         {\r
1893                                                 return false;\r
1894                                         }\r
1895                                 }\r
1896 \r
1897                                 // 宛先ポート番号のチェック\r
1898                                 if (a->DestPortStart != 0 || a->DestPortEnd != 0)\r
1899                                 {\r
1900                                         UINT dest_port = Endian16(udp->DstPort);\r
1901                                         if (dest_port < a->DestPortStart || dest_port > a->DestPortEnd)\r
1902                                         {\r
1903                                                 return false;\r
1904                                         }\r
1905                                 }\r
1906                         }\r
1907                         else\r
1908                         {\r
1909                                 // アクセスリストにポート番号が指定されているときは\r
1910                                 // TCP か UDP 以外のパケットは適用されない\r
1911                                 return false;\r
1912                         }\r
1913                 }\r
1914         }\r
1915 \r
1916         // TCP コネクションの状態チェック\r
1917         if (a->CheckTcpState != false)\r
1918         {\r
1919                 if ((a->IsIPv6 == false && is_ipv4_packet == false) ||\r
1920                         (a->IsIPv6 && is_ipv6_packet == false))\r
1921                 {\r
1922                         return false;\r
1923                 }\r
1924                 else\r
1925                 {\r
1926                         if(p->TypeL4 == L4_TCP)\r
1927                         {\r
1928                                 // by shimizu\r
1929                                 TCP_HEADER *tcp = p->L4.TCPHeader;\r
1930                                 bool est = true;\r
1931 \r
1932                                 if (tcp->Flag & TCP_SYN)\r
1933                                 {\r
1934                                         est = false;\r
1935                                 }\r
1936 \r
1937                                 if((MAKEBOOL(a->Established) ^ MAKEBOOL(est)))\r
1938                                 {\r
1939                                         return false;\r
1940                                 }\r
1941                         }\r
1942                         else\r
1943                         {\r
1944                                 return false;\r
1945                         }\r
1946                 }\r
1947         }\r
1948 \r
1949         return true;\r
1950 }\r
1951 \r
1952 // フォワードするパケットに対してアクセスリストを適用する\r
1953 bool ApplyAccessListToForwardPacket(HUB *hub, SESSION *src_session, SESSION *dest_session, PKT *p)\r
1954 {\r
1955         UINT i;\r
1956         bool pass = true;       // デフォルトでは通過させる\r
1957         bool skip = true;\r
1958         // 引数チェック\r
1959         if (hub == NULL || src_session == NULL || p == NULL || dest_session == NULL)\r
1960         {\r
1961                 return false;\r
1962         }\r
1963 \r
1964         // 既にチェックされたパケットはアクセスリストを再適用しない。\r
1965         if (p->AccessChecked)\r
1966         {\r
1967                 return true;\r
1968         }\r
1969 \r
1970         LockList(hub->AccessList);\r
1971         {\r
1972                 for (i = 0;i < LIST_NUM(hub->AccessList);i++)\r
1973                 {\r
1974                         ACCESS *a = LIST_DATA(hub->AccessList, i);\r
1975 \r
1976                         // あて先ユーザー名が指定されているエントリ以降のみを走査する。\r
1977                         if (a->DestUsernameHash != 0)\r
1978                         {\r
1979                                 skip = false;\r
1980                         }\r
1981 \r
1982                         if (skip == false)\r
1983                         {\r
1984                                 if (IsPacketMaskedByAccessList(src_session, p, a,\r
1985                                         ((HUB_PA *)dest_session->PacketAdapter->Param)->UsernameHash,\r
1986                                         ((HUB_PA *)dest_session->PacketAdapter->Param)->GroupnameHash))\r
1987                                 {\r
1988                                         // パケットの通過または破棄を決定する\r
1989                                         pass = a->Discard ? false : true;\r
1990 \r
1991                                         // リストの走査をここで完了する\r
1992                                         break;\r
1993                                 }\r
1994                         }\r
1995                 }\r
1996         }\r
1997         UnlockList(hub->AccessList);\r
1998 \r
1999         return pass;\r
2000 }\r
2001 \r
2002 // ストアされたパケットに対してアクセスリストを適用する\r
2003 bool ApplyAccessListToStoredPacket(HUB *hub, SESSION *s, PKT *p)\r
2004 {\r
2005         UINT i;\r
2006         bool pass = true;       // デフォルトでは通過させる\r
2007         // 引数チェック\r
2008         if (hub == NULL || s == NULL || p == NULL)\r
2009         {\r
2010                 return false;\r
2011         }\r
2012 \r
2013         if (hub->Option != NULL && hub->Option->FilterPPPoE)\r
2014         {\r
2015                 if (p->MacHeader != NULL)\r
2016                 {\r
2017                         USHORT proto = Endian16(p->MacHeader->Protocol);\r
2018                         if (proto == 0x8863 || proto == 0x8864)\r
2019                         {\r
2020                                 // PPPoE Filter\r
2021                                 return false;\r
2022                         }\r
2023                 }\r
2024         }\r
2025 \r
2026         if (hub->Option != NULL && hub->Option->FilterOSPF)\r
2027         {\r
2028                 if (p->TypeL3 == L3_IPV4)\r
2029                 {\r
2030                         if (p->L3.IPv4Header != NULL)\r
2031                         {\r
2032                                 if (p->L3.IPv4Header->Protocol == 89)\r
2033                                 {\r
2034                                         // OSPF Filter\r
2035                                         return false;\r
2036                                 }\r
2037                         }\r
2038                 }\r
2039         }\r
2040 \r
2041         if (hub->Option != NULL && hub->Option->FilterIPv4)\r
2042         {\r
2043                 if (p->MacHeader != NULL)\r
2044                 {\r
2045                         USHORT proto = Endian16(p->MacHeader->Protocol);\r
2046                         if (proto == 0x0800 || proto == 0x0806)\r
2047                         {\r
2048                                 // IPv4 Filter\r
2049                                 return false;\r
2050                         }\r
2051                 }\r
2052         }\r
2053 \r
2054         if (hub->Option != NULL && hub->Option->FilterIPv6)\r
2055         {\r
2056                 if (p->MacHeader != NULL)\r
2057                 {\r
2058                         USHORT proto = Endian16(p->MacHeader->Protocol);\r
2059                         if (proto == 0x86dd)\r
2060                         {\r
2061                                 // IPv6 Filter\r
2062                                 return false;\r
2063                         }\r
2064                 }\r
2065         }\r
2066 \r
2067         if (hub->Option != NULL && hub->Option->FilterNonIP)\r
2068         {\r
2069                 if (p->MacHeader != NULL)\r
2070                 {\r
2071                         USHORT proto = Endian16(p->MacHeader->Protocol);\r
2072                         if (!(proto == 0x86dd || proto == 0x0800 || proto == 0x0806))\r
2073                         {\r
2074                                 // Non-IP Filter\r
2075                                 return false;\r
2076                         }\r
2077                 }\r
2078         }\r
2079 \r
2080         if (hub->Option != NULL && hub->Option->FilterBPDU)\r
2081         {\r
2082                 if (p->MacHeader != NULL)\r
2083                 {\r
2084                         if (p->TypeL3 == L3_BPDU)\r
2085                         {\r
2086                                 // BPDU Filter\r
2087                                 return false;\r
2088                         }\r
2089                 }\r
2090         }\r
2091 \r
2092         LockList(hub->AccessList);\r
2093         {\r
2094                 for (i = 0;i < LIST_NUM(hub->AccessList);i++)\r
2095                 {\r
2096                         ACCESS *a = LIST_DATA(hub->AccessList, i);\r
2097 \r
2098                         if (a->DestUsernameHash != 0)\r
2099                         {\r
2100                                 // あて先ユーザー名が指定されていたら、そこでリストの走査を中断する。\r
2101                                 break;\r
2102                         }\r
2103 \r
2104                         if (IsPacketMaskedByAccessList(s, p, a, 0, 0))\r
2105                         {\r
2106                                 // パケットの通過または破棄を決定する\r
2107                                 pass = a->Discard ? false : true;\r
2108 \r
2109                                 // ここで処理が決定したパケットはHUBを出るときに走査しない。\r
2110                                 p->AccessChecked = true;\r
2111 \r
2112                                 // 遅延・ジッタ・パケットロスのパラメータのコピー\r
2113                                 p->Delay = a->Delay;\r
2114                                 p->Jitter = a->Jitter;\r
2115                                 p->Loss = a->Loss;\r
2116 \r
2117                                 // リストの走査をここで完了する\r
2118                                 break;\r
2119                         }\r
2120                 }\r
2121         }\r
2122         UnlockList(hub->AccessList);\r
2123 \r
2124         return pass;\r
2125 }\r
2126 \r
2127 // アクセスリストの追加\r
2128 void AddAccessList(HUB *hub, ACCESS *a)\r
2129 {\r
2130         // 引数チェック\r
2131         if (hub == NULL || a == NULL)\r
2132         {\r
2133                 return;\r
2134         }\r
2135 \r
2136         LockList(hub->AccessList);\r
2137         {\r
2138                 ACCESS *access;\r
2139                 UINT i;\r
2140 \r
2141                 // 個数のチェック\r
2142                 if (LIST_NUM(hub->AccessList) >= MAX_ACCESSLISTS)\r
2143                 {\r
2144                         UnlockList(hub->AccessList);\r
2145                         return;\r
2146                 }\r
2147 \r
2148                 access = Malloc(sizeof(ACCESS));\r
2149                 Copy(access, a, sizeof(ACCESS));\r
2150                 access->SrcUsernameHash = UsernameToInt(access->SrcUsername);\r
2151                 access->DestUsernameHash = UsernameToInt(access->DestUsername);\r
2152 \r
2153                 // ポート番号補正\r
2154                 if (access->SrcPortStart != 0)\r
2155                 {\r
2156                         access->SrcPortEnd = MAX(access->SrcPortEnd, access->SrcPortStart);\r
2157                 }\r
2158                 if (access->DestPortStart != 0)\r
2159                 {\r
2160                         access->DestPortEnd = MAX(access->DestPortEnd, access->DestPortStart);\r
2161                 }\r
2162 \r
2163                 // 遅延、ジッタ、パケットロスの補正\r
2164                 access->Delay = MAKESURE(access->Delay, 0, HUB_ACCESSLIST_DELAY_MAX);\r
2165                 access->Jitter = MAKESURE(access->Jitter, 0, HUB_ACCESSLIST_JITTER_MAX);\r
2166                 access->Loss = MAKESURE(access->Loss, 0, HUB_ACCESSLIST_LOSS_MAX);\r
2167 \r
2168                 Insert(hub->AccessList, access);\r
2169 \r
2170                 // ID を振り直す\r
2171                 for (i = 0;i < LIST_NUM(hub->AccessList);i++)\r
2172                 {\r
2173                         ACCESS *a = LIST_DATA(hub->AccessList, i);\r
2174                         a->Id = (i + 1);\r
2175                 }\r
2176         }\r
2177         UnlockList(hub->AccessList);\r
2178 }\r
2179 \r
2180 // アクセスリストの初期化\r
2181 void InitAccessList(HUB *hub)\r
2182 {\r
2183         // 引数チェック\r
2184         if (hub == NULL)\r
2185         {\r
2186                 return;\r
2187         }\r
2188 \r
2189         hub->AccessList = NewList(CmpAccessList);\r
2190 }\r
2191 \r
2192 // アクセスリストの解放\r
2193 void FreeAccessList(HUB *hub)\r
2194 {\r
2195         UINT i;\r
2196         // 引数チェック\r
2197         if (hub == NULL)\r
2198         {\r
2199                 return;\r
2200         }\r
2201 \r
2202         for (i = 0;i < LIST_NUM(hub->AccessList);i++)\r
2203         {\r
2204                 ACCESS *a = LIST_DATA(hub->AccessList, i);\r
2205                 Free(a);\r
2206         }\r
2207 \r
2208         ReleaseList(hub->AccessList);\r
2209         hub->AccessList = NULL;\r
2210 }\r
2211 \r
2212 // アクセスリストの比較\r
2213 int CmpAccessList(void *p1, void *p2)\r
2214 {\r
2215         ACCESS *a1, *a2;\r
2216         if (p1 == NULL || p2 == NULL)\r
2217         {\r
2218                 return 0;\r
2219         }\r
2220         a1 = *(ACCESS **)p1;\r
2221         a2 = *(ACCESS **)p2;\r
2222         if (a1 == NULL || a2 == NULL)\r
2223         {\r
2224                 return 0;\r
2225         }\r
2226         // 優先順位別にソートする\r
2227         if (a1->Priority > a2->Priority)\r
2228         {\r
2229                 return 1;\r
2230         }\r
2231         else if (a1->Priority < a2->Priority)\r
2232         {\r
2233                 return -1;\r
2234         }\r
2235         else if (a1->Discard > a2->Discard)\r
2236         {\r
2237                 return 1;\r
2238         }\r
2239         else if (a1->Discard < a2->Discard)\r
2240         {\r
2241                 return -1;\r
2242         }\r
2243         else\r
2244         {\r
2245                 return Cmp(&a1->Active, &a2->Active, sizeof(ACCESS) - 4);\r
2246         }\r
2247 }\r
2248 \r
2249 // ユーザー名を UINT に変換\r
2250 UINT UsernameToInt(char *name)\r
2251 {\r
2252         UCHAR hash[SHA1_SIZE];\r
2253         UINT ret;\r
2254         char tmp[MAX_USERNAME_LEN + 1];\r
2255         // 引数チェック\r
2256         if (name == 0 || StrLen(name) == 0)\r
2257         {\r
2258                 return 0;\r
2259         }\r
2260 \r
2261         StrCpy(tmp, sizeof(tmp), name);\r
2262         Trim(tmp);\r
2263         StrUpper(tmp);\r
2264 \r
2265         if (StrLen(tmp) == 0)\r
2266         {\r
2267                 return 0;\r
2268         }\r
2269 \r
2270         Hash(hash, tmp, StrLen(tmp), true);\r
2271         Copy(&ret, hash, sizeof(ret));\r
2272 \r
2273         return ret;\r
2274 }\r
2275 \r
2276 // セッションポインタからセッションを検索\r
2277 SESSION *GetSessionByPtr(HUB *hub, void *ptr)\r
2278 {\r
2279         // 引数チェック\r
2280         if (hub == NULL || ptr == NULL)\r
2281         {\r
2282                 return NULL;\r
2283         }\r
2284 \r
2285         LockList(hub->SessionList);\r
2286         {\r
2287                 UINT i;\r
2288                 for (i = 0;i < LIST_NUM(hub->SessionList);i++)\r
2289                 {\r
2290                         SESSION *s = LIST_DATA(hub->SessionList, i);\r
2291                         if (s == (SESSION *)ptr)\r
2292                         {\r
2293                                 // 発見\r
2294                                 AddRef(s->ref);\r
2295                                 UnlockList(hub->SessionList);\r
2296                                 return s;\r
2297                         }\r
2298                 }\r
2299         }\r
2300         UnlockList(hub->SessionList);\r
2301 \r
2302         return NULL;\r
2303 }\r
2304 \r
2305 // セッション名からセッションを検索\r
2306 SESSION *GetSessionByName(HUB *hub, char *name)\r
2307 {\r
2308         // 引数チェック\r
2309         if (hub == NULL || name == NULL)\r
2310         {\r
2311                 return NULL;\r
2312         }\r
2313 \r
2314         LockList(hub->SessionList);\r
2315         {\r
2316                 UINT i;\r
2317                 for (i = 0;i < LIST_NUM(hub->SessionList);i++)\r
2318                 {\r
2319                         SESSION *s = LIST_DATA(hub->SessionList, i);\r
2320                         if (StrCmpi(s->Name, name) == 0)\r
2321                         {\r
2322                                 // 発見\r
2323                                 AddRef(s->ref);\r
2324                                 UnlockList(hub->SessionList);\r
2325                                 return s;\r
2326                         }\r
2327                 }\r
2328         }\r
2329         UnlockList(hub->SessionList);\r
2330 \r
2331         return NULL;\r
2332 }\r
2333 \r
2334 // STORM リストのソート\r
2335 int CompareStormList(void *p1, void *p2)\r
2336 {\r
2337         STORM *s1, *s2;\r
2338         UINT r;\r
2339         // 引数チェック\r
2340         if (p1 == NULL || p2 == NULL)\r
2341         {\r
2342                 return 0;\r
2343         }\r
2344         s1 = *(STORM **)p1;\r
2345         s2 = *(STORM **)p2;\r
2346         if (s1 == NULL || s2 == NULL)\r
2347         {\r
2348                 return 0;\r
2349         }\r
2350         r = CmpIpAddr(&s1->DestIp, &s2->DestIp);\r
2351         if (r != 0)\r
2352         {\r
2353                 return r;\r
2354         }\r
2355         r = CmpIpAddr(&s1->SrcIp, &s2->SrcIp);\r
2356         if (r != 0)\r
2357         {\r
2358                 return r;\r
2359         }\r
2360         r = Cmp(s1->MacAddress, s2->MacAddress, 6);\r
2361         return r;\r
2362 }\r
2363 \r
2364 // パケットアダプタ初期化\r
2365 bool HubPaInit(SESSION *s)\r
2366 {\r
2367         // パケットアダプタ情報の初期化\r
2368         HUB_PA *pa = ZeroMalloc(sizeof(HUB_PA));\r
2369         pa->Cancel = NewCancel();\r
2370         pa->PacketQueue = NewQueue();\r
2371         pa->Now = Tick64();\r
2372         pa->Session = s;\r
2373         pa->StormList = NewList(CompareStormList);\r
2374         pa->UsernameHash = UsernameToInt(s->Username);\r
2375         pa->GroupnameHash = UsernameToInt(s->GroupName);\r
2376 \r
2377         s->PacketAdapter->Param = pa;\r
2378 \r
2379         if (s->Policy->MonitorPort)\r
2380         {\r
2381                 // このポートをモニタリングポートとしてマークする\r
2382                 pa->MonitorPort = true;\r
2383 \r
2384                 // HUB のモニタリングポート一覧にこのセッションを追加する\r
2385                 LockList(s->Hub->MonitorList);\r
2386                 {\r
2387                         Insert(s->Hub->MonitorList, s);\r
2388                 }\r
2389                 UnlockList(s->Hub->MonitorList);\r
2390         }\r
2391 \r
2392         return true;\r
2393 }\r
2394 \r
2395 // パケットアダプタ解放\r
2396 void HubPaFree(SESSION *s)\r
2397 {\r
2398         HUB_PA *pa = (HUB_PA *)s->PacketAdapter->Param;\r
2399         HUB *hub = s->Hub;\r
2400 \r
2401         if (pa->MonitorPort)\r
2402         {\r
2403                 // HUB のモニタポート一覧からこのセッションを削除する\r
2404                 LockList(s->Hub->MonitorList);\r
2405                 {\r
2406                         Delete(s->Hub->MonitorList, s);\r
2407                 }\r
2408                 UnlockList(s->Hub->MonitorList);\r
2409         }\r
2410 \r
2411         // このセッションに関連付けられている MAC アドレステーブルを消去\r
2412         LockList(hub->MacTable);\r
2413         {\r
2414                 UINT i, num = LIST_NUM(hub->MacTable);\r
2415                 LIST *o = NewListFast(NULL);\r
2416                 for (i = 0;i < num;i++)\r
2417                 {\r
2418                         MAC_TABLE_ENTRY *e = (MAC_TABLE_ENTRY *)LIST_DATA(hub->MacTable, i);\r
2419                         if (e->Session == s)\r
2420                         {\r
2421                                 Add(o, e);\r
2422                         }\r
2423                 }\r
2424                 for (i = 0;i < LIST_NUM(o);i++)\r
2425                 {\r
2426                         MAC_TABLE_ENTRY *e = (MAC_TABLE_ENTRY *)LIST_DATA(o, i);\r
2427                         Delete(hub->MacTable, e);\r
2428                         Free(e);\r
2429                 }\r
2430                 ReleaseList(o);\r
2431         }\r
2432         {\r
2433                 UINT i, num = LIST_NUM(hub->IpTable);\r
2434                 LIST *o = NewListFast(NULL);\r
2435                 for (i = 0;i < num;i++)\r
2436                 {\r
2437                         IP_TABLE_ENTRY *e = LIST_DATA(hub->IpTable, i);\r
2438                         if (e->Session == s)\r
2439                         {\r
2440                                 Add(o, e);\r
2441                         }\r
2442                 }\r
2443                 for (i = 0;i < LIST_NUM(o);i++)\r
2444                 {\r
2445                         IP_TABLE_ENTRY *e = LIST_DATA(o, i);\r
2446                         Delete(hub->IpTable, e);\r
2447                         Free(e);\r
2448                 }\r
2449                 ReleaseList(o);\r
2450         }\r
2451         UnlockList(hub->MacTable);\r
2452 \r
2453         // STORM リストを解放\r
2454         LockList(pa->StormList);\r
2455         {\r
2456                 UINT i;\r
2457                 for (i = 0;i < LIST_NUM(pa->StormList);i++)\r
2458                 {\r
2459                         STORM *s = (STORM *)LIST_DATA(pa->StormList, i);\r
2460                         Free(s);\r
2461                 }\r
2462                 DeleteAll(pa->StormList);\r
2463         }\r
2464         UnlockList(pa->StormList);\r
2465 \r
2466         ReleaseList(pa->StormList);\r
2467 \r
2468         // キューに残っているパケットを解放\r
2469         LockQueue(pa->PacketQueue);\r
2470         {\r
2471                 BLOCK *b;\r
2472 \r
2473                 while (b = GetNext(pa->PacketQueue))\r
2474                 {\r
2475                         // ブロックの解放\r
2476                         FreeBlock(b);\r
2477                 }\r
2478         }\r
2479         UnlockQueue(pa->PacketQueue);\r
2480 \r
2481         // キューを解放\r
2482         ReleaseQueue(pa->PacketQueue);\r
2483 \r
2484         // キャンセルオブジェクトの解放\r
2485         ReleaseCancel(pa->Cancel);\r
2486 \r
2487         // パケットアダプタ情報の解放\r
2488         Free(pa);\r
2489         s->PacketAdapter->Param = NULL;\r
2490 }\r
2491 \r
2492 // キャンセルオブジェクトの取得\r
2493 CANCEL *HubPaGetCancel(SESSION *s)\r
2494 {\r
2495         HUB_PA *pa = (HUB_PA *)s->PacketAdapter->Param;\r
2496 \r
2497         AddRef(pa->Cancel->ref);\r
2498         return pa->Cancel;\r
2499 }\r
2500 \r
2501 // 次の送信予定パケットの取得\r
2502 UINT HubPaGetNextPacket(SESSION *s, void **data)\r
2503 {\r
2504         UINT ret = 0;\r
2505         HUB_PA *pa = (HUB_PA *)s->PacketAdapter->Param;\r
2506 \r
2507         // キューの先頭から 1 つ取得する\r
2508         LockQueue(pa->PacketQueue);\r
2509         {\r
2510                 BLOCK *block = GetNext(pa->PacketQueue);\r
2511                 if (block == NULL)\r
2512                 {\r
2513                         // キュー無し\r
2514                         ret = 0;\r
2515                 }\r
2516                 else\r
2517                 {\r
2518                         // あった\r
2519                         *data = block->Buf;\r
2520                         ret = block->Size;\r
2521                         // ブロックの構造体のメモリは解放する\r
2522                         Free(block);\r
2523                 }\r
2524         }\r
2525         UnlockQueue(pa->PacketQueue);\r
2526 \r
2527         return ret;\r
2528 }\r
2529 \r
2530 // パケットの受信\r
2531 bool HubPaPutPacket(SESSION *s, void *data, UINT size)\r
2532 {\r
2533         PKT *packet;\r
2534         HUB_PA *pa = (HUB_PA *)s->PacketAdapter->Param;\r
2535         bool b = false;\r
2536         HUB *hub;\r
2537         bool no_l3 = false;\r
2538         LIST *o = NULL;\r
2539         UINT i;\r
2540         UINT vlan_type_id = 0;\r
2541         bool no_look_bpdu_bridge_id = false;\r
2542 \r
2543         hub = s->Hub;\r
2544 \r
2545         pa->Now = Tick64();\r
2546 \r
2547         if (data == NULL)\r
2548         {\r
2549                 // 遅延パケットのチェック\r
2550                 o = NULL;\r
2551                 LockList(s->DelayedPacketList);\r
2552                 {\r
2553                         UINT i;\r
2554                         if (LIST_NUM(s->DelayedPacketList) >= 1)\r
2555                         {\r
2556                                 UINT64 now = TickHighres64();\r
2557                                 for (i = 0;i < LIST_NUM(s->DelayedPacketList);i++)\r
2558                                 {\r
2559                                         PKT *p = LIST_DATA(s->DelayedPacketList, i);\r
2560 \r
2561                                         if (now >= p->DelayedForwardTick)\r
2562                                         {\r
2563                                                 if (o == NULL)\r
2564                                                 {\r
2565                                                         o = NewListFast(NULL);\r
2566                                                 }\r
2567 \r
2568                                                 Add(o, p);\r
2569                                         }\r
2570                                 }\r
2571                         }\r
2572 \r
2573                         if (o != NULL)\r
2574                         {\r
2575                                 for (i = 0;i < LIST_NUM(o);i++)\r
2576                                 {\r
2577                                         PKT *p = LIST_DATA(o, i);\r
2578 \r
2579                                         Delete(s->DelayedPacketList, p);\r
2580                                 }\r
2581                         }\r
2582                 }\r
2583                 UnlockList(s->DelayedPacketList);\r
2584 \r
2585                 // 遅延パケットがある場合はストアする\r
2586                 if (o != NULL)\r
2587                 {\r
2588                         for (i = 0;i < LIST_NUM(o);i++)\r
2589                         {\r
2590                                 PKT *p = LIST_DATA(o, i);\r
2591 \r
2592                                 StorePacket(s->Hub, s, p);\r
2593                         }\r
2594 \r
2595                         ReleaseList(o);\r
2596                 }\r
2597 \r
2598                 // このセッションからのすべてのパケットの受信が完了した\r
2599                 CancelList(s->CancelList);\r
2600 \r
2601                 // イールドする\r
2602                 if (hub->Option != NULL && hub->Option->YieldAfterStorePacket)\r
2603                 {\r
2604                         YieldCpu();\r
2605                 }\r
2606 \r
2607                 return true;\r
2608         }\r
2609 \r
2610         if (hub != NULL && hub->Option != NULL && hub->Option->DisableIPParsing)\r
2611         {\r
2612                 no_l3 = true;\r
2613         }\r
2614 \r
2615         if (hub != NULL && hub->Option != NULL)\r
2616         {\r
2617                 vlan_type_id = hub->Option->VlanTypeId;\r
2618                 no_look_bpdu_bridge_id = hub->Option->NoLookBPDUBridgeId;\r
2619         }\r
2620 \r
2621         // VLAN タグを挿入する\r
2622         if (s->VLanId != 0)\r
2623         {\r
2624                 VLanInsertTag(&data, &size, s->VLanId);\r
2625         }\r
2626 \r
2627         // パケットをパースする\r
2628         packet = ParsePacketEx3(data, size, no_l3, vlan_type_id, !no_look_bpdu_bridge_id);\r
2629 \r
2630         if (packet != NULL)\r
2631         {\r
2632                 if (packet->InvalidSourcePacket)\r
2633                 {\r
2634                         // 不正な送信元のパケット\r
2635                         FreePacket(packet);\r
2636                         packet = NULL;\r
2637                 }\r
2638         }\r
2639 \r
2640         if (packet != NULL)\r
2641         {\r
2642                 // パケットのストア\r
2643                 StorePacket(s->Hub, s, packet);\r
2644         }\r
2645         else\r
2646         {\r
2647                 // 不良パケット (正しい MAC フレームではない)\r
2648                 // であるのでパケットデータを解放する\r
2649                 Free(data);\r
2650         }\r
2651 \r
2652         return true;\r
2653 }\r
2654 \r
2655 // ブロードキャストストームが発生しないようにチェックするアルゴリズム\r
2656 // 特定のエンドポイントからのブロードキャストが頻繁に来た場合はフィルタリングする\r
2657 bool CheckBroadcastStorm(SESSION *s, PKT *p)\r
2658 {\r
2659         IP src_ip, dest_ip;\r
2660         HUB_PA *pa;\r
2661         UINT64 now = Tick64();\r
2662         UINT limit_start_count;\r
2663         SESSION *sess = s;\r
2664         bool ret = true;\r
2665         // 引数チェック\r
2666         if (s == NULL || p == NULL)\r
2667         {\r
2668                 return false;\r
2669         }\r
2670 \r
2671         if (s->Policy->NoBroadcastLimiter)\r
2672         {\r
2673                 // ブロードキャスト数の制限無し\r
2674                 return true;\r
2675         }\r
2676 \r
2677         pa = (HUB_PA *)s->PacketAdapter->Param;\r
2678 \r
2679         if (p->TypeL3 == L3_IPV4)\r
2680         {\r
2681                 UINTToIP(&src_ip, p->L3.IPv4Header->SrcIP);\r
2682                 UINTToIP(&dest_ip, p->L3.IPv4Header->DstIP);\r
2683         }\r
2684         else if (p->TypeL3 == L3_ARPV4)\r
2685         {\r
2686                 UINTToIP(&src_ip, p->L3.ARPv4Header->SrcIP);\r
2687                 Zero(&dest_ip, sizeof(IP));\r
2688         }\r
2689         else if (p->TypeL3 == L3_IPV6)\r
2690         {\r
2691                 IPv6AddrToIP(&src_ip, &p->L3.IPv6Header->SrcAddress);\r
2692                 IPv6AddrToIP(&dest_ip, &p->L3.IPv6Header->DestAddress);\r
2693         }\r
2694         else\r
2695         {\r
2696                 Zero(&src_ip, sizeof(IP));\r
2697                 Zero(&dest_ip, sizeof(IP));\r
2698         }\r
2699 \r
2700         // 1 間隔ごとに制限を開始する個数\r
2701         limit_start_count = 32;\r
2702 \r
2703         if (s->Hub != NULL && s->Hub->Option->BroadcastStormDetectionThreshold != 0)\r
2704         {\r
2705                 limit_start_count = s->Hub->Option->BroadcastStormDetectionThreshold;\r
2706         }\r
2707 \r
2708         LockList(pa->StormList);\r
2709         {\r
2710                 STORM *s;\r
2711                 UINT num;\r
2712                 s = SearchStormList(pa, p->MacAddressSrc, &src_ip, &dest_ip);\r
2713                 if (s == NULL)\r
2714                 {\r
2715                         s = AddStormList(pa, p->MacAddressSrc, &src_ip, &dest_ip);\r
2716                 }\r
2717 \r
2718                 s->CurrentBroadcastNum++;\r
2719 \r
2720                 if ((s->CheckStartTick + STORM_CHECK_SPAN) < now ||\r
2721                         s->CheckStartTick == 0 || s->CheckStartTick > now)\r
2722                 {\r
2723                         // 一定期間ごとにブロードキャスト数を計測する\r
2724                         UINT64 diff_time;\r
2725                         if (s->CheckStartTick < now)\r
2726                         {\r
2727                                 diff_time = now - s->CheckStartTick;\r
2728                         }\r
2729                         else\r
2730                         {\r
2731                                 diff_time = 0;\r
2732                         }\r
2733                         s->CheckStartTick = now;\r
2734                         num = (UINT)((UINT64)s->CurrentBroadcastNum * (UINT64)1000 / (UINT64)STORM_CHECK_SPAN);\r
2735                         s->CurrentBroadcastNum = 0;\r
2736                         if (num >= limit_start_count)\r
2737                         {\r
2738                                 char ip1[64];\r
2739                                 char ip2[64];\r
2740                                 char mac[MAX_SIZE];\r
2741                                 IPToStr(ip1, sizeof(ip1), &src_ip);\r
2742                                 IPToStr(ip2, sizeof(ip2), &dest_ip);\r
2743                                 ret = false;\r
2744                                 if (s->DiscardValue < STORM_DISCARD_VALUE_END)\r
2745                                 {\r
2746                                         s->DiscardValue = MAX(s->DiscardValue, 1) * 2;\r
2747                                 }\r
2748                                 Debug("s->DiscardValue: %u  (%u)\n", s->DiscardValue, num);\r
2749 \r
2750                                 MacToStr(mac, sizeof(mac), p->MacAddressSrc);\r
2751 \r
2752                                 HLog(sess->Hub, "LH_BCAST_STORM", sess->Name, mac, ip1, ip2, num);\r
2753                         }\r
2754                         else\r
2755                         {\r
2756                                 if (s->DiscardValue >= 1)\r
2757                                 {\r
2758                                         s->DiscardValue = (UINT)((UINT64)s->DiscardValue / MAX((UINT64)2, (UINT64)diff_time / (UINT64)STORM_CHECK_SPAN));\r
2759                                 }\r
2760                         }\r
2761                 }\r
2762 \r
2763                 if (s->DiscardValue >= STORM_DISCARD_VALUE_START)\r
2764                 {\r
2765                         if (s->DiscardValue >= 128)\r
2766                         {\r
2767                                 ret = false;\r
2768                         }\r
2769                         else if ((rand() % s->DiscardValue) != 0)\r
2770                         {\r
2771                                 ret = false;\r
2772                         }\r
2773                 }\r
2774 \r
2775         }\r
2776         UnlockList(pa->StormList);\r
2777 \r
2778         return ret;\r
2779 }\r
2780 \r
2781 // パケットのストア\r
2782 void StorePacket(HUB *hub, SESSION *s, PKT *packet)\r
2783 {\r
2784         MAC_TABLE_ENTRY *entry = NULL;\r
2785         MAC_TABLE_ENTRY t;\r
2786         void *data;\r
2787         UINT size;\r
2788         bool broadcast_mode;\r
2789         HUB_PA *dest_pa;\r
2790         SESSION *dest_session;\r
2791         TRAFFIC traffic;\r
2792         UINT64 now = Tick64();\r
2793         // 引数チェック\r
2794         if (hub == NULL || packet == NULL)\r
2795         {\r
2796                 return;\r
2797         }\r
2798 \r
2799         if (s != NULL)\r
2800         {\r
2801                 if (((HUB_PA *)s->PacketAdapter->Param)->MonitorPort)\r
2802                 {\r
2803                         // モニタポートからもらったパケットはフォワードしてはならない\r
2804                         Free(packet->PacketData);\r
2805                         FreePacket(packet);\r
2806                         return;\r
2807                 }\r
2808         }\r
2809 \r
2810         // MAC アドレステーブル全体をロック\r
2811         LockList(hub->MacTable);\r
2812         {\r
2813                 // フィルタリング\r
2814                 if (s != NULL && (packet->DelayedForwardTick == 0 && StorePacketFilter(s, packet) == false))\r
2815                 {\r
2816 DISCARD_PACKET:\r
2817                         // 通過が不許可となったのでパケットを解放する\r
2818                         Free(packet->PacketData);\r
2819                         FreePacket(packet);\r
2820                 }\r
2821                 else // 通過が許可された\r
2822                 {\r
2823                         bool forward_now = true;\r
2824 \r
2825                         if (packet->Loss >= 1)\r
2826                         {\r
2827                                 // パケットロスを発生させる\r
2828                                 UINT r = rand() % 100;\r
2829                                 if ((packet->Loss >= 100) || (r < packet->Loss))\r
2830                                 {\r
2831                                         // パケットロス\r
2832                                         goto DISCARD_PACKET;\r
2833                                 }\r
2834                         }\r
2835 \r
2836                         if (packet->Delay >= 1)\r
2837                         {\r
2838                                 float delay = (float)packet->Delay;\r
2839                                 float jitter;\r
2840                                 UINT delay_uint;\r
2841                                 bool f = Rand1();\r
2842                                 if (packet->Jitter == 0)\r
2843                                 {\r
2844                                         jitter = 0;\r
2845                                 }\r
2846                                 else\r
2847                                 {\r
2848                                         jitter = (float)(Rand32() % (int)((float)packet->Jitter * delay / 100.0f));\r
2849                                 }\r
2850 \r
2851                                 delay += jitter * (f ? 1 : -1);\r
2852                                 delay_uint = (UINT)delay;\r
2853 \r
2854                                 if (delay_uint >= 1)\r
2855                                 {\r
2856                                         // 遅延を発生させる\r
2857                                         forward_now = false;\r
2858                                         packet->Loss = packet->Jitter = packet->Delay = 0;\r
2859                                         packet->DelayedForwardTick = TickHighres64() + (UINT64)delay_uint;\r
2860                                         packet->DelayedSrcSession = s;\r
2861 \r
2862                                         LockList(s->DelayedPacketList);\r
2863                                         {\r
2864                                                 Add(s->DelayedPacketList, packet);\r
2865                                         }\r
2866                                         UnlockList(s->DelayedPacketList);\r
2867                                 }\r
2868                         }\r
2869 \r
2870                         if (forward_now)\r
2871                         {\r
2872                                 if (Cmp(packet->MacAddressSrc, hub->HubMacAddr, 6) == 0)\r
2873                                 {\r
2874                                         if (s != NULL)\r
2875                                         {\r
2876                                                 // この HUB 自身が発信しようとしたパケットが外部から入力された\r
2877                                                 goto DISCARD_PACKET;\r
2878                                         }\r
2879                                 }\r
2880                                 if (s != NULL && (Cmp(packet->MacAddressSrc, hub->HubMacAddr, 6) != 0))\r
2881                                 {\r
2882                                         // 送信元 MAC アドレスがテーブルに登録されているかどうか調べる\r
2883                                         Copy(t.MacAddress, packet->MacAddressSrc, 6);\r
2884                                         if (hub->Option->NoManageVlanId == false)\r
2885                                         {\r
2886                                                 t.VlanId = packet->VlanId;\r
2887                                         }\r
2888                                         else\r
2889                                         {\r
2890                                                 t.VlanId = 0;\r
2891                                         }\r
2892                                         entry = Search(hub->MacTable, &t);\r
2893 \r
2894                                         if (entry == NULL)\r
2895                                         {\r
2896                                                 // 古いエントリを削除する\r
2897                                                 DeleteExpiredMacTableEntry(hub->MacTable);\r
2898 \r
2899                                                 // 登録されていないので登録する\r
2900                                                 if (s->Policy->MaxMac != 0 || s->Policy->NoBridge)\r
2901                                                 {\r
2902                                                         UINT i, num_mac_for_me = 0;\r
2903                                                         UINT limited_count;\r
2904 \r
2905                                                         // 現在このセッションで登録されている MAC アドレス数を調べる\r
2906                                                         for (i = 0;i < LIST_NUM(hub->MacTable);i++)\r
2907                                                         {\r
2908                                                                 MAC_TABLE_ENTRY *e = LIST_DATA(hub->MacTable, i);\r
2909                                                                 if (e->Session == s)\r
2910                                                                 {\r
2911                                                                         num_mac_for_me++;\r
2912                                                                 }\r
2913                                                         }\r
2914 \r
2915                                                         limited_count = 0xffffffff;\r
2916                                                         if (s->Policy->NoBridge)\r
2917                                                         {\r
2918                                                                 limited_count = MIN(limited_count, MAC_MIN_LIMIT_COUNT);\r
2919                                                         }\r
2920                                                         if (s->Policy->MaxMac != 0)\r
2921                                                         {\r
2922                                                                 limited_count = MIN(limited_count, s->Policy->MaxMac);\r
2923                                                         }\r
2924                                                         limited_count = MAX(limited_count, MAC_MIN_LIMIT_COUNT);\r
2925 \r
2926                                                         if (num_mac_for_me >= limited_count)\r
2927                                                         {\r
2928                                                                 // すでに登録されている MAC アドレス数が上限を超えている\r
2929                                                                 char mac_str[64];\r
2930 \r
2931                                                                 if (s != NULL)\r
2932                                                                 {\r
2933                                                                         MacToStr(mac_str, sizeof(mac_str), packet->MacAddressSrc);\r
2934                                                                         if (s->Policy->NoBridge)\r
2935                                                                         {\r
2936                                                                                 HLog(hub, "LH_BRIDGE_LIMIT", s->Name, mac_str, num_mac_for_me, limited_count);\r
2937                                                                         }\r
2938                                                                         else\r
2939                                                                         {\r
2940                                                                                 HLog(hub, "LH_MAC_LIMIT", s->Name, mac_str, num_mac_for_me, limited_count);\r
2941                                                                         }\r
2942                                                                 }\r
2943 \r
2944                                                                 goto DISCARD_PACKET;    // パケット破棄\r
2945                                                         }\r
2946                                                 }\r
2947 \r
2948                                                 if (LIST_NUM(hub->MacTable) >= MAX_MAC_TABLES)\r
2949                                                 {\r
2950                                                         // MAC テーブルデータベースが最大件数を超えたので\r
2951                                                         // 最も古いテーブルを削除する\r
2952                                                         UINT i;\r
2953                                                         UINT64 old_time = 0xffffffffffffffffULL;\r
2954                                                         MAC_TABLE_ENTRY *old_entry = NULL;\r
2955                                                         for (i = 0;i < LIST_NUM(hub->MacTable);i++)\r
2956                                                         {\r
2957                                                                 MAC_TABLE_ENTRY *e = LIST_DATA(hub->MacTable, i);\r
2958                                                                 if (e->UpdatedTime <= old_time)\r
2959                                                                 {\r
2960                                                                         old_time = e->CreatedTime;\r
2961                                                                         old_entry = e;\r
2962                                                                 }\r
2963                                                         }\r
2964                                                         if (old_entry != NULL)\r
2965                                                         {\r
2966                                                                 Delete(hub->MacTable, old_entry);\r
2967                                                                 Free(old_entry);\r
2968                                                         }\r
2969                                                 }\r
2970 \r
2971                                                 entry = ZeroMalloc(sizeof(MAC_TABLE_ENTRY));\r
2972                                                 entry->HubPa = (HUB_PA *)s->PacketAdapter->Param;\r
2973                                                 Copy(entry->MacAddress, packet->MacAddressSrc, 6);\r
2974                                                 if (hub->Option->NoManageVlanId == false)\r
2975                                                 {\r
2976                                                         entry->VlanId = packet->VlanId;\r
2977                                                 }\r
2978                                                 else\r
2979                                                 {\r
2980                                                         entry->VlanId = 0;\r
2981                                                 }\r
2982                                                 entry->Session = s;\r
2983                                                 entry->UpdatedTime = entry->CreatedTime = now;\r
2984 \r
2985                                                 Insert(hub->MacTable, entry);\r
2986 \r
2987                                                 if (hub->Option->NoMacAddressLog == false)\r
2988                                                 {\r
2989                                                         // デバッグ表示\r
2990                                                         char mac_address[32];\r
2991 \r
2992                                                         if (s != NULL)\r
2993                                                         {\r
2994                                                                 MacToStr(mac_address, sizeof(mac_address), packet->MacAddressSrc);\r
2995 //                                                              Debug("Register MAC Address %s to Session %X.\n", mac_address, s);\r
2996 \r
2997                                                                 if (packet->VlanId == 0)\r
2998                                                                 {\r
2999                                                                         HLog(hub, "LH_MAC_REGIST", s->Name, mac_address);\r
3000                                                                 }\r
3001                                                                 else\r
3002                                                                 {\r
3003                                                                         HLog(hub, "LH_MAC_REGIST_VLAN", s->Name, mac_address, packet->VlanId);\r
3004                                                                 }\r
3005                                                         }\r
3006                                                 }\r
3007                                         }\r
3008                                         else\r
3009                                         {\r
3010                                                 if (entry->Session == s)\r
3011                                                 {\r
3012                                                         // 既に登録されているので何もしない\r
3013                                                         entry->UpdatedTime = now;\r
3014                                                 }\r
3015                                                 else\r
3016                                                 {\r
3017                                                         // 既に登録されていて自分のセッション以外である\r
3018                                                         if (s->Policy->CheckMac && (Cmp(packet->MacAddressSrc, hub->HubMacAddr, 6) != 0) &&\r
3019                                                                 ((entry->UpdatedTime + MAC_TABLE_EXCLUSIVE_TIME) >= now))\r
3020                                                         {\r
3021                                                                 UCHAR *mac = packet->MacAddressSrc;\r
3022                                                                 if (hub->Option != NULL && hub->Option->FixForDLinkBPDU &&\r
3023                                                                         (mac[0] == 0x00 && mac[1] == 0x80 && mac[2] == 0xc8 && mac[3] == 0x00 && mac[4] == 0x00 && mac[5] == 0x00) ||\r
3024                                                                         (mac[0] == 0x00 && mac[1] == 0x0d && mac[2] == 0x88 && mac[3] == 0x00 && mac[4] == 0x00 && mac[5] == 0x00))\r
3025                                                                 {\r
3026                                                                         // D-Link 用バグ対策。D-Link のスパニングツリーパケットは上記アドレスから送出される。\r
3027                                                                         // ローカルブリッジ時の CheckMac オプションが悪影響を与えることがある。\r
3028                                                                         // そこで例外的に処理。\r
3029                                                                         UCHAR hash[MD5_SIZE];\r
3030                                                                         UINT64 tick_diff = Tick64() - s->LastDLinkSTPPacketSendTick;\r
3031 \r
3032                                                                         Hash(hash, packet->PacketData, packet->PacketSize, false);\r
3033 \r
3034                                                                         if ((s->LastDLinkSTPPacketSendTick != 0) &&\r
3035                                                                                 (tick_diff < 750ULL) &&\r
3036                                                                                 (Cmp(hash, s->LastDLinkSTPPacketDataHash, MD5_SIZE) == 0))\r
3037                                                                         {\r
3038                                                                                 // 750ms より前に同一パケットを送信した場合は破棄\r
3039                                                                                 Debug("D-Link Discard %u\n", (UINT)tick_diff);\r
3040                                                                                 goto DISCARD_PACKET;    // パケット破棄\r
3041                                                                         }\r
3042                                                                         else\r
3043                                                                         {\r
3044                                                                                 goto UPDATE_FDB;\r
3045                                                                         }\r
3046                                                                 }\r
3047                                                                 else\r
3048                                                                 {\r
3049                                                                         if (0)\r
3050                                                                         {\r
3051                                                                                 // CheckMac ポリシーが有効な場合\r
3052                                                                                 // 別のセッションが同じ MAC アドレスを持っていることは禁止されている\r
3053                                                                                 // (2 バイト目が 0xAE の場合はこのチェックを行わない)\r
3054                                                                                 char mac_address[32];\r
3055                                                                                 BinToStr(mac_address, sizeof(mac_address), packet->MacAddressSrc, 6);\r
3056                                                                         }\r
3057                                                                 }\r
3058 \r
3059                                                                 goto DISCARD_PACKET;    // パケット破棄\r
3060                                                         }\r
3061                                                         else\r
3062                                                         {\r
3063                                                                 // MAC アドレステーブルのセッションと HUB_PA を書き換える\r
3064                                                                 char mac_address[32];\r
3065 UPDATE_FDB:\r
3066                                                                 BinToStr(mac_address, sizeof(mac_address), packet->MacAddressSrc, 6);\r
3067 \r
3068                                                                 entry->Session = s;\r
3069                                                                 entry->HubPa = (HUB_PA *)s->PacketAdapter->Param;\r
3070                                                                 entry->UpdatedTime = entry->CreatedTime = now;\r
3071 \r
3072                                                                 if (1)\r
3073                                                                 {\r
3074                                                                         // デバッグ表示\r
3075                                                                         char mac_address[32];\r
3076 \r
3077                                                                         if (s != NULL)\r
3078                                                                         {\r
3079                                                                                 MacToStr(mac_address, sizeof(mac_address), packet->MacHeader->SrcAddress);\r
3080                                                                                 Debug("Register MAC Address %s to Session %X.\n", mac_address, s);\r
3081                                                                                 if (packet->VlanId == 0)\r
3082                                                                                 {\r
3083                                                                                         HLog(hub, "LH_MAC_REGIST", s->Name, mac_address);\r
3084                                                                                 }\r
3085                                                                                 else\r
3086                                                                                 {\r
3087                                                                                         HLog(hub, "LH_MAC_REGIST_VLAN", s->Name, mac_address, packet->VlanId);\r
3088                                                                                 }\r
3089                                                                         }\r
3090                                                                 }\r
3091                                                         }\r
3092                                                 }\r
3093                                         }\r
3094                                 }\r
3095 \r
3096                                 broadcast_mode = false;\r
3097                                 dest_pa = NULL;\r
3098                                 dest_session = NULL;\r
3099 \r
3100                                 if (packet->BroadcastPacket)\r
3101                                 {\r
3102                                         // ブロードキャストパケット\r
3103                                         broadcast_mode = true;\r
3104                                 }\r
3105                                 else\r
3106                                 {\r
3107                                         // 宛先 MAC アドレスがテーブルに登録されているかどうか調べる\r
3108                                         Copy(t.MacAddress, packet->MacAddressDest, 6);\r
3109                                         if (hub->Option->NoManageVlanId == false)\r
3110                                         {\r
3111                                                 t.VlanId = packet->VlanId;\r
3112                                         }\r
3113                                         else\r
3114                                         {\r
3115                                                 t.VlanId = 0;\r
3116                                         }\r
3117                                         entry = Search(hub->MacTable, &t);\r
3118 \r
3119                                         if (entry == NULL)\r
3120                                         {\r
3121                                                 // 宛先が見つからないのでブロードキャストする\r
3122                                                 broadcast_mode = true;\r
3123                                         }\r
3124                                         else\r
3125                                         {\r
3126                                                 if (entry->Session != s)\r
3127                                                 {\r
3128                                                         // 宛先が見つかった\r
3129                                                         dest_pa = entry->HubPa;\r
3130                                                         dest_session = entry->Session;\r
3131                                                 }\r
3132                                                 else\r
3133                                                 {\r
3134                                                         // 宛先が自分自身である不正なパケット\r
3135                                                         goto DISCARD_PACKET;\r
3136                                                 }\r
3137                                         }\r
3138                                 }\r
3139 \r
3140                                 if (s != NULL && hub->Option->NoIpTable == false)\r
3141                                 {\r
3142                                         if (packet->TypeL3 == L3_IPV6)\r
3143                                         {\r
3144                                                 // IPv6 パケット\r
3145                                                 IP ip;\r
3146                                                 bool b = true;\r
3147                                                 UINT ip_type;\r
3148                                                 bool dhcp_or_ra = false;\r
3149 \r
3150                                                 IPv6AddrToIP(&ip, &packet->L3.IPv6Header->SrcAddress);\r
3151                                                 ip_type = GetIPv6AddrType(&packet->L3.IPv6Header->SrcAddress);\r
3152 \r
3153                                                 if (!(ip_type & IPV6_ADDR_UNICAST))\r
3154                                                 {\r
3155                                                         // マルチキャストアドレス\r
3156                                                         b = false;\r
3157                                                 }\r
3158                                                 else if ((ip_type & IPV6_ADDR_LOOPBACK) || (ip_type & IPV6_ADDR_ZERO))\r
3159                                                 {\r
3160                                                         // ループバックアドレスまたは All-Zero アドレス\r
3161                                                         b = false;\r
3162                                                 }\r
3163 \r
3164                                                 if (packet->TypeL4 == L4_ICMPV6)\r
3165                                                 {\r
3166                                                         if (packet->ICMPv6HeaderPacketInfo.Type == 133 ||\r
3167                                                                 packet->ICMPv6HeaderPacketInfo.Type == 134)\r
3168                                                         {\r
3169                                                                 // ICMPv6 RS/RA\r
3170                                                                 dhcp_or_ra = true;\r
3171                                                         }\r
3172                                                 }\r
3173                                                 else if (packet->TypeL4 == L4_UDP)\r
3174                                                 {\r
3175                                                         if (Endian16(packet->L4.UDPHeader->DstPort) == 546 ||\r
3176                                                                 Endian16(packet->L4.UDPHeader->DstPort) == 547)\r
3177                                                         {\r
3178                                                                 // DHCPv6\r
3179                                                                 dhcp_or_ra = true;\r
3180                                                         }\r
3181                                                 }\r
3182 \r
3183                                                 if (IsHubMacAddress(packet->MacAddressSrc) &&\r
3184                                                         IsHubIpAddress64(&packet->L3.IPv6Header->SrcAddress))\r
3185                                                 {\r
3186                                                         // 仮想 HUB のポーリング用送信元アドレス\r
3187                                                         b = false;\r
3188                                                 }\r
3189 \r
3190                                                 if (b)\r
3191                                                 {\r
3192                                                         // ICMPv6 RS/RA および DHCPv6 以外のパケット\r
3193                                                         IP_TABLE_ENTRY t, *e;\r
3194 \r
3195                                                         Copy(&t.Ip, &ip, sizeof(IP));\r
3196 \r
3197                                                         // 既存のテーブルに登録されているかどうかチェック\r
3198                                                         e = Search(hub->IpTable, &t);\r
3199 \r
3200                                                         if (e == NULL)\r
3201                                                         {\r
3202                                                                 // 登録されていないので登録する\r
3203                                                                 if (s->Policy->NoRoutingV6 || s->Policy->MaxIPv6 != 0)\r
3204                                                                 {\r
3205                                                                         UINT i, num_ip_for_me = 0;\r
3206                                                                         UINT limited_count = 0xffffffff;\r
3207 \r
3208                                                                         for (i = 0;i < LIST_NUM(hub->IpTable);i++)\r
3209                                                                         {\r
3210                                                                                 IP_TABLE_ENTRY *e = LIST_DATA(hub->IpTable, i);\r
3211 \r
3212                                                                                 if (e->Session == s)\r
3213                                                                                 {\r
3214                                                                                         if (IsIP6(&e->Ip))\r
3215                                                                                         {\r
3216                                                                                                 num_ip_for_me++;\r
3217                                                                                         }\r
3218                                                                                 }\r
3219                                                                         }\r
3220 \r
3221                                                                         if (s->Policy->NoRoutingV6)\r
3222                                                                         {\r
3223                                                                                 limited_count = MIN(limited_count, IP_LIMIT_WHEN_NO_ROUTING_V6);\r
3224                                                                         }\r
3225                                                                         if (s->Policy->MaxIPv6 != 0)\r
3226                                                                         {\r
3227                                                                                 limited_count = MIN(limited_count, s->Policy->MaxIPv6);\r
3228                                                                         }\r
3229                                                                         limited_count = MAX(limited_count, IP_MIN_LIMIT_COUNT_V6);\r
3230 \r
3231                                                                         if (dhcp_or_ra)\r
3232                                                                         {\r
3233                                                                                 limited_count = 0xffffffff;\r
3234                                                                         }\r
3235 \r
3236                                                                         if (num_ip_for_me >= limited_count)\r
3237                                                                         {\r
3238                                                                                 // 使用できる IP アドレスの上限を超えているので\r
3239                                                                                 // このパケットを破棄する\r
3240                                                                                 char tmp[64];\r
3241                                                                                 IPToStr(tmp, sizeof(tmp), &ip);\r
3242                                                                                 if (s->Policy->NoRoutingV6 == false)\r
3243                                                                                 {\r
3244                                                                                         HLog(hub, "LH_IP_LIMIT", s->Name, tmp, num_ip_for_me, limited_count);\r
3245                                                                                 }\r
3246                                                                                 else\r
3247                                                                                 {\r
3248                                                                                         HLog(hub, "LH_ROUTING_LIMIT", s->Name, tmp, num_ip_for_me, limited_count);\r
3249                                                                                 }\r
3250                                                                                 goto DISCARD_PACKET;\r
3251                                                                         }\r
3252                                                                 }\r
3253 \r
3254                                                                 if (IsIPManagementTargetForHUB(&ip, hub))\r
3255                                                                 {\r
3256                                                                         // エントリ作成\r
3257                                                                         e = ZeroMalloc(sizeof(IP_TABLE_ENTRY));\r
3258                                                                         e->CreatedTime = e->UpdatedTime = now;\r
3259                                                                         e->DhcpAllocated = false;\r
3260                                                                         Copy(&e->Ip, &ip, sizeof(IP));\r
3261                                                                         Copy(e->MacAddress, packet->MacAddressSrc, 6);\r
3262                                                                         e->Session = s;\r
3263 \r
3264                                                                         DeleteExpiredIpTableEntry(hub->IpTable);\r
3265 \r
3266                                                                         if (LIST_NUM(hub->IpTable) >= MAX_IP_TABLES)\r
3267                                                                         {\r
3268                                                                                 // 古い IP テーブルエントリを削除する\r
3269                                                                                 DeleteOldIpTableEntry(hub->IpTable);\r
3270                                                                         }\r
3271 \r
3272                                                                         Insert(hub->IpTable, e);\r
3273 \r
3274                                                                         if (0)\r
3275                                                                         {\r
3276                                                                                 char ip_address[64];\r
3277                                                                                 IPToStr(ip_address, sizeof(ip_address), &ip);\r
3278                                                                                 Debug("Registered IP Address %s to Session %X.\n",\r
3279                                                                                         ip_address, s);\r
3280                                                                         }\r
3281                                                                 }\r
3282                                                         }\r
3283                                                         else\r
3284                                                         {\r
3285                                                                 if (e->Session == s)\r
3286                                                                 {\r
3287                                                                         // 自分のセッションであるので何もしない\r
3288                                                                         // 更新日時を上書きする\r
3289                                                                         e->UpdatedTime = now;\r
3290                                                                         Copy(e->MacAddress, packet->MacAddressSrc, 6);\r
3291                                                                 }\r
3292                                                                 else\r
3293                                                                 {\r
3294                                                                         // 別のセッションが以前この IP アドレスを使っていた\r
3295                                                                         if ((s->Policy->CheckIPv6) &&\r
3296                                                                                 ((e->UpdatedTime + IP_TABLE_EXCLUSIVE_TIME) >= now))\r
3297                                                                         {\r
3298                                                                                 // 他のセッションがこの IP アドレスを使っているので\r
3299                                                                                 // パケットを破棄する\r
3300                                                                                 char ip_address[32];\r
3301                                                                                 IPToStr(ip_address, sizeof(ip_address), &ip);\r
3302 \r
3303                                                                                 Debug("IP Address %s is Already used by Session %X.\n",\r
3304                                                                                         ip_address, s);\r
3305 \r
3306                                                                                 HLog(hub, "LH_IP_CONFLICT", s->Name, ip_address, e->Session->Name);\r
3307 \r
3308                                                                                 goto DISCARD_PACKET;\r
3309                                                                         }\r
3310                                                                 }\r
3311                                                         }\r
3312                                                 }\r
3313                                         }\r
3314                                 }\r
3315 \r
3316                                 if (\r
3317                                         (s != NULL) &&\r
3318                                         (hub->Option->NoIpTable == false) &&\r
3319                                         (\r
3320                                                 (packet->TypeL3 == L3_IPV4 ||\r
3321                                                         (packet->TypeL3 == L3_ARPV4 && packet->L3.ARPv4Header->HardwareSize == 6 &&\r
3322                                                         Endian16(packet->L3.ARPv4Header->HardwareType) == ARP_HARDWARE_TYPE_ETHERNET &&\r
3323                                                         packet->L3.ARPv4Header->ProtocolSize == 4 &&\r
3324                                                         Endian16(packet->L3.ARPv4Header->ProtocolType) == 0x0800)\r
3325                                                 ) &&\r
3326                                                 (packet->TypeL7 != L7_DHCPV4)\r
3327                                         )\r
3328                                         ) // DHCP パケット以外\r
3329                                 {\r
3330                                         // IP パケットまたは ARP 応答パケットの場合は IP アドレステーブルを検索する\r
3331                                         IP_TABLE_ENTRY t, *e;\r
3332                                         IP ip;\r
3333                                         UINT uint_ip = 0;\r
3334 \r
3335                                         if (packet->TypeL3 == L3_IPV4)\r
3336                                         {\r
3337                                                 uint_ip = packet->L3.IPv4Header->SrcIP;\r
3338                                         }\r
3339                                         else if (packet->TypeL3 == L3_ARPV4)\r
3340                                         {\r
3341                                                 uint_ip = packet->L3.ARPv4Header->SrcIP;\r
3342                                         }\r
3343 \r
3344                                         if (uint_ip != 0 && uint_ip != 0xffffffff && !(IsHubIpAddress32(uint_ip) && IsHubMacAddress(packet->MacAddressSrc)))\r
3345                                         {\r
3346                                                 UINTToIP(&ip, uint_ip);\r
3347                                                 Copy(&t.Ip, &ip, sizeof(IP));\r
3348 \r
3349                                                 // 既存のテーブルに登録されているかどうかチェック\r
3350                                                 e = Search(hub->IpTable, &t);\r
3351 \r
3352                                                 if (e == NULL)\r
3353                                                 {\r
3354                                                         // 登録されていないので登録する\r
3355                                                         if (s->Policy->DHCPForce)\r
3356                                                         {\r
3357                                                                 char ipstr[MAX_SIZE];\r
3358 \r
3359                                                                 // DHCP サーバーによって割り当てられた IP アドレスではない\r
3360                                                                 // のでこのパケットを破棄する\r
3361                                                                 IPToStr32(ipstr, sizeof(ipstr), uint_ip);\r
3362                                                                 HLog(hub, "LH_DHCP_FORCE", s->Name, ipstr);\r
3363                                                                 goto DISCARD_PACKET;\r
3364                                                         }\r
3365 \r
3366         //                                              if (packet->TypeL3 == L3_ARPV4)\r
3367                                                         {\r
3368                                                                 // すでにこのセッションで登録されている個数を調べる\r
3369                                                                 if (s->Policy->NoRouting || s->Policy->MaxIP != 0)\r
3370                                                                 {\r
3371                                                                         UINT i, num_ip_for_me = 0;\r
3372                                                                         UINT limited_count = 0xffffffff;\r
3373 \r
3374                                                                         for (i = 0;i < LIST_NUM(hub->IpTable);i++)\r
3375                                                                         {\r
3376                                                                                 IP_TABLE_ENTRY *e = LIST_DATA(hub->IpTable, i);\r
3377 \r
3378                                                                                 if (e->Session == s)\r
3379                                                                                 {\r
3380                                                                                         if (IsIP4(&e->Ip))\r
3381                                                                                         {\r
3382                                                                                                 num_ip_for_me++;\r
3383                                                                                         }\r
3384                                                                                 }\r
3385                                                                         }\r
3386 \r
3387                                                                         if (s->Policy->NoRouting)\r
3388                                                                         {\r
3389                                                                                 limited_count = MIN(limited_count, IP_MIN_LIMIT_COUNT);\r
3390                                                                         }\r
3391                                                                         if (s->Policy->MaxIP != 0)\r
3392                                                                         {\r
3393                                                                                 limited_count = MIN(limited_count, s->Policy->MaxIP);\r
3394                                                                         }\r
3395                                                                         limited_count = MAX(limited_count, IP_MIN_LIMIT_COUNT);\r
3396 \r
3397                                                                         if (num_ip_for_me >= limited_count)\r
3398                                                                         {\r
3399                                                                                 // 使用できる IP アドレスの上限を超えているので\r
3400                                                                                 // このパケットを破棄する\r
3401                                                                                 char tmp[64];\r
3402                                                                                 IPToStr32(tmp, sizeof(tmp), uint_ip);\r
3403                                                                                 if (s->Policy->NoRouting == false)\r
3404                                                                                 {\r
3405                                                                                         HLog(hub, "LH_IP_LIMIT", s->Name, tmp, num_ip_for_me, limited_count);\r
3406                                                                                 }\r
3407                                                                                 else\r
3408                                                                                 {\r
3409                                                                                         HLog(hub, "LH_ROUTING_LIMIT", s->Name, tmp, num_ip_for_me, limited_count);\r
3410                                                                                 }\r
3411                                                                                 goto DISCARD_PACKET;\r
3412                                                                         }\r
3413                                                                 }\r
3414 \r
3415                                                                 if (IsIPManagementTargetForHUB(&ip, hub))\r
3416                                                                 {\r
3417                                                                         // エントリ作成\r
3418                                                                         e = ZeroMalloc(sizeof(IP_TABLE_ENTRY));\r
3419                                                                         e->CreatedTime = e->UpdatedTime = now;\r
3420                                                                         e->DhcpAllocated = false;\r
3421                                                                         Copy(&e->Ip, &ip, sizeof(IP));\r
3422                                                                         Copy(e->MacAddress, packet->MacAddressSrc, 6);\r
3423                                                                         e->Session = s;\r
3424 \r
3425                                                                         DeleteExpiredIpTableEntry(hub->IpTable);\r
3426 \r
3427                                                                         if (LIST_NUM(hub->IpTable) >= MAX_IP_TABLES)\r
3428                                                                         {\r
3429                                                                                 // 古い IP テーブルエントリを削除する\r
3430                                                                                 DeleteOldIpTableEntry(hub->IpTable);\r
3431                                                                         }\r
3432 \r
3433                                                                         Insert(hub->IpTable, e);\r
3434 \r
3435                                                                         if (0)\r
3436                                                                         {\r
3437                                                                                 char ip_address[64];\r
3438                                                                                 IPToStr(ip_address, sizeof(ip_address), &ip);\r
3439                                                                                 Debug("Registered IP Address %s to Session %X.\n",\r
3440                                                                                         ip_address, s);\r
3441                                                                         }\r
3442                                                                 }\r
3443                                                         }\r
3444                                                 }\r
3445                                                 else\r
3446                                                 {\r
3447                                                         if (e->Session == s)\r
3448                                                         {\r
3449                                                                 // 自分のセッションであるので何もしない\r
3450                                                                 // 更新日時を上書きする\r
3451                                                                 e->UpdatedTime = now;\r
3452                                                                 Copy(e->MacAddress, packet->MacAddressSrc, 6);\r
3453                                                         }\r
3454                                                         else\r
3455                                                         {\r
3456                                                                 // 別のセッションが以前この IP アドレスを使っていた\r
3457                                                                 if ((s->Policy->CheckIP || s->Policy->DHCPForce) &&\r
3458                                                                         ((e->UpdatedTime + IP_TABLE_EXCLUSIVE_TIME) >= now))\r
3459                                                                 {\r
3460                                                                         // 他のセッションがこの IP アドレスを使っているので\r
3461                                                                         // パケットを破棄する\r
3462                                                                         char ip_address[32];\r
3463                                                                         IPToStr(ip_address, sizeof(ip_address), &ip);\r
3464 \r
3465                                                                         Debug("IP Address %s is Already used by Session %X.\n",\r
3466                                                                                 ip_address, s);\r
3467 \r
3468                                                                         HLog(hub, "LH_IP_CONFLICT", s->Name, ip_address, e->Session->Name);\r
3469 \r
3470                                                                         goto DISCARD_PACKET;\r
3471                                                                 }\r
3472 \r
3473                                                                 if (s->Policy->DHCPForce)\r
3474                                                                 {\r
3475                                                                         if (e->DhcpAllocated == false)\r
3476                                                                         {\r
3477                                                                                 char ipstr[MAX_SIZE];\r
3478 \r
3479                                                                                 // DHCP サーバーによって割り当てられた IP アドレスではない\r
3480                                                                                 // のでこのパケットを破棄する\r
3481                                                                                 IPToStr32(ipstr, sizeof(ipstr), uint_ip);\r
3482                                                                                 HLog(hub, "LH_DHCP_FORCE", s->Name, ipstr);\r
3483                                                                                 goto DISCARD_PACKET;\r
3484                                                                         }\r
3485                                                                 }\r
3486 \r
3487                                                                 // エントリを上書きする\r
3488                                                                 e->Session = s;\r
3489                                                                 e->UpdatedTime = now;\r
3490                                                                 Copy(e->MacAddress, packet->MacAddressSrc, 6);\r
3491                                                         }\r
3492                                                 }\r
3493                                         }\r
3494                                 }\r
3495 \r
3496                                 if (s != NULL && broadcast_mode)\r
3497                                 {\r
3498                                         // ブロードキャストパケットのループや\r
3499                                         // 大量のブロードキャストの発生を防止するため\r
3500                                         // Broadcast Storm 回避アルゴリズムを呼び出す\r
3501                                         if (CheckBroadcastStorm(s, packet) == false)\r
3502                                         {\r
3503                                                 goto DISCARD_PACKET;\r
3504                                         }\r
3505                                 }\r
3506 \r
3507                                 // トラフィック加算\r
3508                                 Zero(&traffic, sizeof(traffic));\r
3509                                 if (packet->BroadcastPacket)\r
3510                                 {\r
3511                                         // ブロードキャスト\r
3512                                         traffic.Send.BroadcastBytes = packet->PacketSize;\r
3513                                         traffic.Send.BroadcastCount = 1;\r
3514                                 }\r
3515                                 else\r
3516                                 {\r
3517                                         // ユニキャスト\r
3518                                         traffic.Send.UnicastBytes = packet->PacketSize;\r
3519                                         traffic.Send.UnicastCount = 1;\r
3520                                 }\r
3521 \r
3522                                 if (s != NULL)\r
3523                                 {\r
3524                                         AddTrafficForSession(s, &traffic);\r
3525                                 }\r
3526 \r
3527                                 // トラフィック情報の Send と Recv を反転\r
3528                                 Copy(&traffic.Recv, &traffic.Send, sizeof(TRAFFIC_ENTRY));\r
3529                                 Zero(&traffic.Send, sizeof(TRAFFIC_ENTRY));\r
3530 \r
3531                                 // HUB のモニタポートにこのパケットをブロードキャストする\r
3532                                 if (hub->MonitorList->num_item != 0)\r
3533                                 {\r
3534                                         LockList(hub->MonitorList);\r
3535                                         {\r
3536                                                 UINT i;\r
3537                                                 void *data;\r
3538                                                 UINT size = packet->PacketSize;\r
3539                                                 for (i = 0;i < LIST_NUM(hub->MonitorList);i++)\r
3540                                                 {\r
3541                                                         SESSION *monitor_session = (SESSION *)LIST_DATA(hub->MonitorList, i);\r
3542 \r
3543                                                         // パケットをフラッディング\r
3544                                                         if (monitor_session->PacketAdapter->Param != NULL)\r
3545                                                         {\r
3546                                                                 data = MallocFast(size);\r
3547                                                                 Copy(data, packet->PacketData, size);\r
3548                                                                 StorePacketToHubPa((HUB_PA *)monitor_session->PacketAdapter->Param,\r
3549                                                                         s, data, size, packet);\r
3550                                                         }\r
3551                                                 }\r
3552                                         }\r
3553                                         UnlockList(hub->MonitorList);\r
3554                                 }\r
3555 \r
3556                                 if (broadcast_mode == false)\r
3557                                 {\r
3558                                         if (dest_pa != NULL)\r
3559                                         {\r
3560                                                 if (dest_session->Policy->NoIPv6DefaultRouterInRA ||\r
3561                                                         (dest_session->Policy->NoIPv6DefaultRouterInRAWhenIPv6 && dest_session->IPv6Session) ||\r
3562                                                         (hub->Option->NoIPv6DefaultRouterInRAWhenIPv6 && dest_session->IPv6Session))\r
3563                                                 {\r
3564                                                         DeleteIPv6DefaultRouterInRA(packet);\r
3565                                                 }\r
3566                                                 if (dest_session->Policy->RSandRAFilter)\r
3567                                                 {\r
3568                                                         if (packet->TypeL3 == L3_IPV6 &&\r
3569                                                                 packet->TypeL4 == L4_ICMPV6 &&\r
3570                                                                 (packet->ICMPv6HeaderPacketInfo.Type == ICMPV6_TYPE_ROUTER_SOLICIATION ||\r
3571                                                                  packet->ICMPv6HeaderPacketInfo.Type == ICMPV6_TYPE_ROUTER_ADVERTISEMENT))\r
3572                                                         {\r
3573                                                                 goto DISCARD_UNICAST_PACKET;\r
3574                                                         }\r
3575                                                 }\r
3576                                                 if (dest_session->Policy->DHCPFilter)\r
3577                                                 {\r
3578                                                         if (packet->TypeL3 == L3_IPV4 &&\r
3579                                                                 packet->TypeL4 == L4_UDP &&\r
3580                                                                 packet->TypeL7 == L7_DHCPV4)\r
3581                                                         {\r
3582                                                                 goto DISCARD_UNICAST_PACKET;\r
3583                                                         }\r
3584                                                 }\r
3585                                                 if (dest_session->Policy->DHCPv6Filter)\r
3586                                                 {\r
3587                                                         if (packet->TypeL3 == L3_IPV6 &&\r
3588                                                                 packet->TypeL4 == L4_UDP &&\r
3589                                                                 (Endian16(packet->L4.UDPHeader->DstPort) == 546 || Endian16(packet->L4.UDPHeader->DstPort) == 547))\r
3590                                                         {\r
3591                                                                 goto DISCARD_UNICAST_PACKET;\r
3592                                                         }\r
3593                                                 }\r
3594                                                 if (dest_session->Policy->ArpDhcpOnly)\r
3595                                                 {\r
3596                                                         if (packet->BroadcastPacket)\r
3597                                                         {\r
3598                                                                 bool b = true;\r
3599 \r
3600                                                                 if (packet->TypeL3 == L3_IPV4 &&\r
3601                                                                         packet->TypeL4 == L4_UDP &&\r
3602                                                                         packet->TypeL7 == L7_DHCPV4)\r
3603                                                                 {\r
3604                                                                         b = false;\r
3605                                                                 }\r
3606                                                                 else if (packet->TypeL3 == L3_ARPV4)\r
3607                                                                 {\r
3608                                                                         b = false;\r
3609                                                                 }\r
3610                                                                 else if (packet->TypeL3 == L3_IPV6 &&\r
3611                                                                         packet->TypeL4 == L4_UDP &&\r
3612                                                                         (Endian16(packet->L4.UDPHeader->DstPort) == 546 || Endian16(packet->L4.UDPHeader->DstPort) == 547))\r
3613                                                                 {\r
3614                                                                         b = false;\r
3615                                                                 }\r
3616                                                                 else if (packet->TypeL3 == L3_IPV6 &&\r
3617                                                                         packet->TypeL4 == L4_ICMPV6)\r
3618                                                                 {\r
3619                                                                         b = false;\r
3620                                                                 }\r
3621 \r
3622                                                                 if (b)\r
3623                                                                 {\r
3624                                                                         goto DISCARD_UNICAST_PACKET;\r
3625                                                                 }\r
3626                                                         }\r
3627                                                 }\r
3628                                                 if (dest_session->Policy->FilterIPv4)\r
3629                                                 {\r
3630                                                         if (packet->TypeL3 == L3_IPV4 || packet->TypeL3 == L3_ARPV4)\r
3631                                                         {\r
3632                                                                 goto DISCARD_UNICAST_PACKET;\r
3633                                                         }\r
3634                                                 }\r
3635                                                 if (dest_session->Policy->FilterIPv6)\r
3636                                                 {\r
3637                                                         if (packet->TypeL3 == L3_IPV6)\r
3638                                                         {\r
3639                                                                 goto DISCARD_UNICAST_PACKET;\r
3640                                                         }\r
3641                                                 }\r
3642                                                 if (dest_session->Policy->FilterNonIP)\r
3643                                                 {\r
3644                                                         if (packet->TypeL3 != L3_IPV4 && packet->TypeL3 != L3_ARPV4 && packet->TypeL3 != L3_IPV6)\r
3645                                                         {\r
3646                                                                 goto DISCARD_UNICAST_PACKET;\r
3647                                                         }\r
3648                                                 }\r
3649 \r
3650                                                 if (s != NULL &&\r
3651                                                         (packet->BroadcastPacket == false &&\r
3652                                                         s->Policy->PrivacyFilter &&\r
3653                                                         dest_session->Policy->PrivacyFilter)\r
3654                                                         )\r
3655                                                 {\r
3656                                                         // プライバシーフィルタ\r
3657                                                         if (packet->TypeL3 != L3_ARPV4)\r
3658                                                         {\r
3659                                                                 goto DISCARD_UNICAST_PACKET;\r
3660                                                         }\r
3661                                                 }\r
3662 \r
3663                                                 if (s != NULL)\r
3664                                                 {\r
3665                                                         if (Cmp(packet->MacAddressSrc, s->Hub->HubMacAddr, 6) == 0 ||\r
3666                                                                 Cmp(packet->MacAddressDest, s->Hub->HubMacAddr, 6) == 0)\r
3667                                                         {\r
3668                                                                 goto DISCARD_UNICAST_PACKET;\r
3669                                                         }\r
3670                                                 }\r
3671 \r
3672                                                 // パケットログをとる\r
3673                                                 if (s != NULL)\r
3674                                                 {\r
3675                                                         PacketLog(s->Hub, s, dest_session, packet);\r
3676                                                 }\r
3677 \r
3678                                                 // 宛先 HUB_PA にストアする\r
3679                                                 StorePacketToHubPa(dest_pa, s, packet->PacketData, packet->PacketSize, packet);\r
3680 \r
3681                                                 // トラフィック加算\r
3682                                                 AddTrafficForSession(dest_session, &traffic);\r
3683                                         }\r
3684                                         else\r
3685                                         {\r
3686 DISCARD_UNICAST_PACKET:\r
3687                                                 Free(packet->PacketData);\r
3688                                         }\r
3689                                 }\r
3690                                 else\r
3691                                 {\r
3692                                         // すべてのセッションにストアする\r
3693                                         LockList(hub->SessionList);\r
3694                                         {\r
3695                                                 UINT i, num = LIST_NUM(hub->SessionList);\r
3696                                                 for (i = 0;i < num;i++)\r
3697                                                 {\r
3698                                                         SESSION *dest_session = LIST_DATA(hub->SessionList, i);\r
3699                                                         HUB_PA *dest_pa = (HUB_PA *)dest_session->PacketAdapter->Param;\r
3700                                                         bool discard = false;\r
3701 \r
3702                                                         if (dest_session != s)\r
3703                                                         {\r
3704                                                                 bool delete_default_router_in_ra = false;\r
3705 \r
3706                                                                 if (dest_session->VLanId != 0 && packet->TypeL3 == L3_TAGVLAN &&\r
3707                                                                         packet->VlanId != dest_session->VLanId)\r
3708                                                                 {\r
3709                                                                         discard = true;\r
3710                                                                 }\r
3711 \r
3712                                                                 if (dest_session->Policy->NoIPv6DefaultRouterInRA ||\r
3713                                                                         (dest_session->Policy->NoIPv6DefaultRouterInRAWhenIPv6 && dest_session->IPv6Session) ||\r
3714                                                                         (hub->Option->NoIPv6DefaultRouterInRAWhenIPv6 && dest_session->IPv6Session))\r
3715                                                                 {\r
3716                                                                         if (packet->TypeL3 == L3_IPV6 && packet->TypeL4 == L4_ICMPV6 &&\r
3717                                                                                 (packet->ICMPv6HeaderPacketInfo.Type == ICMPV6_TYPE_ROUTER_ADVERTISEMENT))\r
3718                                                                         {\r
3719                                                                                 if (packet->ICMPv6HeaderPacketInfo.Headers.RouterAdvertisementHeader->Lifetime != 0)\r
3720                                                                                 {\r
3721                                                                                         delete_default_router_in_ra = true;\r
3722                                                                                 }\r
3723                                                                         }\r
3724                                                                 }\r
3725                                                                 if (dest_session->Policy->RSandRAFilter)\r
3726                                                                 {\r
3727                                                                         if (packet->TypeL3 == L3_IPV6 &&\r
3728                                                                                 packet->TypeL4 == L4_ICMPV6 &&\r
3729                                                                                 (packet->ICMPv6HeaderPacketInfo.Type == ICMPV6_TYPE_ROUTER_SOLICIATION ||\r
3730                                                                                  packet->ICMPv6HeaderPacketInfo.Type == ICMPV6_TYPE_ROUTER_ADVERTISEMENT))\r
3731                                                                         {\r
3732                                                                                 discard = true;\r
3733                                                                         }\r
3734                                                                 }\r
3735 \r
3736                                                                 if (dest_session->Policy->DHCPFilter)\r
3737                                                                 {\r
3738                                                                         if (packet->TypeL3 == L3_IPV4 &&\r
3739                                                                                 packet->TypeL4 == L4_UDP &&\r
3740                                                                                 packet->TypeL7 == L7_DHCPV4)\r
3741                                                                         {\r
3742                                                                                 discard = true;\r
3743                                                                         }\r
3744                                                                 }\r
3745 \r
3746                                                                 if (dest_session->Policy->DHCPv6Filter)\r
3747                                                                 {\r
3748                                                                         if (packet->TypeL3 == L3_IPV6 &&\r
3749                                                                                 packet->TypeL4 == L4_UDP &&\r
3750                                                                                 (Endian16(packet->L4.UDPHeader->DstPort) == 546 || Endian16(packet->L4.UDPHeader->DstPort) == 547))\r
3751                                                                         {\r
3752                                                                                 discard = true;\r
3753                                                                         }\r
3754                                                                 }\r
3755 \r
3756                                                                 if (dest_session->Policy->ArpDhcpOnly)\r
3757                                                                 {\r
3758                                                                         if (packet->BroadcastPacket)\r
3759                                                                         {\r
3760                                                                                 bool b = true;\r
3761 \r
3762                                                                                 if (packet->TypeL3 == L3_IPV4 &&\r
3763                                                                                         packet->TypeL4 == L4_UDP &&\r
3764                                                                                         packet->TypeL7 == L7_DHCPV4)\r
3765                                                                                 {\r
3766                                                                                         b = false;\r
3767                                                                                 }\r
3768                                                                                 else if (packet->TypeL3 == L3_ARPV4)\r
3769                                                                                 {\r
3770                                                                                         b = false;\r
3771                                                                                 }\r
3772                                                                                 else if (packet->TypeL3 == L3_IPV6 &&\r
3773                                                                                         packet->TypeL4 == L4_UDP &&\r
3774                                                                                         (Endian16(packet->L4.UDPHeader->DstPort) == 546 || Endian16(packet->L4.UDPHeader->DstPort) == 547))\r
3775                                                                                 {\r
3776                                                                                         b = false;\r
3777                                                                                 }\r
3778                                                                                 else if (packet->TypeL3 == L3_IPV6 &&\r
3779                                                                                         packet->TypeL4 == L4_ICMPV6)\r
3780                                                                                 {\r
3781                                                                                         b = false;\r
3782                                                                                 }\r
3783 \r
3784                                                                                 if (discard == false)\r
3785                                                                                 {\r
3786                                                                                         discard = b;\r
3787                                                                                 }\r
3788                                                                         }\r
3789                                                                 }\r
3790 \r
3791                                                                 if (dest_session->Policy->FilterIPv4)\r
3792                                                                 {\r
3793                                                                         if (packet->TypeL3 == L3_IPV4 || packet->TypeL3 == L3_ARPV4)\r
3794                                                                         {\r
3795                                                                                 discard = true;\r
3796                                                                         }\r
3797                                                                 }\r
3798                                                                 if (dest_session->Policy->FilterIPv6)\r
3799                                                                 {\r
3800                                                                         if (packet->TypeL3 == L3_IPV6)\r
3801                                                                         {\r
3802                                                                                 discard = true;\r
3803                                                                         }\r
3804                                                                 }\r
3805                                                                 if (dest_session->Policy->FilterNonIP)\r
3806                                                                 {\r
3807                                                                         if (packet->TypeL3 != L3_IPV4 && packet->TypeL3 != L3_ARPV4 && packet->TypeL3 != L3_IPV6)\r
3808                                                                         {\r
3809                                                                                 discard = true;\r
3810                                                                         }\r
3811                                                                 }\r
3812 \r
3813                                                                 if (s != NULL &&\r
3814                                                                         (packet->BroadcastPacket == false &&\r
3815                                                                         s->Policy->PrivacyFilter &&\r
3816                                                                         dest_session->Policy->PrivacyFilter)\r
3817                                                                         )\r
3818                                                                 {\r
3819                                                                         // プライバシーフィルタ\r
3820                                                                         if (packet->TypeL3 != L3_ARPV4)\r
3821                                                                         {\r
3822                                                                                 discard = true;\r
3823                                                                         }\r
3824                                                                 }\r
3825 \r
3826                                                                 if (s != NULL)\r
3827                                                                 {\r
3828                                                                         if (Cmp(packet->MacAddressSrc, s->Hub->HubMacAddr, 6) == 0 ||\r
3829                                                                                 Cmp(packet->MacAddressDest, s->Hub->HubMacAddr, 6) == 0)\r
3830                                                                         {\r
3831                                                                                 discard = true;\r
3832                                                                         }\r
3833                                                                 }\r
3834 \r
3835                                                                 if (discard == false && dest_pa != NULL)\r
3836                                                                 {\r
3837                                                                         // 自分以外のセッションにストア\r
3838                                                                         data = MallocFast(packet->PacketSize);\r
3839                                                                         Copy(data, packet->PacketData, packet->PacketSize);\r
3840                                                                         size = packet->PacketSize;\r
3841 \r
3842                                                                         if (delete_default_router_in_ra)\r
3843                                                                         {\r
3844                                                                                 PKT *pkt2 = ParsePacket(data, size);\r
3845 \r
3846                                                                                 DeleteIPv6DefaultRouterInRA(pkt2);\r
3847 \r
3848                                                                                 FreePacket(pkt2);\r
3849                                                                         }\r
3850 \r
3851                                                                         StorePacketToHubPa(dest_pa, s, data, size, packet);\r
3852 \r
3853                                                                         // トラフィック加算\r
3854                                                                         AddTrafficForSession(dest_session, &traffic);\r
3855                                                                 }\r
3856                                                         }\r
3857                                                 }\r
3858                                         }\r
3859                                         UnlockList(hub->SessionList);\r
3860 \r
3861                                         // パケットログをとる\r
3862                                         if (s != NULL)\r
3863                                         {\r
3864                                                 PacketLog(s->Hub, s, NULL, packet);\r
3865                                         }\r
3866 \r
3867                                         Free(packet->PacketData);\r
3868                                 }\r
3869                                 FreePacket(packet);\r
3870                         }\r
3871                 }\r
3872         }\r
3873         UnlockList(hub->MacTable);\r
3874 }\r
3875 \r
3876 // 指定された IP アドレスがプライベート IP アドレスかどうかチェックする\r
3877 bool IsIPPrivate(IP *ip)\r
3878 {\r
3879         // 引数チェック\r
3880         if (ip == NULL)\r
3881         {\r
3882                 return false;\r
3883         }\r
3884 \r
3885         if (ip->addr[0] == 10)\r
3886         {\r
3887                 return true;\r
3888         }\r
3889 \r
3890         if (ip->addr[0] == 172)\r
3891         {\r
3892                 if (ip->addr[1] >= 16 && ip->addr[1] <= 31)\r
3893                 {\r
3894                         return true;\r
3895                 }\r
3896         }\r
3897 \r
3898         if (ip->addr[0] == 192 && ip->addr[1] == 168)\r
3899         {\r
3900                 return true;\r
3901         }\r
3902 \r
3903         if (ip->addr[0] == 2)\r
3904         {\r
3905                 // Special !!\r
3906                 return true;\r
3907         }\r
3908 \r
3909         if (ip->addr[0] == 169 && ip->addr[1] == 254)\r
3910         {\r
3911                 return true;\r
3912         }\r
3913 \r
3914         return false;\r
3915 }\r
3916 \r
3917 // 指定された IP アドレスが仮想 HUB による管理対象かどうか確認する\r
3918 bool IsIPManagementTargetForHUB(IP *ip, HUB *hub)\r
3919 {\r
3920         // 引数チェック\r
3921         if (ip == NULL || hub == NULL)\r
3922         {\r
3923                 return false;\r
3924         }\r
3925 \r
3926         if (hub->Option == NULL)\r
3927         {\r
3928                 return true;\r
3929         }\r
3930 \r
3931         if (IsIP4(ip))\r
3932         {\r
3933                 if (hub->Option->ManageOnlyPrivateIP)\r
3934                 {\r
3935                         if (IsIPPrivate(ip) == false)\r
3936                         {\r
3937                                 return false;\r
3938                         }\r
3939                 }\r
3940         }\r
3941         else\r
3942         {\r
3943                 if (hub->Option->ManageOnlyLocalUnicastIPv6)\r
3944                 {\r
3945                         UINT ip_type = GetIPAddrType6(ip);\r
3946 \r
3947                         if (!(ip_type & IPV6_ADDR_LOCAL_UNICAST))\r
3948                         {\r
3949                                 return false;\r
3950                         }\r
3951                 }\r
3952         }\r
3953 \r
3954         return true;\r
3955 }\r
3956 \r
3957 // 古い IP テーブルエントリを削除する\r
3958 void DeleteOldIpTableEntry(LIST *o)\r
3959 {\r
3960         UINT i;\r
3961         UINT64 oldest_time = 0xffffffffffffffffULL;\r
3962         IP_TABLE_ENTRY *old = NULL;\r
3963         // 引数チェック\r
3964         if (o == NULL)\r
3965         {\r
3966                 return;\r
3967         }\r
3968 \r
3969         for (i = 0;i < LIST_NUM(o);i++)\r
3970         {\r
3971                 IP_TABLE_ENTRY *e = LIST_DATA(o, i);\r
3972 \r
3973                 if (e->UpdatedTime <= oldest_time)\r
3974                 {\r
3975                         old = e;\r
3976                 }\r
3977         }\r
3978 \r
3979         if (old != NULL)\r
3980         {\r
3981                 Delete(o, old);\r
3982                 Free(old);\r
3983         }\r
3984 }\r
3985 \r
3986 // ストームリストの追加\r
3987 STORM *AddStormList(HUB_PA *pa, UCHAR *mac_address, IP *src_ip, IP *dest_ip)\r
3988 {\r
3989         STORM *s;\r
3990         // 引数チェック\r
3991         if (pa == NULL || mac_address == NULL)\r
3992         {\r
3993                 return NULL;\r
3994         }\r
3995 \r
3996         s = ZeroMalloc(sizeof(STORM));\r
3997         if (src_ip != NULL)\r
3998         {\r
3999                 Copy(&s->SrcIp, src_ip, sizeof(IP));\r
4000         }\r
4001         if (dest_ip != NULL)\r
4002         {\r
4003                 Copy(&s->DestIp, dest_ip, sizeof(IP));\r
4004         }\r
4005         Copy(s->MacAddress, mac_address, 6);\r
4006 \r
4007         Insert(pa->StormList, s);\r
4008 \r
4009         return s;\r
4010 }\r
4011 \r
4012 // ストームリストのサーチ\r
4013 STORM *SearchStormList(HUB_PA *pa, UCHAR *mac_address, IP *src_ip, IP *dest_ip)\r
4014 {\r
4015         STORM t, *s;\r
4016         // 引数チェック\r
4017         if (pa == NULL || mac_address == NULL)\r
4018         {\r
4019                 return NULL;\r
4020         }\r
4021 \r
4022         Zero(&t, sizeof(t));\r
4023         if (src_ip != NULL)\r
4024         {\r
4025                 Copy(&t.SrcIp, src_ip, sizeof(IP));\r
4026         }\r
4027         if (dest_ip != NULL)\r
4028         {\r
4029                 Copy(&t.DestIp, dest_ip, sizeof(IP));\r
4030         }\r
4031         Copy(t.MacAddress, mac_address, 6);\r
4032 \r
4033         s = Search(pa->StormList, &t);\r
4034 \r
4035         return s;\r
4036 }\r
4037 \r
4038 // パケットを宛先の HUB_PA にストアする\r
4039 void StorePacketToHubPa(HUB_PA *dest, SESSION *src, void *data, UINT size, PKT *packet)\r
4040 {\r
4041         BLOCK *b;\r
4042         // 引数チェック\r
4043         if (dest == NULL || data == NULL)\r
4044         {\r
4045                 return;\r
4046         }\r
4047 \r
4048         if (size < 14)\r
4049         {\r
4050                 Free(data);\r
4051                 return;\r
4052         }\r
4053 \r
4054         if (src != NULL)\r
4055         {\r
4056                 // フォワード用のアクセスリスト適用\r
4057                 if (ApplyAccessListToForwardPacket(src->Hub, src, dest->Session, packet) == false)\r
4058                 {\r
4059                         Free(data);\r
4060                         return;\r
4061                 }\r
4062         }\r
4063 \r
4064         if (src != NULL)\r
4065         {\r
4066                 if (dest->Session->Policy->MaxDownload != 0)\r
4067                 {\r
4068                         // トラフィック制限\r
4069                         if (packet != NULL && IsMostHighestPriorityPacket(dest->Session, packet) == false)\r
4070                         {\r
4071                                 TRAFFIC_LIMITER *tr = &dest->DownloadLimiter;\r
4072                                 IntoTrafficLimiter(tr, packet);\r
4073 \r
4074                                 if ((tr->Value * (UINT64)1000 / (UINT64)LIMITER_SAMPLING_SPAN) > dest->Session->Policy->MaxDownload)\r
4075                                 {\r
4076                                         // 制限する\r
4077                                         Free(data);\r
4078                                         return;\r
4079                                 }\r
4080                         }\r
4081                 }\r
4082         }\r
4083 \r
4084         if (src != NULL && src->Hub != NULL && src->Hub->Option != NULL && src->Hub->Option->FixForDLinkBPDU)\r
4085         {\r
4086                 // D-Link バグ対策\r
4087                 UCHAR *mac = packet->MacAddressSrc;\r
4088                 if ((mac[0] == 0x00 && mac[1] == 0x80 && mac[2] == 0xc8 && mac[3] == 0x00 && mac[4] == 0x00 && mac[5] == 0x00) ||\r
4089                         (mac[0] == 0x00 && mac[1] == 0x0d && mac[2] == 0x88 && mac[3] == 0x00 && mac[4] == 0x00 && mac[5] == 0x00))\r
4090                 {\r
4091                         SESSION *session = dest->Session;\r
4092 \r
4093                         if (session != NULL)\r
4094                         {\r
4095                                 if (session->Policy != NULL && session->Policy->CheckMac)\r
4096                                 {\r
4097                                         UCHAR hash[MD5_SIZE];\r
4098                                         Hash(hash, packet->PacketData, packet->PacketSize, false);\r
4099 \r
4100                                         Copy(session->LastDLinkSTPPacketDataHash, hash, MD5_SIZE);\r
4101                                         session->LastDLinkSTPPacketSendTick = Tick64();\r
4102                                 }\r
4103                         }\r
4104                 }\r
4105         }\r
4106 \r
4107         // VLAN タグを除去\r
4108         if (dest->Session != NULL && dest->Session->VLanId != 0)\r
4109         {\r
4110                 if (VLanRemoveTag(&data, &size, dest->Session->VLanId) == false)\r
4111                 {\r
4112                         Free(data);\r
4113                         return;\r
4114                 }\r
4115         }\r
4116 \r
4117         // ブロック作成\r
4118         b = NewBlock(data, size, 0);\r
4119 \r
4120         LockQueue(dest->PacketQueue);\r
4121         {\r
4122                 // キューの数を測定\r
4123                 if ((dest->PacketQueue->num_item < MAX_STORED_QUEUE_NUM) ||\r
4124                         (((UCHAR *)data)[12] == 'S' && ((UCHAR *)data)[13] == 'E'))\r
4125                 {\r
4126                         // ストア\r
4127                         InsertQueue(dest->PacketQueue, b);\r
4128                 }\r
4129                 else\r
4130                 {\r
4131                         // パケット破棄\r
4132                         FreeBlock(b);\r
4133                 }\r
4134         }\r
4135         UnlockQueue(dest->PacketQueue);\r
4136 \r
4137         // キャンセルの発行\r
4138         if (src != NULL)\r
4139         {\r
4140                 AddCancelList(src->CancelList, dest->Cancel);\r
4141         }\r
4142         else\r
4143         {\r
4144                 Cancel(dest->Cancel);\r
4145         }\r
4146 }\r
4147 \r
4148 // IPv6 ルータ広告からデフォルトルータ指定を削除\r
4149 bool DeleteIPv6DefaultRouterInRA(PKT *p)\r
4150 {\r
4151         if (p->TypeL3 == L3_IPV6 && p->TypeL4 == L4_ICMPV6 &&\r
4152                 (p->ICMPv6HeaderPacketInfo.Type == ICMPV6_TYPE_ROUTER_ADVERTISEMENT))\r
4153         {\r
4154                 if (p->ICMPv6HeaderPacketInfo.Headers.RouterAdvertisementHeader->Lifetime != 0)\r
4155                 {\r
4156                         p->ICMPv6HeaderPacketInfo.Headers.RouterAdvertisementHeader->Lifetime = 0;\r
4157 \r
4158                         p->L4.ICMPHeader->Checksum = 0;\r
4159                         p->L4.ICMPHeader->Checksum =\r
4160                                 CalcChecksumForIPv6(&p->L3.IPv6Header->SrcAddress,\r
4161                                         &p->L3.IPv6Header->DestAddress, IP_PROTO_ICMPV6,\r
4162                                         p->L4.ICMPHeader, p->IPv6HeaderPacketInfo.PayloadSize);\r
4163                 }\r
4164         }\r
4165 \r
4166         return false;\r
4167 }\r
4168 \r
4169 // ポリシーによるパケットフィルタ\r
4170 bool StorePacketFilterByPolicy(SESSION *s, PKT *p)\r
4171 {\r
4172         POLICY *pol;\r
4173         HUB *hub;\r
4174         // 引数チェック\r
4175         if (s == NULL || p == NULL)\r
4176         {\r
4177                 return false;\r
4178         }\r
4179 \r
4180         hub = s->Hub;\r
4181 \r
4182         // ポリシー\r
4183         pol = s->Policy;\r
4184 \r
4185         // サーバーとしての動作を禁止する\r
4186         if (pol->NoServer)\r
4187         {\r
4188                 if (p->TypeL3 == L3_IPV4)\r
4189                 {\r
4190                         if (p->TypeL4 == L4_TCP)\r
4191                         {\r
4192                                 UCHAR flag = p->L4.TCPHeader->Flag;\r
4193                                 if ((flag & TCP_SYN) && (flag & TCP_ACK))\r
4194                                 {\r
4195                                         char ip1[64], ip2[64];\r
4196                                         // SYN + ACK パケットを送信させない\r
4197                                         Debug("pol->NoServer: Discard SYN+ACK Packet.\n");\r
4198 \r
4199                                         IPToStr32(ip1, sizeof(ip1), p->L3.IPv4Header->SrcIP);\r
4200                                         IPToStr32(ip2, sizeof(ip2), p->L3.IPv4Header->DstIP);\r
4201 \r
4202                                         HLog(s->Hub, "LH_NO_SERVER", s->Name, ip2, p->L4.TCPHeader->DstPort,\r
4203                                                 ip1, p->L4.TCPHeader->SrcPort);\r
4204 \r
4205                                         return false;\r
4206                                 }\r
4207                         }\r
4208                 }\r
4209         }\r
4210 \r
4211         // サーバーとしての動作を禁止する (IPv6)\r
4212         if (pol->NoServerV6)\r
4213         {\r
4214                 if (p->TypeL3 == L3_IPV6)\r
4215                 {\r
4216                         if (p->TypeL4 == L4_TCP)\r
4217                         {\r
4218                                 UCHAR flag = p->L4.TCPHeader->Flag;\r
4219                                 if ((flag & TCP_SYN) && (flag & TCP_ACK))\r
4220                                 {\r
4221                                         char ip1[128], ip2[128];\r
4222                                         // SYN + ACK パケットを送信させない\r
4223                                         Debug("pol->NoServerV6: Discard SYN+ACK Packet.\n");\r
4224 \r
4225                                         IP6AddrToStr(ip1, sizeof(ip1), &p->IPv6HeaderPacketInfo.IPv6Header->SrcAddress);\r
4226                                         IP6AddrToStr(ip2, sizeof(ip2), &p->IPv6HeaderPacketInfo.IPv6Header->DestAddress);\r
4227 \r
4228                                         HLog(s->Hub, "LH_NO_SERVER", s->Name, ip2, p->L4.TCPHeader->DstPort,\r
4229                                                 ip1, p->L4.TCPHeader->SrcPort);\r
4230 \r
4231                                         return false;\r
4232                                 }\r
4233                         }\r
4234                 }\r
4235         }\r
4236 \r
4237         // ブロードキャストは ARP と DHCP のみ許可\r
4238         if (pol->ArpDhcpOnly && p->BroadcastPacket)\r
4239         {\r
4240                 bool ok = false;\r
4241 \r
4242                 if (p->TypeL3 == L3_ARPV4)\r
4243                 {\r
4244                         ok = true;\r
4245                 }\r
4246                 if (p->TypeL3 == L3_IPV4)\r
4247                 {\r
4248                         if (p->TypeL4 == L4_UDP)\r
4249                         {\r
4250                                 if (p->TypeL7 == L7_DHCPV4)\r
4251                                 {\r
4252                                         ok = true;\r
4253                                 }\r
4254                         }\r
4255                 }\r
4256                 if (p->TypeL3 == L3_IPV6)\r
4257                 {\r
4258                         if (p->TypeL4 == L4_ICMPV6)\r
4259                         {\r
4260                                 ok = true;\r
4261                         }\r
4262                 }\r
4263 \r
4264                 if (p->TypeL3 == L3_IPV6 &&\r
4265                         p->TypeL4 == L4_UDP &&\r
4266                         (Endian16(p->L4.UDPHeader->DstPort) == 546 || Endian16(p->L4.UDPHeader->DstPort) == 547))\r
4267                 {\r
4268                         ok = true;\r
4269                 }\r
4270 \r
4271                 if (ok == false)\r
4272                 {\r
4273                         return false;\r
4274                 }\r
4275         }\r
4276 \r
4277         // IPv4 パケットのフィルタリング\r
4278         if (pol->FilterIPv4)\r
4279         {\r
4280                 if (p->MacHeader != NULL)\r
4281                 {\r
4282                         USHORT proto = Endian16(p->MacHeader->Protocol);\r
4283                         if (proto == 0x0800 || proto == 0x0806)\r
4284                         {\r
4285                                 return false;\r
4286                         }\r
4287                 }\r
4288         }\r
4289 \r
4290         // IPv6 パケットのフィルタリング\r
4291         if (pol->FilterIPv6)\r
4292         {\r
4293                 if (p->MacHeader != NULL)\r
4294                 {\r
4295                         USHORT proto = Endian16(p->MacHeader->Protocol);\r
4296                         if (proto == 0x86dd)\r
4297                         {\r
4298                                 return false;\r
4299                         }\r
4300                 }\r
4301         }\r
4302 \r
4303         // 非 IP パケットのフィルタリング\r
4304         if (pol->FilterNonIP)\r
4305         {\r
4306                 if (p->MacHeader != NULL)\r
4307                 {\r
4308                         USHORT proto = Endian16(p->MacHeader->Protocol);\r
4309                         if (!(proto == 0x86dd || proto == 0x0800 || proto == 0x0806))\r
4310                         {\r
4311                                 return false;\r
4312                         }\r
4313                 }\r
4314         }\r
4315 \r
4316         // DHCP パケットのフィルタリング\r
4317         if (pol->DHCPFilter)\r
4318         {\r
4319                 if (p->TypeL3 == L3_IPV4 &&\r
4320                         p->TypeL4 == L4_UDP &&\r
4321                         p->TypeL7 == L7_DHCPV4)\r
4322                 {\r
4323                         // DHCP パケットを破棄する\r
4324                         Debug("pol->DHCPFilter: Discard DHCP Packet.\n");\r
4325 \r
4326                         return false;\r
4327                 }\r
4328         }\r
4329 \r
4330         // DHCPv6 パケットのフィルタリング\r
4331         if (pol->DHCPv6Filter)\r
4332         {\r
4333                 if (p->TypeL3 == L3_IPV6 &&\r
4334                         p->TypeL4 == L4_UDP)\r
4335                 {\r
4336                         if (Endian16(p->L4.UDPHeader->DstPort) == 546 ||\r
4337                                 Endian16(p->L4.UDPHeader->DstPort) == 547)\r
4338                         {\r
4339                                 // DHCPv6 パケットを破棄する\r
4340                                 Debug("pol->DHCPv6Filter: Discard DHCPv6 Packet.\n");\r
4341 \r
4342                                 return false;\r
4343                         }\r
4344                 }\r
4345         }\r
4346 \r
4347         // DHCP サーバーとしての動作を禁止\r
4348         if (pol->DHCPNoServer)\r
4349         {\r
4350                 if (p->TypeL3 == L3_IPV4 &&\r
4351                         p->TypeL4 == L4_UDP &&\r
4352                         p->TypeL7 == L7_DHCPV4)\r
4353                 {\r
4354                         DHCPV4_HEADER *h = p->L7.DHCPv4Header;\r
4355                         if (h->OpCode == 2)\r
4356                         {\r
4357                                 char ip1[64], ip2[64];\r
4358 \r
4359                                 // DHCP パケットを破棄する\r
4360                                 IPToStr32(ip1, sizeof(ip1), p->L3.IPv4Header->SrcIP);\r
4361                                 IPToStr32(ip2, sizeof(ip2), p->L3.IPv4Header->DstIP);\r
4362 \r
4363                                 HLog(s->Hub, "LH_NO_DHCP", s->Name, ip1, ip2);\r
4364 \r
4365                                 // DHCP 応答パケットを破棄する\r
4366                                 Debug("pol->DHCPNoServer: Discard DHCP Response Packet.\n");\r
4367                                 return false;\r
4368                         }\r
4369                 }\r
4370         }\r
4371 \r
4372         // DHCPv6 サーバーとしての動作を禁止\r
4373         if (pol->DHCPv6NoServer)\r
4374         {\r
4375                 if (p->TypeL3 == L3_IPV6 &&\r
4376                         p->TypeL4 == L4_UDP &&\r
4377                         (Endian16(p->L4.UDPHeader->DstPort) == 546 || Endian16(p->L4.UDPHeader->SrcPort) == 547))\r
4378                 {\r
4379                         char ip1[128], ip2[128];\r
4380 \r
4381                         // DHCP パケットを破棄する\r
4382                         IP6AddrToStr(ip1, sizeof(ip1), &p->L3.IPv6Header->SrcAddress);\r
4383                         IP6AddrToStr(ip2, sizeof(ip2), &p->L3.IPv6Header->DestAddress);\r
4384 \r
4385                         HLog(s->Hub, "LH_NO_DHCP", s->Name, ip1, ip2);\r
4386 \r
4387                         // DHCP 応答パケットを破棄する\r
4388                         Debug("pol->DHCPv6NoServer: Discard DHCPv6 Response Packet.\n");\r
4389                         return false;\r
4390                 }\r
4391         }\r
4392 \r
4393         // ルータ要請/広告パケットをフィルタリング (IPv6)\r
4394         if (pol->RSandRAFilter)\r
4395         {\r
4396                 if (p->TypeL3 == L3_IPV6 && p->TypeL4 == L4_ICMPV6 &&\r
4397                         (p->ICMPv6HeaderPacketInfo.Type == ICMPV6_TYPE_ROUTER_SOLICIATION ||\r
4398                          p->ICMPv6HeaderPacketInfo.Type == ICMPV6_TYPE_ROUTER_ADVERTISEMENT))\r
4399                 {\r
4400                         return false;\r
4401                 }\r
4402         }\r
4403 \r
4404         // ルータ広告パケットをフィルタリング (IPv6)\r
4405         if (pol->RAFilter)\r
4406         {\r
4407                 if (p->TypeL3 == L3_IPV6 && p->TypeL4 == L4_ICMPV6 &&\r
4408                         p->ICMPv6HeaderPacketInfo.Type == ICMPV6_TYPE_ROUTER_ADVERTISEMENT)\r
4409                 {\r
4410                         return false;\r
4411                 }\r
4412         }\r
4413 \r
4414         // DHCP 応答パケットを記録して IP テーブルに登録\r
4415         if (p->TypeL3 == L3_IPV4 &&\r
4416                 p->TypeL4 == L4_UDP &&\r
4417                 p->TypeL7 == L7_DHCPV4 &&\r
4418                 (s->Hub != NULL && s->Hub->Option->NoIpTable == false))\r
4419         {\r
4420                 DHCPV4_HEADER *h = p->L7.DHCPv4Header;\r
4421                 if (h->OpCode == 2)\r
4422                 {\r
4423                         // DHCP 応答パケットの中身を見て IP テーブルに登録する\r
4424                         if (h->HardwareType == ARP_HARDWARE_TYPE_ETHERNET)\r
4425                         {\r
4426                                 if (h->HardwareAddressSize == 6)\r
4427                                 {\r
4428                                         if (h->YourIP != 0 && h->YourIP != 0xffffffff)\r
4429                                         {\r
4430                                                 UINT ip_uint = h->YourIP;\r
4431                                                 IP ip;\r
4432                                                 IP_TABLE_ENTRY *e, t;\r
4433                                                 MAC_TABLE_ENTRY *mac_table, mt;\r
4434                                                 mt.VlanId = 0;\r
4435                                                 Copy(&mt.MacAddress, &h->ClientMacAddress, 6);\r
4436                                                 mac_table = Search(hub->MacTable, &mt);\r
4437 \r
4438                                                 if (mac_table != NULL)\r
4439                                                 {\r
4440                                                         bool new_entry = true;\r
4441                                                         UINTToIP(&ip, ip_uint);\r
4442                                                         Copy(&t.Ip, &ip, sizeof(IP));\r
4443 \r
4444                                                         e = Search(hub->IpTable, &t);\r
4445                                                         if (e == NULL)\r
4446                                                         {\r
4447                                                                 // 新しく登録\r
4448                                                                 e = ZeroMalloc(sizeof(IP_TABLE_ENTRY));\r
4449 UPDATE_DHCP_ALLOC_ENTRY:\r
4450                                                                 e->CreatedTime = e->UpdatedTime = Tick64();\r
4451                                                                 e->DhcpAllocated = true;\r
4452                                                                 Copy(&e->Ip, &ip, sizeof(IP));\r
4453                                                                 e->Session = mac_table->Session;\r
4454                                                                 Copy(e->MacAddress, p->MacAddressDest, 6);\r
4455 \r
4456                                                                 if (new_entry)\r
4457                                                                 {\r
4458                                                                         // 有効期限の切れた IP テーブルエントリを削除する\r
4459                                                                         DeleteExpiredIpTableEntry(hub->IpTable);\r
4460                                                                         if (LIST_NUM(hub->IpTable) >= MAX_IP_TABLES)\r
4461                                                                         {\r
4462                                                                                 // 古いエントリを削除する\r
4463                                                                                 DeleteOldIpTableEntry(hub->IpTable);\r
4464                                                                         }\r
4465                                                                         Insert(hub->IpTable, e);\r
4466                                                                 }\r
4467 \r
4468                                                                 if (new_entry)\r
4469                                                                 {\r
4470                                                                         char dhcp_mac_addr[64];\r
4471                                                                         char dest_mac_addr[64];\r
4472                                                                         char dest_ip_addr[64];\r
4473                                                                         char server_ip_addr[64];\r
4474                                                                         MacToStr(dhcp_mac_addr, sizeof(dhcp_mac_addr), p->MacAddressSrc);\r
4475                                                                         MacToStr(dest_mac_addr, sizeof(dest_mac_addr), h->ClientMacAddress);\r
4476                                                                         IPToStr(dest_ip_addr, sizeof(dest_ip_addr), &ip);\r
4477                                                                         IPToStr32(server_ip_addr, sizeof(server_ip_addr), p->L3.IPv4Header->SrcIP);\r
4478                                                                         Debug("DHCP Allocated; dhcp server: %s, client: %s, new_ip: %s\n",\r
4479                                                                                 dhcp_mac_addr, dest_mac_addr, dest_ip_addr);\r
4480 \r
4481                                                                         HLog(s->Hub, "LH_REGIST_DHCP", s->Name, dhcp_mac_addr, server_ip_addr,\r
4482                                                                                 mac_table->Session->Name, dest_mac_addr, dest_ip_addr);\r
4483                                                                 }\r
4484                                                         }\r
4485                                                         else\r
4486                                                         {\r
4487                                                                 // 更新\r
4488                                                                 new_entry = false;\r
4489                                                                 goto UPDATE_DHCP_ALLOC_ENTRY;\r
4490                                                         }\r
4491                                                 }\r
4492                                         }\r
4493                                 }\r
4494                         }\r
4495                 }\r
4496         }\r
4497 \r
4498         return true;\r
4499 }\r
4500 \r
4501 // 有効期限の切れた MAC テーブルエントリを削除する\r
4502 void DeleteExpiredMacTableEntry(LIST *o)\r
4503 {\r
4504         LIST *o2;\r
4505         UINT i;\r
4506         // 引数チェック\r
4507         if (o == NULL)\r
4508         {\r
4509                 return;\r
4510         }\r
4511 \r
4512         o2 = NewListFast(NULL);\r
4513 \r
4514         for (i = 0;i < LIST_NUM(o);i++)\r
4515         {\r
4516                 MAC_TABLE_ENTRY *e = LIST_DATA(o, i);\r
4517                 if ((e->UpdatedTime + (UINT64)MAC_TABLE_EXPIRE_TIME) <= Tick64())\r
4518                 {\r
4519                         Add(o2, e);\r
4520                 }\r
4521         }\r
4522 \r
4523         for (i = 0;i < LIST_NUM(o2);i++)\r
4524         {\r
4525                 MAC_TABLE_ENTRY *e = LIST_DATA(o2, i);\r
4526                 Delete(o, e);\r
4527                 Free(e);\r
4528         }\r
4529 \r
4530         ReleaseList(o2);\r
4531 }\r
4532 \r
4533 // 有効期限の切れた IP テーブルエントリを削除する\r
4534 void DeleteExpiredIpTableEntry(LIST *o)\r
4535 {\r
4536         LIST *o2;\r
4537         UINT i;\r
4538         // 引数チェック\r
4539         if (o == NULL)\r
4540         {\r
4541                 return;\r
4542         }\r
4543 \r
4544         o2 = NewListFast(NULL);\r
4545 \r
4546         for (i = 0;i < LIST_NUM(o);i++)\r
4547         {\r
4548                 IP_TABLE_ENTRY *e = LIST_DATA(o, i);\r
4549                 if ((e->UpdatedTime + (UINT64)(e->DhcpAllocated ? IP_TABLE_EXPIRE_TIME_DHCP : IP_TABLE_EXPIRE_TIME)) <= Tick64())\r
4550                 {\r
4551                         Add(o2, e);\r
4552                 }\r
4553         }\r
4554 \r
4555         for (i = 0;i < LIST_NUM(o2);i++)\r
4556         {\r
4557                 IP_TABLE_ENTRY *e = LIST_DATA(o2, i);\r
4558                 Delete(o, e);\r
4559                 Free(e);\r
4560         }\r
4561 \r
4562         ReleaseList(o2);\r
4563 }\r
4564 \r
4565 // 優先して取り扱うべきパケットかどうかを判断\r
4566 bool IsMostHighestPriorityPacket(SESSION *s, PKT *p)\r
4567 {\r
4568         // 引数チェック\r
4569         if (s == NULL || p == NULL)\r
4570         {\r
4571                 return false;\r
4572         }\r
4573 \r
4574         if (p->TypeL3 == L3_ARPV4)\r
4575         {\r
4576                 // ARP パケット\r
4577                 return true;\r
4578         }\r
4579 \r
4580         if (p->TypeL3 == L3_IPV4)\r
4581         {\r
4582                 if (p->TypeL4 == L4_ICMPV4)\r
4583                 {\r
4584                         // ICMP パケット\r
4585                         return true;\r
4586                 }\r
4587 \r
4588                 if (p->TypeL4 == L4_TCP)\r
4589                 {\r
4590                         if ((p->L4.TCPHeader->Flag & TCP_SYN) || (p->L4.TCPHeader->Flag & TCP_FIN)\r
4591                                 || (p->L4.TCPHeader->Flag & TCP_RST))\r
4592                         {\r
4593                                 // SYN, FIN, RST パケット\r
4594                                 return true;\r
4595                         }\r
4596                 }\r
4597 \r
4598                 if (p->TypeL4 == L4_UDP)\r
4599                 {\r
4600                         if (p->TypeL7 == L7_DHCPV4)\r
4601                         {\r
4602                                 // DHCP パケット\r
4603                                 return true;\r
4604                         }\r
4605                 }\r
4606         }\r
4607 \r
4608         return false;\r
4609 }\r
4610 \r
4611 // トラフィック リミッターへのパケット追加\r
4612 void IntoTrafficLimiter(TRAFFIC_LIMITER *tr, PKT *p)\r
4613 {\r
4614         UINT64 now = Tick64();\r
4615         // 引数チェック\r
4616         if (tr == NULL || p == NULL)\r
4617         {\r
4618                 return;\r
4619         }\r
4620 \r
4621         if (tr->LastTime == 0 || tr->LastTime > now ||\r
4622                 (tr->LastTime + LIMITER_SAMPLING_SPAN) < now)\r
4623         {\r
4624                 // サンプリング初期化\r
4625                 tr->Value = 0;\r
4626                 tr->LastTime = now;\r
4627         }\r
4628 \r
4629         // 値増加\r
4630         tr->Value += (UINT64)(p->PacketSize * 8);\r
4631 }\r
4632 \r
4633 // トラフィック リミッターによる帯域幅削減\r
4634 bool StorePacketFilterByTrafficLimiter(SESSION *s, PKT *p)\r
4635 {\r
4636         HUB_PA *pa;\r
4637         TRAFFIC_LIMITER *tr;\r
4638         // 引数チェック\r
4639         if (s == NULL || p == NULL)\r
4640         {\r
4641                 return false;\r
4642         }\r
4643 \r
4644         if (s->Policy->MaxUpload == 0)\r
4645         {\r
4646                 // 制限無し\r
4647                 return true;\r
4648         }\r
4649 \r
4650         pa = (HUB_PA *)s->PacketAdapter->Param;\r
4651         tr = &pa->UploadLimiter;\r
4652 \r
4653         // 優先パケットは制限を適用しない\r
4654         if (IsMostHighestPriorityPacket(s, p))\r
4655         {\r
4656                 return true;\r
4657         }\r
4658 \r
4659         // リミッターへパケットを投入\r
4660         IntoTrafficLimiter(tr, p);\r
4661 \r
4662         // 現在の帯域幅と制限値を比較\r
4663         if ((tr->Value * (UINT64)1000 / (UINT64)LIMITER_SAMPLING_SPAN) > s->Policy->MaxUpload)\r
4664         {\r
4665                 // パケットを破棄\r
4666                 return false;\r
4667         }\r
4668 \r
4669         return true;\r
4670 }\r
4671 \r
4672 // ストアするパケットのフィルタリング\r
4673 bool StorePacketFilter(SESSION *s, PKT *packet)\r
4674 {\r
4675         // 引数チェック\r
4676         if (s == NULL || packet == NULL)\r
4677         {\r
4678                 return false;\r
4679         }\r
4680 \r
4681         // トラフィック リミッターによる帯域幅削減\r
4682         if (StorePacketFilterByTrafficLimiter(s, packet) == false)\r
4683         {\r
4684                 return false;\r
4685         }\r
4686 \r
4687         // ポリシーによるパケットフィルタ\r
4688         if (StorePacketFilterByPolicy(s, packet) == false)\r
4689         {\r
4690                 return false;\r
4691         }\r
4692 \r
4693         // アクセスリストによるパケットフィルタ\r
4694         if (ApplyAccessListToStoredPacket(s->Hub, s, packet) == false)\r
4695         {\r
4696                 return false;\r
4697         }\r
4698 \r
4699         return true;\r
4700 }\r
4701 \r
4702 // HUB 用のパケットアダプタの取得\r
4703 PACKET_ADAPTER *GetHubPacketAdapter()\r
4704 {\r
4705         // 関数リストを生成して引き渡す\r
4706         PACKET_ADAPTER *pa = NewPacketAdapter(HubPaInit,\r
4707                 HubPaGetCancel, HubPaGetNextPacket, HubPaPutPacket, HubPaFree);\r
4708 \r
4709         return pa;\r
4710 }\r
4711 \r
4712 // HUB のすべての SESSION を停止させる\r
4713 void StopAllSession(HUB *h)\r
4714 {\r
4715         SESSION **s;\r
4716         UINT i, num;\r
4717         // 引数チェック\r
4718         if (h == NULL)\r
4719         {\r
4720                 return;\r
4721         }\r
4722 \r
4723         LockList(h->SessionList);\r
4724         {\r
4725                 num = LIST_NUM(h->SessionList);\r
4726                 s = ToArray(h->SessionList);\r
4727                 DeleteAll(h->SessionList);\r
4728         }\r
4729         UnlockList(h->SessionList);\r
4730 \r
4731         for (i = 0;i < num;i++)\r
4732         {\r
4733                 StopSession(s[i]);\r
4734                 ReleaseSession(s[i]);\r
4735         }\r
4736 \r
4737         Free(s);\r
4738 }\r
4739 \r
4740 // HUB から SESSION を削除\r
4741 void DelSession(HUB *h, SESSION *s)\r
4742 {\r
4743         // 引数チェック\r
4744         if (h == NULL || s == NULL)\r
4745         {\r
4746                 return;\r
4747         }\r
4748 \r
4749         LockList(h->SessionList);\r
4750         {\r
4751                 if (Delete(h->SessionList, s))\r
4752                 {\r
4753                         Debug("Session %s was Deleted from %s.\n", s->Name, h->Name);\r
4754                         ReleaseSession(s);\r
4755                 }\r
4756         }\r
4757         UnlockList(h->SessionList);\r
4758 }\r
4759 \r
4760 // HUB に SESSION を追加\r
4761 void AddSession(HUB *h, SESSION *s)\r
4762 {\r
4763         // 引数チェック\r
4764         if (h == NULL || s == NULL)\r
4765         {\r
4766                 return;\r
4767         }\r
4768 \r
4769         LockList(h->SessionList);\r
4770         {\r
4771                 Insert(h->SessionList, s);\r
4772                 AddRef(s->ref);\r
4773                 Debug("Session %s Inserted to %s.\n", s->Name, h->Name);\r
4774         }\r
4775         UnlockList(h->SessionList);\r
4776 }\r
4777 \r
4778 // HUB の動作を停止する\r
4779 void StopHub(HUB *h)\r
4780 {\r
4781         bool old_status = false;\r
4782         // 引数チェック\r
4783         if (h == NULL)\r
4784         {\r
4785                 return;\r
4786         }\r
4787 \r
4788         old_status = h->Offline;\r
4789         h->HubIsOnlineButHalting = true;\r
4790 \r
4791         SetHubOffline(h);\r
4792 \r
4793         if (h->Halt == false)\r
4794         {\r
4795                 SLog(h->Cedar, "LS_HUB_STOP", h->Name);\r
4796                 h->Halt = true;\r
4797         }\r
4798 \r
4799         h->Offline = old_status;\r
4800         h->HubIsOnlineButHalting = false;\r
4801 }\r
4802 \r
4803 // HUB をオンラインにする\r
4804 void SetHubOnline(HUB *h)\r
4805 {\r
4806         bool for_cluster = false;\r
4807         // 引数チェック\r
4808         if (h == NULL)\r
4809         {\r
4810                 return;\r
4811         }\r
4812 \r
4813         if (h->Cedar->Server != NULL && h->Cedar->Server->ServerType == SERVER_TYPE_FARM_CONTROLLER)\r
4814         {\r
4815                 if (h->Type == HUB_TYPE_FARM_DYNAMIC)\r
4816                 {\r
4817                         for_cluster = true;\r
4818                 }\r
4819         }\r
4820 \r
4821         Lock(h->lock_online);\r
4822         {\r
4823                 if (h->Offline == false)\r
4824                 {\r
4825                         Unlock(h->lock_online);\r
4826                         return;\r
4827                 }\r
4828                 HLog(h, "LH_ONLINE");\r
4829 \r
4830                 // すべてのリンクを開始\r
4831                 StartAllLink(h);\r
4832 \r
4833                 // SecureNAT を開始\r
4834                 if (h->EnableSecureNAT)\r
4835                 {\r
4836                         if (h->SecureNAT == NULL)\r
4837                         {\r
4838                                 if (for_cluster == false)\r
4839                                 {\r
4840                                         h->SecureNAT = SnNewSecureNAT(h, h->SecureNATOption);\r
4841                                 }\r
4842                         }\r
4843                 }\r
4844 \r
4845                 // この HUB に関連付けられているローカルブリッジをすべて開始する\r
4846                 if (h->Type != HUB_TYPE_FARM_DYNAMIC)\r
4847                 {\r
4848                         LockList(h->Cedar->LocalBridgeList);\r
4849                         {\r
4850                                 UINT i;\r
4851                                 for (i = 0;i < LIST_NUM(h->Cedar->LocalBridgeList);i++)\r
4852                                 {\r
4853                                         LOCALBRIDGE *br = LIST_DATA(h->Cedar->LocalBridgeList, i);\r
4854 \r
4855                                         if (StrCmpi(br->HubName, h->Name) == 0)\r
4856                                         {\r
4857                                                 if (br->Bridge == NULL)\r
4858                                                 {\r
4859                                                         br->Bridge = BrNewBridge(h, br->DeviceName, NULL, br->Local, br->Monitor,\r
4860                                                                 br->TapMode, br->TapMacAddress, br->FullBroadcast);\r
4861                                                 }\r
4862                                         }\r
4863                                 }\r
4864                         }\r
4865                         UnlockList(h->Cedar->LocalBridgeList);\r
4866                 }\r
4867 \r
4868                 h->Offline = false;\r
4869         }\r
4870         Unlock(h->lock_online);\r
4871 \r
4872         if (h->Cedar->Server != NULL)\r
4873         {\r
4874                 SiHubOnlineProc(h);\r
4875         }\r
4876 }\r
4877 \r
4878 // HUB をオフラインにする\r
4879 void SetHubOffline(HUB *h)\r
4880 {\r
4881         UINT i;\r
4882         bool for_cluster = false;\r
4883         // 引数チェック\r
4884         if (h == NULL)\r
4885         {\r
4886                 return;\r
4887         }\r
4888 \r
4889         if (h->Cedar->Server != NULL && h->Cedar->Server->ServerType == SERVER_TYPE_FARM_CONTROLLER)\r
4890         {\r
4891                 if (h->Type == HUB_TYPE_FARM_DYNAMIC)\r
4892                 {\r
4893                         for_cluster = true;\r
4894                 }\r
4895         }\r
4896 \r
4897         h->BeingOffline = true;\r
4898 \r
4899         Lock(h->lock_online);\r
4900         {\r
4901                 if (h->Offline || h->Halt)\r
4902                 {\r
4903                         Unlock(h->lock_online);\r
4904                         h->BeingOffline = false;\r
4905                         return;\r
4906                 }\r
4907 \r
4908                 HLog(h, "LH_OFFLINE");\r
4909 \r
4910                 // すべてのリンクを停止\r
4911                 StopAllLink(h);\r
4912 \r
4913                 // SecureNAT を停止\r
4914                 SnFreeSecureNAT(h->SecureNAT);\r
4915                 h->SecureNAT = NULL;\r
4916 \r
4917                 // この HUB に関連付けられているローカルブリッジをすべて停止する\r
4918                 LockList(h->Cedar->LocalBridgeList);\r
4919                 {\r
4920                         for (i = 0;i < LIST_NUM(h->Cedar->LocalBridgeList);i++)\r
4921                         {\r
4922                                 LOCALBRIDGE *br = LIST_DATA(h->Cedar->LocalBridgeList, i);\r
4923 \r
4924                                 if (StrCmpi(br->HubName, h->Name) == 0)\r
4925                                 {\r
4926                                         BrFreeBridge(br->Bridge);\r
4927                                         br->Bridge = NULL;\r
4928                                 }\r
4929                         }\r
4930                 }\r
4931                 UnlockList(h->Cedar->LocalBridgeList);\r
4932 \r
4933                 // オフラインにする\r
4934                 h->Offline = true;\r
4935 \r
4936                 // すべてのセッションを切断する\r
4937                 StopAllSession(h);\r
4938         }\r
4939         Unlock(h->lock_online);\r
4940 \r
4941         h->BeingOffline = false;\r
4942 \r
4943         if (h->Cedar->Server != NULL)\r
4944         {\r
4945                 SiHubOfflineProc(h);\r
4946         }\r
4947 }\r
4948 \r
4949 // 指定された名前の HUB が存在するかどうか取得\r
4950 bool IsHub(CEDAR *cedar, char *name)\r
4951 {\r
4952         HUB *h;\r
4953         // 引数チェック\r
4954         if (cedar == NULL || name == NULL)\r
4955         {\r
4956                 return false;\r
4957         }\r
4958 \r
4959         h = GetHub(cedar, name);\r
4960         if (h == NULL)\r
4961         {\r
4962                 return false;\r
4963         }\r
4964 \r
4965         ReleaseHub(h);\r
4966 \r
4967         return true;\r
4968 }\r
4969 \r
4970 // HUB の取得\r
4971 HUB *GetHub(CEDAR *cedar, char *name)\r
4972 {\r
4973         HUB *h, t;\r
4974         // 引数チェック\r
4975         if (cedar == NULL || name == NULL)\r
4976         {\r
4977                 return NULL;\r
4978         }\r
4979 \r
4980         LockHubList(cedar);\r
4981 \r
4982         t.Name = name;\r
4983         h = Search(cedar->HubList, &t);\r
4984         if (h == NULL)\r
4985         {\r
4986                 UnlockHubList(cedar);\r
4987                 return NULL;\r
4988         }\r
4989 \r
4990         AddRef(h->ref);\r
4991 \r
4992         UnlockHubList(cedar);\r
4993 \r
4994         return h;\r
4995 }\r
4996 \r
4997 // HUB リストのロック\r
4998 void LockHubList(CEDAR *cedar)\r
4999 {\r
5000         // 引数チェック\r
5001         if (cedar == NULL)\r
5002         {\r
5003                 return;\r
5004         }\r
5005 \r
5006         LockList(cedar->HubList);\r
5007 }\r
5008 \r
5009 // HUB リストのロック解除\r
5010 void UnlockHubList(CEDAR *cedar)\r
5011 {\r
5012         // 引数チェック\r
5013         if (cedar == NULL)\r
5014         {\r
5015                 return;\r
5016         }\r
5017 \r
5018         UnlockList(cedar->HubList);\r
5019 }\r
5020 \r
5021 // HUB の解放\r
5022 void ReleaseHub(HUB *h)\r
5023 {\r
5024         // 引数チェック\r
5025         if (h == NULL)\r
5026         {\r
5027                 return;\r
5028         }\r
5029 \r
5030         if (Release(h->ref) == 0)\r
5031         {\r
5032                 CleanupHub(h);\r
5033         }\r
5034 }\r
5035 \r
5036 // Radius サーバー情報を取得\r
5037 bool GetRadiusServer(HUB *hub, char *name, UINT size, UINT *port, char *secret, UINT secret_size)\r
5038 {\r
5039         UINT interval;\r
5040         return GetRadiusServerEx(hub, name, size, port, secret, secret_size, &interval);\r
5041 }\r
5042 bool GetRadiusServerEx(HUB *hub, char *name, UINT size, UINT *port, char *secret, UINT secret_size, UINT *interval)\r
5043 {\r
5044         bool ret = false;\r
5045         // 引数チェック\r
5046         if (hub == NULL || name == NULL || port == NULL || secret == NULL || interval == NULL)\r
5047         {\r
5048                 return false;\r
5049         }\r
5050 \r
5051         Lock(hub->RadiusOptionLock);\r
5052         {\r
5053                 if (hub->RadiusServerName != NULL)\r
5054                 {\r
5055                         char *tmp;\r
5056                         UINT tmp_size;\r
5057                         StrCpy(name, size, hub->RadiusServerName);\r
5058                         *port = hub->RadiusServerPort;\r
5059                         *interval = hub->RadiusRetryInterval;\r
5060 \r
5061                         tmp_size = hub->RadiusSecret->Size + 1;\r
5062                         tmp = ZeroMalloc(tmp_size);\r
5063                         Copy(tmp, hub->RadiusSecret->Buf, hub->RadiusSecret->Size);\r
5064                         StrCpy(secret, secret_size, tmp);\r
5065                         Free(tmp);\r
5066 \r
5067                         ret = true;\r
5068                 }\r
5069         }\r
5070         Unlock(hub->RadiusOptionLock);\r
5071 \r
5072         return ret;\r
5073 }\r
5074 \r
5075 // Radius サーバー情報を設定\r
5076 void SetRadiusServer(HUB *hub, char *name, UINT port, char *secret)\r
5077 {\r
5078         SetRadiusServerEx(hub, name, port, secret, RADIUS_RETRY_INTERVAL);\r
5079 }\r
5080 void SetRadiusServerEx(HUB *hub, char *name, UINT port, char *secret, UINT interval)\r
5081 {\r
5082         // 引数チェック\r
5083         if (hub == NULL)\r
5084         {\r
5085                 return;\r
5086         }\r
5087 \r
5088         Lock(hub->RadiusOptionLock);\r
5089         {\r
5090                 if (hub->RadiusServerName != NULL)\r
5091                 {\r
5092                         Free(hub->RadiusServerName);\r
5093                 }\r
5094 \r
5095                 if (name == NULL)\r
5096                 {\r
5097                         hub->RadiusServerName = NULL;\r
5098                         hub->RadiusServerPort = 0;\r
5099                         hub->RadiusRetryInterval = RADIUS_RETRY_INTERVAL;\r
5100                         FreeBuf(hub->RadiusSecret);\r
5101                 }\r
5102                 else\r
5103                 {\r
5104                         hub->RadiusServerName = CopyStr(name);\r
5105                         hub->RadiusServerPort = port;\r
5106                         if (interval == 0)\r
5107                         {\r
5108                                 hub->RadiusRetryInterval = RADIUS_RETRY_INTERVAL;\r
5109                         }\r
5110                         else if (interval > RADIUS_RETRY_TIMEOUT)\r
5111                         {\r
5112                                 hub->RadiusRetryInterval = RADIUS_RETRY_TIMEOUT;\r
5113                         }\r
5114                         else\r
5115                         {\r
5116                                 hub->RadiusRetryInterval = interval;\r
5117                         }\r
5118                         FreeBuf(hub->RadiusSecret);\r
5119 \r
5120                         if (secret == NULL)\r
5121                         {\r
5122                                 hub->RadiusSecret = NewBuf();\r
5123                         }\r
5124                         else\r
5125                         {\r
5126                                 hub->RadiusSecret = NewBuf();\r
5127                                 WriteBuf(hub->RadiusSecret, secret, StrLen(secret));\r
5128                                 SeekBuf(hub->RadiusSecret, 0, 0);\r
5129                         }\r
5130                 }\r
5131         }\r
5132         Unlock(hub->RadiusOptionLock);\r
5133 }\r
5134 \r
5135 // 仮想 HUB のトラフィック情報の追加\r
5136 void IncrementHubTraffic(HUB *h)\r
5137 {\r
5138         TRAFFIC t;\r
5139         // 引数チェック\r
5140         if (h == NULL || h->FarmMember == false)\r
5141         {\r
5142                 return;\r
5143         }\r
5144 \r
5145         Zero(&t, sizeof(t));\r
5146 \r
5147         Lock(h->TrafficLock);\r
5148         {\r
5149                 t.Send.BroadcastBytes =\r
5150                         h->Traffic->Send.BroadcastBytes - h->OldTraffic->Send.BroadcastBytes;\r
5151                 t.Send.BroadcastCount =\r
5152                         h->Traffic->Send.BroadcastCount - h->OldTraffic->Send.BroadcastCount;\r
5153                 t.Send.UnicastBytes =\r
5154                         h->Traffic->Send.UnicastBytes - h->OldTraffic->Send.UnicastBytes;\r
5155                 t.Send.UnicastCount =\r
5156                         h->Traffic->Send.UnicastCount - h->OldTraffic->Send.UnicastCount;\r
5157                 t.Recv.BroadcastBytes =\r
5158                         h->Traffic->Recv.BroadcastBytes - h->OldTraffic->Recv.BroadcastBytes;\r
5159                 t.Recv.BroadcastCount =\r
5160                         h->Traffic->Recv.BroadcastCount - h->OldTraffic->Recv.BroadcastCount;\r
5161                 t.Recv.UnicastBytes =\r
5162                         h->Traffic->Recv.UnicastBytes - h->OldTraffic->Recv.UnicastBytes;\r
5163                 t.Recv.UnicastCount =\r
5164                         h->Traffic->Recv.UnicastCount - h->OldTraffic->Recv.UnicastCount;\r
5165                 Copy(h->OldTraffic, h->Traffic, sizeof(TRAFFIC));\r
5166         }\r
5167         Unlock(h->TrafficLock);\r
5168 \r
5169         if (IsZero(&t, sizeof(TRAFFIC)))\r
5170         {\r
5171                 return;\r
5172         }\r
5173 \r
5174         AddTrafficDiff(h, h->Name, TRAFFIC_DIFF_HUB, &t);\r
5175 }\r
5176 \r
5177 // トラフィック情報の追加\r
5178 void AddTrafficDiff(HUB *h, char *name, UINT type, TRAFFIC *traffic)\r
5179 {\r
5180         TRAFFIC_DIFF *d;\r
5181         // 引数チェック\r
5182         if (h == NULL || h->FarmMember == false || name == NULL || traffic == NULL)\r
5183         {\r
5184                 return;\r
5185         }\r
5186 \r
5187         if (LIST_NUM(h->Cedar->TrafficDiffList) > MAX_TRAFFIC_DIFF)\r
5188         {\r
5189                 return;\r
5190         }\r
5191 \r
5192         d = ZeroMallocFast(sizeof(TRAFFIC_DIFF));\r
5193         d->HubName = CopyStr(h->Name);\r
5194         d->Name = CopyStr(name);\r
5195         d->Type = type;\r
5196         Copy(&d->Traffic, traffic, sizeof(TRAFFIC));\r
5197 \r
5198         LockList(h->Cedar->TrafficDiffList);\r
5199         {\r
5200                 Insert(h->Cedar->TrafficDiffList, d);\r
5201         }\r
5202         UnlockList(h->Cedar->TrafficDiffList);\r
5203 }\r
5204 \r
5205 // HUB のクリーンアップ\r
5206 void CleanupHub(HUB *h)\r
5207 {\r
5208         UINT i;\r
5209         char name[MAX_SIZE];\r
5210         // 引数チェック\r
5211         if (h == NULL)\r
5212         {\r
5213                 return;\r
5214         }\r
5215 \r
5216         StrCpy(name, sizeof(name), h->Name);\r
5217 \r
5218         if (h->WatchDogStarted)\r
5219         {\r
5220                 StopHubWatchDog(h);\r
5221         }\r
5222 \r
5223         FreeAccessList(h);\r
5224 \r
5225         if (h->RadiusServerName != NULL)\r
5226         {\r
5227                 Free(h->RadiusServerName);\r
5228                 FreeBuf(h->RadiusSecret);\r
5229         }\r
5230         ReleaseAllLink(h);\r
5231         DeleteHubDb(h->HubDb);\r
5232         ReleaseCedar(h->Cedar);\r
5233         DeleteLock(h->lock);\r
5234         DeleteLock(h->lock_online);\r
5235         Free(h->Name);\r
5236         ReleaseList(h->SessionList);\r
5237         ReleaseList(h->MacTable);\r
5238         ReleaseList(h->IpTable);\r
5239         ReleaseList(h->MonitorList);\r
5240         ReleaseList(h->LinkList);\r
5241         DeleteCounter(h->NumSessions);\r
5242         DeleteCounter(h->NumSessionsClient);\r
5243         DeleteCounter(h->NumSessionsBridge);\r
5244         DeleteCounter(h->SessionCounter);\r
5245         FreeTraffic(h->Traffic);\r
5246         FreeTraffic(h->OldTraffic);\r
5247         Free(h->Option);\r
5248 \r
5249         Free(h->SecureNATOption);\r
5250 \r
5251         DeleteLock(h->TrafficLock);\r
5252 \r
5253         for (i = 0;i < LIST_NUM(h->TicketList);i++)\r
5254         {\r
5255                 Free(LIST_DATA(h->TicketList, i));\r
5256         }\r
5257 \r
5258         ReleaseList(h->TicketList);\r
5259 \r
5260         DeleteLock(h->RadiusOptionLock);\r
5261 \r
5262         FreeLog(h->PacketLogger);\r
5263         FreeLog(h->SecurityLogger);\r
5264 \r
5265         for (i = 0;i < LIST_NUM(h->AdminOptionList);i++)\r
5266         {\r
5267                 Free(LIST_DATA(h->AdminOptionList, i));\r
5268         }\r
5269         ReleaseList(h->AdminOptionList);\r
5270 \r
5271         if (h->Msg != NULL)\r
5272         {\r
5273                 Free(h->Msg);\r
5274         }\r
5275 \r
5276         Free(h);\r
5277 }\r
5278 \r
5279 // IP テーブルの比較関数\r
5280 int CompareIpTable(void *p1, void *p2)\r
5281 {\r
5282         IP_TABLE_ENTRY *e1, *e2;\r
5283         if (p1 == NULL || p2 == NULL)\r
5284         {\r
5285                 return 0;\r
5286         }\r
5287         e1 = *(IP_TABLE_ENTRY **)p1;\r
5288         e2 = *(IP_TABLE_ENTRY **)p2;\r
5289         if (e1 == NULL || e2 == NULL)\r
5290         {\r
5291                 return 0;\r
5292         }\r
5293         return CmpIpAddr(&e1->Ip, &e2->Ip);\r
5294 }\r
5295 \r
5296 // MAC テーブルの比較関数\r
5297 int CompareMacTable(void *p1, void *p2)\r
5298 {\r
5299         int r;\r
5300         MAC_TABLE_ENTRY *e1, *e2;\r
5301         if (p1 == NULL || p2 == NULL)\r
5302         {\r
5303                 return 0;\r
5304         }\r
5305         e1 = *(MAC_TABLE_ENTRY **)p1;\r
5306         e2 = *(MAC_TABLE_ENTRY **)p2;\r
5307         if (e1 == NULL || e2 == NULL)\r
5308         {\r
5309                 return 0;\r
5310         }\r
5311         r = Cmp(e1->MacAddress, e2->MacAddress, 6);\r
5312         if (r != 0)\r
5313         {\r
5314                 return r;\r
5315         }\r
5316         if (e1->VlanId > e2->VlanId)\r
5317         {\r
5318                 return 1;\r
5319         }\r
5320         else if (e1->VlanId < e2->VlanId)\r
5321         {\r
5322                 return -1;\r
5323         }\r
5324         return 0;\r
5325 }\r
5326 \r
5327 // HUB の比較関数\r
5328 int CompareHub(void *p1, void *p2)\r
5329 {\r
5330         HUB *h1, *h2;\r
5331         if (p1 == NULL || p2 == NULL)\r
5332         {\r
5333                 return 0;\r
5334         }\r
5335         h1 = *(HUB **)p1;\r
5336         h2 = *(HUB **)p2;\r
5337         if (h1 == NULL || h2 == NULL)\r
5338         {\r
5339                 return 0;\r
5340         }\r
5341         return StrCmpi(h1->Name, h2->Name);\r
5342 }\r
5343 \r
5344 // MAC アドレスが仮想 HUB の ARP ポーリング用の MAC アドレスかどうか調べる\r
5345 bool IsHubMacAddress(UCHAR *mac)\r
5346 {\r
5347         // 引数チェック\r
5348         if (mac == NULL)\r
5349         {\r
5350                 return false;\r
5351         }\r
5352 \r
5353         if (mac[0] == 0x00 && mac[1] == SE_HUB_MAC_ADDR_SIGN)\r
5354         {\r
5355                 return true;\r
5356         }\r
5357 \r
5358         return false;\r
5359 }\r
5360 \r
5361 // IP アドレスが仮想 HUB の ARP ポーリング用の IP アドレスかどうか調べる\r
5362 bool IsHubIpAddress32(UINT ip32)\r
5363 {\r
5364         IP ip;\r
5365 \r
5366         UINTToIP(&ip, ip32);\r
5367 \r
5368         return IsHubIpAddress(&ip);\r
5369 }\r
5370 bool IsHubIpAddress(IP *ip)\r
5371 {\r
5372         // 引数チェック\r
5373         if (ip == NULL)\r
5374         {\r
5375                 return false;\r
5376         }\r
5377 \r
5378         if (ip->addr[0] == 172 && ip->addr[1] == 31)\r
5379         {\r
5380                 if (ip->addr[2] >= 1 && ip->addr[2] <= 254)\r
5381                 {\r
5382                         if (ip->addr[3] >= 1 && ip->addr[3] <= 254)\r
5383                         {\r
5384                                 return true;\r
5385                         }\r
5386                 }\r
5387         }\r
5388 \r
5389         return false;\r
5390 }\r
5391 bool IsHubIpAddress64(IPV6_ADDR *addr)\r
5392 {\r
5393         // 引数チェック\r
5394         if (addr == NULL)\r
5395         {\r
5396                 return false;\r
5397         }\r
5398 \r
5399         if (addr->Value[0] == 0xfe && addr->Value[1] == 0x80 &&\r
5400                 addr->Value[2] == 0 &&\r
5401                 addr->Value[3] == 0 &&\r
5402                 addr->Value[4] == 0 &&\r
5403                 addr->Value[5] == 0 &&\r
5404                 addr->Value[6] == 0 &&\r
5405                 addr->Value[7] == 0 &&\r
5406                 addr->Value[8] == 0x02 && addr->Value[9] == 0xae && \r
5407                 addr->Value[11] == 0xff && addr->Value[12] == 0xfe)\r
5408         {\r
5409                 return true;\r
5410         }\r
5411 \r
5412         return false;\r
5413 }\r
5414 \r
5415 // 仮想 HUB 用 IP アドレスの生成\r
5416 void GenHubIpAddress(IP *ip, char *name)\r
5417 {\r
5418         char tmp1[MAX_SIZE];\r
5419         char tmp2[MAX_SIZE];\r
5420         UCHAR hash[SHA1_SIZE];\r
5421         // 引数チェック\r
5422         if (ip == NULL || name == NULL)\r
5423         {\r
5424                 return;\r
5425         }\r
5426 \r
5427         StrCpy(tmp1, sizeof(tmp1), name);\r
5428         Trim(tmp1);\r
5429         GenerateMachineUniqueHash(hash);\r
5430         BinToStr(tmp2, sizeof(tmp2), hash, sizeof(hash));\r
5431         StrCat(tmp2, sizeof(tmp2), tmp1);\r
5432         StrUpper(tmp2);\r
5433 \r
5434         Hash(hash, tmp2, StrLen(tmp2), true);\r
5435 \r
5436         Zero(ip, sizeof(IP));\r
5437         ip->addr[0] = 172;\r
5438         ip->addr[1] = 31;\r
5439         ip->addr[2] = hash[0] % 254 + 1;\r
5440         ip->addr[3] = hash[1] % 254 + 1;\r
5441 }\r
5442 \r
5443 // 仮想 HUB 用 MAC アドレスの生成\r
5444 void GenHubMacAddress(UCHAR *mac, char *name)\r
5445 {\r
5446         char tmp1[MAX_SIZE];\r
5447         char tmp2[MAX_SIZE];\r
5448         UCHAR hash[SHA1_SIZE];\r
5449         // 引数チェック\r
5450         if (mac == NULL || name == NULL)\r
5451         {\r
5452                 return;\r
5453         }\r
5454 \r
5455         StrCpy(tmp1, sizeof(tmp1), name);\r
5456         Trim(tmp1);\r
5457         GenerateMachineUniqueHash(hash);\r
5458         BinToStr(tmp2, sizeof(tmp2), hash, sizeof(hash));\r
5459         StrCat(tmp2, sizeof(tmp2), tmp1);\r
5460         StrUpper(tmp2);\r
5461 \r
5462         Hash(hash, tmp2, StrLen(tmp2), true);\r
5463 \r
5464         mac[0] = 0x00;\r
5465         mac[1] = SE_HUB_MAC_ADDR_SIGN;\r
5466         mac[2] = hash[0];\r
5467         mac[3] = hash[1];\r
5468         mac[4] = hash[2];\r
5469         mac[5] = hash[3];\r
5470 }\r
5471 \r
5472 // HUB からメッセージを取得\r
5473 wchar_t *GetHubMsg(HUB *h)\r
5474 {\r
5475         wchar_t *ret = NULL;\r
5476         // 引数チェック\r
5477         if (h == NULL)\r
5478         {\r
5479                 return NULL;\r
5480         }\r
5481 \r
5482         Lock(h->lock);\r
5483         {\r
5484                 if (h->Msg != NULL)\r
5485                 {\r
5486                         ret = CopyUniStr(h->Msg);\r
5487                 }\r
5488         }\r
5489         Unlock(h->lock);\r
5490 \r
5491         return ret;\r
5492 }\r
5493 \r
5494 // HUB にメッセージを設定\r
5495 void SetHubMsg(HUB *h, wchar_t *msg)\r
5496 {\r
5497         // 引数チェック\r
5498         if (h == NULL)\r
5499         {\r
5500                 return;\r
5501         }\r
5502 \r
5503         Lock(h->lock);\r
5504         {\r
5505                 if (h->Msg != NULL)\r
5506                 {\r
5507                         Free(h->Msg);\r
5508                         h->Msg = NULL;\r
5509                 }\r
5510 \r
5511                 if (UniIsEmptyStr(msg) == false)\r
5512                 {\r
5513                         h->Msg = UniCopyStr(msg);\r
5514                 }\r
5515         }\r
5516         Unlock(h->lock);\r
5517 }\r
5518 \r
5519 // 新しい HUB の作成\r
5520 HUB *NewHub(CEDAR *cedar, char *HubName, HUB_OPTION *option)\r
5521 {\r
5522         HUB *h;\r
5523         char packet_logger_name[MAX_SIZE];\r
5524         char tmp[MAX_SIZE];\r
5525         char safe_hub_name[MAX_HUBNAME_LEN + 1];\r
5526         UCHAR hash[SHA1_SIZE];\r
5527         IP ip6;\r
5528         // 引数チェック\r
5529         if (cedar == NULL || option == NULL || HubName == NULL)\r
5530         {\r
5531                 return NULL;\r
5532         }\r
5533 \r
5534         h = ZeroMalloc(sizeof(HUB));\r
5535         Hash(h->HashedPassword, "", 0, true);\r
5536         HashPassword(h->SecurePassword, ADMINISTRATOR_USERNAME, "");\r
5537         h->lock = NewLock();\r
5538         h->lock_online = NewLock();\r
5539         h->ref = NewRef();\r
5540         h->Cedar = cedar;\r
5541         AddRef(h->Cedar->ref);\r
5542         h->Type = HUB_TYPE_STANDALONE;\r
5543 \r
5544         ConvertSafeFileName(safe_hub_name, sizeof(safe_hub_name), HubName);\r
5545         h->Name = CopyStr(safe_hub_name);\r
5546 \r
5547         h->AdminOptionList = NewList(CompareAdminOption);\r
5548         AddHubAdminOptionsDefaults(h, true);\r
5549 \r
5550         h->LastCommTime = SystemTime64();\r
5551         h->LastLoginTime = SystemTime64();\r
5552         h->NumLogin = 0;\r
5553 \r
5554         h->TrafficLock = NewLock();\r
5555 \r
5556         h->HubDb = NewHubDb();\r
5557 \r
5558         h->SessionList = NewList(NULL);\r
5559         h->SessionCounter = NewCounter();\r
5560         h->NumSessions = NewCounter();\r
5561         h->NumSessionsClient = NewCounter();\r
5562         h->NumSessionsBridge = NewCounter();\r
5563         h->MacTable = NewList(CompareMacTable);\r
5564         h->IpTable = NewList(CompareIpTable);\r
5565         h->MonitorList = NewList(NULL);\r
5566         h->LinkList = NewList(NULL);\r
5567 \r
5568         h->Traffic = NewTraffic();\r
5569         h->OldTraffic = NewTraffic();\r
5570 \r
5571         h->Option = ZeroMalloc(sizeof(HUB_OPTION));\r
5572         Copy(h->Option, option, sizeof(HUB_OPTION));\r
5573 \r
5574         if (h->Option->VlanTypeId == 0)\r
5575         {\r
5576                 h->Option->VlanTypeId = MAC_PROTO_TAGVLAN;\r
5577         }\r
5578 \r
5579         Rand(h->HubSignature, sizeof(h->HubSignature));\r
5580 \r
5581         // SecureNAT 関係\r
5582         h->EnableSecureNAT = false;\r
5583         h->SecureNAT = NULL;\r
5584         h->SecureNATOption = ZeroMalloc(sizeof(VH_OPTION));\r
5585         NiSetDefaultVhOption(NULL, h->SecureNATOption);\r
5586 \r
5587         if (h->Cedar != NULL && h->Cedar->Server != NULL && h->Cedar->Server->ServerType == SERVER_TYPE_FARM_CONTROLLER)\r
5588         {\r
5589                 NiClearUnsupportedVhOptionForDynamicHub(h->SecureNATOption, true);\r
5590         }\r
5591 \r
5592         // HUB 用の一時的な MAC アドレスを生成する\r
5593         GenerateMachineUniqueHash(hash);\r
5594         GenHubMacAddress(h->HubMacAddr, h->Name);\r
5595         GenHubIpAddress(&h->HubIp, h->Name);\r
5596 \r
5597         // HUB 用 IPv6 アドレス\r
5598         GenerateEui64LocalAddress(&ip6, h->HubMacAddr);\r
5599         IPToIPv6Addr(&h->HubIpV6, &ip6);\r
5600 \r
5601         h->RadiusOptionLock = NewLock();\r
5602         h->RadiusServerPort = RADIUS_DEFAULT_PORT;\r
5603 \r
5604         h->TicketList = NewList(NULL);\r
5605 \r
5606         InitAccessList(h);\r
5607 \r
5608         // デフォルトのログ設定\r
5609         h->LogSetting.SaveSecurityLog = true;\r
5610         h->LogSetting.SavePacketLog = false;\r
5611         h->LogSetting.PacketLogConfig[PACKET_LOG_TCP_CONN] =\r
5612                 h->LogSetting.PacketLogConfig[PACKET_LOG_DHCP] = PACKET_LOG_HEADER;\r
5613         h->LogSetting.SecurityLogSwitchType = LOG_SWITCH_DAY;\r
5614         h->LogSetting.PacketLogSwitchType = LOG_SWITCH_DAY;\r
5615 \r
5616         MakeDir(HUB_SECURITY_LOG_DIR_NAME);\r
5617         MakeDir(HUB_PACKET_LOG_DIR_NAME);\r
5618 \r
5619         // パケットロガーの開始\r
5620         Format(packet_logger_name, sizeof(packet_logger_name), HUB_PACKET_LOG_FILE_NAME, h->Name);\r
5621         h->PacketLogger = NewLog(packet_logger_name, HUB_PACKET_LOG_PREFIX, h->LogSetting.PacketLogSwitchType);\r
5622 \r
5623         // セキュリティロガーの開始\r
5624         Format(tmp, sizeof(tmp), HUB_SECURITY_LOG_FILE_NAME, h->Name);\r
5625         h->SecurityLogger = NewLog(tmp, HUB_SECURITY_LOG_PREFIX, h->LogSetting.SecurityLogSwitchType);\r
5626 \r
5627         if (h->Cedar->Server != NULL && h->Cedar->Server->ServerType == SERVER_TYPE_FARM_MEMBER)\r
5628         {\r
5629                 h->FarmMember = true;\r
5630         }\r
5631 \r
5632         // HUB の開始\r
5633         SetHubOnline(h);\r
5634 \r
5635         if (h->Cedar->Bridge)\r
5636         {\r
5637                 h->Option->NoArpPolling = true;\r
5638         }\r
5639 \r
5640         if (h->Option->NoArpPolling == false && h->Option->NoIpTable == false)\r
5641         {\r
5642                 StartHubWatchDog(h);\r
5643                 h->WatchDogStarted = true;\r
5644         }\r
5645 \r
5646         SLog(h->Cedar, "LS_HUB_START", h->Name);\r
5647 \r
5648         MacToStr(tmp, sizeof(tmp), h->HubMacAddr);\r
5649         SLog(h->Cedar, "LS_HUB_MAC", h->Name, tmp);\r
5650 \r
5651         return h;\r
5652 }\r
5653 \r
5654 // HUBDB の削除\r
5655 void DeleteHubDb(HUBDB *d)\r
5656 {\r
5657         // 引数チェック\r
5658         if (d == NULL)\r
5659         {\r
5660                 return;\r
5661         }\r
5662 \r
5663         LockList(d->UserList);\r
5664         {\r
5665                 LockList(d->GroupList);\r
5666                 {\r
5667                         // すべてのユーザーとグループを解放\r
5668                         UINT i;\r
5669                         USER **users;\r
5670                         USERGROUP **groups;\r
5671 \r
5672                         users = ToArray(d->UserList);\r
5673                         groups = ToArray(d->GroupList);\r
5674 \r
5675                         for (i = 0;i < LIST_NUM(d->UserList);i++)\r
5676                         {\r
5677                                 ReleaseUser(users[i]);\r
5678                         }\r
5679                         for (i = 0;i < LIST_NUM(d->GroupList);i++)\r
5680                         {\r
5681                                 ReleaseGroup(groups[i]);\r
5682                         }\r
5683 \r
5684                         Free(users);\r
5685                         Free(groups);\r
5686                 }\r
5687                 UnlockList(d->GroupList);\r
5688         }\r
5689         UnlockList(d->UserList);\r
5690 \r
5691         // ルート証明書一覧を解放\r
5692         LockList(d->RootCertList);\r
5693         {\r
5694                 UINT i;\r
5695                 for (i = 0;i < LIST_NUM(d->RootCertList);i++)\r
5696                 {\r
5697                         X *x = LIST_DATA(d->RootCertList, i);\r
5698                         FreeX(x);\r
5699                 }\r
5700         }\r
5701         UnlockList(d->RootCertList);\r
5702 \r
5703         // CRL を解放\r
5704         LockList(d->CrlList);\r
5705         {\r
5706                 UINT i;\r
5707                 for (i = 0;i < LIST_NUM(d->CrlList);i++)\r
5708                 {\r
5709                         CRL *crl = LIST_DATA(d->CrlList, i);\r
5710                         FreeCrl(crl);\r
5711                 }\r
5712         }\r
5713         UnlockList(d->CrlList);\r
5714 \r
5715         ReleaseList(d->GroupList);\r
5716         ReleaseList(d->UserList);\r
5717         ReleaseList(d->RootCertList);\r
5718         ReleaseList(d->CrlList);\r
5719         Free(d);\r
5720 }\r
5721 \r
5722 // HUB のログ設定を取得する\r
5723 void GetHubLogSetting(HUB *h, HUB_LOG *setting)\r
5724 {\r
5725         // 引数チェック\r
5726         if (setting == NULL || h == NULL)\r
5727         {\r
5728                 return;\r
5729         }\r
5730 \r
5731         Copy(setting, &h->LogSetting, sizeof(HUB_LOG));\r
5732 }\r
5733 \r
5734 // HUB のログ設定を更新する\r
5735 void SetHubLogSettingEx(HUB *h, HUB_LOG *setting, bool no_change_switch_type)\r
5736 {\r
5737         UINT i1, i2;\r
5738         // 引数チェック\r
5739         if (setting == NULL || h == NULL)\r
5740         {\r
5741                 return;\r
5742         }\r
5743 \r
5744         i1 = h->LogSetting.PacketLogSwitchType;\r
5745         i2 = h->LogSetting.SecurityLogSwitchType;\r
5746 \r
5747         Copy(&h->LogSetting, setting, sizeof(HUB_LOG));\r
5748 \r
5749         if (no_change_switch_type)\r
5750         {\r
5751                 h->LogSetting.PacketLogSwitchType = i1;\r
5752                 h->LogSetting.SecurityLogSwitchType = i2;\r
5753         }\r
5754 \r
5755         // パケットロガー設定\r
5756         SetLogSwitchType(h->PacketLogger, setting->PacketLogSwitchType);\r
5757         SetLogSwitchType(h->SecurityLogger, setting->SecurityLogSwitchType);\r
5758 }\r
5759 void SetHubLogSetting(HUB *h, HUB_LOG *setting)\r
5760 {\r
5761         SetHubLogSettingEx(h, setting, false);\r
5762 }\r
5763 \r
5764 // HUB に信頼するルート証明書を追加する\r
5765 void AddRootCert(HUB *hub, X *x)\r
5766 {\r
5767         HUBDB *db;\r
5768         // 引数チェック\r
5769         if (hub == NULL || x == NULL)\r
5770         {\r
5771                 return;\r
5772         }\r
5773 \r
5774         db = hub->HubDb;\r
5775         if (db != NULL)\r
5776         {\r
5777                 LockList(db->RootCertList);\r
5778                 {\r
5779                         if (LIST_NUM(db->RootCertList) < MAX_HUB_CERTS)\r
5780                         {\r
5781                                 UINT i;\r
5782                                 bool ok = true;\r
5783 \r
5784                                 for (i = 0;i < LIST_NUM(db->RootCertList);i++)\r
5785                                 {\r
5786                                         X *exist_x = LIST_DATA(db->RootCertList, i);\r
5787                                         if (CompareX(exist_x, x))\r
5788                                         {\r
5789                                                 ok = false;\r
5790                                                 break;\r
5791                                         }\r
5792                                 }\r
5793 \r
5794                                 if (ok)\r
5795                                 {\r
5796                                         Insert(db->RootCertList, CloneX(x));\r
5797                                 }\r
5798                         }\r
5799                 }\r
5800                 UnlockList(db->RootCertList);\r
5801         }\r
5802 }\r
5803 \r
5804 // 証明書リストの比較\r
5805 int CompareCert(void *p1, void *p2)\r
5806 {\r
5807         X *x1, *x2;\r
5808         wchar_t tmp1[MAX_SIZE];\r
5809         wchar_t tmp2[MAX_SIZE];\r
5810         if (p1 == NULL || p2 == NULL)\r
5811         {\r
5812                 return 0;\r
5813         }\r
5814         x1 = *(X **)p1;\r
5815         x2 = *(X **)p2;\r
5816         if (x1 == NULL || x2 == NULL)\r
5817         {\r
5818                 return 0;\r
5819         }\r
5820 \r
5821         GetPrintNameFromX(tmp1, sizeof(tmp1), x1);\r
5822         GetPrintNameFromX(tmp2, sizeof(tmp2), x2);\r
5823 \r
5824         return UniStrCmpi(tmp1, tmp2);\r
5825 }\r
5826 \r
5827 // 新しい HUBDB の作成\r
5828 HUBDB *NewHubDb()\r
5829 {\r
5830         HUBDB *d = ZeroMalloc(sizeof(HUBDB));\r
5831 \r
5832         d->GroupList = NewList(CompareGroupName);\r
5833         d->UserList = NewList(CompareUserName);\r
5834         d->RootCertList = NewList(CompareCert);\r
5835         d->CrlList = NewList(NULL);\r
5836 \r
5837         return d;\r
5838 }\r
5839 \r
5840 \r