1 // SoftEther UT-VPN SourceCode
\r
3 // Copyright (C) 2004-2010 SoftEther Corporation.
\r
4 // Copyright (C) 2004-2010 University of Tsukuba, Japan.
\r
5 // Copyright (C) 2003-2010 Daiyuu Nobori.
\r
6 // All Rights Reserved.
\r
8 // http://utvpn.tsukuba.ac.jp/
\r
10 // This program is free software; you can redistribute it and/or
\r
11 // modify it under the terms of the GNU General Public License
\r
12 // version 2 as published by the Free Software Foundation.
\r
14 // This program is distributed in the hope that it will be useful,
\r
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
17 // GNU General Public License for more details.
\r
19 // You should have received a copy of the GNU General Public License version 2
\r
20 // along with this program; if not, write to the Free Software
\r
21 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
\r
23 // このファイルは GPL バージョン 2 ライセンスで公開されています。
\r
24 // 誰でもこのファイルの内容を複製、改変したり、改変したバージョンを再配布
\r
25 // することができます。ただし、原著作物を改変した場合は、原著作物の著作権表示
\r
26 // を除去することはできません。改変した著作物を配布する場合は、改変実施者の
\r
27 // 著作権表示を原著作物の著作権表示に付随して記載するようにしてください。
\r
29 // この SoftEther UT-VPN オープンソース・プロジェクトは、日本国の
\r
30 // ソフトイーサ株式会社 (SoftEther Corporation, http://www.softether.co.jp/ )
\r
31 // および筑波大学 (University of Tsukuba, http://www.tsukuba.ac.jp/ ) によって
\r
33 // 本プログラムの配布者は、本プログラムを、業としての利用以外のため、
\r
34 // および、試験または研究のために利用が行われることを想定して配布
\r
36 // SoftEther UT-VPN プロジェクトの Web サイトは http://utvpn.tsukuba.ac.jp/ に
\r
38 // 本ソフトウェアの不具合の修正、機能改良、セキュリティホールの修復などのコード
\r
39 // の改変を行った場合で、その成果物を SoftEther UT-VPN プロジェクトに提出して
\r
40 // いただける場合は、 http://utvpn.tsukuba.ac.jp/ までソースコードを送付して
\r
41 // ください。SoftEther UT-VPN プロジェクトの本体リリースまたはブランチリリース
\r
44 // GPL に基づいて原著作物が提供される本ソフトウェアの改良版を配布、販売する
\r
45 // 場合は、そのソースコードを GPL に基づいて誰にでも開示する義務が生じます。
\r
47 // 本ソフトウェアに関連する著作権、特許権、商標権はソフトイーサ株式会社
\r
48 // (SoftEther Corporation) およびその他の著作権保持者が保有しています。
\r
49 // ソフトイーサ株式会社等はこれらの権利を放棄していません。本ソフトウェアの
\r
50 // 二次著作物を配布、販売する場合は、これらの権利を侵害しないようにご注意
\r
53 // お願い: どのような通信ソフトウェアにも通常は必ず未発見の
\r
54 // セキュリティホールが潜んでいます。本ソースコードをご覧いただいた結果、
\r
55 // UT-VPN にセキュリティホールを発見された場合は、当該セキュリティホールの
\r
56 // 情報を不特定多数に開示される前に、必ず、ソフトイーサ株式会社
\r
57 // および脆弱性情報の届出を受け付ける公的機関まで通報いただき、
\r
58 // 公益保護にご協力いただきますようお願い申し上げます。
\r
60 // ソフトイーサ株式会社は、当該セキュリティホールについて迅速に対処を
\r
61 // 行い、UT-VPN および UT-VPN に関連するソフトウェアのユーザー・顧客
\r
64 // ソフトイーサへの届出先: http://www.softether.co.jp/jp/contact/
\r
65 // 日本国内の脆弱性情報届出受付公的機関:
\r
67 // http://www.ipa.go.jp/security/vuln/report/
\r
69 // 上記各事項について不明な点は、ソフトイーサ株式会社までご連絡ください。
\r
70 // 連絡先: http://www.softether.co.jp/jp/contact/
\r
72 // -----------------------------------------------
\r
75 // 新規リリース by SoftEther
\r
76 // -----------------------------------------------
\r
81 #include "CedarPch.h"
\r
83 static UCHAR broadcast[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
\r
85 // 現在サポートされている管理オプションの一覧とデフォルト値
\r
87 ADMIN_OPTION admin_options[] =
\r
89 {"allow_hub_admin_change_option", 0},
\r
91 {"max_multilogins_per_user", 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
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
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
131 UINT num_admin_options = sizeof(admin_options) / sizeof(ADMIN_OPTION);
\r
133 // 指定されたメッセージが URL 文字列かどうか取得
\r
134 bool IsURLMsg(wchar_t *str, char *url, UINT url_size)
\r
146 t = UniParseToken(str, L"\r\n");
\r
148 for (i = 0;i < t->NumTokens;i++)
\r
150 wchar_t *str = t->Token[i];
\r
152 if (IsEmptyUniStr(str) == false)
\r
160 if (UniStartWith(str, L"http://") ||
\r
161 UniStartWith(str, L"https://") ||
\r
162 UniStartWith(str, L"ftp://"))
\r
166 UniToStr(url, url_size, str);
\r
182 // RPC_ADMIN_OPTION からデータを取得
\r
183 UINT GetHubAdminOptionData(RPC_ADMIN_OPTION *ao, char *name)
\r
187 if (ao == NULL || name == NULL)
\r
192 for (i = 0;i < ao->NumItem;i++)
\r
194 ADMIN_OPTION *a = &ao->Items[i];
\r
196 if (StrCmpi(a->Name, name) == 0)
\r
204 void GetHubAdminOptionDataAndSet(RPC_ADMIN_OPTION *ao, char *name, UINT *dest)
\r
208 if (ao == NULL || name == NULL || dest == NULL)
\r
213 value = GetHubAdminOptionData(ao, name);
\r
214 if (value == INFINITE)
\r
222 // データをもとに HUB_OPTION の内容を設定
\r
223 void DataToHubOptionStruct(HUB_OPTION *o, RPC_ADMIN_OPTION *ao)
\r
226 if (o == NULL || ao == NULL)
\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
258 // HUB_OPTION の内容をデータに変換
\r
259 void HubOptionStructToData(RPC_ADMIN_OPTION *ao, HUB_OPTION *o, char *hub_name)
\r
264 if (ao == NULL || o == NULL || hub_name == NULL)
\r
269 aol = NewListFast(NULL);
\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
297 Zero(ao, sizeof(RPC_ADMIN_OPTION));
\r
299 StrCpy(ao->HubName, sizeof(ao->HubName), hub_name);
\r
301 ao->NumItem = LIST_NUM(aol);
\r
302 ao->Items = ZeroMalloc(sizeof(ADMIN_OPTION) * ao->NumItem);
\r
304 for (i = 0;i < LIST_NUM(aol);i++)
\r
306 ADMIN_OPTION *a = LIST_DATA(aol, i);
\r
308 Copy(&ao->Items[i], a, sizeof(ADMIN_OPTION));
\r
316 // 新しい ADMIN OPTION の作成
\r
317 ADMIN_OPTION *NewAdminOption(char *name, UINT value)
\r
326 a = ZeroMalloc(sizeof(ADMIN_OPTION));
\r
327 StrCpy(a->Name, sizeof(a->Name), name);
\r
334 LIST *CloneAcList(LIST *o)
\r
350 void SetAcList(LIST *o, LIST *src)
\r
354 if (o == NULL || src == NULL)
\r
361 for (i = 0;i < LIST_NUM(src);i++)
\r
363 AC *ac = LIST_DATA(src, i);
\r
369 // AC リストからすべての AC を削除する
\r
370 void DelAllAc(LIST *o)
\r
379 for (i = 0;i < LIST_NUM(o);i++)
\r
381 AC *ac = LIST_DATA(o, i);
\r
390 void FreeAcList(LIST *o)
\r
399 for (i = 0;i < LIST_NUM(o);i++)
\r
401 AC *ac = LIST_DATA(o, i);
\r
409 // AC の内容を示す文字列を生成する
\r
410 char *GenerateAcStr(AC *ac)
\r
412 char tmp[MAX_SIZE];
\r
413 char ip[64], mask[64];
\r
420 IPToStr(ip, sizeof(ip), &ac->IpAddress);
\r
421 MaskToStr(mask, sizeof(mask), &ac->SubnetMask);
\r
423 if (ac->Masked == false)
\r
425 Format(tmp, sizeof(tmp), "%s", ip);
\r
429 Format(tmp, sizeof(tmp), "%s/%s", ip, mask);
\r
432 return CopyStr(tmp);
\r
436 void SetAc(LIST *o, UINT id, AC *ac)
\r
439 if (o == NULL || id == 0 || ac == NULL)
\r
451 AC *GetAc(LIST *o, UINT id)
\r
455 if (o == NULL || id == 0)
\r
460 for (i = 0;i < LIST_NUM(o);i++)
\r
462 AC *ac = LIST_DATA(o, i);
\r
466 return Clone(ac, sizeof(AC));
\r
474 bool DelAc(LIST *o, UINT id)
\r
478 if (o == NULL || id == 0)
\r
483 for (i = 0;i < LIST_NUM(o);i++)
\r
485 AC *ac = LIST_DATA(o, i);
\r
493 NormalizeAcList(o);
\r
504 void AddAc(LIST *o, AC *ac)
\r
507 if (o == NULL || ac == NULL)
\r
512 if (LIST_NUM(o) < MAX_HUB_ACS)
\r
514 Insert(o, Clone(ac, sizeof(AC)));
\r
516 NormalizeAcList(o);
\r
521 void NormalizeAcList(LIST *o)
\r
530 for (i = 0;i < LIST_NUM(o);i++)
\r
532 AC *ac = LIST_DATA(o, i);
\r
534 if (IsIP6(&ac->IpAddress))
\r
536 ac->IpAddress.ipv6_scope_id = 0;
\r
546 return NewList(CmpAc);
\r
550 int CmpAc(void *p1, void *p2)
\r
553 if (p1 == NULL || p2 == NULL)
\r
559 if (a1 == NULL || a2 == NULL)
\r
563 if (a1->Priority > a2->Priority)
\r
567 else if (a1->Priority < a2->Priority)
\r
571 else if (a1->Deny > a2->Deny)
\r
575 else if (a1->Deny < a2->Deny)
\r
586 CRL *CopyCrl(CRL *crl)
\r
595 ret = ZeroMalloc(sizeof(CRL));
\r
597 if (crl->Serial != NULL)
\r
599 ret->Serial = NewXSerial(crl->Serial->data, crl->Serial->size);
\r
602 ret->Name = CopyName(crl->Name);
\r
604 Copy(ret->DigestMD5, crl->DigestMD5, MD5_SIZE);
\r
605 Copy(ret->DigestSHA1, crl->DigestSHA1, SHA1_SIZE);
\r
611 void FreeCrl(CRL *crl)
\r
619 if (crl->Serial != NULL)
\r
621 FreeXSerial(crl->Serial);
\r
624 if (crl->Name != NULL)
\r
626 FreeName(crl->Name);
\r
632 // 仮想 HUB の CRL リストを検索して証明書が無効化されていないかどうか調べる
\r
633 bool IsValidCertInHub(HUB *h, X *x)
\r
637 if (h == NULL || x == NULL)
\r
642 if (h->HubDb == NULL)
\r
649 // ファイルに保存されている CRL によって無効化されている
\r
653 LockList(h->HubDb->CrlList);
\r
655 ret = IsCertMatchCrlList(x, h->HubDb->CrlList);
\r
657 UnlockList(h->HubDb->CrlList);
\r
669 // CRL リストに証明書が一致するかどうか検索
\r
670 bool IsCertMatchCrlList(X *x, LIST *o)
\r
674 if (x == NULL || o == NULL)
\r
679 for (i = 0;i < LIST_NUM(o);i++)
\r
681 CRL *crl = LIST_DATA(o, i);
\r
683 if (IsCertMatchCrl(x, crl))
\r
693 wchar_t *GenerateCrlStr(CRL *crl)
\r
702 UniStrCpy(tmp, sizeof(tmp), L"");
\r
704 if (crl->Name != NULL)
\r
707 wchar_t name[MAX_SIZE];
\r
709 UniStrCat(tmp, sizeof(tmp), L"Subject=\"");
\r
711 GetAllNameFromName(name, sizeof(name), crl->Name);
\r
712 UniStrCat(tmp, sizeof(tmp), name);
\r
713 UniStrCat(tmp, sizeof(tmp), L"\", ");
\r
716 if (crl->Serial != NULL)
\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
729 if (IsZero(crl->DigestMD5, MD5_SIZE) == false)
\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
742 if (IsZero(crl->DigestSHA1, SHA1_SIZE) == false)
\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
755 if (UniEndWith(tmp, L", "))
\r
757 tmp[UniStrLen(tmp) - 2] = 0;
\r
760 return CopyUniStr(tmp);
\r
763 // 証明書無効リストエントリに一致するかどうか検査する
\r
764 bool IsCertMatchCrl(X *x, CRL *crl)
\r
766 // このあたりは急いで実装したのでコードがあまり美しくない。
\r
769 if (x == NULL || crl == NULL)
\r
774 if (crl->Serial != NULL)
\r
776 // CRL にシリアル番号が定義されている場合
\r
777 if (x->serial == NULL || CompareXSerial(x->serial, crl->Serial) == false)
\r
784 if (IsZero(crl->DigestMD5, sizeof(crl->DigestMD5)) == false)
\r
786 UCHAR test[MD5_SIZE];
\r
787 // CRL に DigestMD5 が定義されている場合
\r
788 GetXDigest(x, test, false);
\r
790 if (Cmp(test, crl->DigestMD5, MD5_SIZE) != 0)
\r
796 if (IsZero(crl->DigestSHA1, sizeof(crl->DigestSHA1)) == false)
\r
798 UCHAR test[SHA1_SIZE];
\r
799 // CRL に DigestSHA1 が定義されている場合
\r
800 GetXDigest(x, test, true);
\r
802 if (Cmp(test, crl->DigestSHA1, SHA1_SIZE) != 0)
\r
808 if (crl->Name != NULL)
\r
810 // CRL に名前が定義されている場合
\r
812 xn = x->subject_name;
\r
815 if (cn->CommonName != NULL && (UniIsEmptyStr(cn->CommonName) == false))
\r
817 if (xn->CommonName == NULL || UniSoftStrCmp(xn->CommonName, cn->CommonName) != 0)
\r
824 if (cn->Organization != NULL && (UniIsEmptyStr(cn->Organization) == false))
\r
826 if (xn->Organization == NULL || UniSoftStrCmp(xn->Organization, cn->Organization) != 0)
\r
828 // Organization 不一致
\r
833 if (cn->Unit != NULL && (UniIsEmptyStr(cn->Unit) == false))
\r
835 if (xn->Unit == NULL || UniSoftStrCmp(xn->Unit, cn->Unit) != 0)
\r
842 if (cn->Country != NULL && (UniIsEmptyStr(cn->Country) == false))
\r
844 if (xn->Country == NULL || UniSoftStrCmp(xn->Country, cn->Country) != 0)
\r
851 if (cn->State != NULL && (UniIsEmptyStr(cn->State) == false))
\r
853 if (xn->State == NULL || UniSoftStrCmp(xn->State, cn->State) != 0)
\r
860 if (cn->Local != NULL && (UniIsEmptyStr(cn->Local) == false))
\r
862 if (xn->Local == NULL || UniSoftStrCmp(xn->Local, cn->Local) != 0)
\r
873 // 管理オプションのヘルプ文字列を取得する
\r
874 wchar_t *GetHubAdminOptionHelpString(char *name)
\r
876 char tmp[MAX_SIZE];
\r
884 Format(tmp, sizeof(tmp), "HUB_AO_%s", name);
\r
887 if (UniIsEmptyStr(ret))
\r
889 ret = _UU("HUB_AO_UNKNOWN");
\r
895 // 仮想 HUB にデフォルトの管理オプションを追加する
\r
896 void AddHubAdminOptionsDefaults(HUB *h, bool lock)
\r
907 LockList(h->AdminOptionList);
\r
910 for (i = 0;i < num_admin_options;i++)
\r
912 ADMIN_OPTION *e = &admin_options[i];
\r
913 ADMIN_OPTION t, *r;
\r
915 Zero(&t, sizeof(t));
\r
916 StrCpy(t.Name, sizeof(t.Name), e->Name);
\r
918 r = Search(h->AdminOptionList, &t);
\r
921 ADMIN_OPTION *a = ZeroMalloc(sizeof(ADMIN_OPTION));
\r
923 StrCpy(a->Name, sizeof(a->Name), e->Name);
\r
924 a->Value = e->Value;
\r
926 Insert(h->AdminOptionList, a);
\r
932 UnlockList(h->AdminOptionList);
\r
936 // 仮想 HUB のすべての管理オプションの削除
\r
937 void DeleteAllHubAdminOption(HUB *h, bool lock)
\r
948 LockList(h->AdminOptionList);
\r
951 for (i = 0;i < LIST_NUM(h->AdminOptionList);i++)
\r
953 Free(LIST_DATA(h->AdminOptionList, i));
\r
956 DeleteAll(h->AdminOptionList);
\r
960 UnlockList(h->AdminOptionList);
\r
964 // 仮想 HUB の管理オプションの取得
\r
965 UINT GetHubAdminOptionEx(HUB *h, char *name, UINT default_value)
\r
967 UINT ret = default_value;
\r
969 if (h == NULL || name == NULL)
\r
974 LockList(h->AdminOptionList);
\r
976 ADMIN_OPTION *a, t;
\r
978 Zero(&t, sizeof(t));
\r
979 StrCpy(t.Name, sizeof(t.Name), name);
\r
982 a = Search(h->AdminOptionList, &t);
\r
989 UnlockList(h->AdminOptionList);
\r
993 UINT GetHubAdminOption(HUB *h, char *name)
\r
995 return GetHubAdminOptionEx(h, name, 0);
\r
999 int CompareAdminOption(void *p1, void *p2)
\r
1001 ADMIN_OPTION *a1, *a2;
\r
1002 if (p1 == NULL || p2 == NULL)
\r
1006 a1 = *(ADMIN_OPTION **)p1;
\r
1007 a2 = *(ADMIN_OPTION **)p2;
\r
1008 if (a1 == NULL || a2 == NULL)
\r
1012 return StrCmpi(a1->Name, a2->Name);
\r
1016 void StartHubWatchDog(HUB *h)
\r
1025 h->HaltWatchDog = false;
\r
1026 h->WatchDogEvent = NewEvent();
\r
1028 t = NewThread(HubWatchDogThread, h);
\r
1029 WaitThreadInit(t);
\r
1034 void StopHubWatchDog(HUB *h)
\r
1042 h->HaltWatchDog = true;
\r
1043 Set(h->WatchDogEvent);
\r
1045 WaitThread(h->WatchDogThread, INFINITE);
\r
1046 ReleaseThread(h->WatchDogThread);
\r
1047 h->WatchDogThread = NULL;
\r
1048 h->HaltWatchDog = false;
\r
1050 ReleaseEvent(h->WatchDogEvent);
\r
1051 h->WatchDogEvent = NULL;
\r
1055 void HubWatchDogThread(THREAD *t, void *param)
\r
1057 UINT num_packets_v4 = 0;
\r
1058 UINT num_packets_v6 = 0;
\r
1061 if (t == NULL || param == NULL)
\r
1066 hub = (HUB *)param;
\r
1068 hub->WatchDogThread = t;
\r
1071 NoticeThreadInit(t);
\r
1079 UINT wait_time = 100;
\r
1080 if (hub->HaltWatchDog)
\r
1085 o = NewListFast(NULL);
\r
1086 o2 = NewListFast(NULL);
\r
1089 LockList(hub->IpTable);
\r
1091 num = LIST_NUM(hub->IpTable);
\r
1092 for (i = 0;i < LIST_NUM(hub->IpTable);i++)
\r
1094 IP_TABLE_ENTRY *e = LIST_DATA(hub->IpTable, i);
\r
1096 if ((e->UpdatedTime + (UINT64)(IP_TABLE_EXPIRE_TIME)) > Tick64())
\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
1101 if (hub->Option != NULL && hub->Option->NoArpPolling == false)
\r
1103 if (IsIP4(&e->Ip))
\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
1109 Copy(mac->DestAddress, e->MacAddress, 6);
\r
1110 Copy(mac->SrcAddress, hub->HubMacAddr, 6);
\r
1111 mac->Protocol = Endian16(MAC_PROTO_ARPV4);
\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
1131 if (hub->Option != NULL && hub->Option->NoIPv6AddrPolling == false)
\r
1133 if (IsIP6(&e->Ip))
\r
1137 IPV6_ADDR ip6addr;
\r
1139 if (IPToIPv6Addr(&ip6addr, &e->Ip))
\r
1141 buf = BuildICMPv6NeighborSoliciation(&hub->HubIpV6,
\r
1143 hub->HubMacAddr, ++hub->HubIP6Id);
\r
1147 BUF *buf2 = NewBuf();
\r
1150 Zero(&mac, sizeof(mac));
\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
1156 WriteBuf(buf2, &mac, sizeof(MAC_HEADER));
\r
1158 WriteBuf(buf2, buf->Buf, buf->Size);
\r
1171 UnlockList(hub->IpTable);
\r
1173 if ((LIST_NUM(o) + LIST_NUM(o2)) != 0)
\r
1175 interval = HUB_ARP_SEND_INTERVAL / (LIST_NUM(o) + LIST_NUM(o2));
\r
1179 interval = HUB_ARP_SEND_INTERVAL;
\r
1182 for (i = 0;i < LIST_NUM(o);i++)
\r
1185 void *p = LIST_DATA(o, i);
\r
1187 Wait(hub->WatchDogEvent, interval);
\r
1188 if (hub->HaltWatchDog)
\r
1190 for (;i < LIST_NUM(o);i++)
\r
1192 Free(LIST_DATA(o, i));
\r
1196 for (i = 0;i < LIST_NUM(o2);i++)
\r
1198 FreeBuf(LIST_DATA(o2, i));
\r
1204 packet = ParsePacket((UCHAR *)p, sizeof(MAC_HEADER) + sizeof(ARPV4_HEADER));
\r
1205 if (packet != NULL)
\r
1207 StorePacket(hub, NULL, packet);
\r
1216 for (i = 0;i < LIST_NUM(o2);i++)
\r
1219 BUF *buf = LIST_DATA(o2, i);
\r
1221 Wait(hub->WatchDogEvent, interval);
\r
1222 if (hub->HaltWatchDog)
\r
1226 for (;i < LIST_NUM(o2);i++)
\r
1228 FreeBuf(LIST_DATA(o2, i));
\r
1234 packet = ParsePacket(buf->Buf, buf->Size);
\r
1235 if (packet != NULL)
\r
1237 StorePacket(hub, NULL, packet);
\r
1253 wait_time = HUB_ARP_SEND_INTERVAL;
\r
1256 Wait(hub->WatchDogEvent, wait_time);
\r
1262 // SecureNAT を有効/無効に設定する
\r
1263 void EnableSecureNAT(HUB *h, bool enable)
\r
1265 EnableSecureNATEx(h, enable, false);
\r
1267 void EnableSecureNATEx(HUB *h, bool enable, bool no_change)
\r
1269 bool for_cluster = false;
\r
1276 if (h->Cedar->Server != NULL && h->Cedar->Server->ServerType == SERVER_TYPE_FARM_CONTROLLER)
\r
1278 if (h->Type == HUB_TYPE_FARM_DYNAMIC)
\r
1280 for_cluster = true;
\r
1284 Lock(h->lock_online);
\r
1286 if (no_change == false)
\r
1288 h->EnableSecureNAT = enable;
\r
1291 if (h->EnableSecureNAT == false)
\r
1294 // すでに開始している場合は停止する
\r
1295 if (h->SecureNAT != NULL)
\r
1297 SnFreeSecureNAT(h->SecureNAT);
\r
1298 h->SecureNAT = NULL;
\r
1305 if ((h->SecureNAT != NULL && LIST_NUM(h->SessionList) <= 1) ||
\r
1306 (h->SecureNAT == NULL && LIST_NUM(h->SessionList) == 0))
\r
1308 // 開始モードだが、ダイナミック仮想 HUB で他にセッションが無い場合
\r
1314 // まだ開始していない場合で HUB がオンラインの場合は開始する
\r
1315 if (h->SecureNAT == NULL && h->Offline == false)
\r
1317 h->SecureNAT = SnNewSecureNAT(h, h->SecureNATOption);
\r
1321 Unlock(h->lock_online);
\r
1324 // アクセスリストを文字列に変換する
\r
1325 void GetAccessListStr(char *str, UINT size, ACCESS *a)
\r
1327 char tmp[MAX_SIZE];
\r
1328 char tmp1[MAX_SIZE];
\r
1329 char tmp2[MAX_SIZE];
\r
1331 bool asterisk = false;
\r
1333 if (str == NULL || a == NULL)
\r
1338 StrCpy(str, size, "");
\r
1340 if (a->IsIPv6 == false)
\r
1342 if (a->SrcIpAddress != 0 || a->SrcSubnetMask != 0)
\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
1352 if (a->DestIpAddress != 0 || a->DestSubnetMask != 0)
\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
1364 if (IsZeroIP6Addr(&a->SrcIpAddress6) == false || IsZeroIP6Addr(&a->SrcSubnetMask6) == false)
\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
1374 if (IsZeroIP6Addr(&a->DestIpAddress6) == false || IsZeroIP6Addr(&a->DestSubnetMask6) == false)
\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
1385 if (a->Protocol != 0)
\r
1387 StrCpy(tmp1, sizeof(tmp1), "");
\r
1388 switch (a->Protocol)
\r
1391 StrCpy(tmp1, sizeof(tmp1), "ICMPv4");
\r
1394 StrCpy(tmp1, sizeof(tmp1), "GGP");
\r
1397 StrCpy(tmp1, sizeof(tmp1), "TCP");
\r
1400 StrCpy(tmp1, sizeof(tmp1), "EGP");
\r
1403 StrCpy(tmp1, sizeof(tmp1), "PUP");
\r
1406 StrCpy(tmp1, sizeof(tmp1), "UDP");
\r
1409 StrCpy(tmp1, sizeof(tmp1), "HMP");
\r
1412 StrCpy(tmp1, sizeof(tmp1), "XNS-IDP");
\r
1415 StrCpy(tmp1, sizeof(tmp1), "RDP");
\r
1418 StrCpy(tmp1, sizeof(tmp1), "ICMPv6");
\r
1421 StrCpy(tmp1, sizeof(tmp1), "RVD");
\r
1424 Format(tmp, sizeof(tmp), "Protocol=%s(%u), ", tmp1, a->Protocol);
\r
1425 StrCat(str, size, tmp);
\r
1430 if (a->SrcPortStart != 0)
\r
1432 if (a->SrcPortEnd == a->SrcPortStart)
\r
1434 Format(tmp, sizeof(tmp), "SrcPort=%u, ", a->SrcPortStart);
\r
1435 StrCat(str, size, tmp);
\r
1439 Format(tmp, sizeof(tmp), "SrcPort=%u-%u, ", a->SrcPortStart, a->SrcPortEnd);
\r
1440 StrCat(str, size, tmp);
\r
1446 if (a->DestPortStart != 0)
\r
1448 if (a->DestPortEnd == a->DestPortStart)
\r
1450 Format(tmp, sizeof(tmp), "DstPort=%u, ", a->DestPortStart);
\r
1451 StrCat(str, size, tmp);
\r
1455 Format(tmp, sizeof(tmp), "DstPort=%u-%u, ", a->DestPortStart, a->DestPortEnd);
\r
1456 StrCat(str, size, tmp);
\r
1462 if (StrLen(a->SrcUsername) != 0)
\r
1464 Format(tmp, sizeof(tmp), "SrcUser=%s, ", a->SrcUsername);
\r
1465 StrCat(str, size, tmp);
\r
1468 if (StrLen(a->DestUsername) != 0)
\r
1470 Format(tmp, sizeof(tmp), "DstUser=%s, ", a->DestUsername);
\r
1471 StrCat(str, size, tmp);
\r
1474 if (a->CheckSrcMac != false)
\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
1482 if (a->CheckDstMac != false)
\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
1491 if (a->CheckTcpState)
\r
1493 if(a->Established)
\r
1495 StrCat(str, size, "Established, ");
\r
1499 StrCat(str, size, "Unestablished, ");
\r
1505 if (a->Discard == false)
\r
1507 if (a->Delay >= 1)
\r
1509 Format(tmp, sizeof(tmp), "Delay=%u, ", a->Delay);
\r
1510 StrCat(str, size, tmp);
\r
1513 if (a->Jitter >= 1)
\r
1515 Format(tmp, sizeof(tmp), "Jitter=%u, ", a->Jitter);
\r
1516 StrCat(str, size, tmp);
\r
1521 Format(tmp, sizeof(tmp), "Loss=%u, " , a->Loss);
\r
1522 StrCat(str, size, tmp);
\r
1526 if (StrLen(str) == 0)
\r
1535 StrCatLeft(str, size, "(ipv6) ");
\r
1539 StrCatLeft(str, size, "(ipv4) ");
\r
1544 StrCatLeft(str, size, "(ether) ");
\r
1547 if (EndWith(str, ", "))
\r
1549 str[StrLen(str) - 2] = 0;
\r
1554 StrCat(str, size, "*");
\r
1558 // パケットをアクセスリストによってマスクすることができるかどうか判定する
\r
1559 bool IsPacketMaskedByAccessList(SESSION *s, PKT *p, ACCESS *a, UINT dest_username, UINT dest_groupname)
\r
1561 UINT src_username;
\r
1562 UINT src_groupname;
\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
1569 if (s == NULL || p == NULL || a == NULL)
\r
1573 if (a->Active == false)
\r
1579 pa = (HUB_PA *)s->PacketAdapter->Param;
\r
1582 src_username = pa->UsernameHash;
\r
1583 src_groupname = pa->GroupnameHash;
\r
1585 // 送信元・宛先 MAC アドレスの判定
\r
1586 if (a->CheckSrcMac != false)
\r
1589 for (i = 0; i < 6; i++)
\r
1591 if((a->SrcMacAddress[i] & a->SrcMacMask[i]) != (a->SrcMacMask[i] & p->MacAddressSrc[i]))
\r
1598 if (a->CheckDstMac != false)
\r
1601 for (i = 0; i < 6; i++)
\r
1603 if ((a->DstMacAddress[i] & a->DstMacMask[i]) != (a->DstMacMask[i] & p->MacAddressDest[i]))
\r
1610 // 送信元ユーザー名 / グループ名のチェック
\r
1611 if (a->SrcUsernameHash != 0)
\r
1613 if ((a->SrcUsernameHash != src_username) && (a->SrcUsernameHash != src_groupname))
\r
1619 // 宛先ユーザー名 / グループ名のチェック
\r
1620 if (a->DestUsernameHash != 0)
\r
1622 if ((a->DestUsernameHash != dest_username) && (a->DestUsernameHash != dest_groupname))
\r
1629 if (p->TypeL3 != L3_IPV4)
\r
1631 is_ipv4_packet = false;
\r
1635 is_ipv4_packet = true;
\r
1638 if (p->TypeL3 != L3_IPV6)
\r
1640 is_ipv6_packet = false;
\r
1644 is_ipv6_packet = true;
\r
1647 if (is_ipv4_packet)
\r
1649 ip = p->L3.IPv4Header;
\r
1652 if (is_ipv6_packet)
\r
1654 ip6 = p->L3.IPv6Header;
\r
1657 if (a->IsIPv6 == false)
\r
1661 // 送信元 IP アドレスのチェック
\r
1662 if (a->SrcIpAddress != 0 || a->SrcSubnetMask != 0)
\r
1664 if (is_ipv4_packet == false)
\r
1666 if (p->TypeL3 == L3_ARPV4)
\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
1674 UINT uint_ip = p->L3.ARPv4Header->SrcIP;
\r
1676 if (uint_ip != 0 && uint_ip != 0xffffffff && !(IsHubIpAddress32(uint_ip) && IsHubMacAddress(p->MacAddressSrc)))
\r
1678 if ((uint_ip & a->SrcSubnetMask) != (a->SrcIpAddress & a->SrcSubnetMask))
\r
1688 if (arp_match == false)
\r
1700 if ((ip->SrcIP & a->SrcSubnetMask) != (a->SrcIpAddress & a->SrcSubnetMask))
\r
1707 // 宛先 IP アドレスのチェック
\r
1708 if (a->DestIpAddress != 0 || a->DestSubnetMask != 0)
\r
1710 if (is_ipv4_packet == false)
\r
1712 if (p->TypeL3 == L3_ARPV4)
\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
1720 UINT uint_ip = p->L3.ARPv4Header->TargetIP;
\r
1722 if (uint_ip != 0 && uint_ip != 0xffffffff && !(IsHubIpAddress32(uint_ip) && IsHubMacAddress(p->MacAddressSrc)))
\r
1724 if ((uint_ip & a->DestSubnetMask) != (a->DestIpAddress & a->DestSubnetMask))
\r
1734 if (arp_match == false)
\r
1746 if ((ip->DstIP & a->DestSubnetMask) != (a->DestIpAddress & a->DestSubnetMask))
\r
1757 // 送信元 IP アドレスのチェック
\r
1758 if (IsZeroIP6Addr(&a->SrcIpAddress6) == false ||
\r
1759 IsZeroIP6Addr(&a->SrcSubnetMask6) == false)
\r
1761 if (is_ipv6_packet == false)
\r
1767 IP a_ip, a_subnet, p_ip;
\r
1770 IPv6AddrToIP(&a_ip, &a->SrcIpAddress6);
\r
1771 IPv6AddrToIP(&a_subnet, &a->SrcSubnetMask6);
\r
1772 IPv6AddrToIP(&p_ip, &ip6->SrcAddress);
\r
1774 IPAnd6(&and1, &a_ip, &a_subnet);
\r
1775 IPAnd6(&and2, &p_ip, &a_subnet);
\r
1777 if (CmpIpAddr(&and1, &and2) != 0)
\r
1784 // 宛先 IP アドレスのチェック
\r
1785 if (IsZeroIP6Addr(&a->DestIpAddress6) == false ||
\r
1786 IsZeroIP6Addr(&a->DestSubnetMask6) == false)
\r
1788 if (is_ipv6_packet == false)
\r
1794 IP a_ip, a_subnet, p_ip;
\r
1797 IPv6AddrToIP(&a_ip, &a->DestIpAddress6);
\r
1798 IPv6AddrToIP(&a_subnet, &a->DestSubnetMask6);
\r
1799 IPv6AddrToIP(&p_ip, &ip6->DestAddress);
\r
1801 IPAnd6(&and1, &a_ip, &a_subnet);
\r
1802 IPAnd6(&and2, &p_ip, &a_subnet);
\r
1804 if (CmpIpAddr(&and1, &and2) != 0)
\r
1812 // IPv4 でも IPv6 でもないパケットはマッチさせない。
\r
1813 if(is_ipv4_packet == false && is_ipv6_packet==false){
\r
1818 if (a->Protocol != 0)
\r
1820 if (a->IsIPv6 == false)
\r
1822 if (is_ipv4_packet == false)
\r
1828 if (ip->Protocol != a->Protocol)
\r
1836 if (is_ipv6_packet == false)
\r
1842 if (p->IPv6HeaderPacketInfo.Protocol != a->Protocol)
\r
1851 if (a->SrcPortStart != 0 || a->DestPortStart != 0 ||
\r
1852 a->SrcPortEnd != 0 || a->DestPortEnd != 0)
\r
1854 if ((a->IsIPv6 == false && is_ipv4_packet == false) ||
\r
1855 (a->IsIPv6 && is_ipv6_packet == false))
\r
1861 if (p->TypeL4 == L4_TCP)
\r
1863 TCP_HEADER *tcp = p->L4.TCPHeader;
\r
1865 if (a->SrcPortStart != 0 || a->SrcPortEnd != 0)
\r
1867 UINT src_port = Endian16(tcp->SrcPort);
\r
1868 if (src_port < a->SrcPortStart || src_port > a->SrcPortEnd)
\r
1875 if (a->DestPortStart != 0 || a->DestPortEnd != 0)
\r
1877 UINT dest_port = Endian16(tcp->DstPort);
\r
1878 if (dest_port < a->DestPortStart || dest_port > a->DestPortEnd)
\r
1884 else if (p->TypeL4 == L4_UDP)
\r
1886 UDP_HEADER *udp = p->L4.UDPHeader;
\r
1888 if (a->SrcPortStart != 0 || a->SrcPortEnd != 0)
\r
1890 UINT src_port = Endian16(udp->SrcPort);
\r
1891 if (src_port < a->SrcPortStart || src_port > a->SrcPortEnd)
\r
1898 if (a->DestPortStart != 0 || a->DestPortEnd != 0)
\r
1900 UINT dest_port = Endian16(udp->DstPort);
\r
1901 if (dest_port < a->DestPortStart || dest_port > a->DestPortEnd)
\r
1909 // アクセスリストにポート番号が指定されているときは
\r
1910 // TCP か UDP 以外のパケットは適用されない
\r
1916 // TCP コネクションの状態チェック
\r
1917 if (a->CheckTcpState != false)
\r
1919 if ((a->IsIPv6 == false && is_ipv4_packet == false) ||
\r
1920 (a->IsIPv6 && is_ipv6_packet == false))
\r
1926 if(p->TypeL4 == L4_TCP)
\r
1929 TCP_HEADER *tcp = p->L4.TCPHeader;
\r
1932 if (tcp->Flag & TCP_SYN)
\r
1937 if((MAKEBOOL(a->Established) ^ MAKEBOOL(est)))
\r
1952 // フォワードするパケットに対してアクセスリストを適用する
\r
1953 bool ApplyAccessListToForwardPacket(HUB *hub, SESSION *src_session, SESSION *dest_session, PKT *p)
\r
1956 bool pass = true; // デフォルトでは通過させる
\r
1959 if (hub == NULL || src_session == NULL || p == NULL || dest_session == NULL)
\r
1964 // 既にチェックされたパケットはアクセスリストを再適用しない。
\r
1965 if (p->AccessChecked)
\r
1970 LockList(hub->AccessList);
\r
1972 for (i = 0;i < LIST_NUM(hub->AccessList);i++)
\r
1974 ACCESS *a = LIST_DATA(hub->AccessList, i);
\r
1976 // あて先ユーザー名が指定されているエントリ以降のみを走査する。
\r
1977 if (a->DestUsernameHash != 0)
\r
1982 if (skip == false)
\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
1988 // パケットの通過または破棄を決定する
\r
1989 pass = a->Discard ? false : true;
\r
1997 UnlockList(hub->AccessList);
\r
2002 // ストアされたパケットに対してアクセスリストを適用する
\r
2003 bool ApplyAccessListToStoredPacket(HUB *hub, SESSION *s, PKT *p)
\r
2006 bool pass = true; // デフォルトでは通過させる
\r
2008 if (hub == NULL || s == NULL || p == NULL)
\r
2013 if (hub->Option != NULL && hub->Option->FilterPPPoE)
\r
2015 if (p->MacHeader != NULL)
\r
2017 USHORT proto = Endian16(p->MacHeader->Protocol);
\r
2018 if (proto == 0x8863 || proto == 0x8864)
\r
2026 if (hub->Option != NULL && hub->Option->FilterOSPF)
\r
2028 if (p->TypeL3 == L3_IPV4)
\r
2030 if (p->L3.IPv4Header != NULL)
\r
2032 if (p->L3.IPv4Header->Protocol == 89)
\r
2041 if (hub->Option != NULL && hub->Option->FilterIPv4)
\r
2043 if (p->MacHeader != NULL)
\r
2045 USHORT proto = Endian16(p->MacHeader->Protocol);
\r
2046 if (proto == 0x0800 || proto == 0x0806)
\r
2054 if (hub->Option != NULL && hub->Option->FilterIPv6)
\r
2056 if (p->MacHeader != NULL)
\r
2058 USHORT proto = Endian16(p->MacHeader->Protocol);
\r
2059 if (proto == 0x86dd)
\r
2067 if (hub->Option != NULL && hub->Option->FilterNonIP)
\r
2069 if (p->MacHeader != NULL)
\r
2071 USHORT proto = Endian16(p->MacHeader->Protocol);
\r
2072 if (!(proto == 0x86dd || proto == 0x0800 || proto == 0x0806))
\r
2080 if (hub->Option != NULL && hub->Option->FilterBPDU)
\r
2082 if (p->MacHeader != NULL)
\r
2084 if (p->TypeL3 == L3_BPDU)
\r
2092 LockList(hub->AccessList);
\r
2094 for (i = 0;i < LIST_NUM(hub->AccessList);i++)
\r
2096 ACCESS *a = LIST_DATA(hub->AccessList, i);
\r
2098 if (a->DestUsernameHash != 0)
\r
2100 // あて先ユーザー名が指定されていたら、そこでリストの走査を中断する。
\r
2104 if (IsPacketMaskedByAccessList(s, p, a, 0, 0))
\r
2106 // パケットの通過または破棄を決定する
\r
2107 pass = a->Discard ? false : true;
\r
2109 // ここで処理が決定したパケットはHUBを出るときに走査しない。
\r
2110 p->AccessChecked = true;
\r
2112 // 遅延・ジッタ・パケットロスのパラメータのコピー
\r
2113 p->Delay = a->Delay;
\r
2114 p->Jitter = a->Jitter;
\r
2115 p->Loss = a->Loss;
\r
2122 UnlockList(hub->AccessList);
\r
2128 void AddAccessList(HUB *hub, ACCESS *a)
\r
2131 if (hub == NULL || a == NULL)
\r
2136 LockList(hub->AccessList);
\r
2142 if (LIST_NUM(hub->AccessList) >= MAX_ACCESSLISTS)
\r
2144 UnlockList(hub->AccessList);
\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
2154 if (access->SrcPortStart != 0)
\r
2156 access->SrcPortEnd = MAX(access->SrcPortEnd, access->SrcPortStart);
\r
2158 if (access->DestPortStart != 0)
\r
2160 access->DestPortEnd = MAX(access->DestPortEnd, access->DestPortStart);
\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
2168 Insert(hub->AccessList, access);
\r
2171 for (i = 0;i < LIST_NUM(hub->AccessList);i++)
\r
2173 ACCESS *a = LIST_DATA(hub->AccessList, i);
\r
2177 UnlockList(hub->AccessList);
\r
2181 void InitAccessList(HUB *hub)
\r
2189 hub->AccessList = NewList(CmpAccessList);
\r
2193 void FreeAccessList(HUB *hub)
\r
2202 for (i = 0;i < LIST_NUM(hub->AccessList);i++)
\r
2204 ACCESS *a = LIST_DATA(hub->AccessList, i);
\r
2208 ReleaseList(hub->AccessList);
\r
2209 hub->AccessList = NULL;
\r
2213 int CmpAccessList(void *p1, void *p2)
\r
2216 if (p1 == NULL || p2 == NULL)
\r
2220 a1 = *(ACCESS **)p1;
\r
2221 a2 = *(ACCESS **)p2;
\r
2222 if (a1 == NULL || a2 == NULL)
\r
2227 if (a1->Priority > a2->Priority)
\r
2231 else if (a1->Priority < a2->Priority)
\r
2235 else if (a1->Discard > a2->Discard)
\r
2239 else if (a1->Discard < a2->Discard)
\r
2245 return Cmp(&a1->Active, &a2->Active, sizeof(ACCESS) - 4);
\r
2249 // ユーザー名を UINT に変換
\r
2250 UINT UsernameToInt(char *name)
\r
2252 UCHAR hash[SHA1_SIZE];
\r
2254 char tmp[MAX_USERNAME_LEN + 1];
\r
2256 if (name == 0 || StrLen(name) == 0)
\r
2261 StrCpy(tmp, sizeof(tmp), name);
\r
2265 if (StrLen(tmp) == 0)
\r
2270 Hash(hash, tmp, StrLen(tmp), true);
\r
2271 Copy(&ret, hash, sizeof(ret));
\r
2276 // セッションポインタからセッションを検索
\r
2277 SESSION *GetSessionByPtr(HUB *hub, void *ptr)
\r
2280 if (hub == NULL || ptr == NULL)
\r
2285 LockList(hub->SessionList);
\r
2288 for (i = 0;i < LIST_NUM(hub->SessionList);i++)
\r
2290 SESSION *s = LIST_DATA(hub->SessionList, i);
\r
2291 if (s == (SESSION *)ptr)
\r
2295 UnlockList(hub->SessionList);
\r
2300 UnlockList(hub->SessionList);
\r
2305 // セッション名からセッションを検索
\r
2306 SESSION *GetSessionByName(HUB *hub, char *name)
\r
2309 if (hub == NULL || name == NULL)
\r
2314 LockList(hub->SessionList);
\r
2317 for (i = 0;i < LIST_NUM(hub->SessionList);i++)
\r
2319 SESSION *s = LIST_DATA(hub->SessionList, i);
\r
2320 if (StrCmpi(s->Name, name) == 0)
\r
2324 UnlockList(hub->SessionList);
\r
2329 UnlockList(hub->SessionList);
\r
2335 int CompareStormList(void *p1, void *p2)
\r
2340 if (p1 == NULL || p2 == NULL)
\r
2344 s1 = *(STORM **)p1;
\r
2345 s2 = *(STORM **)p2;
\r
2346 if (s1 == NULL || s2 == NULL)
\r
2350 r = CmpIpAddr(&s1->DestIp, &s2->DestIp);
\r
2355 r = CmpIpAddr(&s1->SrcIp, &s2->SrcIp);
\r
2360 r = Cmp(s1->MacAddress, s2->MacAddress, 6);
\r
2365 bool HubPaInit(SESSION *s)
\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
2373 pa->StormList = NewList(CompareStormList);
\r
2374 pa->UsernameHash = UsernameToInt(s->Username);
\r
2375 pa->GroupnameHash = UsernameToInt(s->GroupName);
\r
2377 s->PacketAdapter->Param = pa;
\r
2379 if (s->Policy->MonitorPort)
\r
2381 // このポートをモニタリングポートとしてマークする
\r
2382 pa->MonitorPort = true;
\r
2384 // HUB のモニタリングポート一覧にこのセッションを追加する
\r
2385 LockList(s->Hub->MonitorList);
\r
2387 Insert(s->Hub->MonitorList, s);
\r
2389 UnlockList(s->Hub->MonitorList);
\r
2396 void HubPaFree(SESSION *s)
\r
2398 HUB_PA *pa = (HUB_PA *)s->PacketAdapter->Param;
\r
2399 HUB *hub = s->Hub;
\r
2401 if (pa->MonitorPort)
\r
2403 // HUB のモニタポート一覧からこのセッションを削除する
\r
2404 LockList(s->Hub->MonitorList);
\r
2406 Delete(s->Hub->MonitorList, s);
\r
2408 UnlockList(s->Hub->MonitorList);
\r
2411 // このセッションに関連付けられている MAC アドレステーブルを消去
\r
2412 LockList(hub->MacTable);
\r
2414 UINT i, num = LIST_NUM(hub->MacTable);
\r
2415 LIST *o = NewListFast(NULL);
\r
2416 for (i = 0;i < num;i++)
\r
2418 MAC_TABLE_ENTRY *e = (MAC_TABLE_ENTRY *)LIST_DATA(hub->MacTable, i);
\r
2419 if (e->Session == s)
\r
2424 for (i = 0;i < LIST_NUM(o);i++)
\r
2426 MAC_TABLE_ENTRY *e = (MAC_TABLE_ENTRY *)LIST_DATA(o, i);
\r
2427 Delete(hub->MacTable, e);
\r
2433 UINT i, num = LIST_NUM(hub->IpTable);
\r
2434 LIST *o = NewListFast(NULL);
\r
2435 for (i = 0;i < num;i++)
\r
2437 IP_TABLE_ENTRY *e = LIST_DATA(hub->IpTable, i);
\r
2438 if (e->Session == s)
\r
2443 for (i = 0;i < LIST_NUM(o);i++)
\r
2445 IP_TABLE_ENTRY *e = LIST_DATA(o, i);
\r
2446 Delete(hub->IpTable, e);
\r
2451 UnlockList(hub->MacTable);
\r
2454 LockList(pa->StormList);
\r
2457 for (i = 0;i < LIST_NUM(pa->StormList);i++)
\r
2459 STORM *s = (STORM *)LIST_DATA(pa->StormList, i);
\r
2462 DeleteAll(pa->StormList);
\r
2464 UnlockList(pa->StormList);
\r
2466 ReleaseList(pa->StormList);
\r
2468 // キューに残っているパケットを解放
\r
2469 LockQueue(pa->PacketQueue);
\r
2473 while (b = GetNext(pa->PacketQueue))
\r
2479 UnlockQueue(pa->PacketQueue);
\r
2482 ReleaseQueue(pa->PacketQueue);
\r
2485 ReleaseCancel(pa->Cancel);
\r
2489 s->PacketAdapter->Param = NULL;
\r
2493 CANCEL *HubPaGetCancel(SESSION *s)
\r
2495 HUB_PA *pa = (HUB_PA *)s->PacketAdapter->Param;
\r
2497 AddRef(pa->Cancel->ref);
\r
2498 return pa->Cancel;
\r
2502 UINT HubPaGetNextPacket(SESSION *s, void **data)
\r
2505 HUB_PA *pa = (HUB_PA *)s->PacketAdapter->Param;
\r
2507 // キューの先頭から 1 つ取得する
\r
2508 LockQueue(pa->PacketQueue);
\r
2510 BLOCK *block = GetNext(pa->PacketQueue);
\r
2511 if (block == NULL)
\r
2519 *data = block->Buf;
\r
2520 ret = block->Size;
\r
2521 // ブロックの構造体のメモリは解放する
\r
2525 UnlockQueue(pa->PacketQueue);
\r
2531 bool HubPaPutPacket(SESSION *s, void *data, UINT size)
\r
2534 HUB_PA *pa = (HUB_PA *)s->PacketAdapter->Param;
\r
2537 bool no_l3 = false;
\r
2540 UINT vlan_type_id = 0;
\r
2541 bool no_look_bpdu_bridge_id = false;
\r
2545 pa->Now = Tick64();
\r
2551 LockList(s->DelayedPacketList);
\r
2554 if (LIST_NUM(s->DelayedPacketList) >= 1)
\r
2556 UINT64 now = TickHighres64();
\r
2557 for (i = 0;i < LIST_NUM(s->DelayedPacketList);i++)
\r
2559 PKT *p = LIST_DATA(s->DelayedPacketList, i);
\r
2561 if (now >= p->DelayedForwardTick)
\r
2565 o = NewListFast(NULL);
\r
2575 for (i = 0;i < LIST_NUM(o);i++)
\r
2577 PKT *p = LIST_DATA(o, i);
\r
2579 Delete(s->DelayedPacketList, p);
\r
2583 UnlockList(s->DelayedPacketList);
\r
2585 // 遅延パケットがある場合はストアする
\r
2588 for (i = 0;i < LIST_NUM(o);i++)
\r
2590 PKT *p = LIST_DATA(o, i);
\r
2592 StorePacket(s->Hub, s, p);
\r
2598 // このセッションからのすべてのパケットの受信が完了した
\r
2599 CancelList(s->CancelList);
\r
2602 if (hub->Option != NULL && hub->Option->YieldAfterStorePacket)
\r
2610 if (hub != NULL && hub->Option != NULL && hub->Option->DisableIPParsing)
\r
2615 if (hub != NULL && hub->Option != NULL)
\r
2617 vlan_type_id = hub->Option->VlanTypeId;
\r
2618 no_look_bpdu_bridge_id = hub->Option->NoLookBPDUBridgeId;
\r
2622 if (s->VLanId != 0)
\r
2624 VLanInsertTag(&data, &size, s->VLanId);
\r
2628 packet = ParsePacketEx3(data, size, no_l3, vlan_type_id, !no_look_bpdu_bridge_id);
\r
2630 if (packet != NULL)
\r
2632 if (packet->InvalidSourcePacket)
\r
2635 FreePacket(packet);
\r
2640 if (packet != NULL)
\r
2643 StorePacket(s->Hub, s, packet);
\r
2647 // 不良パケット (正しい MAC フレームではない)
\r
2648 // であるのでパケットデータを解放する
\r
2655 // ブロードキャストストームが発生しないようにチェックするアルゴリズム
\r
2656 // 特定のエンドポイントからのブロードキャストが頻繁に来た場合はフィルタリングする
\r
2657 bool CheckBroadcastStorm(SESSION *s, PKT *p)
\r
2659 IP src_ip, dest_ip;
\r
2661 UINT64 now = Tick64();
\r
2662 UINT limit_start_count;
\r
2663 SESSION *sess = s;
\r
2666 if (s == NULL || p == NULL)
\r
2671 if (s->Policy->NoBroadcastLimiter)
\r
2677 pa = (HUB_PA *)s->PacketAdapter->Param;
\r
2679 if (p->TypeL3 == L3_IPV4)
\r
2681 UINTToIP(&src_ip, p->L3.IPv4Header->SrcIP);
\r
2682 UINTToIP(&dest_ip, p->L3.IPv4Header->DstIP);
\r
2684 else if (p->TypeL3 == L3_ARPV4)
\r
2686 UINTToIP(&src_ip, p->L3.ARPv4Header->SrcIP);
\r
2687 Zero(&dest_ip, sizeof(IP));
\r
2689 else if (p->TypeL3 == L3_IPV6)
\r
2691 IPv6AddrToIP(&src_ip, &p->L3.IPv6Header->SrcAddress);
\r
2692 IPv6AddrToIP(&dest_ip, &p->L3.IPv6Header->DestAddress);
\r
2696 Zero(&src_ip, sizeof(IP));
\r
2697 Zero(&dest_ip, sizeof(IP));
\r
2700 // 1 間隔ごとに制限を開始する個数
\r
2701 limit_start_count = 32;
\r
2703 if (s->Hub != NULL && s->Hub->Option->BroadcastStormDetectionThreshold != 0)
\r
2705 limit_start_count = s->Hub->Option->BroadcastStormDetectionThreshold;
\r
2708 LockList(pa->StormList);
\r
2712 s = SearchStormList(pa, p->MacAddressSrc, &src_ip, &dest_ip);
\r
2715 s = AddStormList(pa, p->MacAddressSrc, &src_ip, &dest_ip);
\r
2718 s->CurrentBroadcastNum++;
\r
2720 if ((s->CheckStartTick + STORM_CHECK_SPAN) < now ||
\r
2721 s->CheckStartTick == 0 || s->CheckStartTick > now)
\r
2723 // 一定期間ごとにブロードキャスト数を計測する
\r
2725 if (s->CheckStartTick < now)
\r
2727 diff_time = now - s->CheckStartTick;
\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
2740 char mac[MAX_SIZE];
\r
2741 IPToStr(ip1, sizeof(ip1), &src_ip);
\r
2742 IPToStr(ip2, sizeof(ip2), &dest_ip);
\r
2744 if (s->DiscardValue < STORM_DISCARD_VALUE_END)
\r
2746 s->DiscardValue = MAX(s->DiscardValue, 1) * 2;
\r
2748 Debug("s->DiscardValue: %u (%u)\n", s->DiscardValue, num);
\r
2750 MacToStr(mac, sizeof(mac), p->MacAddressSrc);
\r
2752 HLog(sess->Hub, "LH_BCAST_STORM", sess->Name, mac, ip1, ip2, num);
\r
2756 if (s->DiscardValue >= 1)
\r
2758 s->DiscardValue = (UINT)((UINT64)s->DiscardValue / MAX((UINT64)2, (UINT64)diff_time / (UINT64)STORM_CHECK_SPAN));
\r
2763 if (s->DiscardValue >= STORM_DISCARD_VALUE_START)
\r
2765 if (s->DiscardValue >= 128)
\r
2769 else if ((rand() % s->DiscardValue) != 0)
\r
2776 UnlockList(pa->StormList);
\r
2782 void StorePacket(HUB *hub, SESSION *s, PKT *packet)
\r
2784 MAC_TABLE_ENTRY *entry = NULL;
\r
2785 MAC_TABLE_ENTRY t;
\r
2788 bool broadcast_mode;
\r
2790 SESSION *dest_session;
\r
2792 UINT64 now = Tick64();
\r
2794 if (hub == NULL || packet == NULL)
\r
2801 if (((HUB_PA *)s->PacketAdapter->Param)->MonitorPort)
\r
2803 // モニタポートからもらったパケットはフォワードしてはならない
\r
2804 Free(packet->PacketData);
\r
2805 FreePacket(packet);
\r
2810 // MAC アドレステーブル全体をロック
\r
2811 LockList(hub->MacTable);
\r
2814 if (s != NULL && (packet->DelayedForwardTick == 0 && StorePacketFilter(s, packet) == false))
\r
2817 // 通過が不許可となったのでパケットを解放する
\r
2818 Free(packet->PacketData);
\r
2819 FreePacket(packet);
\r
2823 bool forward_now = true;
\r
2825 if (packet->Loss >= 1)
\r
2828 UINT r = rand() % 100;
\r
2829 if ((packet->Loss >= 100) || (r < packet->Loss))
\r
2832 goto DISCARD_PACKET;
\r
2836 if (packet->Delay >= 1)
\r
2838 float delay = (float)packet->Delay;
\r
2842 if (packet->Jitter == 0)
\r
2848 jitter = (float)(Rand32() % (int)((float)packet->Jitter * delay / 100.0f));
\r
2851 delay += jitter * (f ? 1 : -1);
\r
2852 delay_uint = (UINT)delay;
\r
2854 if (delay_uint >= 1)
\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
2862 LockList(s->DelayedPacketList);
\r
2864 Add(s->DelayedPacketList, packet);
\r
2866 UnlockList(s->DelayedPacketList);
\r
2872 if (Cmp(packet->MacAddressSrc, hub->HubMacAddr, 6) == 0)
\r
2876 // この HUB 自身が発信しようとしたパケットが外部から入力された
\r
2877 goto DISCARD_PACKET;
\r
2880 if (s != NULL && (Cmp(packet->MacAddressSrc, hub->HubMacAddr, 6) != 0))
\r
2882 // 送信元 MAC アドレスがテーブルに登録されているかどうか調べる
\r
2883 Copy(t.MacAddress, packet->MacAddressSrc, 6);
\r
2884 if (hub->Option->NoManageVlanId == false)
\r
2886 t.VlanId = packet->VlanId;
\r
2892 entry = Search(hub->MacTable, &t);
\r
2894 if (entry == NULL)
\r
2897 DeleteExpiredMacTableEntry(hub->MacTable);
\r
2900 if (s->Policy->MaxMac != 0 || s->Policy->NoBridge)
\r
2902 UINT i, num_mac_for_me = 0;
\r
2903 UINT limited_count;
\r
2905 // 現在このセッションで登録されている MAC アドレス数を調べる
\r
2906 for (i = 0;i < LIST_NUM(hub->MacTable);i++)
\r
2908 MAC_TABLE_ENTRY *e = LIST_DATA(hub->MacTable, i);
\r
2909 if (e->Session == s)
\r
2915 limited_count = 0xffffffff;
\r
2916 if (s->Policy->NoBridge)
\r
2918 limited_count = MIN(limited_count, MAC_MIN_LIMIT_COUNT);
\r
2920 if (s->Policy->MaxMac != 0)
\r
2922 limited_count = MIN(limited_count, s->Policy->MaxMac);
\r
2924 limited_count = MAX(limited_count, MAC_MIN_LIMIT_COUNT);
\r
2926 if (num_mac_for_me >= limited_count)
\r
2928 // すでに登録されている MAC アドレス数が上限を超えている
\r
2933 MacToStr(mac_str, sizeof(mac_str), packet->MacAddressSrc);
\r
2934 if (s->Policy->NoBridge)
\r
2936 HLog(hub, "LH_BRIDGE_LIMIT", s->Name, mac_str, num_mac_for_me, limited_count);
\r
2940 HLog(hub, "LH_MAC_LIMIT", s->Name, mac_str, num_mac_for_me, limited_count);
\r
2944 goto DISCARD_PACKET; // パケット破棄
\r
2948 if (LIST_NUM(hub->MacTable) >= MAX_MAC_TABLES)
\r
2950 // MAC テーブルデータベースが最大件数を超えたので
\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
2957 MAC_TABLE_ENTRY *e = LIST_DATA(hub->MacTable, i);
\r
2958 if (e->UpdatedTime <= old_time)
\r
2960 old_time = e->CreatedTime;
\r
2964 if (old_entry != NULL)
\r
2966 Delete(hub->MacTable, old_entry);
\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
2976 entry->VlanId = packet->VlanId;
\r
2980 entry->VlanId = 0;
\r
2982 entry->Session = s;
\r
2983 entry->UpdatedTime = entry->CreatedTime = now;
\r
2985 Insert(hub->MacTable, entry);
\r
2987 if (hub->Option->NoMacAddressLog == false)
\r
2990 char mac_address[32];
\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
2997 if (packet->VlanId == 0)
\r
2999 HLog(hub, "LH_MAC_REGIST", s->Name, mac_address);
\r
3003 HLog(hub, "LH_MAC_REGIST_VLAN", s->Name, mac_address, packet->VlanId);
\r
3010 if (entry->Session == s)
\r
3012 // 既に登録されているので何もしない
\r
3013 entry->UpdatedTime = now;
\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
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
3026 // D-Link 用バグ対策。D-Link のスパニングツリーパケットは上記アドレスから送出される。
\r
3027 // ローカルブリッジ時の CheckMac オプションが悪影響を与えることがある。
\r
3029 UCHAR hash[MD5_SIZE];
\r
3030 UINT64 tick_diff = Tick64() - s->LastDLinkSTPPacketSendTick;
\r
3032 Hash(hash, packet->PacketData, packet->PacketSize, false);
\r
3034 if ((s->LastDLinkSTPPacketSendTick != 0) &&
\r
3035 (tick_diff < 750ULL) &&
\r
3036 (Cmp(hash, s->LastDLinkSTPPacketDataHash, MD5_SIZE) == 0))
\r
3038 // 750ms より前に同一パケットを送信した場合は破棄
\r
3039 Debug("D-Link Discard %u\n", (UINT)tick_diff);
\r
3040 goto DISCARD_PACKET; // パケット破棄
\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
3059 goto DISCARD_PACKET; // パケット破棄
\r
3063 // MAC アドレステーブルのセッションと HUB_PA を書き換える
\r
3064 char mac_address[32];
\r
3066 BinToStr(mac_address, sizeof(mac_address), packet->MacAddressSrc, 6);
\r
3068 entry->Session = s;
\r
3069 entry->HubPa = (HUB_PA *)s->PacketAdapter->Param;
\r
3070 entry->UpdatedTime = entry->CreatedTime = now;
\r
3075 char mac_address[32];
\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
3083 HLog(hub, "LH_MAC_REGIST", s->Name, mac_address);
\r
3087 HLog(hub, "LH_MAC_REGIST_VLAN", s->Name, mac_address, packet->VlanId);
\r
3096 broadcast_mode = false;
\r
3098 dest_session = NULL;
\r
3100 if (packet->BroadcastPacket)
\r
3103 broadcast_mode = true;
\r
3107 // 宛先 MAC アドレスがテーブルに登録されているかどうか調べる
\r
3108 Copy(t.MacAddress, packet->MacAddressDest, 6);
\r
3109 if (hub->Option->NoManageVlanId == false)
\r
3111 t.VlanId = packet->VlanId;
\r
3117 entry = Search(hub->MacTable, &t);
\r
3119 if (entry == NULL)
\r
3121 // 宛先が見つからないのでブロードキャストする
\r
3122 broadcast_mode = true;
\r
3126 if (entry->Session != s)
\r
3129 dest_pa = entry->HubPa;
\r
3130 dest_session = entry->Session;
\r
3134 // 宛先が自分自身である不正なパケット
\r
3135 goto DISCARD_PACKET;
\r
3140 if (s != NULL && hub->Option->NoIpTable == false)
\r
3142 if (packet->TypeL3 == L3_IPV6)
\r
3148 bool dhcp_or_ra = false;
\r
3150 IPv6AddrToIP(&ip, &packet->L3.IPv6Header->SrcAddress);
\r
3151 ip_type = GetIPv6AddrType(&packet->L3.IPv6Header->SrcAddress);
\r
3153 if (!(ip_type & IPV6_ADDR_UNICAST))
\r
3158 else if ((ip_type & IPV6_ADDR_LOOPBACK) || (ip_type & IPV6_ADDR_ZERO))
\r
3160 // ループバックアドレスまたは All-Zero アドレス
\r
3164 if (packet->TypeL4 == L4_ICMPV6)
\r
3166 if (packet->ICMPv6HeaderPacketInfo.Type == 133 ||
\r
3167 packet->ICMPv6HeaderPacketInfo.Type == 134)
\r
3170 dhcp_or_ra = true;
\r
3173 else if (packet->TypeL4 == L4_UDP)
\r
3175 if (Endian16(packet->L4.UDPHeader->DstPort) == 546 ||
\r
3176 Endian16(packet->L4.UDPHeader->DstPort) == 547)
\r
3179 dhcp_or_ra = true;
\r
3183 if (IsHubMacAddress(packet->MacAddressSrc) &&
\r
3184 IsHubIpAddress64(&packet->L3.IPv6Header->SrcAddress))
\r
3186 // 仮想 HUB のポーリング用送信元アドレス
\r
3192 // ICMPv6 RS/RA および DHCPv6 以外のパケット
\r
3193 IP_TABLE_ENTRY t, *e;
\r
3195 Copy(&t.Ip, &ip, sizeof(IP));
\r
3197 // 既存のテーブルに登録されているかどうかチェック
\r
3198 e = Search(hub->IpTable, &t);
\r
3203 if (s->Policy->NoRoutingV6 || s->Policy->MaxIPv6 != 0)
\r
3205 UINT i, num_ip_for_me = 0;
\r
3206 UINT limited_count = 0xffffffff;
\r
3208 for (i = 0;i < LIST_NUM(hub->IpTable);i++)
\r
3210 IP_TABLE_ENTRY *e = LIST_DATA(hub->IpTable, i);
\r
3212 if (e->Session == s)
\r
3214 if (IsIP6(&e->Ip))
\r
3221 if (s->Policy->NoRoutingV6)
\r
3223 limited_count = MIN(limited_count, IP_LIMIT_WHEN_NO_ROUTING_V6);
\r
3225 if (s->Policy->MaxIPv6 != 0)
\r
3227 limited_count = MIN(limited_count, s->Policy->MaxIPv6);
\r
3229 limited_count = MAX(limited_count, IP_MIN_LIMIT_COUNT_V6);
\r
3233 limited_count = 0xffffffff;
\r
3236 if (num_ip_for_me >= limited_count)
\r
3238 // 使用できる IP アドレスの上限を超えているので
\r
3241 IPToStr(tmp, sizeof(tmp), &ip);
\r
3242 if (s->Policy->NoRoutingV6 == false)
\r
3244 HLog(hub, "LH_IP_LIMIT", s->Name, tmp, num_ip_for_me, limited_count);
\r
3248 HLog(hub, "LH_ROUTING_LIMIT", s->Name, tmp, num_ip_for_me, limited_count);
\r
3250 goto DISCARD_PACKET;
\r
3254 if (IsIPManagementTargetForHUB(&ip, hub))
\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
3264 DeleteExpiredIpTableEntry(hub->IpTable);
\r
3266 if (LIST_NUM(hub->IpTable) >= MAX_IP_TABLES)
\r
3268 // 古い IP テーブルエントリを削除する
\r
3269 DeleteOldIpTableEntry(hub->IpTable);
\r
3272 Insert(hub->IpTable, e);
\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
3285 if (e->Session == s)
\r
3287 // 自分のセッションであるので何もしない
\r
3289 e->UpdatedTime = now;
\r
3290 Copy(e->MacAddress, packet->MacAddressSrc, 6);
\r
3294 // 別のセッションが以前この IP アドレスを使っていた
\r
3295 if ((s->Policy->CheckIPv6) &&
\r
3296 ((e->UpdatedTime + IP_TABLE_EXCLUSIVE_TIME) >= now))
\r
3298 // 他のセッションがこの IP アドレスを使っているので
\r
3300 char ip_address[32];
\r
3301 IPToStr(ip_address, sizeof(ip_address), &ip);
\r
3303 Debug("IP Address %s is Already used by Session %X.\n",
\r
3306 HLog(hub, "LH_IP_CONFLICT", s->Name, ip_address, e->Session->Name);
\r
3308 goto DISCARD_PACKET;
\r
3318 (hub->Option->NoIpTable == false) &&
\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
3326 (packet->TypeL7 != L7_DHCPV4)
\r
3330 // IP パケットまたは ARP 応答パケットの場合は IP アドレステーブルを検索する
\r
3331 IP_TABLE_ENTRY t, *e;
\r
3335 if (packet->TypeL3 == L3_IPV4)
\r
3337 uint_ip = packet->L3.IPv4Header->SrcIP;
\r
3339 else if (packet->TypeL3 == L3_ARPV4)
\r
3341 uint_ip = packet->L3.ARPv4Header->SrcIP;
\r
3344 if (uint_ip != 0 && uint_ip != 0xffffffff && !(IsHubIpAddress32(uint_ip) && IsHubMacAddress(packet->MacAddressSrc)))
\r
3346 UINTToIP(&ip, uint_ip);
\r
3347 Copy(&t.Ip, &ip, sizeof(IP));
\r
3349 // 既存のテーブルに登録されているかどうかチェック
\r
3350 e = Search(hub->IpTable, &t);
\r
3355 if (s->Policy->DHCPForce)
\r
3357 char ipstr[MAX_SIZE];
\r
3359 // DHCP サーバーによって割り当てられた IP アドレスではない
\r
3361 IPToStr32(ipstr, sizeof(ipstr), uint_ip);
\r
3362 HLog(hub, "LH_DHCP_FORCE", s->Name, ipstr);
\r
3363 goto DISCARD_PACKET;
\r
3366 // if (packet->TypeL3 == L3_ARPV4)
\r
3368 // すでにこのセッションで登録されている個数を調べる
\r
3369 if (s->Policy->NoRouting || s->Policy->MaxIP != 0)
\r
3371 UINT i, num_ip_for_me = 0;
\r
3372 UINT limited_count = 0xffffffff;
\r
3374 for (i = 0;i < LIST_NUM(hub->IpTable);i++)
\r
3376 IP_TABLE_ENTRY *e = LIST_DATA(hub->IpTable, i);
\r
3378 if (e->Session == s)
\r
3380 if (IsIP4(&e->Ip))
\r
3387 if (s->Policy->NoRouting)
\r
3389 limited_count = MIN(limited_count, IP_MIN_LIMIT_COUNT);
\r
3391 if (s->Policy->MaxIP != 0)
\r
3393 limited_count = MIN(limited_count, s->Policy->MaxIP);
\r
3395 limited_count = MAX(limited_count, IP_MIN_LIMIT_COUNT);
\r
3397 if (num_ip_for_me >= limited_count)
\r
3399 // 使用できる IP アドレスの上限を超えているので
\r
3402 IPToStr32(tmp, sizeof(tmp), uint_ip);
\r
3403 if (s->Policy->NoRouting == false)
\r
3405 HLog(hub, "LH_IP_LIMIT", s->Name, tmp, num_ip_for_me, limited_count);
\r
3409 HLog(hub, "LH_ROUTING_LIMIT", s->Name, tmp, num_ip_for_me, limited_count);
\r
3411 goto DISCARD_PACKET;
\r
3415 if (IsIPManagementTargetForHUB(&ip, hub))
\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
3425 DeleteExpiredIpTableEntry(hub->IpTable);
\r
3427 if (LIST_NUM(hub->IpTable) >= MAX_IP_TABLES)
\r
3429 // 古い IP テーブルエントリを削除する
\r
3430 DeleteOldIpTableEntry(hub->IpTable);
\r
3433 Insert(hub->IpTable, e);
\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
3447 if (e->Session == s)
\r
3449 // 自分のセッションであるので何もしない
\r
3451 e->UpdatedTime = now;
\r
3452 Copy(e->MacAddress, packet->MacAddressSrc, 6);
\r
3456 // 別のセッションが以前この IP アドレスを使っていた
\r
3457 if ((s->Policy->CheckIP || s->Policy->DHCPForce) &&
\r
3458 ((e->UpdatedTime + IP_TABLE_EXCLUSIVE_TIME) >= now))
\r
3460 // 他のセッションがこの IP アドレスを使っているので
\r
3462 char ip_address[32];
\r
3463 IPToStr(ip_address, sizeof(ip_address), &ip);
\r
3465 Debug("IP Address %s is Already used by Session %X.\n",
\r
3468 HLog(hub, "LH_IP_CONFLICT", s->Name, ip_address, e->Session->Name);
\r
3470 goto DISCARD_PACKET;
\r
3473 if (s->Policy->DHCPForce)
\r
3475 if (e->DhcpAllocated == false)
\r
3477 char ipstr[MAX_SIZE];
\r
3479 // DHCP サーバーによって割り当てられた IP アドレスではない
\r
3481 IPToStr32(ipstr, sizeof(ipstr), uint_ip);
\r
3482 HLog(hub, "LH_DHCP_FORCE", s->Name, ipstr);
\r
3483 goto DISCARD_PACKET;
\r
3489 e->UpdatedTime = now;
\r
3490 Copy(e->MacAddress, packet->MacAddressSrc, 6);
\r
3496 if (s != NULL && broadcast_mode)
\r
3498 // ブロードキャストパケットのループや
\r
3499 // 大量のブロードキャストの発生を防止するため
\r
3500 // Broadcast Storm 回避アルゴリズムを呼び出す
\r
3501 if (CheckBroadcastStorm(s, packet) == false)
\r
3503 goto DISCARD_PACKET;
\r
3508 Zero(&traffic, sizeof(traffic));
\r
3509 if (packet->BroadcastPacket)
\r
3512 traffic.Send.BroadcastBytes = packet->PacketSize;
\r
3513 traffic.Send.BroadcastCount = 1;
\r
3518 traffic.Send.UnicastBytes = packet->PacketSize;
\r
3519 traffic.Send.UnicastCount = 1;
\r
3524 AddTrafficForSession(s, &traffic);
\r
3527 // トラフィック情報の Send と Recv を反転
\r
3528 Copy(&traffic.Recv, &traffic.Send, sizeof(TRAFFIC_ENTRY));
\r
3529 Zero(&traffic.Send, sizeof(TRAFFIC_ENTRY));
\r
3531 // HUB のモニタポートにこのパケットをブロードキャストする
\r
3532 if (hub->MonitorList->num_item != 0)
\r
3534 LockList(hub->MonitorList);
\r
3538 UINT size = packet->PacketSize;
\r
3539 for (i = 0;i < LIST_NUM(hub->MonitorList);i++)
\r
3541 SESSION *monitor_session = (SESSION *)LIST_DATA(hub->MonitorList, i);
\r
3544 if (monitor_session->PacketAdapter->Param != NULL)
\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
3553 UnlockList(hub->MonitorList);
\r
3556 if (broadcast_mode == false)
\r
3558 if (dest_pa != NULL)
\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
3564 DeleteIPv6DefaultRouterInRA(packet);
\r
3566 if (dest_session->Policy->RSandRAFilter)
\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
3573 goto DISCARD_UNICAST_PACKET;
\r
3576 if (dest_session->Policy->DHCPFilter)
\r
3578 if (packet->TypeL3 == L3_IPV4 &&
\r
3579 packet->TypeL4 == L4_UDP &&
\r
3580 packet->TypeL7 == L7_DHCPV4)
\r
3582 goto DISCARD_UNICAST_PACKET;
\r
3585 if (dest_session->Policy->DHCPv6Filter)
\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
3591 goto DISCARD_UNICAST_PACKET;
\r
3594 if (dest_session->Policy->ArpDhcpOnly)
\r
3596 if (packet->BroadcastPacket)
\r
3600 if (packet->TypeL3 == L3_IPV4 &&
\r
3601 packet->TypeL4 == L4_UDP &&
\r
3602 packet->TypeL7 == L7_DHCPV4)
\r
3606 else if (packet->TypeL3 == L3_ARPV4)
\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
3616 else if (packet->TypeL3 == L3_IPV6 &&
\r
3617 packet->TypeL4 == L4_ICMPV6)
\r
3624 goto DISCARD_UNICAST_PACKET;
\r
3628 if (dest_session->Policy->FilterIPv4)
\r
3630 if (packet->TypeL3 == L3_IPV4 || packet->TypeL3 == L3_ARPV4)
\r
3632 goto DISCARD_UNICAST_PACKET;
\r
3635 if (dest_session->Policy->FilterIPv6)
\r
3637 if (packet->TypeL3 == L3_IPV6)
\r
3639 goto DISCARD_UNICAST_PACKET;
\r
3642 if (dest_session->Policy->FilterNonIP)
\r
3644 if (packet->TypeL3 != L3_IPV4 && packet->TypeL3 != L3_ARPV4 && packet->TypeL3 != L3_IPV6)
\r
3646 goto DISCARD_UNICAST_PACKET;
\r
3651 (packet->BroadcastPacket == false &&
\r
3652 s->Policy->PrivacyFilter &&
\r
3653 dest_session->Policy->PrivacyFilter)
\r
3657 if (packet->TypeL3 != L3_ARPV4)
\r
3659 goto DISCARD_UNICAST_PACKET;
\r
3665 if (Cmp(packet->MacAddressSrc, s->Hub->HubMacAddr, 6) == 0 ||
\r
3666 Cmp(packet->MacAddressDest, s->Hub->HubMacAddr, 6) == 0)
\r
3668 goto DISCARD_UNICAST_PACKET;
\r
3675 PacketLog(s->Hub, s, dest_session, packet);
\r
3678 // 宛先 HUB_PA にストアする
\r
3679 StorePacketToHubPa(dest_pa, s, packet->PacketData, packet->PacketSize, packet);
\r
3682 AddTrafficForSession(dest_session, &traffic);
\r
3686 DISCARD_UNICAST_PACKET:
\r
3687 Free(packet->PacketData);
\r
3692 // すべてのセッションにストアする
\r
3693 LockList(hub->SessionList);
\r
3695 UINT i, num = LIST_NUM(hub->SessionList);
\r
3696 for (i = 0;i < num;i++)
\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
3702 if (dest_session != s)
\r
3704 bool delete_default_router_in_ra = false;
\r
3706 if (dest_session->VLanId != 0 && packet->TypeL3 == L3_TAGVLAN &&
\r
3707 packet->VlanId != dest_session->VLanId)
\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
3716 if (packet->TypeL3 == L3_IPV6 && packet->TypeL4 == L4_ICMPV6 &&
\r
3717 (packet->ICMPv6HeaderPacketInfo.Type == ICMPV6_TYPE_ROUTER_ADVERTISEMENT))
\r
3719 if (packet->ICMPv6HeaderPacketInfo.Headers.RouterAdvertisementHeader->Lifetime != 0)
\r
3721 delete_default_router_in_ra = true;
\r
3725 if (dest_session->Policy->RSandRAFilter)
\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
3736 if (dest_session->Policy->DHCPFilter)
\r
3738 if (packet->TypeL3 == L3_IPV4 &&
\r
3739 packet->TypeL4 == L4_UDP &&
\r
3740 packet->TypeL7 == L7_DHCPV4)
\r
3746 if (dest_session->Policy->DHCPv6Filter)
\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
3756 if (dest_session->Policy->ArpDhcpOnly)
\r
3758 if (packet->BroadcastPacket)
\r
3762 if (packet->TypeL3 == L3_IPV4 &&
\r
3763 packet->TypeL4 == L4_UDP &&
\r
3764 packet->TypeL7 == L7_DHCPV4)
\r
3768 else if (packet->TypeL3 == L3_ARPV4)
\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
3778 else if (packet->TypeL3 == L3_IPV6 &&
\r
3779 packet->TypeL4 == L4_ICMPV6)
\r
3784 if (discard == false)
\r
3791 if (dest_session->Policy->FilterIPv4)
\r
3793 if (packet->TypeL3 == L3_IPV4 || packet->TypeL3 == L3_ARPV4)
\r
3798 if (dest_session->Policy->FilterIPv6)
\r
3800 if (packet->TypeL3 == L3_IPV6)
\r
3805 if (dest_session->Policy->FilterNonIP)
\r
3807 if (packet->TypeL3 != L3_IPV4 && packet->TypeL3 != L3_ARPV4 && packet->TypeL3 != L3_IPV6)
\r
3814 (packet->BroadcastPacket == false &&
\r
3815 s->Policy->PrivacyFilter &&
\r
3816 dest_session->Policy->PrivacyFilter)
\r
3820 if (packet->TypeL3 != L3_ARPV4)
\r
3828 if (Cmp(packet->MacAddressSrc, s->Hub->HubMacAddr, 6) == 0 ||
\r
3829 Cmp(packet->MacAddressDest, s->Hub->HubMacAddr, 6) == 0)
\r
3835 if (discard == false && dest_pa != NULL)
\r
3838 data = MallocFast(packet->PacketSize);
\r
3839 Copy(data, packet->PacketData, packet->PacketSize);
\r
3840 size = packet->PacketSize;
\r
3842 if (delete_default_router_in_ra)
\r
3844 PKT *pkt2 = ParsePacket(data, size);
\r
3846 DeleteIPv6DefaultRouterInRA(pkt2);
\r
3851 StorePacketToHubPa(dest_pa, s, data, size, packet);
\r
3854 AddTrafficForSession(dest_session, &traffic);
\r
3859 UnlockList(hub->SessionList);
\r
3864 PacketLog(s->Hub, s, NULL, packet);
\r
3867 Free(packet->PacketData);
\r
3869 FreePacket(packet);
\r
3873 UnlockList(hub->MacTable);
\r
3876 // 指定された IP アドレスがプライベート IP アドレスかどうかチェックする
\r
3877 bool IsIPPrivate(IP *ip)
\r
3885 if (ip->addr[0] == 10)
\r
3890 if (ip->addr[0] == 172)
\r
3892 if (ip->addr[1] >= 16 && ip->addr[1] <= 31)
\r
3898 if (ip->addr[0] == 192 && ip->addr[1] == 168)
\r
3903 if (ip->addr[0] == 2)
\r
3909 if (ip->addr[0] == 169 && ip->addr[1] == 254)
\r
3917 // 指定された IP アドレスが仮想 HUB による管理対象かどうか確認する
\r
3918 bool IsIPManagementTargetForHUB(IP *ip, HUB *hub)
\r
3921 if (ip == NULL || hub == NULL)
\r
3926 if (hub->Option == NULL)
\r
3933 if (hub->Option->ManageOnlyPrivateIP)
\r
3935 if (IsIPPrivate(ip) == false)
\r
3943 if (hub->Option->ManageOnlyLocalUnicastIPv6)
\r
3945 UINT ip_type = GetIPAddrType6(ip);
\r
3947 if (!(ip_type & IPV6_ADDR_LOCAL_UNICAST))
\r
3957 // 古い IP テーブルエントリを削除する
\r
3958 void DeleteOldIpTableEntry(LIST *o)
\r
3961 UINT64 oldest_time = 0xffffffffffffffffULL;
\r
3962 IP_TABLE_ENTRY *old = NULL;
\r
3969 for (i = 0;i < LIST_NUM(o);i++)
\r
3971 IP_TABLE_ENTRY *e = LIST_DATA(o, i);
\r
3973 if (e->UpdatedTime <= oldest_time)
\r
3987 STORM *AddStormList(HUB_PA *pa, UCHAR *mac_address, IP *src_ip, IP *dest_ip)
\r
3991 if (pa == NULL || mac_address == NULL)
\r
3996 s = ZeroMalloc(sizeof(STORM));
\r
3997 if (src_ip != NULL)
\r
3999 Copy(&s->SrcIp, src_ip, sizeof(IP));
\r
4001 if (dest_ip != NULL)
\r
4003 Copy(&s->DestIp, dest_ip, sizeof(IP));
\r
4005 Copy(s->MacAddress, mac_address, 6);
\r
4007 Insert(pa->StormList, s);
\r
4013 STORM *SearchStormList(HUB_PA *pa, UCHAR *mac_address, IP *src_ip, IP *dest_ip)
\r
4017 if (pa == NULL || mac_address == NULL)
\r
4022 Zero(&t, sizeof(t));
\r
4023 if (src_ip != NULL)
\r
4025 Copy(&t.SrcIp, src_ip, sizeof(IP));
\r
4027 if (dest_ip != NULL)
\r
4029 Copy(&t.DestIp, dest_ip, sizeof(IP));
\r
4031 Copy(t.MacAddress, mac_address, 6);
\r
4033 s = Search(pa->StormList, &t);
\r
4038 // パケットを宛先の HUB_PA にストアする
\r
4039 void StorePacketToHubPa(HUB_PA *dest, SESSION *src, void *data, UINT size, PKT *packet)
\r
4043 if (dest == NULL || data == NULL)
\r
4056 // フォワード用のアクセスリスト適用
\r
4057 if (ApplyAccessListToForwardPacket(src->Hub, src, dest->Session, packet) == false)
\r
4066 if (dest->Session->Policy->MaxDownload != 0)
\r
4069 if (packet != NULL && IsMostHighestPriorityPacket(dest->Session, packet) == false)
\r
4071 TRAFFIC_LIMITER *tr = &dest->DownloadLimiter;
\r
4072 IntoTrafficLimiter(tr, packet);
\r
4074 if ((tr->Value * (UINT64)1000 / (UINT64)LIMITER_SAMPLING_SPAN) > dest->Session->Policy->MaxDownload)
\r
4084 if (src != NULL && src->Hub != NULL && src->Hub->Option != NULL && src->Hub->Option->FixForDLinkBPDU)
\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
4091 SESSION *session = dest->Session;
\r
4093 if (session != NULL)
\r
4095 if (session->Policy != NULL && session->Policy->CheckMac)
\r
4097 UCHAR hash[MD5_SIZE];
\r
4098 Hash(hash, packet->PacketData, packet->PacketSize, false);
\r
4100 Copy(session->LastDLinkSTPPacketDataHash, hash, MD5_SIZE);
\r
4101 session->LastDLinkSTPPacketSendTick = Tick64();
\r
4108 if (dest->Session != NULL && dest->Session->VLanId != 0)
\r
4110 if (VLanRemoveTag(&data, &size, dest->Session->VLanId) == false)
\r
4118 b = NewBlock(data, size, 0);
\r
4120 LockQueue(dest->PacketQueue);
\r
4123 if ((dest->PacketQueue->num_item < MAX_STORED_QUEUE_NUM) ||
\r
4124 (((UCHAR *)data)[12] == 'S' && ((UCHAR *)data)[13] == 'E'))
\r
4127 InsertQueue(dest->PacketQueue, b);
\r
4135 UnlockQueue(dest->PacketQueue);
\r
4140 AddCancelList(src->CancelList, dest->Cancel);
\r
4144 Cancel(dest->Cancel);
\r
4148 // IPv6 ルータ広告からデフォルトルータ指定を削除
\r
4149 bool DeleteIPv6DefaultRouterInRA(PKT *p)
\r
4151 if (p->TypeL3 == L3_IPV6 && p->TypeL4 == L4_ICMPV6 &&
\r
4152 (p->ICMPv6HeaderPacketInfo.Type == ICMPV6_TYPE_ROUTER_ADVERTISEMENT))
\r
4154 if (p->ICMPv6HeaderPacketInfo.Headers.RouterAdvertisementHeader->Lifetime != 0)
\r
4156 p->ICMPv6HeaderPacketInfo.Headers.RouterAdvertisementHeader->Lifetime = 0;
\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
4169 // ポリシーによるパケットフィルタ
\r
4170 bool StorePacketFilterByPolicy(SESSION *s, PKT *p)
\r
4175 if (s == NULL || p == NULL)
\r
4185 // サーバーとしての動作を禁止する
\r
4186 if (pol->NoServer)
\r
4188 if (p->TypeL3 == L3_IPV4)
\r
4190 if (p->TypeL4 == L4_TCP)
\r
4192 UCHAR flag = p->L4.TCPHeader->Flag;
\r
4193 if ((flag & TCP_SYN) && (flag & TCP_ACK))
\r
4195 char ip1[64], ip2[64];
\r
4196 // SYN + ACK パケットを送信させない
\r
4197 Debug("pol->NoServer: Discard SYN+ACK Packet.\n");
\r
4199 IPToStr32(ip1, sizeof(ip1), p->L3.IPv4Header->SrcIP);
\r
4200 IPToStr32(ip2, sizeof(ip2), p->L3.IPv4Header->DstIP);
\r
4202 HLog(s->Hub, "LH_NO_SERVER", s->Name, ip2, p->L4.TCPHeader->DstPort,
\r
4203 ip1, p->L4.TCPHeader->SrcPort);
\r
4211 // サーバーとしての動作を禁止する (IPv6)
\r
4212 if (pol->NoServerV6)
\r
4214 if (p->TypeL3 == L3_IPV6)
\r
4216 if (p->TypeL4 == L4_TCP)
\r
4218 UCHAR flag = p->L4.TCPHeader->Flag;
\r
4219 if ((flag & TCP_SYN) && (flag & TCP_ACK))
\r
4221 char ip1[128], ip2[128];
\r
4222 // SYN + ACK パケットを送信させない
\r
4223 Debug("pol->NoServerV6: Discard SYN+ACK Packet.\n");
\r
4225 IP6AddrToStr(ip1, sizeof(ip1), &p->IPv6HeaderPacketInfo.IPv6Header->SrcAddress);
\r
4226 IP6AddrToStr(ip2, sizeof(ip2), &p->IPv6HeaderPacketInfo.IPv6Header->DestAddress);
\r
4228 HLog(s->Hub, "LH_NO_SERVER", s->Name, ip2, p->L4.TCPHeader->DstPort,
\r
4229 ip1, p->L4.TCPHeader->SrcPort);
\r
4237 // ブロードキャストは ARP と DHCP のみ許可
\r
4238 if (pol->ArpDhcpOnly && p->BroadcastPacket)
\r
4242 if (p->TypeL3 == L3_ARPV4)
\r
4246 if (p->TypeL3 == L3_IPV4)
\r
4248 if (p->TypeL4 == L4_UDP)
\r
4250 if (p->TypeL7 == L7_DHCPV4)
\r
4256 if (p->TypeL3 == L3_IPV6)
\r
4258 if (p->TypeL4 == L4_ICMPV6)
\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
4277 // IPv4 パケットのフィルタリング
\r
4278 if (pol->FilterIPv4)
\r
4280 if (p->MacHeader != NULL)
\r
4282 USHORT proto = Endian16(p->MacHeader->Protocol);
\r
4283 if (proto == 0x0800 || proto == 0x0806)
\r
4290 // IPv6 パケットのフィルタリング
\r
4291 if (pol->FilterIPv6)
\r
4293 if (p->MacHeader != NULL)
\r
4295 USHORT proto = Endian16(p->MacHeader->Protocol);
\r
4296 if (proto == 0x86dd)
\r
4303 // 非 IP パケットのフィルタリング
\r
4304 if (pol->FilterNonIP)
\r
4306 if (p->MacHeader != NULL)
\r
4308 USHORT proto = Endian16(p->MacHeader->Protocol);
\r
4309 if (!(proto == 0x86dd || proto == 0x0800 || proto == 0x0806))
\r
4316 // DHCP パケットのフィルタリング
\r
4317 if (pol->DHCPFilter)
\r
4319 if (p->TypeL3 == L3_IPV4 &&
\r
4320 p->TypeL4 == L4_UDP &&
\r
4321 p->TypeL7 == L7_DHCPV4)
\r
4324 Debug("pol->DHCPFilter: Discard DHCP Packet.\n");
\r
4330 // DHCPv6 パケットのフィルタリング
\r
4331 if (pol->DHCPv6Filter)
\r
4333 if (p->TypeL3 == L3_IPV6 &&
\r
4334 p->TypeL4 == L4_UDP)
\r
4336 if (Endian16(p->L4.UDPHeader->DstPort) == 546 ||
\r
4337 Endian16(p->L4.UDPHeader->DstPort) == 547)
\r
4339 // DHCPv6 パケットを破棄する
\r
4340 Debug("pol->DHCPv6Filter: Discard DHCPv6 Packet.\n");
\r
4347 // DHCP サーバーとしての動作を禁止
\r
4348 if (pol->DHCPNoServer)
\r
4350 if (p->TypeL3 == L3_IPV4 &&
\r
4351 p->TypeL4 == L4_UDP &&
\r
4352 p->TypeL7 == L7_DHCPV4)
\r
4354 DHCPV4_HEADER *h = p->L7.DHCPv4Header;
\r
4355 if (h->OpCode == 2)
\r
4357 char ip1[64], ip2[64];
\r
4360 IPToStr32(ip1, sizeof(ip1), p->L3.IPv4Header->SrcIP);
\r
4361 IPToStr32(ip2, sizeof(ip2), p->L3.IPv4Header->DstIP);
\r
4363 HLog(s->Hub, "LH_NO_DHCP", s->Name, ip1, ip2);
\r
4365 // DHCP 応答パケットを破棄する
\r
4366 Debug("pol->DHCPNoServer: Discard DHCP Response Packet.\n");
\r
4372 // DHCPv6 サーバーとしての動作を禁止
\r
4373 if (pol->DHCPv6NoServer)
\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
4379 char ip1[128], ip2[128];
\r
4382 IP6AddrToStr(ip1, sizeof(ip1), &p->L3.IPv6Header->SrcAddress);
\r
4383 IP6AddrToStr(ip2, sizeof(ip2), &p->L3.IPv6Header->DestAddress);
\r
4385 HLog(s->Hub, "LH_NO_DHCP", s->Name, ip1, ip2);
\r
4387 // DHCP 応答パケットを破棄する
\r
4388 Debug("pol->DHCPv6NoServer: Discard DHCPv6 Response Packet.\n");
\r
4393 // ルータ要請/広告パケットをフィルタリング (IPv6)
\r
4394 if (pol->RSandRAFilter)
\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
4404 // ルータ広告パケットをフィルタリング (IPv6)
\r
4405 if (pol->RAFilter)
\r
4407 if (p->TypeL3 == L3_IPV6 && p->TypeL4 == L4_ICMPV6 &&
\r
4408 p->ICMPv6HeaderPacketInfo.Type == ICMPV6_TYPE_ROUTER_ADVERTISEMENT)
\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
4420 DHCPV4_HEADER *h = p->L7.DHCPv4Header;
\r
4421 if (h->OpCode == 2)
\r
4423 // DHCP 応答パケットの中身を見て IP テーブルに登録する
\r
4424 if (h->HardwareType == ARP_HARDWARE_TYPE_ETHERNET)
\r
4426 if (h->HardwareAddressSize == 6)
\r
4428 if (h->YourIP != 0 && h->YourIP != 0xffffffff)
\r
4430 UINT ip_uint = h->YourIP;
\r
4432 IP_TABLE_ENTRY *e, t;
\r
4433 MAC_TABLE_ENTRY *mac_table, mt;
\r
4435 Copy(&mt.MacAddress, &h->ClientMacAddress, 6);
\r
4436 mac_table = Search(hub->MacTable, &mt);
\r
4438 if (mac_table != NULL)
\r
4440 bool new_entry = true;
\r
4441 UINTToIP(&ip, ip_uint);
\r
4442 Copy(&t.Ip, &ip, sizeof(IP));
\r
4444 e = Search(hub->IpTable, &t);
\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
4458 // 有効期限の切れた IP テーブルエントリを削除する
\r
4459 DeleteExpiredIpTableEntry(hub->IpTable);
\r
4460 if (LIST_NUM(hub->IpTable) >= MAX_IP_TABLES)
\r
4463 DeleteOldIpTableEntry(hub->IpTable);
\r
4465 Insert(hub->IpTable, e);
\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
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
4488 new_entry = false;
\r
4489 goto UPDATE_DHCP_ALLOC_ENTRY;
\r
4501 // 有効期限の切れた MAC テーブルエントリを削除する
\r
4502 void DeleteExpiredMacTableEntry(LIST *o)
\r
4512 o2 = NewListFast(NULL);
\r
4514 for (i = 0;i < LIST_NUM(o);i++)
\r
4516 MAC_TABLE_ENTRY *e = LIST_DATA(o, i);
\r
4517 if ((e->UpdatedTime + (UINT64)MAC_TABLE_EXPIRE_TIME) <= Tick64())
\r
4523 for (i = 0;i < LIST_NUM(o2);i++)
\r
4525 MAC_TABLE_ENTRY *e = LIST_DATA(o2, i);
\r
4533 // 有効期限の切れた IP テーブルエントリを削除する
\r
4534 void DeleteExpiredIpTableEntry(LIST *o)
\r
4544 o2 = NewListFast(NULL);
\r
4546 for (i = 0;i < LIST_NUM(o);i++)
\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
4555 for (i = 0;i < LIST_NUM(o2);i++)
\r
4557 IP_TABLE_ENTRY *e = LIST_DATA(o2, i);
\r
4565 // 優先して取り扱うべきパケットかどうかを判断
\r
4566 bool IsMostHighestPriorityPacket(SESSION *s, PKT *p)
\r
4569 if (s == NULL || p == NULL)
\r
4574 if (p->TypeL3 == L3_ARPV4)
\r
4580 if (p->TypeL3 == L3_IPV4)
\r
4582 if (p->TypeL4 == L4_ICMPV4)
\r
4588 if (p->TypeL4 == L4_TCP)
\r
4590 if ((p->L4.TCPHeader->Flag & TCP_SYN) || (p->L4.TCPHeader->Flag & TCP_FIN)
\r
4591 || (p->L4.TCPHeader->Flag & TCP_RST))
\r
4593 // SYN, FIN, RST パケット
\r
4598 if (p->TypeL4 == L4_UDP)
\r
4600 if (p->TypeL7 == L7_DHCPV4)
\r
4611 // トラフィック リミッターへのパケット追加
\r
4612 void IntoTrafficLimiter(TRAFFIC_LIMITER *tr, PKT *p)
\r
4614 UINT64 now = Tick64();
\r
4616 if (tr == NULL || p == NULL)
\r
4621 if (tr->LastTime == 0 || tr->LastTime > now ||
\r
4622 (tr->LastTime + LIMITER_SAMPLING_SPAN) < now)
\r
4626 tr->LastTime = now;
\r
4630 tr->Value += (UINT64)(p->PacketSize * 8);
\r
4633 // トラフィック リミッターによる帯域幅削減
\r
4634 bool StorePacketFilterByTrafficLimiter(SESSION *s, PKT *p)
\r
4637 TRAFFIC_LIMITER *tr;
\r
4639 if (s == NULL || p == NULL)
\r
4644 if (s->Policy->MaxUpload == 0)
\r
4650 pa = (HUB_PA *)s->PacketAdapter->Param;
\r
4651 tr = &pa->UploadLimiter;
\r
4653 // 優先パケットは制限を適用しない
\r
4654 if (IsMostHighestPriorityPacket(s, p))
\r
4660 IntoTrafficLimiter(tr, p);
\r
4663 if ((tr->Value * (UINT64)1000 / (UINT64)LIMITER_SAMPLING_SPAN) > s->Policy->MaxUpload)
\r
4672 // ストアするパケットのフィルタリング
\r
4673 bool StorePacketFilter(SESSION *s, PKT *packet)
\r
4676 if (s == NULL || packet == NULL)
\r
4681 // トラフィック リミッターによる帯域幅削減
\r
4682 if (StorePacketFilterByTrafficLimiter(s, packet) == false)
\r
4687 // ポリシーによるパケットフィルタ
\r
4688 if (StorePacketFilterByPolicy(s, packet) == false)
\r
4693 // アクセスリストによるパケットフィルタ
\r
4694 if (ApplyAccessListToStoredPacket(s->Hub, s, packet) == false)
\r
4702 // HUB 用のパケットアダプタの取得
\r
4703 PACKET_ADAPTER *GetHubPacketAdapter()
\r
4706 PACKET_ADAPTER *pa = NewPacketAdapter(HubPaInit,
\r
4707 HubPaGetCancel, HubPaGetNextPacket, HubPaPutPacket, HubPaFree);
\r
4712 // HUB のすべての SESSION を停止させる
\r
4713 void StopAllSession(HUB *h)
\r
4723 LockList(h->SessionList);
\r
4725 num = LIST_NUM(h->SessionList);
\r
4726 s = ToArray(h->SessionList);
\r
4727 DeleteAll(h->SessionList);
\r
4729 UnlockList(h->SessionList);
\r
4731 for (i = 0;i < num;i++)
\r
4733 StopSession(s[i]);
\r
4734 ReleaseSession(s[i]);
\r
4740 // HUB から SESSION を削除
\r
4741 void DelSession(HUB *h, SESSION *s)
\r
4744 if (h == NULL || s == NULL)
\r
4749 LockList(h->SessionList);
\r
4751 if (Delete(h->SessionList, s))
\r
4753 Debug("Session %s was Deleted from %s.\n", s->Name, h->Name);
\r
4754 ReleaseSession(s);
\r
4757 UnlockList(h->SessionList);
\r
4760 // HUB に SESSION を追加
\r
4761 void AddSession(HUB *h, SESSION *s)
\r
4764 if (h == NULL || s == NULL)
\r
4769 LockList(h->SessionList);
\r
4771 Insert(h->SessionList, s);
\r
4773 Debug("Session %s Inserted to %s.\n", s->Name, h->Name);
\r
4775 UnlockList(h->SessionList);
\r
4779 void StopHub(HUB *h)
\r
4781 bool old_status = false;
\r
4788 old_status = h->Offline;
\r
4789 h->HubIsOnlineButHalting = true;
\r
4793 if (h->Halt == false)
\r
4795 SLog(h->Cedar, "LS_HUB_STOP", h->Name);
\r
4799 h->Offline = old_status;
\r
4800 h->HubIsOnlineButHalting = false;
\r
4804 void SetHubOnline(HUB *h)
\r
4806 bool for_cluster = false;
\r
4813 if (h->Cedar->Server != NULL && h->Cedar->Server->ServerType == SERVER_TYPE_FARM_CONTROLLER)
\r
4815 if (h->Type == HUB_TYPE_FARM_DYNAMIC)
\r
4817 for_cluster = true;
\r
4821 Lock(h->lock_online);
\r
4823 if (h->Offline == false)
\r
4825 Unlock(h->lock_online);
\r
4828 HLog(h, "LH_ONLINE");
\r
4834 if (h->EnableSecureNAT)
\r
4836 if (h->SecureNAT == NULL)
\r
4838 if (for_cluster == false)
\r
4840 h->SecureNAT = SnNewSecureNAT(h, h->SecureNATOption);
\r
4845 // この HUB に関連付けられているローカルブリッジをすべて開始する
\r
4846 if (h->Type != HUB_TYPE_FARM_DYNAMIC)
\r
4848 LockList(h->Cedar->LocalBridgeList);
\r
4851 for (i = 0;i < LIST_NUM(h->Cedar->LocalBridgeList);i++)
\r
4853 LOCALBRIDGE *br = LIST_DATA(h->Cedar->LocalBridgeList, i);
\r
4855 if (StrCmpi(br->HubName, h->Name) == 0)
\r
4857 if (br->Bridge == NULL)
\r
4859 br->Bridge = BrNewBridge(h, br->DeviceName, NULL, br->Local, br->Monitor,
\r
4860 br->TapMode, br->TapMacAddress, br->FullBroadcast);
\r
4865 UnlockList(h->Cedar->LocalBridgeList);
\r
4868 h->Offline = false;
\r
4870 Unlock(h->lock_online);
\r
4872 if (h->Cedar->Server != NULL)
\r
4874 SiHubOnlineProc(h);
\r
4879 void SetHubOffline(HUB *h)
\r
4882 bool for_cluster = false;
\r
4889 if (h->Cedar->Server != NULL && h->Cedar->Server->ServerType == SERVER_TYPE_FARM_CONTROLLER)
\r
4891 if (h->Type == HUB_TYPE_FARM_DYNAMIC)
\r
4893 for_cluster = true;
\r
4897 h->BeingOffline = true;
\r
4899 Lock(h->lock_online);
\r
4901 if (h->Offline || h->Halt)
\r
4903 Unlock(h->lock_online);
\r
4904 h->BeingOffline = false;
\r
4908 HLog(h, "LH_OFFLINE");
\r
4914 SnFreeSecureNAT(h->SecureNAT);
\r
4915 h->SecureNAT = NULL;
\r
4917 // この HUB に関連付けられているローカルブリッジをすべて停止する
\r
4918 LockList(h->Cedar->LocalBridgeList);
\r
4920 for (i = 0;i < LIST_NUM(h->Cedar->LocalBridgeList);i++)
\r
4922 LOCALBRIDGE *br = LIST_DATA(h->Cedar->LocalBridgeList, i);
\r
4924 if (StrCmpi(br->HubName, h->Name) == 0)
\r
4926 BrFreeBridge(br->Bridge);
\r
4927 br->Bridge = NULL;
\r
4931 UnlockList(h->Cedar->LocalBridgeList);
\r
4934 h->Offline = true;
\r
4937 StopAllSession(h);
\r
4939 Unlock(h->lock_online);
\r
4941 h->BeingOffline = false;
\r
4943 if (h->Cedar->Server != NULL)
\r
4945 SiHubOfflineProc(h);
\r
4949 // 指定された名前の HUB が存在するかどうか取得
\r
4950 bool IsHub(CEDAR *cedar, char *name)
\r
4954 if (cedar == NULL || name == NULL)
\r
4959 h = GetHub(cedar, name);
\r
4971 HUB *GetHub(CEDAR *cedar, char *name)
\r
4975 if (cedar == NULL || name == NULL)
\r
4980 LockHubList(cedar);
\r
4983 h = Search(cedar->HubList, &t);
\r
4986 UnlockHubList(cedar);
\r
4992 UnlockHubList(cedar);
\r
4998 void LockHubList(CEDAR *cedar)
\r
5001 if (cedar == NULL)
\r
5006 LockList(cedar->HubList);
\r
5010 void UnlockHubList(CEDAR *cedar)
\r
5013 if (cedar == NULL)
\r
5018 UnlockList(cedar->HubList);
\r
5022 void ReleaseHub(HUB *h)
\r
5030 if (Release(h->ref) == 0)
\r
5036 // Radius サーバー情報を取得
\r
5037 bool GetRadiusServer(HUB *hub, char *name, UINT size, UINT *port, char *secret, UINT secret_size)
\r
5040 return GetRadiusServerEx(hub, name, size, port, secret, secret_size, &interval);
\r
5042 bool GetRadiusServerEx(HUB *hub, char *name, UINT size, UINT *port, char *secret, UINT secret_size, UINT *interval)
\r
5046 if (hub == NULL || name == NULL || port == NULL || secret == NULL || interval == NULL)
\r
5051 Lock(hub->RadiusOptionLock);
\r
5053 if (hub->RadiusServerName != NULL)
\r
5057 StrCpy(name, size, hub->RadiusServerName);
\r
5058 *port = hub->RadiusServerPort;
\r
5059 *interval = hub->RadiusRetryInterval;
\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
5070 Unlock(hub->RadiusOptionLock);
\r
5075 // Radius サーバー情報を設定
\r
5076 void SetRadiusServer(HUB *hub, char *name, UINT port, char *secret)
\r
5078 SetRadiusServerEx(hub, name, port, secret, RADIUS_RETRY_INTERVAL);
\r
5080 void SetRadiusServerEx(HUB *hub, char *name, UINT port, char *secret, UINT interval)
\r
5088 Lock(hub->RadiusOptionLock);
\r
5090 if (hub->RadiusServerName != NULL)
\r
5092 Free(hub->RadiusServerName);
\r
5097 hub->RadiusServerName = NULL;
\r
5098 hub->RadiusServerPort = 0;
\r
5099 hub->RadiusRetryInterval = RADIUS_RETRY_INTERVAL;
\r
5100 FreeBuf(hub->RadiusSecret);
\r
5104 hub->RadiusServerName = CopyStr(name);
\r
5105 hub->RadiusServerPort = port;
\r
5106 if (interval == 0)
\r
5108 hub->RadiusRetryInterval = RADIUS_RETRY_INTERVAL;
\r
5110 else if (interval > RADIUS_RETRY_TIMEOUT)
\r
5112 hub->RadiusRetryInterval = RADIUS_RETRY_TIMEOUT;
\r
5116 hub->RadiusRetryInterval = interval;
\r
5118 FreeBuf(hub->RadiusSecret);
\r
5120 if (secret == NULL)
\r
5122 hub->RadiusSecret = NewBuf();
\r
5126 hub->RadiusSecret = NewBuf();
\r
5127 WriteBuf(hub->RadiusSecret, secret, StrLen(secret));
\r
5128 SeekBuf(hub->RadiusSecret, 0, 0);
\r
5132 Unlock(hub->RadiusOptionLock);
\r
5135 // 仮想 HUB のトラフィック情報の追加
\r
5136 void IncrementHubTraffic(HUB *h)
\r
5140 if (h == NULL || h->FarmMember == false)
\r
5145 Zero(&t, sizeof(t));
\r
5147 Lock(h->TrafficLock);
\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
5167 Unlock(h->TrafficLock);
\r
5169 if (IsZero(&t, sizeof(TRAFFIC)))
\r
5174 AddTrafficDiff(h, h->Name, TRAFFIC_DIFF_HUB, &t);
\r
5178 void AddTrafficDiff(HUB *h, char *name, UINT type, TRAFFIC *traffic)
\r
5182 if (h == NULL || h->FarmMember == false || name == NULL || traffic == NULL)
\r
5187 if (LIST_NUM(h->Cedar->TrafficDiffList) > MAX_TRAFFIC_DIFF)
\r
5192 d = ZeroMallocFast(sizeof(TRAFFIC_DIFF));
\r
5193 d->HubName = CopyStr(h->Name);
\r
5194 d->Name = CopyStr(name);
\r
5196 Copy(&d->Traffic, traffic, sizeof(TRAFFIC));
\r
5198 LockList(h->Cedar->TrafficDiffList);
\r
5200 Insert(h->Cedar->TrafficDiffList, d);
\r
5202 UnlockList(h->Cedar->TrafficDiffList);
\r
5206 void CleanupHub(HUB *h)
\r
5209 char name[MAX_SIZE];
\r
5216 StrCpy(name, sizeof(name), h->Name);
\r
5218 if (h->WatchDogStarted)
\r
5220 StopHubWatchDog(h);
\r
5223 FreeAccessList(h);
\r
5225 if (h->RadiusServerName != NULL)
\r
5227 Free(h->RadiusServerName);
\r
5228 FreeBuf(h->RadiusSecret);
\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
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
5249 Free(h->SecureNATOption);
\r
5251 DeleteLock(h->TrafficLock);
\r
5253 for (i = 0;i < LIST_NUM(h->TicketList);i++)
\r
5255 Free(LIST_DATA(h->TicketList, i));
\r
5258 ReleaseList(h->TicketList);
\r
5260 DeleteLock(h->RadiusOptionLock);
\r
5262 FreeLog(h->PacketLogger);
\r
5263 FreeLog(h->SecurityLogger);
\r
5265 for (i = 0;i < LIST_NUM(h->AdminOptionList);i++)
\r
5267 Free(LIST_DATA(h->AdminOptionList, i));
\r
5269 ReleaseList(h->AdminOptionList);
\r
5271 if (h->Msg != NULL)
\r
5280 int CompareIpTable(void *p1, void *p2)
\r
5282 IP_TABLE_ENTRY *e1, *e2;
\r
5283 if (p1 == NULL || p2 == NULL)
\r
5287 e1 = *(IP_TABLE_ENTRY **)p1;
\r
5288 e2 = *(IP_TABLE_ENTRY **)p2;
\r
5289 if (e1 == NULL || e2 == NULL)
\r
5293 return CmpIpAddr(&e1->Ip, &e2->Ip);
\r
5297 int CompareMacTable(void *p1, void *p2)
\r
5300 MAC_TABLE_ENTRY *e1, *e2;
\r
5301 if (p1 == NULL || p2 == NULL)
\r
5305 e1 = *(MAC_TABLE_ENTRY **)p1;
\r
5306 e2 = *(MAC_TABLE_ENTRY **)p2;
\r
5307 if (e1 == NULL || e2 == NULL)
\r
5311 r = Cmp(e1->MacAddress, e2->MacAddress, 6);
\r
5316 if (e1->VlanId > e2->VlanId)
\r
5320 else if (e1->VlanId < e2->VlanId)
\r
5328 int CompareHub(void *p1, void *p2)
\r
5331 if (p1 == NULL || p2 == NULL)
\r
5337 if (h1 == NULL || h2 == NULL)
\r
5341 return StrCmpi(h1->Name, h2->Name);
\r
5344 // MAC アドレスが仮想 HUB の ARP ポーリング用の MAC アドレスかどうか調べる
\r
5345 bool IsHubMacAddress(UCHAR *mac)
\r
5353 if (mac[0] == 0x00 && mac[1] == SE_HUB_MAC_ADDR_SIGN)
\r
5361 // IP アドレスが仮想 HUB の ARP ポーリング用の IP アドレスかどうか調べる
\r
5362 bool IsHubIpAddress32(UINT ip32)
\r
5366 UINTToIP(&ip, ip32);
\r
5368 return IsHubIpAddress(&ip);
\r
5370 bool IsHubIpAddress(IP *ip)
\r
5378 if (ip->addr[0] == 172 && ip->addr[1] == 31)
\r
5380 if (ip->addr[2] >= 1 && ip->addr[2] <= 254)
\r
5382 if (ip->addr[3] >= 1 && ip->addr[3] <= 254)
\r
5391 bool IsHubIpAddress64(IPV6_ADDR *addr)
\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
5415 // 仮想 HUB 用 IP アドレスの生成
\r
5416 void GenHubIpAddress(IP *ip, char *name)
\r
5418 char tmp1[MAX_SIZE];
\r
5419 char tmp2[MAX_SIZE];
\r
5420 UCHAR hash[SHA1_SIZE];
\r
5422 if (ip == NULL || name == NULL)
\r
5427 StrCpy(tmp1, sizeof(tmp1), name);
\r
5429 GenerateMachineUniqueHash(hash);
\r
5430 BinToStr(tmp2, sizeof(tmp2), hash, sizeof(hash));
\r
5431 StrCat(tmp2, sizeof(tmp2), tmp1);
\r
5434 Hash(hash, tmp2, StrLen(tmp2), true);
\r
5436 Zero(ip, sizeof(IP));
\r
5437 ip->addr[0] = 172;
\r
5439 ip->addr[2] = hash[0] % 254 + 1;
\r
5440 ip->addr[3] = hash[1] % 254 + 1;
\r
5443 // 仮想 HUB 用 MAC アドレスの生成
\r
5444 void GenHubMacAddress(UCHAR *mac, char *name)
\r
5446 char tmp1[MAX_SIZE];
\r
5447 char tmp2[MAX_SIZE];
\r
5448 UCHAR hash[SHA1_SIZE];
\r
5450 if (mac == NULL || name == NULL)
\r
5455 StrCpy(tmp1, sizeof(tmp1), name);
\r
5457 GenerateMachineUniqueHash(hash);
\r
5458 BinToStr(tmp2, sizeof(tmp2), hash, sizeof(hash));
\r
5459 StrCat(tmp2, sizeof(tmp2), tmp1);
\r
5462 Hash(hash, tmp2, StrLen(tmp2), true);
\r
5465 mac[1] = SE_HUB_MAC_ADDR_SIGN;
\r
5473 wchar_t *GetHubMsg(HUB *h)
\r
5475 wchar_t *ret = NULL;
\r
5484 if (h->Msg != NULL)
\r
5486 ret = CopyUniStr(h->Msg);
\r
5495 void SetHubMsg(HUB *h, wchar_t *msg)
\r
5505 if (h->Msg != NULL)
\r
5511 if (UniIsEmptyStr(msg) == false)
\r
5513 h->Msg = UniCopyStr(msg);
\r
5520 HUB *NewHub(CEDAR *cedar, char *HubName, HUB_OPTION *option)
\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
5529 if (cedar == NULL || option == NULL || HubName == NULL)
\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
5541 AddRef(h->Cedar->ref);
\r
5542 h->Type = HUB_TYPE_STANDALONE;
\r
5544 ConvertSafeFileName(safe_hub_name, sizeof(safe_hub_name), HubName);
\r
5545 h->Name = CopyStr(safe_hub_name);
\r
5547 h->AdminOptionList = NewList(CompareAdminOption);
\r
5548 AddHubAdminOptionsDefaults(h, true);
\r
5550 h->LastCommTime = SystemTime64();
\r
5551 h->LastLoginTime = SystemTime64();
\r
5554 h->TrafficLock = NewLock();
\r
5556 h->HubDb = NewHubDb();
\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
5568 h->Traffic = NewTraffic();
\r
5569 h->OldTraffic = NewTraffic();
\r
5571 h->Option = ZeroMalloc(sizeof(HUB_OPTION));
\r
5572 Copy(h->Option, option, sizeof(HUB_OPTION));
\r
5574 if (h->Option->VlanTypeId == 0)
\r
5576 h->Option->VlanTypeId = MAC_PROTO_TAGVLAN;
\r
5579 Rand(h->HubSignature, sizeof(h->HubSignature));
\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
5587 if (h->Cedar != NULL && h->Cedar->Server != NULL && h->Cedar->Server->ServerType == SERVER_TYPE_FARM_CONTROLLER)
\r
5589 NiClearUnsupportedVhOptionForDynamicHub(h->SecureNATOption, true);
\r
5592 // HUB 用の一時的な MAC アドレスを生成する
\r
5593 GenerateMachineUniqueHash(hash);
\r
5594 GenHubMacAddress(h->HubMacAddr, h->Name);
\r
5595 GenHubIpAddress(&h->HubIp, h->Name);
\r
5597 // HUB 用 IPv6 アドレス
\r
5598 GenerateEui64LocalAddress(&ip6, h->HubMacAddr);
\r
5599 IPToIPv6Addr(&h->HubIpV6, &ip6);
\r
5601 h->RadiusOptionLock = NewLock();
\r
5602 h->RadiusServerPort = RADIUS_DEFAULT_PORT;
\r
5604 h->TicketList = NewList(NULL);
\r
5606 InitAccessList(h);
\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
5616 MakeDir(HUB_SECURITY_LOG_DIR_NAME);
\r
5617 MakeDir(HUB_PACKET_LOG_DIR_NAME);
\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
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
5627 if (h->Cedar->Server != NULL && h->Cedar->Server->ServerType == SERVER_TYPE_FARM_MEMBER)
\r
5629 h->FarmMember = true;
\r
5635 if (h->Cedar->Bridge)
\r
5637 h->Option->NoArpPolling = true;
\r
5640 if (h->Option->NoArpPolling == false && h->Option->NoIpTable == false)
\r
5642 StartHubWatchDog(h);
\r
5643 h->WatchDogStarted = true;
\r
5646 SLog(h->Cedar, "LS_HUB_START", h->Name);
\r
5648 MacToStr(tmp, sizeof(tmp), h->HubMacAddr);
\r
5649 SLog(h->Cedar, "LS_HUB_MAC", h->Name, tmp);
\r
5655 void DeleteHubDb(HUBDB *d)
\r
5663 LockList(d->UserList);
\r
5665 LockList(d->GroupList);
\r
5667 // すべてのユーザーとグループを解放
\r
5670 USERGROUP **groups;
\r
5672 users = ToArray(d->UserList);
\r
5673 groups = ToArray(d->GroupList);
\r
5675 for (i = 0;i < LIST_NUM(d->UserList);i++)
\r
5677 ReleaseUser(users[i]);
\r
5679 for (i = 0;i < LIST_NUM(d->GroupList);i++)
\r
5681 ReleaseGroup(groups[i]);
\r
5687 UnlockList(d->GroupList);
\r
5689 UnlockList(d->UserList);
\r
5692 LockList(d->RootCertList);
\r
5695 for (i = 0;i < LIST_NUM(d->RootCertList);i++)
\r
5697 X *x = LIST_DATA(d->RootCertList, i);
\r
5701 UnlockList(d->RootCertList);
\r
5704 LockList(d->CrlList);
\r
5707 for (i = 0;i < LIST_NUM(d->CrlList);i++)
\r
5709 CRL *crl = LIST_DATA(d->CrlList, i);
\r
5713 UnlockList(d->CrlList);
\r
5715 ReleaseList(d->GroupList);
\r
5716 ReleaseList(d->UserList);
\r
5717 ReleaseList(d->RootCertList);
\r
5718 ReleaseList(d->CrlList);
\r
5723 void GetHubLogSetting(HUB *h, HUB_LOG *setting)
\r
5726 if (setting == NULL || h == NULL)
\r
5731 Copy(setting, &h->LogSetting, sizeof(HUB_LOG));
\r
5735 void SetHubLogSettingEx(HUB *h, HUB_LOG *setting, bool no_change_switch_type)
\r
5739 if (setting == NULL || h == NULL)
\r
5744 i1 = h->LogSetting.PacketLogSwitchType;
\r
5745 i2 = h->LogSetting.SecurityLogSwitchType;
\r
5747 Copy(&h->LogSetting, setting, sizeof(HUB_LOG));
\r
5749 if (no_change_switch_type)
\r
5751 h->LogSetting.PacketLogSwitchType = i1;
\r
5752 h->LogSetting.SecurityLogSwitchType = i2;
\r
5756 SetLogSwitchType(h->PacketLogger, setting->PacketLogSwitchType);
\r
5757 SetLogSwitchType(h->SecurityLogger, setting->SecurityLogSwitchType);
\r
5759 void SetHubLogSetting(HUB *h, HUB_LOG *setting)
\r
5761 SetHubLogSettingEx(h, setting, false);
\r
5764 // HUB に信頼するルート証明書を追加する
\r
5765 void AddRootCert(HUB *hub, X *x)
\r
5769 if (hub == NULL || x == NULL)
\r
5777 LockList(db->RootCertList);
\r
5779 if (LIST_NUM(db->RootCertList) < MAX_HUB_CERTS)
\r
5784 for (i = 0;i < LIST_NUM(db->RootCertList);i++)
\r
5786 X *exist_x = LIST_DATA(db->RootCertList, i);
\r
5787 if (CompareX(exist_x, x))
\r
5796 Insert(db->RootCertList, CloneX(x));
\r
5800 UnlockList(db->RootCertList);
\r
5805 int CompareCert(void *p1, void *p2)
\r
5808 wchar_t tmp1[MAX_SIZE];
\r
5809 wchar_t tmp2[MAX_SIZE];
\r
5810 if (p1 == NULL || p2 == NULL)
\r
5816 if (x1 == NULL || x2 == NULL)
\r
5821 GetPrintNameFromX(tmp1, sizeof(tmp1), x1);
\r
5822 GetPrintNameFromX(tmp2, sizeof(tmp2), x2);
\r
5824 return UniStrCmpi(tmp1, tmp2);
\r
5830 HUBDB *d = ZeroMalloc(sizeof(HUBDB));
\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