source: lab/vendor/utvpn/utvpn-unix-v101-7101-public/src/Cedar/Hub.c

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