source: lab.git/Dev/utvpn/utvpn-unix-v101-7101-public/src/Cedar/Layer3.c @ a1bae3e

trunk
Last change on this file since a1bae3e was a1bae3e, checked in by mitty <mitty@…>, 12 years ago
  • copy vendor drop to trunk

git-svn-id: https://lab.mitty.jp/svn/lab/trunk@147 7d2118f6-f56c-43e7-95a2-4bb3031d96e7

  • Property mode set to 100644
File size: 45.4 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// Layer3.c
79// Layer-3 スイッチ モジュール
80
81#include "CedarPch.h"
82
83static UCHAR broadcast[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
84
85// IP キューの処理
86void L3PollingIpQueue(L3IF *f)
87{
88    L3PACKET *p;
89    // 引数チェック
90    if (f == NULL)
91    {
92        return;
93    }
94
95    // 別のセッションから来たパケットを処理する
96    while (p = GetNext(f->IpPacketQueue))
97    {
98        PKT *pkt = p->Packet;
99
100        // IP パケットとして送信する
101        L3SendIp(f, p);
102    }
103}
104
105// IP パケットの処理
106void L3RecvIp(L3IF *f, PKT *p, bool self)
107{
108    IPV4_HEADER *ip;
109    UINT header_size;
110    UINT next_hop = 0;
111    L3IF *dst;
112    L3PACKET *packet;
113    UINT new_ttl = 0;
114    // 引数チェック
115    if (f == NULL || p == NULL)
116    {
117        return;
118    }
119
120    ip = p->L3.IPv4Header;
121    header_size = IPV4_GET_HEADER_LEN(p->L3.IPv4Header) * 4;
122
123    // チェックサムの計算
124    if (IpCheckChecksum(ip) == false)
125    {
126        // チェックサムが一致しない
127        goto FREE_PACKET;
128    }
129
130    // ARP テーブルに登録
131    L3KnownArp(f, ip->SrcIP, p->MacAddressSrc);
132
133    if (p->BroadcastPacket)
134    {
135        // ブロードキャストパケットの場合はルーティングしない
136        goto FREE_PACKET;
137    }
138
139    // TTL を計算
140    if (ip->TimeToLive >= 1)
141    {
142        new_ttl = ip->TimeToLive - 1;
143    }
144    else
145    {
146        new_ttl = 0;
147    }
148
149    if (new_ttl == 0)
150    {
151        if (ip->DstIP != f->IpAddress)
152        {
153            UINT src_packet_size = p->PacketSize - sizeof(MAC_HEADER);
154            UINT icmp_packet_total_size = sizeof(MAC_HEADER) + sizeof(IPV4_HEADER) + sizeof(ICMP_HEADER) + 4 + header_size + 8;
155            UCHAR *buf;
156            IPV4_HEADER *ipv4;
157            ICMP_HEADER *icmpv4;
158            UCHAR *data;
159            PKT *pkt;
160            UINT data_size = MIN(p->PacketSize - header_size, header_size + 8);
161
162            // TTL 切れが発生したことを知らせる ICMP メッセージを生成する
163            buf = ZeroMalloc(icmp_packet_total_size);
164            ipv4 = (IPV4_HEADER *)(buf + sizeof(MAC_HEADER));
165            icmpv4 = (ICMP_HEADER *)(buf + sizeof(MAC_HEADER) + sizeof(IPV4_HEADER));
166            data = buf + sizeof(MAC_HEADER) + sizeof(IPV4_HEADER) + sizeof(ICMP_HEADER) + 4;
167
168            IPV4_SET_VERSION(ipv4, 4);
169            IPV4_SET_HEADER_LEN(ipv4, sizeof(IPV4_HEADER) / 4);
170            ipv4->TotalLength = Endian16((USHORT)(icmp_packet_total_size - sizeof(MAC_HEADER)));
171            ipv4->TimeToLive = 0xff;
172            ipv4->Protocol = IP_PROTO_ICMPV4;
173            ipv4->SrcIP = f->IpAddress;
174            ipv4->DstIP = ip->SrcIP;
175            ipv4->Checksum = IpChecksum(ipv4, sizeof(IPV4_HEADER));
176
177            icmpv4->Type = 11;
178            Copy(data, ip, data_size);
179            icmpv4->Checksum = IpChecksum(icmpv4, sizeof(ICMP_HEADER) + data_size + 4);
180
181            buf[12] = 0x08;
182            buf[13] = 0x00;
183
184            pkt = ParsePacket(buf, icmp_packet_total_size);
185            if (pkt == NULL)
186            {
187                Free(buf);
188            }
189            else
190            {
191                L3RecvIp(f, pkt, true);
192            }
193
194            // TTL が切れたパケット本体は破棄する
195            goto FREE_PACKET;
196        }
197    }
198
199    // 書き換える
200    p->L3.IPv4Header->TimeToLive = (UCHAR)new_ttl;
201
202    // 宛先 IP アドレスに対するインターフェイスを取得する
203    dst = L3GetNextIf(f->Switch, ip->DstIP, &next_hop);
204
205    if (dst == NULL && self == false)
206    {
207        UINT src_packet_size = p->PacketSize - sizeof(MAC_HEADER);
208        UINT icmp_packet_total_size = sizeof(MAC_HEADER) + sizeof(IPV4_HEADER) + sizeof(ICMP_HEADER) + 4 + header_size + 8;
209        UCHAR *buf;
210        IPV4_HEADER *ipv4;
211        ICMP_HEADER *icmpv4;
212        UCHAR *data;
213        PKT *pkt;
214            UINT data_size = MIN(p->PacketSize - header_size, header_size + 8);
215
216        // ルートが見つからない旨を ICMP で応答する
217        buf = ZeroMalloc(icmp_packet_total_size);
218        ipv4 = (IPV4_HEADER *)(buf + sizeof(MAC_HEADER));
219        icmpv4 = (ICMP_HEADER *)(buf + sizeof(MAC_HEADER) + sizeof(IPV4_HEADER));
220        data = buf + sizeof(MAC_HEADER) + sizeof(IPV4_HEADER) + sizeof(ICMP_HEADER) + 4;
221
222        IPV4_SET_VERSION(ipv4, 4);
223        IPV4_SET_HEADER_LEN(ipv4, sizeof(IPV4_HEADER) / 4);
224        ipv4->TotalLength = Endian16((USHORT)(icmp_packet_total_size - sizeof(MAC_HEADER)));
225        ipv4->TimeToLive = 0xff;
226        ipv4->Protocol = IP_PROTO_ICMPV4;
227        ipv4->SrcIP = f->IpAddress;
228        ipv4->DstIP = ip->SrcIP;
229        ipv4->Checksum = IpChecksum(ipv4, sizeof(IPV4_HEADER));
230
231        icmpv4->Type = 3;
232        Copy(data, ip, data_size);
233        icmpv4->Checksum = IpChecksum(icmpv4, sizeof(ICMP_HEADER) + data_size + 4);
234
235        buf[12] = 0x08;
236        buf[13] = 0x00;
237
238        pkt = ParsePacket(buf, icmp_packet_total_size);
239        if (pkt == NULL)
240        {
241            Free(buf);
242        }
243        else
244        {
245            L3RecvIp(f, pkt, true);
246        }
247
248        // ルートが見つからないパケット本体は破棄する
249        goto FREE_PACKET;
250    }
251
252    if (dst != NULL && ip->DstIP == dst->IpAddress)
253    {
254        bool free_packet = true;
255        // 自分宛の IP パケットが届いた
256        if (p->TypeL4 == L4_ICMPV4)
257        {
258            ICMP_HEADER *icmp = p->L4.ICMPHeader;
259            if (icmp->Type == ICMP_TYPE_ECHO_REQUEST)
260            {
261                // この IP パケットの宛先と送信元を書き換えて返信する
262                UINT src_ip, dst_ip;
263                src_ip = p->L3.IPv4Header->DstIP;
264                dst_ip = p->L3.IPv4Header->SrcIP;
265
266                p->L3.IPv4Header->DstIP = dst_ip;
267                p->L3.IPv4Header->SrcIP = src_ip;
268
269                ip->TimeToLive = 0xff;
270
271                // チェックサムを再計算する
272                ip->FlagsAndFlagmentOffset[0] = ip->FlagsAndFlagmentOffset[1] = 0;
273                icmp->Checksum = 0;
274                icmp->Type = ICMP_TYPE_ECHO_RESPONSE;
275                icmp->Checksum = IpChecksum(icmp, p->PacketSize - sizeof(MAC_HEADER) - header_size);
276
277                dst = L3GetNextIf(f->Switch, ip->DstIP, &next_hop);
278
279                free_packet = false;
280            }
281        }
282
283        if (free_packet)
284        {
285            goto FREE_PACKET;
286        }
287    }
288
289    if (dst == NULL)
290    {
291        // 宛先が存在しない
292        goto FREE_PACKET;
293    }
294
295    // IP チェックサムの再計算
296    ip->Checksum = 0;
297    ip->Checksum = IpChecksum(ip, header_size);
298
299    // Layer-3 パケットとして処理する
300    packet = ZeroMalloc(sizeof(L3PACKET));
301    packet->Expire = Tick64() + IP_WAIT_FOR_ARP_TIMEOUT;
302    packet->NextHopIp = next_hop;
303    packet->Packet = p;
304
305    // 宛先セッションにストアする
306    L3StoreIpPacketToIf(f, dst, packet);
307
308    return;
309
310FREE_PACKET:
311    // パケットの解放
312    Free(p->PacketData);
313    FreePacket(p);
314    return;
315}
316
317// レイヤ 2 パケットの処理
318void L3RecvL2(L3IF *f, PKT *p)
319{
320    // 引数チェック
321    if (f == NULL || p == NULL)
322    {
323        return;
324    }
325
326    // 自分が送信したパケットか、ユニキャストパケットで自分宛で無いパケット
327    // はすべて無視する
328    if (Cmp(p->MacAddressSrc, f->MacAddress, 6) == 0 ||
329        (p->BroadcastPacket == false && Cmp(p->MacAddressDest, f->MacAddress, 6) != 0))
330    {
331        // パケット解放
332        Free(p->PacketData);
333        FreePacket(p);
334        return;
335    }
336
337    if (p->TypeL3 == L3_ARPV4)
338    {
339        // ARP パケットを受信した
340        L3RecvArp(f, p);
341
342        // パケット解放
343        Free(p->PacketData);
344        FreePacket(p);
345    }
346    else if (p->TypeL3 == L3_IPV4)
347    {
348        // IP パケットを受信した
349        L3RecvIp(f, p, false);
350    }
351    else
352    {
353        // パケット解放
354        Free(p->PacketData);
355        FreePacket(p);
356    }
357}
358
359// IP パケットを別のインターフェイスにストアする
360void L3StoreIpPacketToIf(L3IF *src_if, L3IF *dst_if, L3PACKET *p)
361{
362    // 引数チェック
363    if (src_if == NULL || p == NULL || dst_if == NULL)
364    {
365        return;
366    }
367
368    // ストア先セッションのキューに追加する
369    InsertQueue(dst_if->IpPacketQueue, p);
370
371    // ストア先セッションの Cancel オブジェクトを叩くことにする
372    AddCancelList(src_if->CancelList, dst_if->Session->Cancel1);
373}
374
375// パケットを書き込む (新しいパケットが届いたので処理する)
376void L3PutPacket(L3IF *f, void *data, UINT size)
377{
378    PKT *p;
379    L3SW *s;
380    if (f == NULL)
381    {
382        return;
383    }
384
385    s = f->Switch;
386
387    if (data != NULL)
388    {
389        // 次のパケットを処理する
390        if (f->CancelList == NULL)
391        {
392            f->CancelList = NewCancelList();
393        }
394
395        // パケット解析
396        p = ParsePacket(data, size);
397
398        if (p == NULL)
399        {
400            // パケット解析失敗
401            Free(data);
402        }
403        else
404        {
405            // パケット解析成功
406            Lock(s->lock);
407            {
408                L3RecvL2(f, p);
409            }
410            Unlock(s->lock);
411        }
412    }
413    else
414    {
415        // すべてのパケットの処理が終わったらキャンセルリストをキャンセル処理する
416        if (f->CancelList != NULL)
417        {
418            CancelList(f->CancelList);
419            ReleaseCancelList(f->CancelList);
420            f->CancelList = NULL;
421        }
422    }
423}
424
425// 待機している IP パケットのうち送信先 MAC アドレスが解決したものを送信する
426void L3SendWaitingIp(L3IF *f, UCHAR *mac, UINT ip, L3ARPENTRY *a)
427{
428    UINT i;
429    LIST *o = NULL;
430    // 引数チェック
431    if (f == NULL || mac == NULL || a == NULL)
432    {
433        return;
434    }
435
436    for (i = 0;i < LIST_NUM(f->IpWaitList);i++)
437    {
438        L3PACKET *p = LIST_DATA(f->IpWaitList, i);
439
440        if (p->NextHopIp == ip)
441        {
442            if (o == NULL)
443            {
444                o = NewListFast(NULL);
445            }
446            Add(o, p);
447        }
448    }
449
450    if (o != NULL)
451    {
452        for (i = 0;i < LIST_NUM(o);i++)
453        {
454            L3PACKET *p = LIST_DATA(o, i);
455
456            // 送信
457            L3SendIpNow(f, a, p);
458
459            Delete(f->IpWaitList, p);
460            Free(p->Packet->PacketData);
461            FreePacket(p->Packet);
462            Free(p);
463        }
464
465        ReleaseList(o);
466    }
467}
468
469// ARP テーブルに登録する
470void L3InsertArpTable(L3IF *f, UINT ip, UCHAR *mac)
471{
472    L3ARPENTRY *a, t;
473    // 引数チェック
474    if (f == NULL || ip == 0 || ip == 0xffffffff || mac == NULL)
475    {
476        return;
477    }
478
479    Zero(&t, sizeof(t));
480    t.IpAddress = ip;
481
482    a = Search(f->ArpTable, &t);
483
484    if (a == NULL)
485    {
486        // リストに登録されていないので登録する
487        a = ZeroMalloc(sizeof(L3ARPENTRY));
488        a->IpAddress = ip;
489        Copy(a->MacAddress, mac, 6);
490        Insert(f->ArpTable, a);
491    }
492
493    // 有効期限を延長する
494    a->Expire = Tick64() + ARP_ENTRY_EXPIRES;
495
496    // 待機している IP パケットを送信させる
497    L3SendWaitingIp(f, mac, ip, a);
498}
499
500// ARP テーブルを知ったときに呼ばれる関数
501void L3KnownArp(L3IF *f, UINT ip, UCHAR *mac)
502{
503    L3ARPWAIT t, *w;
504    // 引数チェック
505    if (f == NULL || ip == 0 || ip == 0xffffffff || mac == NULL)
506    {
507        return;
508    }
509
510    // この IP アドレスへの ARP 問い合わせテーブルを削除する
511    Zero(&t, sizeof(t));
512    t.IpAddress = ip;
513    w = Search(f->IpWaitList, &t);
514    if (w != NULL)
515    {
516        Delete(f->IpWaitList, w);
517        Free(w);
518    }
519
520    // ARP テーブルに登録する
521    L3InsertArpTable(f, ip, mac);
522}
523
524// ARP を発行する
525void L3SendArp(L3IF *f, UINT ip)
526{
527    L3ARPWAIT t, *w;
528    // 引数チェック
529    if (f == NULL || ip == 0 || ip == 0xffffffff)
530    {
531        return;
532    }
533
534    // すでに登録されていないかどうか調べる
535    Zero(&t, sizeof(t));
536    t.IpAddress = ip;
537    w = Search(f->ArpWaitTable, &t);
538
539    if (w != NULL)
540    {
541        // すでに待機リストに登録されているので何もしない
542        return;
543    }
544    else
545    {
546        // 新しくリストに登録する
547        w = ZeroMalloc(sizeof(L3ARPWAIT));
548        w->Expire = Tick64() + ARP_REQUEST_GIVEUP;
549        w->IpAddress = ip;
550        Insert(f->ArpWaitTable, w);
551    }
552}
553
554// ARP 要求を受信した
555void L3RecvArpRequest(L3IF *f, PKT *p)
556{
557    ARPV4_HEADER *a;
558    // 引数チェック
559    if (f == NULL || p == NULL)
560    {
561        return;
562    }
563
564    a = p->L3.ARPv4Header;
565
566    L3KnownArp(f, a->SrcIP, a->SrcAddress);
567
568    if (a->TargetIP == f->IpAddress)
569    {
570        // 自分宛の ARP パケットの場合のみ応答する
571        L3SendArpResponseNow(f, a->SrcAddress, a->SrcIP, f->IpAddress);
572    }
573}
574
575// ARP 応答を受信した
576void L3RecvArpResponse(L3IF *f, PKT *p)
577{
578    ARPV4_HEADER *a;
579    // 引数チェック
580    if (f == NULL || p == NULL)
581    {
582        return;
583    }
584
585    a = p->L3.ARPv4Header;
586
587    L3KnownArp(f, a->SrcIP, a->SrcAddress);
588}
589
590// ARP パケットを受信した
591void L3RecvArp(L3IF *f, PKT *p)
592{
593    ARPV4_HEADER *a;
594    // 引数チェック
595    if (f == NULL || p == NULL)
596    {
597        return;
598    }
599
600    a = p->L3.ARPv4Header;
601
602    if (Endian16(a->HardwareType) != ARP_HARDWARE_TYPE_ETHERNET ||
603        Endian16(a->ProtocolType) != MAC_PROTO_IPV4 ||
604        a->HardwareSize != 6 || a->ProtocolSize != 4)
605    {
606        return;
607    }
608    if (Cmp(a->SrcAddress, p->MacAddressSrc, 6) != 0)
609    {
610        return;
611    }
612
613    switch (Endian16(a->Operation))
614    {
615    case ARP_OPERATION_REQUEST:
616        // ARP 要求が届いた
617        L3RecvArpRequest(f, p);
618        break;
619
620    case ARP_OPERATION_RESPONSE:
621        // ARP 応答が届いた
622        L3RecvArpResponse(f, p);
623        break;
624    }
625}
626
627// IP パケットを送信する
628void L3SendIp(L3IF *f, L3PACKET *p)
629{
630    L3ARPENTRY *a = NULL;
631    bool broadcast = false;
632    IPV4_HEADER *ip;
633    bool for_me = false;
634    // 引数チェック
635    if (f == NULL || p == NULL)
636    {
637        return;
638    }
639    if (p->Packet->TypeL3 != L3_IPV4)
640    {
641        return;
642    }
643
644    ip = p->Packet->L3.IPv4Header;
645
646    // ブロードキャストかどうか判定
647    if (p->NextHopIp == 0xffffffff ||
648        ((p->NextHopIp & f->SubnetMask) == (f->IpAddress & f->SubnetMask)) &&
649        ((p->NextHopIp & (~f->SubnetMask)) == (~f->SubnetMask)))
650    {
651        broadcast = true;
652    }
653
654    if (broadcast == false && ip->DstIP == f->IpAddress)
655    {
656        // me?
657    }
658    else if (broadcast == false)
659    {
660        // ユニキャストの場合 ARP エントリに入っているかどうか調べる
661        a = L3SearchArpTable(f, p->NextHopIp);
662
663        if (a == NULL)
664        {
665            // ARP エントリに入っていないので、すぐに送信せずに
666            // IP 待ちリストに挿入する
667            p->Expire = Tick64() + IP_WAIT_FOR_ARP_TIMEOUT;
668
669            Insert(f->IpWaitList, p);
670
671            // ARP を発行しておく
672            L3SendArp(f, p->NextHopIp);
673            return;
674        }
675    }
676
677    if (for_me == false)
678    {
679        // IP パケットを送信する
680        L3SendIpNow(f, a, p);
681    }
682
683    // パケットを解放する
684    Free(p->Packet->PacketData);
685    FreePacket(p->Packet);
686    Free(p);
687}
688
689// IP パケットをすぐに送信する
690void L3SendIpNow(L3IF *f, L3ARPENTRY *a, L3PACKET *p)
691{
692    // 引数チェック
693    if (f == NULL || p == NULL)
694    {
695        return;
696    }
697
698    L3SendL2Now(f, a != NULL ? a->MacAddress : broadcast, f->MacAddress, Endian16(p->Packet->MacHeader->Protocol),
699        p->Packet->L3.PointerL3, p->Packet->PacketSize - sizeof(MAC_HEADER));
700}
701
702// ARP テーブルを検索する
703L3ARPENTRY *L3SearchArpTable(L3IF *f, UINT ip)
704{
705    L3ARPENTRY *e, t;
706    // 引数チェック
707    if (f == NULL || ip == 0 || ip == 0xffffffff)
708    {
709        return NULL;
710    }
711
712    Zero(&t, sizeof(t));
713    t.IpAddress = ip;
714
715    e = Search(f->ArpTable, &t);
716
717    return e;
718}
719
720// ARP 要求パケットを送信する
721void L3SendArpRequestNow(L3IF *f, UINT dest_ip)
722{
723    ARPV4_HEADER arp;
724    // 引数チェック
725    if (f == NULL)
726    {
727        return;
728    }
729
730    // ARP ヘッダを構築
731    arp.HardwareType = Endian16(ARP_HARDWARE_TYPE_ETHERNET);
732    arp.ProtocolType = Endian16(MAC_PROTO_IPV4);
733    arp.HardwareSize = 6;
734    arp.ProtocolSize = 4;
735    arp.Operation = Endian16(ARP_OPERATION_REQUEST);
736    Copy(arp.SrcAddress, f->MacAddress, 6);
737    arp.SrcIP = f->IpAddress;
738    Zero(&arp.TargetAddress, 6);
739    arp.TargetIP = dest_ip;
740
741    // 送信
742    L3SendL2Now(f, broadcast, f->MacAddress, MAC_PROTO_ARPV4, &arp, sizeof(arp));
743}
744
745// ARP 応答パケットを送信する
746void L3SendArpResponseNow(L3IF *f, UCHAR *dest_mac, UINT dest_ip, UINT src_ip)
747{
748    ARPV4_HEADER arp;
749    // 引数チェック
750    if (f == NULL || dest_mac == NULL)
751    {
752        return;
753    }
754
755    // ヘッダ構築
756    arp.HardwareType = Endian16(ARP_HARDWARE_TYPE_ETHERNET);
757    arp.ProtocolType = Endian16(MAC_PROTO_IPV4);
758    arp.HardwareSize = 6;
759    arp.ProtocolSize = 4;
760    arp.Operation = Endian16(ARP_OPERATION_RESPONSE);
761    Copy(arp.SrcAddress, f->MacAddress, 6);
762    Copy(arp.TargetAddress, dest_mac, 6);
763    arp.SrcIP = src_ip;
764    arp.TargetIP = dest_ip;
765
766    // 送信
767    L3SendL2Now(f, dest_mac, f->MacAddress, MAC_PROTO_ARPV4, &arp, sizeof(arp));
768}
769
770// インターフェイスの MAC アドレスの生成
771void L3GenerateMacAddress(L3IF *f)
772{
773    BUF *b;
774    UCHAR hash[SHA1_SIZE];
775    // 引数チェック
776    if (f == NULL)
777    {
778        return;
779    }
780
781    b = NewBuf();
782    WriteBuf(b, f->Switch->Name, StrLen(f->Switch->Name));
783    WriteBuf(b, f->HubName, StrLen(f->HubName));
784    WriteBuf(b, &f->IpAddress, sizeof(f->IpAddress));
785
786    GenMacAddress(f->MacAddress);
787    Hash(hash, b->Buf, b->Size, true);
788    Copy(f->MacAddress + 2, hash, 4);
789    f->MacAddress[1] = 0xA3;
790    FreeBuf(b);
791}
792
793// L2 パケットをすぐに送信する
794void L3SendL2Now(L3IF *f, UCHAR *dest_mac, UCHAR *src_mac, USHORT protocol, void *data, UINT size)
795{
796    UCHAR *buf;
797    MAC_HEADER *mac_header;
798    PKT *p;
799    // 引数チェック
800    if (f == NULL || dest_mac == NULL || src_mac == NULL || data == NULL)
801    {
802        return;
803    }
804
805    // バッファ生成
806    buf = Malloc(MAC_HEADER_SIZE + size);
807
808    // MAC ヘッダ
809    mac_header = (MAC_HEADER *)&buf[0];
810    Copy(mac_header->DestAddress, dest_mac, 6);
811    Copy(mac_header->SrcAddress, src_mac, 6);
812    mac_header->Protocol = Endian16(protocol);
813
814    // データのコピー
815    Copy(&buf[sizeof(MAC_HEADER)], data, size);
816
817    // サイズ
818    size += sizeof(MAC_HEADER);
819
820    // パケット生成
821    p = ZeroMalloc(sizeof(PKT));
822    p->PacketData = buf;
823    p->PacketSize = size;
824
825    // キューに追加する
826    InsertQueue(f->SendQueue, p);
827}
828
829// ARP 解決待ちリストのポーリング
830void L3PollingArpWaitTable(L3IF *f)
831{
832    UINT i;
833    LIST *o = NULL;
834    // 引数チェック
835    if (f == NULL)
836    {
837        return;
838    }
839
840    for (i = 0;i < LIST_NUM(f->ArpWaitTable);i++)
841    {
842        L3ARPWAIT *w = LIST_DATA(f->ArpWaitTable, i);
843
844        if (w->Expire <= Tick64())
845        {
846            // ARP 要求テーブルが期限切れである
847            if (o == NULL)
848            {
849                o = NewListFast(NULL);
850            }
851
852            Insert(o, w);
853        }
854        else if ((w->LastSentTime + ARP_REQUEST_TIMEOUT) <= Tick64())
855        {
856            // 次の ARP 要求パケットを送信する
857            w->LastSentTime = Tick64();
858
859            L3SendArpRequestNow(f, w->IpAddress);
860        }
861    }
862
863    if (o != NULL)
864    {
865        for (i = 0;i < LIST_NUM(o);i++)
866        {
867            L3ARPWAIT *w = LIST_DATA(o, i);
868
869            Delete(f->ArpWaitTable, w);
870            Free(w);
871        }
872
873        ReleaseList(o);
874    }
875}
876
877// 古い ARP テーブルの清掃
878void L3DeleteOldArpTable(L3IF *f)
879{
880    UINT i;
881    LIST *o = NULL;
882    // 引数チェック
883    if (f == NULL)
884    {
885        return;
886    }
887
888    if ((f->LastDeleteOldArpTable + ARP_ENTRY_POLLING_TIME) > Tick64())
889    {
890        return;
891    }
892    f->LastDeleteOldArpTable = Tick64();
893
894    for (i = 0;i < LIST_NUM(f->ArpTable);i++)
895    {
896        L3ARPENTRY *a = LIST_DATA(f->ArpTable, i);
897
898        if (a->Expire <= Tick64())
899        {
900            // 有効期限切れ
901            if (o == NULL)
902            {
903                o = NewListFast(NULL);
904            }
905
906            Insert(o, a);
907        }
908    }
909
910    if (o != NULL)
911    {
912        for (i = 0;i < LIST_NUM(o);i++)
913        {
914            L3ARPENTRY *a = LIST_DATA(o, i);
915
916            Delete(f->ArpTable, a);
917            Free(a);
918        }
919
920        ReleaseList(o);
921    }
922}
923
924// IP 待ちリストの清掃
925void L3DeleteOldIpWaitList(L3IF *f)
926{
927    UINT i;
928    LIST *o = NULL;
929    // 引数チェック
930    if (f == NULL)
931    {
932        return;
933    }
934
935    for (i = 0;i < LIST_NUM(f->IpWaitList);i++)
936    {
937        L3PACKET *p = LIST_DATA(f->IpWaitList, i);
938
939        if (p->Expire <= Tick64())
940        {
941            if (o == NULL)
942            {
943                o = NewListFast(NULL);
944            }
945
946            Insert(o, p);
947        }
948    }
949
950    if (o != NULL)
951    {
952        for (i = 0;i < LIST_NUM(o);i++)
953        {
954            L3PACKET *p = LIST_DATA(o, i);
955
956            Delete(f->IpWaitList, p);
957
958            Free(p->Packet->PacketData);
959            FreePacket(p->Packet);
960            Free(p);
961        }
962
963        ReleaseList(o);
964    }
965}
966
967// ビーコン送信
968void L3PollingBeacon(L3IF *f)
969{
970    // 引数チェック
971    if (f == NULL)
972    {
973        return;
974    }
975
976    if (f->LastBeaconSent == 0 ||
977        (f->LastBeaconSent + BEACON_SEND_INTERVAL) <= Tick64())
978    {
979        UINT dest_ip;
980        UCHAR *udp_buf;
981        UINT udp_buf_size;
982        ARPV4_HEADER arp;
983        IPV4_HEADER *ip;
984        UDP_HEADER *udp;
985        static char beacon_str[] =
986            "SoftEther UT-VPN Virtual Layer-3 Switch Beacon";
987
988        // UDP を送信
989        dest_ip = (f->IpAddress & f->SubnetMask) | (~f->SubnetMask);
990        udp_buf_size = sizeof(IPV4_HEADER) + sizeof(UDP_HEADER) + sizeof(beacon_str);
991        udp_buf = ZeroMalloc(udp_buf_size);
992
993        ip = (IPV4_HEADER *)udp_buf;
994        udp = (UDP_HEADER *)(udp_buf + sizeof(IPV4_HEADER));
995        udp->DstPort = Endian16(7);
996        udp->SrcPort = Endian16(7);
997        udp->PacketLength = Endian16(sizeof(UDP_HEADER) + sizeof(beacon_str));
998
999        Copy(udp_buf + sizeof(IPV4_HEADER) + sizeof(UDP_HEADER), beacon_str, sizeof(beacon_str));
1000
1001        udp->Checksum = IpChecksum(udp, sizeof(UDP_HEADER) + sizeof(beacon_str));
1002
1003        ip->DstIP = dest_ip;
1004        IPV4_SET_VERSION(ip, 4);
1005        IPV4_SET_HEADER_LEN(ip, (IP_HEADER_SIZE / 4));
1006        ip->TypeOfService = DEFAULT_IP_TOS;
1007        ip->TotalLength = Endian16((USHORT)(udp_buf_size));
1008        ip->TimeToLive = DEFAULT_IP_TTL;
1009        ip->Protocol = IP_PROTO_UDP;
1010        ip->SrcIP = f->IpAddress;
1011        ip->Checksum = IpChecksum(ip, IP_HEADER_SIZE);
1012
1013        L3SendL2Now(f, broadcast, f->MacAddress, MAC_PROTO_IPV4, udp_buf, udp_buf_size);
1014
1015        Free(udp_buf);
1016
1017        // ARP ヘッダを構築
1018        arp.HardwareType = Endian16(ARP_HARDWARE_TYPE_ETHERNET);
1019        arp.ProtocolType = Endian16(MAC_PROTO_IPV4);
1020        arp.HardwareSize = 6;
1021        arp.ProtocolSize = 4;
1022        arp.Operation = Endian16(ARP_OPERATION_RESPONSE);
1023        Copy(arp.SrcAddress, f->MacAddress, 6);
1024        arp.SrcIP = f->IpAddress;
1025        arp.TargetAddress[0] =
1026            arp.TargetAddress[1] =
1027            arp.TargetAddress[2] =
1028            arp.TargetAddress[3] =
1029            arp.TargetAddress[4] =
1030            arp.TargetAddress[5] = 0xff;
1031        arp.TargetIP = dest_ip;
1032
1033        // 送信
1034        L3SendL2Now(f, broadcast, f->MacAddress, MAC_PROTO_ARPV4, &arp, sizeof(arp));
1035
1036        f->LastBeaconSent = Tick64();
1037    }
1038}
1039
1040// ポーリング処理
1041void L3Polling(L3IF *f)
1042{
1043    L3SW *s;
1044    // 引数チェック
1045    if (f == NULL)
1046    {
1047        return;
1048    }
1049
1050    s = f->Switch;
1051
1052    // ポーリング処理の途中ではスイッチ全体にロックをかける
1053    Lock(s->lock);
1054    {
1055        // ビーコン送信
1056        L3PollingBeacon(f);
1057
1058        // IP キューの処理
1059        L3PollingIpQueue(f);
1060
1061        // 古い ARP テーブルの清掃
1062        L3DeleteOldArpTable(f);
1063
1064        // ARP 解決待ちリストのポーリング
1065        L3PollingArpWaitTable(f);
1066
1067        // IP 待ちリストの清掃
1068        L3DeleteOldIpWaitList(f);
1069    }
1070    Unlock(s->lock);
1071}
1072
1073// 次のパケットを取得する
1074UINT L3GetNextPacket(L3IF *f, void **data)
1075{
1076    UINT ret = 0;
1077    // 引数チェック
1078    if (f == NULL || data == NULL)
1079    {
1080        return 0;
1081    }
1082
1083START:
1084    // 送信キューを調べる
1085    LockQueue(f->SendQueue);
1086    {
1087        PKT *p = GetNext(f->SendQueue);
1088
1089        if (p != NULL)
1090        {
1091            // パケットがあった
1092            ret = p->PacketSize;
1093            *data = p->PacketData;
1094            // パケット構造体は破棄して良い
1095            Free(p);
1096        }
1097    }
1098    UnlockQueue(f->SendQueue);
1099
1100    if (ret == 0)
1101    {
1102        // ポーリング処理
1103        L3Polling(f);
1104
1105        // ポーリング処理の結果、新たにパケットがキューに入っていないか
1106        // どうか調べる
1107        if (f->SendQueue->num_item != 0)
1108        {
1109            // キューに入っていたら早速そのパケットを取得させる
1110            goto START;
1111        }
1112    }
1113
1114    return ret;
1115}
1116
1117// 指定した IP アドレス宛のパケットをどのインターフェイスに投げれば良いか決める
1118L3IF *L3GetNextIf(L3SW *s, UINT ip, UINT *next_hop)
1119{
1120    UINT i;
1121    L3IF *f;
1122    UINT next_hop_ip = 0;
1123    // 引数チェック
1124    if (s == NULL || ip == 0 || ip == 0xffffffff)
1125    {
1126        return NULL;
1127    }
1128
1129    f = NULL;
1130
1131    // まず各インターフェイスの所属しているネットワークに指定した IP アドレスが
1132    // 含まれるものが無いかどうか調べる
1133    for (i = 0;i < LIST_NUM(s->IfList);i++)
1134    {
1135        L3IF *ff = LIST_DATA(s->IfList, i);
1136
1137        if ((ff->IpAddress & ff->SubnetMask) == (ip & ff->SubnetMask))
1138        {
1139            f = ff;
1140            next_hop_ip = ip;
1141            break;
1142        }
1143    }
1144
1145    if (f == NULL)
1146    {
1147        // 見つからなかったらルーティングテーブルを探す
1148        L3TABLE *t = L3GetBestRoute(s, ip);
1149
1150        if (t == NULL)
1151        {
1152            // それでも見つからなかった
1153            return NULL;
1154        }
1155        else
1156        {
1157            // 見つかったルートの NextHop のルータの IP アドレスを持つ
1158            // インターフェイスを探す
1159            for (i = 0;i < LIST_NUM(s->IfList);i++)
1160            {
1161                L3IF *ff = LIST_DATA(s->IfList, i);
1162
1163                if ((ff->IpAddress & ff->SubnetMask) == (t->GatewayAddress & ff->SubnetMask))
1164                {
1165                    f = ff;
1166                    next_hop_ip = t->GatewayAddress;
1167                    break;
1168                }
1169            }
1170        }
1171    }
1172
1173    if (f == NULL)
1174    {
1175        // 結局宛先インターフェイスが不明であった
1176        return NULL;
1177    }
1178
1179    if (next_hop != NULL)
1180    {
1181        *next_hop = next_hop_ip;
1182    }
1183
1184    return f;
1185}
1186
1187// 指定した IP アドレス宛の最適なルーティングテーブルエントリを取得する
1188L3TABLE *L3GetBestRoute(L3SW *s, UINT ip)
1189{
1190    UINT i;
1191    UINT max_mask = 0;
1192    UINT min_metric = INFINITE;
1193    L3TABLE *ret = NULL;
1194    // 引数チェック
1195    if (s == NULL || ip == 0)
1196    {
1197        return NULL;
1198    }
1199
1200    // 第一条件: サブネットマスクが最も大きいものを選択
1201    // 第二条件: メトリックが最も小さいものを選択
1202    for (i = 0;i < LIST_NUM(s->TableList);i++)
1203    {
1204        L3TABLE *t = LIST_DATA(s->TableList, i);
1205
1206        if ((t->NetworkAddress & t->SubnetMask) == (ip & t->SubnetMask))
1207        {
1208            if (t->SubnetMask >= max_mask)
1209            {
1210                max_mask = t->SubnetMask;
1211                if (min_metric >= t->Metric)
1212                {
1213                    min_metric = t->Metric;
1214                    ret = t;
1215                }
1216            }
1217        }
1218    }
1219
1220    return ret;
1221}
1222
1223// Layer-3 インターフェイスの初期化
1224void L3InitInterface(L3IF *f)
1225{
1226    // 引数チェック
1227    if (f == NULL)
1228    {
1229        return;
1230    }
1231
1232    // MAC アドレス生成
1233    L3GenerateMacAddress(f);
1234
1235    // リスト生成
1236    f->ArpTable = NewList(CmpL3ArpEntry);
1237    f->ArpWaitTable = NewList(CmpL3ArpWaitTable);
1238    f->IpPacketQueue = NewQueue();
1239    f->IpWaitList = NewList(NULL);
1240    f->SendQueue = NewQueue();
1241}
1242
1243// Layer-3 インターフェイスの解放
1244void L3FreeInterface(L3IF *f)
1245{
1246    UINT i;
1247    L3PACKET *p;
1248    PKT *pkt;
1249    // 引数チェック
1250    if (f == NULL)
1251    {
1252        return;
1253    }
1254
1255    for (i = 0;i < LIST_NUM(f->ArpTable);i++)
1256    {
1257        L3ARPENTRY *a = LIST_DATA(f->ArpTable, i);
1258        Free(a);
1259    }
1260    ReleaseList(f->ArpTable);
1261    f->ArpTable = NULL;
1262
1263    for (i = 0;i < LIST_NUM(f->ArpWaitTable);i++)
1264    {
1265        L3ARPWAIT *w = LIST_DATA(f->ArpWaitTable, i);
1266        Free(w);
1267    }
1268    ReleaseList(f->ArpWaitTable);
1269    f->ArpWaitTable = NULL;
1270
1271    while (p = GetNext(f->IpPacketQueue))
1272    {
1273        Free(p->Packet->PacketData);
1274        FreePacket(p->Packet);
1275        Free(p);
1276    }
1277    ReleaseQueue(f->IpPacketQueue);
1278    f->IpPacketQueue = NULL;
1279
1280    for (i = 0;i < LIST_NUM(f->IpWaitList);i++)
1281    {
1282        L3PACKET *p = LIST_DATA(f->IpWaitList, i);
1283        Free(p->Packet->PacketData);
1284        FreePacket(p->Packet);
1285        Free(p);
1286    }
1287    ReleaseList(f->IpWaitList);
1288    f->IpWaitList = NULL;
1289
1290    while (pkt = GetNext(f->SendQueue))
1291    {
1292        Free(pkt->PacketData);
1293        FreePacket(pkt);
1294    }
1295    ReleaseQueue(f->SendQueue);
1296    f->SendQueue = NULL;
1297}
1298
1299// Layer-3 インターフェイスのスレッド
1300void L3IfThread(THREAD *t, void *param)
1301{
1302    L3IF *f;
1303    CONNECTION *c;
1304    SESSION *s;
1305    POLICY *policy;
1306    char tmp[MAX_SIZE];
1307    char name[MAX_SIZE];
1308    char username[MAX_SIZE];
1309    // 引数チェック
1310    if (t == NULL || param == NULL)
1311    {
1312        return;
1313    }
1314
1315    f = (L3IF *)param;
1316
1317    StrCpy(username, sizeof(username), L3_USERNAME);
1318    if (f->Switch != NULL)
1319    {
1320        StrCat(username, sizeof(username), f->Switch->Name);
1321    }
1322
1323    // コネクションの作成
1324    c = NewServerConnection(f->Switch->Cedar, NULL, t);
1325    c->Protocol = CONNECTION_HUB_LAYER3;
1326
1327    // セッションの作成
1328    policy = ClonePolicy(GetDefaultPolicy());
1329    // ポリシーではブロードキャスト数を制限しない
1330    policy->NoBroadcastLimiter = true;
1331    s = NewServerSession(f->Switch->Cedar, c, f->Hub, username, policy);
1332    c->Session = s;
1333
1334    ReleaseConnection(c);
1335
1336    // セッション名を決定する
1337    GetMachineHostName(tmp, sizeof(tmp));
1338    if (f->Switch->Cedar->Server->ServerType == SERVER_TYPE_STANDALONE)
1339    {
1340        Format(name, sizeof(name), "SID-L3-%s-%u", f->Switch->Name, Inc(f->Hub->SessionCounter));
1341    }
1342    else
1343    {
1344        Format(name, sizeof(name), "SID-L3-%s-%s-%u", tmp, f->Switch->Name, Inc(f->Hub->SessionCounter));
1345    }
1346    ConvertSafeFileName(name, sizeof(name), name);
1347    StrUpper(name);
1348
1349    Free(s->Name);
1350    s->Name = CopyStr(name);
1351
1352    s->L3SwitchMode = true;
1353    s->L3If = f;
1354
1355    if (s->Username != NULL)
1356    {
1357        Free(s->Username);
1358    }
1359    s->Username = CopyStr(username);
1360
1361    StrCpy(s->UserNameReal, sizeof(s->UserNameReal), username);
1362
1363    f->Session = s;
1364    AddRef(s->ref);
1365
1366    // 初期化完了を通知
1367    NoticeThreadInit(t);
1368
1369    // セッションメイン処理
1370    SessionMain(s);
1371
1372    // セッションの解放
1373    ReleaseSession(s);
1374}
1375
1376// すべての Layer-3 インターフェイスの初期化をする
1377void L3InitAllInterfaces(L3SW *s)
1378{
1379    UINT i;
1380    // 引数チェック
1381    if (s == NULL)
1382    {
1383        return;
1384    }
1385
1386    for (i = 0;i < LIST_NUM(s->IfList);i++)
1387    {
1388        L3IF *f = LIST_DATA(s->IfList, i);
1389        THREAD *t;
1390
1391        L3InitInterface(f);
1392
1393        f->Hub = GetHub(s->Cedar, f->HubName);
1394        t = NewThread(L3IfThread, f);
1395        WaitThreadInit(t);
1396        ReleaseThread(t);
1397    }
1398}
1399
1400// すべての Layer-3 インターフェイスの解放をする
1401void L3FreeAllInterfaces(L3SW *s)
1402{
1403    UINT i;
1404    // 引数チェック
1405    if (s == NULL)
1406    {
1407        return;
1408    }
1409
1410    for (i = 0;i < LIST_NUM(s->IfList);i++)
1411    {
1412        L3IF *f = LIST_DATA(s->IfList, i);
1413
1414        ReleaseHub(f->Hub);
1415        f->Hub = NULL;
1416        ReleaseSession(f->Session);
1417        f->Session = NULL;
1418
1419        L3FreeInterface(f);
1420    }
1421}
1422
1423// Layer-3 テスト
1424void L3Test(SERVER *s)
1425{
1426    L3SW *ss = L3AddSw(s->Cedar, "TEST");
1427    L3AddIf(ss, "DEFAULT", 0x0101a8c0, 0x00ffffff);
1428    L3AddIf(ss, "DEFAULT2", 0x0102a8c0, 0x00ffffff);
1429    L3SwStart(ss);
1430    ReleaseL3Sw(ss);
1431}
1432
1433// Layer-3 スイッチスレッド
1434void L3SwThread(THREAD *t, void *param)
1435{
1436    L3SW *s;
1437    bool shutdown_now = false;
1438    // 引数チェック
1439    if (t == NULL || param == NULL)
1440    {
1441        return;
1442    }
1443
1444    s = (L3SW *)param;
1445
1446    s->Active = true;
1447
1448    NoticeThreadInit(t);
1449
1450    // 動作開始
1451    SLog(s->Cedar, "L3_SWITCH_START", s->Name);
1452
1453    while (s->Halt == false)
1454    {
1455        if (s->Online == false)
1456        {
1457            // 現在 L3 スイッチはオフラインなので、一定時間ごとにオンライン化
1458            // を試みる
1459            LockList(s->Cedar->HubList);
1460            {
1461                Lock(s->lock);
1462                {
1463                    UINT i;
1464                    UINT n = 0;
1465                    bool all_exists = true;
1466                    if (LIST_NUM(s->IfList) == 0)
1467                    {
1468                        // 1 つもインターフェイスが無い場合は動作しない
1469                        all_exists = false;
1470                    }
1471                    for (i = 0;i < LIST_NUM(s->IfList);i++)
1472                    {
1473                        L3IF *f = LIST_DATA(s->IfList, i);
1474                        HUB *h = GetHub(s->Cedar, f->HubName);
1475
1476                        if (h != NULL)
1477                        {
1478                            if (h->Offline || h->Type == HUB_TYPE_FARM_DYNAMIC)
1479                            {
1480                                all_exists = false;
1481                            }
1482                            else
1483                            {
1484                                n++;
1485                            }
1486                            ReleaseHub(h);
1487                        }
1488                        else
1489                        {
1490                            all_exists = false;
1491                        }
1492                    }
1493
1494                    if (all_exists && n >= 1)
1495                    {
1496                        // すべてのインターフェイスの仮想 HUB が有効になったので
1497                        // 動作を開始する
1498                        SLog(s->Cedar, "L3_SWITCH_ONLINE", s->Name);
1499                        L3InitAllInterfaces(s);
1500                        s->Online = true;
1501                    }
1502                }
1503                Unlock(s->lock);
1504            }
1505            UnlockList(s->Cedar->HubList);
1506        }
1507        else
1508        {
1509            // 一定時間ごとにすべてのセッションが終了していないかどうか調査する
1510            UINT i;
1511            bool any_halted = false;
1512            LIST *o = NULL;
1513
1514SHUTDOWN:
1515
1516            Lock(s->lock);
1517            {
1518                for (i = 0;i < LIST_NUM(s->IfList);i++)
1519                {
1520                    L3IF *f = LIST_DATA(s->IfList, i);
1521                    if (f->Session->Halt || f->Hub->Offline != false)
1522                    {
1523                        any_halted = true;
1524                        break;
1525                    }
1526                }
1527
1528                if (shutdown_now)
1529                {
1530                    any_halted = true;
1531                }
1532
1533                if (any_halted)
1534                {
1535                    SLog(s->Cedar, "L3_SWITCH_OFFLINE", s->Name);
1536                    o = NewListFast(NULL);
1537                    // 1 つでも終了したセッションがあれば、すべてのセッションを終了する
1538                    for (i = 0;i < LIST_NUM(s->IfList);i++)
1539                    {
1540                        L3IF *f = LIST_DATA(s->IfList, i);
1541                        Insert(o, f->Session);
1542                    }
1543
1544                    // オフラインに戻す
1545                    s->Online = false;
1546                }
1547            }
1548            Unlock(s->lock);
1549
1550            if (o != NULL)
1551            {
1552                UINT i;
1553                for (i = 0;i < LIST_NUM(o);i++)
1554                {
1555                    SESSION *s = LIST_DATA(o, i);
1556                    StopSession(s);
1557                }
1558                L3FreeAllInterfaces(s);
1559                ReleaseList(o);
1560                o = NULL;
1561            }
1562        }
1563
1564        SleepThread(50);
1565    }
1566
1567    if (s->Online != false)
1568    {
1569        shutdown_now = true;
1570        goto SHUTDOWN;
1571    }
1572
1573    // 動作停止
1574    SLog(s->Cedar, "L3_SWITCH_STOP", s->Name);
1575}
1576
1577// Layer-3 スイッチを開始する
1578void L3SwStart(L3SW *s)
1579{
1580    // 引数チェック
1581    if (s == NULL)
1582    {
1583        return;
1584    }
1585
1586    Lock(s->lock);
1587    {
1588        if (s->Active == false)
1589        {
1590            // 登録されている IF 数が 1 以上でないと開始しない
1591            if (LIST_NUM(s->IfList) >= 1)
1592            {
1593                s->Halt = false;
1594
1595                // スレッド作成
1596                s->Thread = NewThread(L3SwThread, s);
1597                WaitThreadInit(s->Thread);
1598            }
1599        }
1600    }
1601    Unlock(s->lock);
1602}
1603
1604// Layer-3 スイッチを停止する
1605void L3SwStop(L3SW *s)
1606{
1607    THREAD *t = NULL;
1608    // 引数チェック
1609    if (s == NULL)
1610    {
1611        return;
1612    }
1613
1614    Lock(s->lock);
1615    {
1616        if (s->Active == false)
1617        {
1618            Unlock(s->lock);
1619            return;
1620        }
1621
1622        s->Halt = true;
1623
1624        t = s->Thread;
1625
1626        s->Active = false;
1627    }
1628    Unlock(s->lock);
1629
1630    WaitThread(t, INFINITE);
1631    ReleaseThread(t);
1632}
1633
1634// Layer-3 スイッチを追加する
1635L3SW *L3AddSw(CEDAR *c, char *name)
1636{
1637    L3SW *s = NULL;
1638    // 引数チェック
1639    if (c == NULL || name == NULL)
1640    {
1641        return NULL;
1642    }
1643
1644    LockList(c->L3SwList);
1645    {
1646        s = L3GetSw(c, name);
1647
1648        if (s == NULL)
1649        {
1650            s = NewL3Sw(c, name);
1651
1652            Insert(c->L3SwList, s);
1653
1654            AddRef(s->ref);
1655        }
1656        else
1657        {
1658            ReleaseL3Sw(s);
1659            s = NULL;
1660        }
1661    }
1662    UnlockList(c->L3SwList);
1663
1664    return s;
1665}
1666
1667// Layer-3 スイッチを削除する
1668bool L3DelSw(CEDAR *c, char *name)
1669{
1670    L3SW *s;
1671    bool ret = false;
1672    // 引数チェック
1673    if (c == NULL || name == NULL)
1674    {
1675        return false;
1676    }
1677
1678    LockList(c->L3SwList);
1679    {
1680        s = L3GetSw(c, name);
1681
1682        if (s != NULL)
1683        {
1684            // 停止して削除
1685            L3SwStop(s);
1686            Delete(c->L3SwList, s);
1687            ReleaseL3Sw(s);
1688            ReleaseL3Sw(s);
1689
1690            ret = true;
1691        }
1692    }
1693    UnlockList(c->L3SwList);
1694
1695    return ret;
1696}
1697
1698
1699// ルーティングテーブルの削除
1700bool L3DelTable(L3SW *s, L3TABLE *tbl)
1701{
1702    bool ret = false;
1703    // 引数チェック
1704    if (s == NULL || tbl == NULL)
1705    {
1706        return false;
1707    }
1708
1709    Lock(s->lock);
1710    {
1711        if (s->Active == false)
1712        {
1713            L3TABLE *t = Search(s->TableList, tbl);
1714
1715            if (t != NULL)
1716            {
1717                Delete(s->TableList, t);
1718                Free(t);
1719
1720                ret = true;
1721            }
1722        }
1723    }
1724    Unlock(s->lock);
1725
1726    return ret;
1727}
1728
1729// ルーティングテーブルの追加
1730bool L3AddTable(L3SW *s, L3TABLE *tbl)
1731{
1732    bool ret = false;
1733    // 引数チェック
1734    if (s == NULL || tbl == NULL)
1735    {
1736        return false;
1737    }
1738
1739    if (tbl->Metric == 0 || tbl->GatewayAddress == 0 || tbl->GatewayAddress == 0xffffffff)
1740    {
1741        return false;
1742    }
1743
1744    Lock(s->lock);
1745    {
1746        if (LIST_NUM(s->TableList) >= GetServerCapsInt(s->Cedar->Server, "i_max_l3_table"))
1747        {
1748            // 数が多すぎる
1749        }
1750        else
1751        {
1752            // 作成
1753            if (s->Active == false)
1754            {
1755                if (Search(s->TableList, tbl) == NULL)
1756                {
1757                    L3TABLE *t = ZeroMalloc(sizeof(L3TABLE));
1758
1759                    Copy(t, tbl, sizeof(L3TABLE));
1760
1761                    Insert(s->TableList, t);
1762
1763                    ret = true;
1764                }
1765            }
1766        }
1767    }
1768    Unlock(s->lock);
1769
1770    return ret;
1771}
1772
1773// L3 スイッチを取得する
1774L3SW *L3GetSw(CEDAR *c, char *name)
1775{
1776    L3SW t, *s;
1777    // 引数チェック
1778    if (c == NULL || name == NULL)
1779    {
1780        return NULL;
1781    }
1782
1783    Zero(&t, sizeof(t));
1784    StrCpy(t.Name, sizeof(t.Name), name);
1785
1786    LockList(c->L3SwList);
1787    {
1788        s = Search(c->L3SwList, &t);
1789    }
1790    UnlockList(c->L3SwList);
1791
1792    if (s != NULL)
1793    {
1794        AddRef(s->ref);
1795    }
1796
1797    return s;
1798}
1799
1800// L3 スイッチから指定した仮想 HUB に接続されているインターフェイスを取得する
1801L3IF *L3SearchIf(L3SW *s, char *hubname)
1802{
1803    L3IF t, *f;
1804    // 引数チェック
1805    if (s == NULL || hubname == NULL)
1806    {
1807        return NULL;
1808    }
1809
1810    Zero(&t, sizeof(t));
1811    StrCpy(t.HubName, sizeof(t.HubName), hubname);
1812
1813    f = Search(s->IfList, &t);
1814
1815    return f;
1816}
1817
1818// インターフェイスの削除
1819bool L3DelIf(L3SW *s, char *hubname)
1820{
1821    L3IF *f;
1822    bool ret = false;
1823    // 引数チェック
1824    if (s == NULL || hubname == NULL)
1825    {
1826        return false;
1827    }
1828
1829    Lock(s->lock);
1830    {
1831        if (s->Active == false)
1832        {
1833            f = L3SearchIf(s, hubname);
1834
1835            if (f != NULL)
1836            {
1837                // 削除する
1838                Delete(s->IfList, f);
1839                Free(f);
1840
1841                ret = true;
1842            }
1843        }
1844    }
1845    Unlock(s->lock);
1846
1847    return ret;
1848}
1849
1850// インターフェイスの追加
1851bool L3AddIf(L3SW *s, char *hubname, UINT ip, UINT subnet)
1852{
1853    L3IF *f;
1854    bool ret = false;
1855    // 引数チェック
1856    if (s == NULL || hubname == NULL || IsSafeStr(hubname) == false ||
1857        ip == 0 || ip == 0xffffffff)
1858    {
1859        return false;
1860    }
1861
1862    Lock(s->lock);
1863    {
1864        if (LIST_NUM(s->TableList) >= GetServerCapsInt(s->Cedar->Server, "i_max_l3_if"))
1865        {
1866            // 数が多すぎる
1867        }
1868        else
1869        {
1870            if (s->Active == false)
1871            {
1872                // 同じ仮想 HUB にすでにインターフェイスが入っていないかどうか調べる
1873                if (L3SearchIf(s, hubname) == NULL)
1874                {
1875                    // 追加
1876                    f = ZeroMalloc(sizeof(L3IF));
1877
1878                    f->Switch = s;
1879                    StrCpy(f->HubName, sizeof(f->HubName), hubname);
1880                    f->IpAddress = ip;
1881                    f->SubnetMask = subnet;
1882
1883                    Insert(s->IfList, f);
1884
1885                    ret = true;
1886                }
1887            }
1888        }
1889    }
1890    Unlock(s->lock);
1891
1892    return ret;
1893}
1894
1895// L3 スイッチのクリーンアップ
1896void CleanupL3Sw(L3SW *s)
1897{
1898    UINT i;
1899    // 引数チェック
1900    if (s == NULL)
1901    {
1902        return;
1903    }
1904
1905    for (i = 0;i < LIST_NUM(s->IfList);i++)
1906    {
1907        L3IF *f = LIST_DATA(s->IfList, i);
1908        Free(f);
1909    }
1910    ReleaseList(s->IfList);
1911
1912    for (i = 0;i < LIST_NUM(s->TableList);i++)
1913    {
1914        L3TABLE *t = LIST_DATA(s->TableList, i);
1915        Free(t);
1916    }
1917    ReleaseList(s->TableList);
1918
1919    DeleteLock(s->lock);
1920    Free(s);
1921}
1922
1923// L3 スイッチの解放
1924void ReleaseL3Sw(L3SW *s)
1925{
1926    // 引数チェック
1927    if (s == NULL)
1928    {
1929        return;
1930    }
1931
1932    if (Release(s->ref) == 0)
1933    {
1934        CleanupL3Sw(s);
1935    }
1936}
1937
1938// 新しい L3 スイッチを作成する
1939L3SW *NewL3Sw(CEDAR *c, char *name)
1940{
1941    L3SW *o;
1942    // 引数チェック
1943    if (c == NULL || name == NULL)
1944    {
1945        return NULL;
1946    }
1947
1948    o = ZeroMalloc(sizeof(L3SW));
1949
1950    StrCpy(o->Name, sizeof(o->Name), name);
1951
1952    o->lock = NewLock();
1953    o->ref = NewRef();
1954    o->Cedar = c;
1955    o->Active = false;
1956
1957    o->IfList = NewList(CmpL3If);
1958    o->TableList = NewList(CmpL3Table);
1959
1960    return o;
1961}
1962
1963// Cedar にあるすべての L3 スイッチを停止する
1964void L3FreeAllSw(CEDAR *c)
1965{
1966    LIST *o;
1967    UINT i;
1968    // 引数チェック
1969    if (c == NULL)
1970    {
1971        return;
1972    }
1973
1974    o = NewListFast(NULL);
1975
1976    LockList(c->L3SwList);
1977    {
1978        for (i = 0;i < LIST_NUM(c->L3SwList);i++)
1979        {
1980            L3SW *s = LIST_DATA(c->L3SwList, i);
1981            Insert(o, CopyStr(s->Name));
1982        }
1983
1984        for (i = 0;i < LIST_NUM(o);i++)
1985        {
1986            char *name = LIST_DATA(o, i);
1987
1988            L3DelSw(c, name);
1989
1990            Free(name);
1991        }
1992
1993        ReleaseList(o);
1994    }
1995    UnlockList(c->L3SwList);
1996}
1997
1998// Cedar の L3 スイッチ機能を停止する
1999void FreeCedarLayer3(CEDAR *c)
2000{
2001    // 引数チェック
2002    if (c == NULL)
2003    {
2004        return;
2005    }
2006
2007    ReleaseList(c->L3SwList);
2008    c->L3SwList = NULL;
2009}
2010
2011// Cedar の L3 スイッチ機能を開始する
2012void InitCedarLayer3(CEDAR *c)
2013{
2014    // 引数チェック
2015    if (c == NULL)
2016    {
2017        return;
2018    }
2019
2020    c->L3SwList = NewList(CmpL3Sw);
2021}
2022
2023// インターフェイス比較関数
2024int CmpL3If(void *p1, void *p2)
2025{
2026    L3IF *f1, *f2;
2027    if (p1 == NULL || p2 == NULL)
2028    {
2029        return 0;
2030    }
2031    f1 = *(L3IF **)p1;
2032    f2 = *(L3IF **)p2;
2033    if (f1 == NULL || f2 == NULL)
2034    {
2035        return 0;
2036    }
2037
2038    return StrCmpi(f1->HubName, f2->HubName);
2039}
2040
2041// ルーティングテーブル比較関数
2042int CmpL3Table(void *p1, void *p2)
2043{
2044    L3TABLE *t1, *t2;
2045    if (p1 == NULL || p2 == NULL)
2046    {
2047        return 0;
2048    }
2049    t1 = *(L3TABLE **)p1;
2050    t2 = *(L3TABLE **)p2;
2051    if (t1 == NULL || t2 == NULL)
2052    {
2053        return 0;
2054    }
2055
2056    if (t1->NetworkAddress > t2->NetworkAddress)
2057    {
2058        return 1;
2059    }
2060    else if (t1->NetworkAddress < t2->NetworkAddress)
2061    {
2062        return -1;
2063    }
2064    else if (t1->SubnetMask > t2->SubnetMask)
2065    {
2066        return 1;
2067    }
2068    else if (t1->SubnetMask < t2->SubnetMask)
2069    {
2070        return -1;
2071    }
2072    else if (t1->GatewayAddress > t2->GatewayAddress)
2073    {
2074        return 1;
2075    }
2076    else if (t1->GatewayAddress < t2->GatewayAddress)
2077    {
2078        return -1;
2079    }
2080    else if (t1->Metric > t2->Metric)
2081    {
2082        return 1;
2083    }
2084    else if (t1->Metric < t2->Metric)
2085    {
2086        return -1;
2087    }
2088    else
2089    {
2090        return 0;
2091    }
2092}
2093
2094// L3SW 比較関数
2095int CmpL3Sw(void *p1, void *p2)
2096{
2097    L3SW *s1, *s2;
2098    if (p1 == NULL || p2 == NULL)
2099    {
2100        return 0;
2101    }
2102    s1 = *(L3SW **)p1;
2103    s2 = *(L3SW **)p2;
2104    if (s1 == NULL || s2 == NULL)
2105    {
2106        return 0;
2107    }
2108
2109    return StrCmpi(s1->Name, s2->Name);
2110}
2111
2112// ARP 待機エントリ比較関数
2113int CmpL3ArpWaitTable(void *p1, void *p2)
2114{
2115    L3ARPWAIT *w1, *w2;
2116    if (p1 == NULL || p2 == NULL)
2117    {
2118        return 0;
2119    }
2120    w1 = *(L3ARPWAIT **)p1;
2121    w2 = *(L3ARPWAIT **)p2;
2122    if (w1 == NULL || w2 == NULL)
2123    {
2124        return 0;
2125    }
2126    if (w1->IpAddress > w2->IpAddress)
2127    {
2128        return 1;
2129    }
2130    else if (w1->IpAddress < w2->IpAddress)
2131    {
2132        return -1;
2133    }
2134    else
2135    {
2136        return 0;
2137    }
2138}
2139
2140// ARP エントリ比較関数
2141int CmpL3ArpEntry(void *p1, void *p2)
2142{
2143    L3ARPENTRY *e1, *e2;
2144    if (p1 == NULL || p2 == NULL)
2145    {
2146        return 0;
2147    }
2148    e1 = *(L3ARPENTRY **)p1;
2149    e2 = *(L3ARPENTRY **)p2;
2150    if (e1 == NULL || e2 == NULL)
2151    {
2152        return 0;
2153    }
2154    if (e1->IpAddress > e2->IpAddress)
2155    {
2156        return 1;
2157    }
2158    else if (e1->IpAddress < e2->IpAddress)
2159    {
2160        return -1;
2161    }
2162    else
2163    {
2164        return 0;
2165    }
2166}
2167
Note: See TracBrowser for help on using the repository browser.