source: lab.git/Dev/utvpn/utvpn-unix-v101-7101-public/src/Cedar/Virtual.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: 128.0 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// Virtual.c
79// ユーザーモード仮想ホストプログラム
80
81// Q. このプログラムには大変多くの TCP/IP 関係の奥の深い処理が入っていて
82//    さらに TCP スタックの簡易的な実装まで完結しているように見えるが
83//    なぜこのように気合の入ったコードを書いたのか?
84// A. 作者の所属していた筑波大学第三学群情報学類という学科では、
85//    「情報特別演習」という授業がある。なんとこれは専門基礎単位を取得
86//    することができる貴重なコマである。専門基礎単位を取得するための他の
87//    方法としては、解析学Ⅲなどという授業等がある。しかし、作者は受験勉強
88//    のような数学のテスト勉強は嫌いであるし、また、SoftEther に関する打ち合わせ
89//    のために大学の某所に駐車したときにその解析学Ⅲの当時の担当教員の車のミラー
90//    をこすってしまって少し怒られたのでその単位の取得は難しくなった (?) のである。
91//    だが、専門基礎の単位を取得しなければ、卒業することができない。
92//    そこで代わりに「情報特別演習」で単位をとることにしたのだが、この授業は、
93//    何か面白いコンピュータの作品を作ってプレゼンテーションすれば 2 単位がくる
94//    という名目なのであった。しかし、実際のところ、ろくな作品を 1 年間で
95//    作ってプレゼンする人はとても少なく、たいていが「無線 LAN の実験」とか
96//    そういうほとんどクリエイティブな作業を必要とせずにできるいいかげんな
97//    「実習」を行ったと言って結果を報告すれば 2 単位来るという程度の難易度
98//    であることが後になって分かった。
99//    作者は大変真面目なので、部類としてはかなり難しい難易度に入る TCP/IP
100//    スタックの開発を実習としてやってみようと思い、数週間かけていろいろ
101//    プログラムを書いた。その成果の一部がこの Virtual.c というコードである。
102//    逆にいうと、大学の授業の実習程度で開発することができるくらいの簡単な
103//    プログラムなので、実装は簡易的であり、効率が悪く、メンテナンス性にも欠け
104//    ている。結構場当たり的なプログラミングを行ったためである。
105//    それでも 2004 年末に本プログラムをインターネットで配布してから今まで
106//    一応は深刻な不具合は発生していない。ただし探せば深刻な障害が潜んでいる
107//    かも知れない。
108
109
110#include "CedarPch.h"
111
112static UCHAR broadcast[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
113
114// Virtual Host のログをとる
115void VLog(VH *v, char *str)
116{
117    // とらん!!
118    return;
119}
120
121// NAT が使用可能かどうかチェック
122bool CanCreateNewNatEntry(VH *v)
123{
124    // 引数チェック
125    if (v == NULL)
126    {
127        return false;
128    }
129
130    if (v->UseNat == false)
131    {
132        // NAT 停止中
133        return false;
134    }
135
136    if (v->NatTable->num_item > NAT_MAX_SESSIONS)
137    {
138        // セッション数超過
139        return false;
140    }
141
142    return true;
143}
144
145// NAT 処理スレッドのメイン関数
146void NatThreadMain(VH *v)
147{
148    bool halt_flag;
149    // 引数チェック
150    if (v == NULL)
151    {
152        return;
153    }
154
155    v->TmpBuf = Malloc(NAT_TMPBUF_SIZE);
156
157    while (true)
158    {
159        // 次のイベントがセットされるまで待機する
160        WaitSockEvent(v->SockEvent, SELECT_TIME);
161
162        halt_flag = false;
163
164        LockVirtual(v);
165        {
166            // すべての NAT セッションに対して処理を行う
167            UINT i, num;
168
169            v->Now = Tick64();
170            v->NatDoCancelFlag = false;
171
172LIST_ELEMENT_DELETED:
173            num = LIST_NUM(v->NatTable);
174            for (i = 0;i < num;i++)
175            {
176                NAT_ENTRY *n = LIST_DATA(v->NatTable, i);
177
178                switch (n->Protocol)
179                {
180                case NAT_TCP:       // TCP
181                    if (NatTransactTcp(v, n) == false)
182                    {
183                        goto LIST_ELEMENT_DELETED;
184                    }
185                    break;
186
187                case NAT_UDP:       // UDP
188                    if (NatTransactUdp(v, n) == false)
189                    {
190                        goto LIST_ELEMENT_DELETED;
191                    }
192                    break;
193
194                case NAT_DNS:       // DNS
195                    if (NatTransactDns(v, n) == false)
196                    {
197                        goto LIST_ELEMENT_DELETED;
198                    }
199                    break;
200                }
201            }
202
203            if (v->NatDoCancelFlag)
204            {
205                // 親スレッドの Cancel を叩く
206                Cancel(v->Cancel);
207            }
208
209            // 停止フラグチェック
210            if (v->HaltNat)
211            {
212                halt_flag = true;
213            }
214        }
215        UnlockVirtual(v);
216
217        if (halt_flag)
218        {
219            // すべてのエントリを強制切断してからスレッドを終了する
220            LockVirtual(v);
221            {
222                UINT num = LIST_NUM(v->NatTable);
223                NAT_ENTRY **nn = ToArray(v->NatTable);
224                UINT i;
225
226                for (i = 0;i < num;i++)
227                {
228                    NAT_ENTRY *n = nn[i];
229                    n->DisconnectNow = true;
230
231                    switch (n->Protocol)
232                    {
233                    case NAT_TCP:       // TCP
234                        NatTransactTcp(v, n);
235                        break;
236
237                    case NAT_UDP:       // UDP
238                        NatTransactUdp(v, n);
239                        break;
240
241                    case NAT_DNS:       // DNS
242                        NatTransactDns(v, n);
243                        break;
244                    }
245                }
246
247                Free(nn);
248            }
249            UnlockVirtual(v);
250            break;
251        }
252    }
253
254    Free(v->TmpBuf);
255}
256
257// DNS: IP アドレスを取得するスレッド
258void NatGetIPThread(THREAD *t, void *param)
259{
260    NAT_DNS_QUERY *q;
261    // 引数チェック
262    if (t == NULL || param == NULL)
263    {
264        return;
265    }
266
267    q = (NAT_DNS_QUERY *)param;
268    AddWaitThread(t);
269
270    q->Ok = GetIP(&q->Ip, q->Hostname);
271
272    DelWaitThread(t);
273
274    if (Release(q->ref) == 0)
275    {
276        Free(q);
277    }
278}
279
280// DNS: ホスト名から IP アドレスを取得する
281bool NatGetIP(IP *ip, char *hostname)
282{
283    TOKEN_LIST *t;
284    bool ret = false;
285    // 引数チェック
286    if (ip == NULL || hostname == NULL)
287    {
288        return false;
289    }
290
291    t = ParseToken(hostname, ".");
292    if (t == NULL)
293    {
294        return false;
295    }
296    if (t->NumTokens == 0)
297    {
298        FreeToken(t);
299        return false;
300    }
301
302    if (t->NumTokens == 1)
303    {
304        ret = GetIP(ip, hostname);
305    }
306    else
307    {
308        char *hostname2 = t->Token[0];
309        NAT_DNS_QUERY *q1, *q2;
310        THREAD *t1, *t2;
311
312        q1 = ZeroMalloc(sizeof(NAT_DNS_QUERY));
313        q2 = ZeroMalloc(sizeof(NAT_DNS_QUERY));
314        q1->ref = NewRef();
315        q2->ref = NewRef();
316        AddRef(q1->ref);
317        AddRef(q2->ref);
318        StrCpy(q1->Hostname, sizeof(q1->Hostname), hostname);
319        StrCpy(q2->Hostname, sizeof(q2->Hostname), hostname2);
320
321        t1 = NewThread(NatGetIPThread, q1);
322        t2 = NewThread(NatGetIPThread, q2);
323
324        WaitThread(t1, NAT_DNS_QUERY_TIMEOUT);
325
326        if (q1->Ok)
327        {
328            ret = true;
329            Copy(ip, &q1->Ip, sizeof(IP));
330        }
331        else
332        {
333            WaitThread(t2, NAT_DNS_QUERY_TIMEOUT);
334            if (q1->Ok)
335            {
336                ret = true;
337                Copy(ip, &q1->Ip, sizeof(IP));
338            }
339            else if (q2->Ok)
340            {
341                ret = true;
342                Copy(ip, &q2->Ip, sizeof(IP));
343            }
344        }
345
346        ReleaseThread(t1);
347        ReleaseThread(t2);
348
349        if (Release(q1->ref) == 0)
350        {
351            Free(q1);
352        }
353        if (Release(q2->ref) == 0)
354        {
355            Free(q2);
356        }
357    }
358
359    FreeToken(t);
360
361    return ret;
362}
363
364// DNS 問い合わせ関数
365void NatDnsThread(THREAD *t, void *param)
366{
367    NAT_ENTRY *n;
368    IP ip;
369    // 引数チェック
370    if (t == NULL || param == NULL)
371    {
372        return;
373    }
374    n = (NAT_ENTRY *)param;
375
376    // 初期化完了を通知
377    NoticeThreadInit(t);
378
379    // 処理を実行
380    if (EndWith(n->DnsTargetHostName, ".in-addr.arpa") == false)
381    {
382        // 正引き
383        if (NatGetIP(&ip, n->DnsTargetHostName))
384        {
385            // 正引き成功
386            Copy(&n->DnsResponseIp, &ip, sizeof(IP));
387            n->DnsOk = true;
388        }
389    }
390    else
391    {
392        // 逆引き
393        IP ip;
394        n->DnsGetIpFromHost = true;     // 逆引きフラグを設定
395        // *.in-addr.arpa 文字列を IP アドレスに変換してもらう
396        if (ArpaToIP(&ip, n->DnsTargetHostName))
397        {
398            // 逆引き処理
399            char tmp[256];
400            if (GetHostName(tmp, sizeof(tmp), &ip))
401            {
402                // 逆引き成功
403                n->DnsResponseHostName = CopyStr(tmp);
404                n->DnsOk = true;
405            }
406        }
407    }
408
409    // 結果を通知
410    n->DnsFinished = true;
411
412    SetSockEvent(n->v->SockEvent);
413}
414
415// 逆引き用アドレスを IP アドレスに変換する
416bool ArpaToIP(IP *ip, char *str)
417{
418    TOKEN_LIST *token;
419    bool ret = false;
420    // 引数チェック
421    if (ip == NULL || str == NULL)
422    {
423        return false;
424    }
425
426    // トークン変換
427    token = ParseToken(str, ".");
428    if (token->NumTokens == 6)
429    {
430        // token[0, 1, 2, 3] を IP に変換
431        UINT i;
432        Zero(ip, sizeof(IP));
433        for (i = 0;i < 4;i++)
434        {
435            ip->addr[i] = (UCHAR)ToInt(token->Token[3 - i]);
436        }
437        ret = true;
438    }
439
440    FreeToken(token);
441
442    if (IPToUINT(ip) == 0)
443    {
444        ret = false;
445    }
446
447    return ret;
448}
449
450// DNS エントリを処理する
451bool NatTransactDns(VH *v, NAT_ENTRY *n)
452{
453    // 引数チェック
454    if (v == NULL || n == NULL)
455    {
456        return true;
457    }
458
459    if (n->DisconnectNow)
460    {
461        goto DISCONNECT;
462    }
463
464    if (n->DnsThread == NULL && n->DnsFinished == false)
465    {
466        // スレッドを作成する
467        THREAD *t = NewThread(NatDnsThread, (void *)n);
468        WaitThreadInit(t);
469        n->DnsThread = t;
470    }
471    else
472    {
473        // 結果を待機する
474        if (n->DnsFinished)
475        {
476            // 結果が届いている
477            WaitThread(n->DnsThread, INFINITE);
478            ReleaseThread(n->DnsThread);
479            n->DnsThread = NULL;
480            // メインスレッドに通知
481            v->NatDoCancelFlag = true;
482        }
483    }
484
485    return true;
486
487DISCONNECT:
488
489    // 解放処理
490    if (n->DnsThread != NULL)
491    {
492        WaitThread(n->DnsThread, INFINITE);
493        ReleaseThread(n->DnsThread);
494        n->DnsThread = NULL;
495    }
496
497    if (n->DnsTargetHostName != NULL)
498    {
499        Free(n->DnsTargetHostName);
500        n->DnsTargetHostName = NULL;
501    }
502
503    if (n->DnsResponseHostName != NULL)
504    {
505        Free(n->DnsResponseHostName);
506        n->DnsResponseHostName = NULL;
507    }
508
509    DeleteLock(n->lock);
510    Delete(v->NatTable, n);
511    Free(n);
512
513    return false;
514}
515
516// UDP エントリを処理する
517bool NatTransactUdp(VH *v, NAT_ENTRY *n)
518{
519    void *buf;
520    UINT recv_size;
521    BLOCK *block;
522    UINT dest_port = n->DestPort;
523    IP dest_ip;
524    // 引数チェック
525    if (v == NULL || n == NULL)
526    {
527        return true;
528    }
529
530    if (n->DisconnectNow)
531    {
532        goto DISCONNECT;
533    }
534
535    if (n->UdpSocketCreated == false)
536    {
537        // UDP ソケットを作成する
538        n->Sock = NewUDP(0);
539        if (n->Sock == NULL)
540        {
541            // ソケット作成失敗
542            goto DISCONNECT;
543        }
544        else
545        {
546            n->PublicIp = IPToUINT(&n->Sock->LocalIP);
547            n->PublicPort = n->Sock->LocalPort;
548
549            JoinSockToSockEvent(n->Sock, v->SockEvent);
550            n->UdpSocketCreated = true;
551        }
552    }
553
554    buf = v->TmpBuf;
555    if (n->ProxyDns == false)
556    {
557        UINTToIP(&dest_ip, n->DestIp);
558    }
559    else
560    {
561        UINTToIP(&dest_ip, n->DestIpProxy);
562    }
563
564    // UDP ソケットからデータを受信してみる
565    while (true)
566    {
567        IP src_ip;
568        UINT src_port;
569        recv_size = RecvFrom(n->Sock, &src_ip, &src_port, buf, 65536);
570
571        if (recv_size == SOCK_LATER)
572        {
573            // パケットが届いていない
574            break;
575        }
576        else if (recv_size == 0)
577        {
578            // エラー?
579            if (n->Sock->IgnoreRecvErr == false)
580            {
581                // 致命的なエラーが発生した
582                goto DISCONNECT;
583            }
584        }
585        else
586        {
587            // パケットが届いた。送信元 IP をチェック
588            if (IPToUINT(&src_ip) == n->DestIp || (IPToUINT(&src_ip) == n->DestIpProxy && n->ProxyDns) && src_port == n->DestPort)
589            {
590                // キューに挿入
591                void *data = Malloc(recv_size);
592                Copy(data, buf, recv_size);
593                block = NewBlock(data, recv_size, 0);
594                InsertQueue(n->UdpRecvQueue, block);
595                v->NatDoCancelFlag = true;
596                n->LastCommTime = v->Now;
597            }
598        }
599    }
600
601    // UDP ソケットにデータを送信してみる
602    while (block = GetNext(n->UdpSendQueue))
603    {
604        UINT send_size = SendTo(n->Sock, &dest_ip, dest_port, block->Buf, block->Size);
605
606        FreeBlock(block);
607        if (send_size == 0)
608        {
609            // 致命的なエラーかどうか判定
610            if (n->Sock->IgnoreSendErr == false)
611            {
612                // 致命的なエラーが発生した
613                goto DISCONNECT;
614            }
615        }
616        else
617        {
618            n->LastCommTime = v->Now;
619        }
620    }
621
622    // このセッションがタイムアウトになっていないかどうか調べる
623    if ((n->LastCommTime + (UINT64)v->NatUdpTimeout) < v->Now || n->LastCommTime > v->Now)
624    {
625        // タイムアウトである
626        goto DISCONNECT;
627    }
628
629    return true;
630
631DISCONNECT:
632    // このセッションを切断
633    if (n->UdpSocketCreated)
634    {
635        // ソケットを閉じる
636        Disconnect(n->Sock);
637        ReleaseSock(n->Sock);
638        n->Sock = NULL;
639    }
640
641    // エントリを削除
642    DeleteNatUdp(v, n);
643
644    return false;
645}
646
647// TCP ホストへの接続処理を行うためのスレッド
648void NatTcpConnectThread(THREAD *t, void *p)
649{
650    NAT_ENTRY *n = (NAT_ENTRY *)p;
651    IP ip;
652    char hostname[MAX_SIZE];
653    UINT port_number;
654    SOCK *sock;
655    SOCK_EVENT *e;
656    // 引数チェック
657    if (n == NULL || t == NULL)
658    {
659        return;
660    }
661
662    UINTToIP(&ip, n->DestIp);
663    IPToStr(hostname, sizeof(hostname), &ip);
664    port_number = n->DestPort;
665    e = n->v->SockEvent;
666    AddRef(e->ref);
667
668    // 初期化完了を通知
669    NoticeThreadInit(t);
670
671    // TCP ホストへの接続を試行
672    Debug("NatTcpConnect Connecting to %s:%u\n", hostname, port_number);
673    sock = Connect(hostname, port_number);
674    if (sock == NULL)
675    {
676        // 接続失敗
677        n->TcpMakeConnectionFailed = true;
678    }
679    else
680    {
681        // 接続成功
682        n->TcpMakeConnectionSucceed = true;
683    }
684    n->Sock = sock;
685    JoinSockToSockEvent(sock, e);
686    SetSockEvent(e);
687
688    ReleaseSockEvent(e);
689}
690
691// TCP ホストに接続するためのスレッドを作成する
692void CreateNatTcpConnectThread(VH *v, NAT_ENTRY *n)
693{
694    // 引数チェック
695    if (v == NULL || n == NULL)
696    {
697        return;
698    }
699
700    // スレッド作成
701    n->NatTcpConnectThread = NewThread(NatTcpConnectThread, (void *)n);
702
703    // スレッド初期化完了を待機
704    WaitThreadInit(n->NatTcpConnectThread);
705}
706
707// TCP エントリを処理する
708bool NatTransactTcp(VH *v, NAT_ENTRY *n)
709{
710    char str[MAX_SIZE];
711    // 引数チェック
712    if (v == NULL || n == NULL)
713    {
714        return false;
715    }
716
717    if (n->DisconnectNow)
718    {
719        goto DISCONNECT;
720    }
721
722    // TCP の状態別に処理を行う
723    switch (n->TcpStatus)
724    {
725    case NAT_TCP_CONNECTING:        // 接続待機中
726        if (n->NatTcpConnectThread == NULL)
727        {
728            // 接続スレッドを作成し接続を開始する
729            CreateNatTcpConnectThread(v, n);
730        }
731        else
732        {
733            // すでに開始されている接続スレッドの結果を待機
734            if (n->TcpMakeConnectionFailed || n->TcpMakeConnectionSucceed)
735            {
736                // スレッドの動作はすでに完了しているので結果を使用する
737                WaitThread(n->NatTcpConnectThread, INFINITE);
738                ReleaseThread(n->NatTcpConnectThread);
739                n->NatTcpConnectThread = NULL;
740
741                if (n->TcpMakeConnectionSucceed)
742                {
743                    // 接続は成功し Sock が作成された
744                    n->TcpStatus = NAT_TCP_CONNECTED;
745                    IPToStr32(str, sizeof(str), n->DestIp);
746                    NLog(v, "LH_NAT_TCP_SUCCEED", n->Id, n->Sock->RemoteHostname, str, n->DestPort);
747                }
748                else
749                {
750                    // 接続に失敗した
751                    n->TcpStatus = NAT_TCP_SEND_RESET;
752                    IPToStr32(str, sizeof(str), n->DestIp);
753                    NLog(v, "LH_NAT_TCP_FAILED", n->Id, str, n->DestPort);
754                }
755                v->NatDoCancelFlag = true;
756            }
757        }
758        break;
759
760    case NAT_TCP_CONNECTED:         // TCP ソケット接続完了 クライアントホストとの間で交渉中
761        break;
762
763    case NAT_TCP_SEND_RESET:        // TCP 通信切断 クライアントホストへ RST を送信
764        break;
765
766    case NAT_TCP_ESTABLISHED:       // TCP 接続確立済み
767        {
768            // 受信バッファにデータがあればソケットに対して送信する
769            while (n->RecvFifo->size > 0)
770            {
771                UINT sent_size = Send(n->Sock, ((UCHAR *)n->RecvFifo->p) + n->RecvFifo->pos,
772                    n->RecvFifo->size, false);
773                if (sent_size == 0)
774                {
775                    // 通信が切断された
776                    n->TcpFinished = true;
777                    v->NatDoCancelFlag = true;
778                    break;
779                }
780                else if (sent_size == SOCK_LATER)
781                {
782                    // ブロッキング
783                    break;
784                }
785                else
786                {
787                    // 送信成功
788                    ReadFifo(n->RecvFifo, NULL, sent_size);
789                    n->SendAckNext = true;
790                }
791            }
792            // ソケットからデータを取得して送信バッファに書き込む
793            while (true)
794            {
795                void *buf = (void *)v->TmpBuf;
796                UINT want_to_recv_size = 0;
797                UINT recv_size;
798                // 受信したいサイズを計算する
799                if (n->SendFifo->size < NAT_SEND_BUF_SIZE)
800                {
801                    // まだ受信できる
802                    want_to_recv_size = MIN(NAT_SEND_BUF_SIZE - n->SendFifo->size, NAT_TMPBUF_SIZE);
803                }
804                if (want_to_recv_size == 0)
805                {
806                    break;
807                }
808                recv_size = Recv(n->Sock, buf, want_to_recv_size, false);
809                if (recv_size == 0)
810                {
811                    // 通信が切断された
812                    n->TcpFinished = true;
813                    v->NatDoCancelFlag = true;
814                    break;
815                }
816                else if (recv_size == SOCK_LATER)
817                {
818                    // ブロッキング
819                    break;
820                }
821                else
822                {
823                    // 受信成功
824                    WriteFifo(n->SendFifo, buf, recv_size);
825                    v->NatDoCancelFlag = true;
826                }
827            }
828        }
829        break;
830
831    }
832
833    // タイムアウトの検出
834    if ((n->LastCommTime + (UINT64)v->NatTcpTimeout) < v->Now || n->LastCommTime > v->Now)
835    {
836        // タイムアウトが発生、セッション切断
837        n->TcpStatus = NAT_TCP_SEND_RESET;
838        v->NatDoCancelFlag = true;
839    }
840
841    return true;
842
843DISCONNECT:     // 切断とセッション廃棄処理
844    DeleteNatTcp(v, n);
845
846    return false;
847}
848
849// TCP NAT エントリの削除
850void DeleteNatTcp(VH *v, NAT_ENTRY *n)
851{
852    // 引数チェック
853    if (v == NULL || n == NULL)
854    {
855        return;
856    }
857
858    NLog(v, "LH_NAT_TCP_DELETED", n->Id);
859
860    // 接続スレッドのシャットダウン
861    if (n->NatTcpConnectThread != NULL)
862    {
863        WaitThread(n->NatTcpConnectThread, INFINITE);
864        ReleaseThread(n->NatTcpConnectThread);
865        n->NatTcpConnectThread = NULL;
866    }
867    if (n->Sock != NULL)
868    {
869        // ソケット切断
870        Disconnect(n->Sock);
871        ReleaseSock(n->Sock);
872        n->Sock = NULL;
873    }
874
875    // ウインドウメモリ解放
876    if (n->TcpRecvWindow != NULL)
877    {
878        ReleaseFifo(n->TcpRecvWindow);
879        n->TcpRecvWindow = NULL;
880    }
881
882    // ウインドウ受信リスト解放
883    if (n->TcpRecvList != NULL)
884    {
885        UINT i;
886        for (i = 0;i < LIST_NUM(n->TcpRecvList);i++)
887        {
888            IP_PART *p = LIST_DATA(n->TcpRecvList, i);
889            Free(p);
890        }
891        ReleaseList(n->TcpRecvList);
892        n->TcpRecvList = NULL;
893    }
894
895    // FIFO 解放
896    ReleaseFifo(n->SendFifo);
897    ReleaseFifo(n->RecvFifo);
898
899    // NAT エントリから削除
900    Delete(v->NatTable, n);
901
902    DeleteLock(n->lock);
903
904    // メモリ解放
905    Free(n);
906
907    Debug("NAT_ENTRY: DeleteNatTcp\n");
908}
909
910// NAT 処理スレッド
911void NatThread(THREAD *t, void *param)
912{
913    // 引数チェック
914    if (t == NULL || param == NULL)
915    {
916        return;
917    }
918
919    // 初期化完了を通知
920    NoticeThreadInit(t);
921
922    NatThreadMain((VH *)param);
923}
924
925// ビーコンパケットの送信
926void SendBeacon(VH *v)
927{
928    UINT dest_ip;
929    ARPV4_HEADER arp;
930    static char beacon_str[] =
931        "SecureNAT Virtual TCP/IP Stack Beacon";
932    // 引数チェック
933    if (v == NULL)
934    {
935        return;
936    }
937
938    // UDP を送信
939    dest_ip = (v->HostIP & v->HostMask) | (~v->HostMask);
940    SendUdp(v, dest_ip, 7, v->HostIP, 7, beacon_str, sizeof(beacon_str));
941
942    // ARP ヘッダを構築
943    arp.HardwareType = Endian16(ARP_HARDWARE_TYPE_ETHERNET);
944    arp.ProtocolType = Endian16(MAC_PROTO_IPV4);
945    arp.HardwareSize = 6;
946    arp.ProtocolSize = 4;
947    arp.Operation = Endian16(ARP_OPERATION_RESPONSE);
948    Copy(arp.SrcAddress, v->MacAddress, 6);
949    arp.SrcIP = v->HostIP;
950    arp.TargetAddress[0] =
951        arp.TargetAddress[1] =
952        arp.TargetAddress[2] =
953        arp.TargetAddress[3] =
954        arp.TargetAddress[4] =
955        arp.TargetAddress[5] = 0xff;
956    arp.TargetIP = dest_ip;
957
958    // 送信
959    VirtualLayer2Send(v, broadcast, v->MacAddress, MAC_PROTO_ARPV4, &arp, sizeof(arp));
960}
961
962// TCP パケットの送信
963void SendTcp(VH *v, UINT src_ip, UINT src_port, UINT dest_ip, UINT dest_port, UINT seq, UINT ack, UINT flag, UINT window_size, UINT mss, void *data, UINT size)
964{
965    static UCHAR tcp_mss_option[] = {0x02, 0x04, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00};
966    TCPV4_PSEUDO_HEADER *vh;
967    TCP_HEADER *tcp;
968    UINT header_size = TCP_HEADER_SIZE;
969    UINT total_size;
970    // 引数チェック
971    if (v == NULL || (size != 0 && data == NULL))
972    {
973        return;
974    }
975
976    // メモリ確保
977    vh = Malloc(sizeof(TCPV4_PSEUDO_HEADER) + TCP_HEADER_SIZE + size + 32);
978    tcp = (TCP_HEADER *)(((UCHAR *)vh) + sizeof(TCPV4_PSEUDO_HEADER));
979
980    if (mss != 0)
981    {
982        USHORT *mss_size;
983        mss_size = (USHORT *)(&tcp_mss_option[2]);
984        *mss_size = Endian16((USHORT)mss);
985        header_size += sizeof(tcp_mss_option);
986    }
987
988    total_size = header_size + size;
989    if (total_size > 65536)
990    {
991        // パケットが長すぎる
992        Free(vh);
993        return;
994    }
995
996    // 擬似ヘッダ生成
997    vh->SrcIP = src_ip;
998    vh->DstIP = dest_ip;
999    vh->Reserved = 0;
1000    vh->Protocol = IP_PROTO_TCP;
1001    vh->PacketLength = Endian16((USHORT)total_size);
1002
1003    // TCP ヘッダ生成
1004    tcp->SrcPort = Endian16((USHORT)src_port);
1005    tcp->DstPort = Endian16((USHORT)dest_port);
1006    tcp->SeqNumber = Endian32(seq);
1007    tcp->AckNumber = Endian32(ack);
1008    tcp->HeaderSizeAndReserved = 0;
1009    TCP_SET_HEADER_SIZE(tcp, (UCHAR)(header_size / 4));
1010    tcp->Flag = (UCHAR)flag;
1011    tcp->WindowSize = Endian16((USHORT)window_size);
1012    tcp->Checksum = 0;
1013    tcp->UrgentPointer = 0;
1014
1015    // オプション値コピー
1016    if (mss != 0)
1017    {
1018        Copy(((UCHAR *)tcp) + TCP_HEADER_SIZE, tcp_mss_option, sizeof(tcp_mss_option));
1019    }
1020
1021    // データコピー
1022    Copy(((UCHAR *)tcp) + header_size, data, size);
1023
1024    // チェックサム計算
1025    tcp->Checksum = IpChecksum(vh, total_size + 12);
1026
1027    // IP パケットとして送信
1028    SendIp(v, dest_ip, src_ip, IP_PROTO_TCP, tcp, total_size);
1029
1030    // メモリ解放
1031    Free(vh);
1032}
1033
1034// TCP のポーリング処理
1035void PollingNatTcp(VH *v, NAT_ENTRY *n)
1036{
1037    // 引数チェック
1038    if (v == NULL || n == NULL)
1039    {
1040        return;
1041    }
1042
1043    switch (n->TcpStatus)
1044    {
1045    case NAT_TCP_CONNECTING:        // ソケット接続中: 何もしない
1046        break;
1047
1048    case NAT_TCP_CONNECTED:         // ソケット接続が完了した SYN+ACK, ACK 処理
1049        if ((n->LastSynAckSentTime > v->Now) || n->LastSynAckSentTime == 0 || ((n->LastSynAckSentTime + (UINT64)(NAT_TCP_SYNACK_SEND_TIMEOUT * (UINT64)(n->SynAckSentCount + 1)) <= v->Now)))
1050        {
1051            n->LastSynAckSentTime = v->Now;
1052            // SYN+ACK を送信する
1053            SendTcp(v, n->DestIp, n->DestPort, n->SrcIp, n->SrcPort,
1054                (UINT)(n->SendSeqInit + n->SendSeq),
1055                (UINT)(n->RecvSeqInit + n->RecvSeq),
1056                TCP_SYN | TCP_ACK, n->TcpRecvWindowSize,
1057                v->TcpMss, NULL, 0);
1058            n->SynAckSentCount++;
1059        }
1060        break;
1061
1062    case NAT_TCP_SEND_RESET:        // コネクションのリセット
1063        // RST を送信する
1064        if (n->TcpFinished == false)
1065        {
1066            SendTcp(v, n->DestIp, n->DestPort, n->SrcIp, n->SrcPort,
1067                (UINT)(n->SendSeq + n->SendSeqInit),
1068                (UINT)(n->SendSeq + n->SendSeqInit),
1069                TCP_RST, 0,
1070                0, NULL, 0);
1071            // 切断する
1072            n->TcpStatus = NAT_TCP_WAIT_DISCONNECT;
1073            n->DisconnectNow = true;
1074        }
1075        else
1076        {
1077            // 合計 NAT_FIN_SEND_MAX_COUNT 回の FIN を送信する
1078            if (n->FinSentTime == 0 || (n->FinSentTime > v->Now) || (n->FinSentTime + NAT_FIN_SEND_INTERVAL * (n->FinSentCount + 1)) < v->Now)
1079            {
1080                SendTcp(v, n->DestIp, n->DestPort, n->SrcIp, n->SrcPort,
1081                    (UINT)(n->SendSeq + n->SendSeqInit),
1082                    (UINT)(n->RecvSeq + n->RecvSeqInit),
1083                    TCP_ACK | TCP_FIN, 0,
1084                    0, NULL, 0);
1085                n->FinSentTime = v->Now;
1086                n->FinSentCount++;
1087                if (n->FinSentCount >= NAT_FIN_SEND_MAX_COUNT)
1088                {
1089                    n->TcpFinished = false;
1090                }
1091            }
1092        }
1093        break;
1094
1095    case NAT_TCP_ESTABLISHED:       // 接続確立済み
1096        {
1097            UINT send_data_size;
1098            UINT current_pointer;
1099            UINT notice_window_size_value = 0;
1100            UINT buf_free_bytes = 0;
1101            // 通知するウインドウサイズの値を決定する
1102            if (FifoSize(n->RecvFifo) < NAT_RECV_BUF_SIZE)
1103            {
1104                buf_free_bytes = NAT_RECV_BUF_SIZE - FifoSize(n->RecvFifo);
1105            }
1106            notice_window_size_value = MIN(n->TcpRecvWindowSize, buf_free_bytes);
1107            if (n->LastSentKeepAliveTime == 0 ||
1108                (n->LastSentKeepAliveTime + (UINT64)NAT_ACK_KEEPALIVE_SPAN) < v->Now ||
1109                (n->LastSentKeepAliveTime > v->Now))
1110            {
1111                if (n->LastSentKeepAliveTime != 0)
1112                {
1113                    // Keep-Alive 用 ACK パケットの送信
1114                    SendTcp(v, n->DestIp, n->DestPort, n->SrcIp, n->SrcPort,
1115                            (UINT)(n->SendSeqInit + n->SendSeq),
1116                            (UINT)(n->RecvSeqInit + n->RecvSeq) - 1,
1117                            TCP_ACK,
1118                            notice_window_size_value,
1119                            0,
1120                            NULL,
1121                            0);
1122                }
1123                n->LastSentKeepAliveTime = v->Now;
1124            }
1125            if (n->TcpLastSentTime == 0 ||
1126                (n->TcpLastSentTime > v->Now) ||
1127                ((n->TcpLastSentTime + (UINT64)n->TcpSendTimeoutSpan) < v->Now) ||
1128                n->SendAckNext)
1129            {
1130                // 送信すべきデータがある場合は送信する
1131                // 送信すべきセグメントサイズを計算する
1132                send_data_size = n->TcpSendWindowSize;
1133                if (send_data_size > (n->TcpSendCWnd * n->TcpSendMaxSegmentSize))
1134                {
1135                    // cwnd 値を適用する
1136                    send_data_size = n->TcpSendCWnd * n->TcpSendMaxSegmentSize;
1137                }
1138                if (send_data_size > n->SendFifo->size)
1139                {
1140                    // 現在保有しているデータ以上は送れない
1141                    send_data_size = n->SendFifo->size;
1142                }
1143                if (send_data_size >= 1)
1144                {
1145                    // セグメントに分割して送信する
1146                    current_pointer = 0;
1147                    while (send_data_size > 0)
1148                    {
1149                        UINT send_segment_size = MIN(n->TcpSendMaxSegmentSize, send_data_size);
1150                        void *send_segment = (void *)(((UCHAR *)n->SendFifo->p) + n->SendFifo->pos + current_pointer);
1151                        SendTcp(v, n->DestIp, n->DestPort, n->SrcIp, n->SrcPort,
1152                            (UINT)(n->SendSeqInit + n->SendSeq + (UINT64)current_pointer),
1153                            (UINT)(n->RecvSeqInit + n->RecvSeq),
1154                            TCP_ACK | TCP_PSH,
1155                            notice_window_size_value,
1156                            0,
1157                            send_segment,
1158                            send_segment_size);
1159                        current_pointer += send_segment_size;
1160                        send_data_size -= send_segment_size;
1161                    }
1162                    // 送信時刻を記録する
1163                    n->TcpLastSentTime = v->Now;
1164                    // 今回送信するストリームサイズを記録する
1165                    n->SendMissionSize = current_pointer;
1166                    n->CurrentSendingMission = true;
1167                    // RTT 測定
1168                    if (n->CalcRTTStartTime == 0)
1169                    {
1170                        n->CalcRTTStartTime = v->Now;
1171                        n->CalcRTTStartValue = n->SendSeq + current_pointer - 1;
1172                    }
1173                    if (n->RetransmissionUsedFlag == false)
1174                    {
1175                        n->RetransmissionUsedFlag = true;
1176                    }
1177                    else
1178                    {
1179                        // 輻輳発生を検出
1180                        if (n->TcpSendCWnd > 2)
1181                        {
1182                            n->TcpSendCWnd--;
1183                        }
1184                    }
1185                }
1186                else if (n->SendAckNext)
1187                {
1188                    // ACK のみ送信する
1189                    SendTcp(v, n->DestIp, n->DestPort, n->SrcIp, n->SrcPort,
1190                            (UINT)(n->SendSeqInit + n->SendSeq),
1191                            (UINT)(n->RecvSeqInit + n->RecvSeq),
1192                            TCP_ACK,
1193                            notice_window_size_value,
1194                            0,
1195                            NULL,
1196                            0);
1197                }
1198                n->SendAckNext = false;
1199            }
1200            if (n->TcpFinished)
1201            {
1202                // すべてのデータ送信が完了していたら切断する
1203                if (n->SendFifo->size == 0)
1204                {
1205                    n->TcpStatus = NAT_TCP_SEND_RESET;
1206                }
1207            }
1208        }
1209        break;
1210    }
1211}
1212
1213// インターネットへ向かう TCP パケットの受信処理
1214void TcpRecvForInternet(VH *v, UINT src_ip, UINT src_port, UINT dest_ip, UINT dest_port, TCP_HEADER *tcp, void *data, UINT size)
1215{
1216    NAT_ENTRY *n, t;
1217    UINT seq, ack;
1218    UINT64 seq64 = 0, ack64 = 0;
1219    // 引数チェック
1220    if (v == NULL || tcp == NULL || data == NULL)
1221    {
1222        return;
1223    }
1224
1225    // このパケットに関するセッションを NAT テーブルから検索
1226    SetNat(&t, NAT_TCP, src_ip, src_port, dest_ip, dest_port, 0, 0);
1227    n = SearchNat(v, &t);
1228
1229    if (n == NULL)
1230    {
1231        // 既存のセッションが存在しない
1232        // SYN パケットのみ通過を許可する
1233        if ((tcp->Flag & TCP_SYN) && ((tcp->Flag & TCP_ACK) == false))
1234        {
1235            TCP_OPTION o;
1236            // 新しいセッションを作成する
1237            n = CreateNatTcp(v, src_ip, src_port, dest_ip, dest_port);
1238            if (n == NULL)
1239            {
1240                return;
1241            }
1242
1243            // オプションの取得
1244            ParseTcpOption(&o, ((UCHAR *)tcp) + TCP_HEADER_SIZE, TCP_GET_HEADER_SIZE(tcp) * 4 - TCP_HEADER_SIZE);
1245            if (o.MaxSegmentSize == 0)
1246            {
1247                o.MaxSegmentSize = v->TcpMss;
1248            }
1249
1250            Debug("TCP SYN: MSS=%u, WS=%u\n", o.MaxSegmentSize, o.WindowScaling);
1251
1252            // 初期シーケンス番号
1253            n->RecvSeqInit = (UINT64)Endian32(tcp->SeqNumber);
1254            n->RecvSeq = 1;
1255
1256            n->TcpSendMaxSegmentSize = o.MaxSegmentSize;
1257            n->TcpRecvWindowSize = NAT_TCP_RECV_WINDOW_SIZE;
1258            n->TcpSendWindowSize = (UINT)Endian16(tcp->WindowSize);
1259            if (o.WindowScaling != 0)
1260            {
1261                if (o.WindowScaling > 14)
1262                {
1263                    o.WindowScaling = 14;
1264                }
1265                n->TcpSendWindowSize = (n->TcpSendWindowSize << o.WindowScaling);
1266            }
1267        }
1268    }
1269
1270    seq = Endian32(tcp->SeqNumber);
1271    ack = Endian32(tcp->AckNumber);
1272
1273    if (n == NULL)
1274    {
1275        // NAT エントリに登録されていないパケットが届いたので RST を返す
1276        SendTcp(v, dest_ip, dest_port, src_ip, src_port,
1277            ack, ack, TCP_RST, 0, 0, NULL, 0);
1278        return;
1279    }
1280
1281    switch (n->TcpStatus)
1282    {
1283    case NAT_TCP_SEND_RESET:        // リセットを送信してコネクションを切断
1284        break;
1285
1286    case NAT_TCP_CONNECTED:         // ソケット接続完了 SYN+ACK, ACK 処理
1287        if ((tcp->Flag & TCP_ACK) && ((tcp->Flag & TCP_SYN) == false))
1288        {
1289            if (seq == (UINT)(n->RecvSeqInit + n->RecvSeq) &&
1290                ack == (UINT)(n->SendSeqInit + n->SendSeq + 1))
1291            {
1292                // ACK パケットが戻ってきたのでハンドシェイク完了
1293                n->SendSeq++;       // SYN パケットは seq を 1 消費する
1294                Debug("TCP Connection Established.\n");
1295                n->TcpStatus = NAT_TCP_ESTABLISHED;
1296                // 輻輳ウインドウサイズを初期化
1297                n->TcpSendCWnd = 1;
1298                n->LastCommTime = v->Now;
1299            }
1300            else
1301            {
1302                goto TCP_RESET;
1303            }
1304        }
1305        else if (tcp->Flag & TCP_RST)
1306        {
1307TCP_RESET:
1308            // RST を受信
1309            Debug("TCP Connection Reseted.\n");
1310            n->TcpStatus = NAT_TCP_SEND_RESET;
1311        }
1312        break;
1313
1314    case NAT_TCP_ESTABLISHED:       // 接続確立済み
1315        if (tcp->Flag & TCP_FIN)
1316        {
1317            // 接続を完了させる
1318            n->TcpFinished = true;
1319        }
1320        if (tcp->Flag & TCP_RST)
1321        {
1322            // RST を受信
1323            goto TCP_RESET;
1324        }
1325        else if (tcp->Flag & TCP_ACK)
1326        {
1327            TCP_OPTION opt;
1328            n->LastCommTime = v->Now;
1329            // ウインドウサイズなどのオプションの取得
1330            n->TcpSendWindowSize = Endian16(tcp->WindowSize);
1331            ParseTcpOption(&opt, ((UCHAR *)tcp) + TCP_HEADER_SIZE, TCP_GET_HEADER_SIZE(tcp) * 4 - TCP_HEADER_SIZE);
1332            if (opt.WindowScaling != 0)
1333            {
1334                if (opt.WindowScaling > 14)
1335                {
1336                    opt.WindowScaling = 14;
1337                }
1338                n->TcpSendWindowSize = (n->TcpSendWindowSize << opt.WindowScaling);
1339            }
1340            // まず受信した ACK の処理を行う
1341            // ack64 に応答確認を受けたストリームの終端位置を格納する
1342            ack64 = n->SendSeq + (UINT64)ack - (n->SendSeqInit + n->SendSeq) % X32;
1343            if ((n->SendSeqInit + n->SendSeq) % X32 > ack)
1344            {
1345                if (((n->SendSeqInit + n->SendSeq) % X32 - ack) >= 0x80000000)
1346                {
1347                    ack64 = n->SendSeq + (UINT64)ack + X32 - (n->SendSeqInit + n->SendSeq) % X32;
1348                }
1349            }
1350            if (ack64 > n->SendSeq)
1351            {
1352                // クライアントによって 1 バイト以上の受信が完了したらしい
1353                UINT slide_offset = (UINT)(ack64 - n->SendSeq); // ウインドウのスライド量
1354                if (slide_offset == 0 || slide_offset > n->TcpSendWindowSize || slide_offset > n->SendFifo->size)
1355                {
1356                    // 確認応答のオフセット値がこれまでに送信したはずのサイズ
1357                    // よりも大きいので無視する
1358                }
1359                else
1360                {
1361                    // RTT 測定
1362                    if (n->CalcRTTStartTime != 0)
1363                    {
1364                        if (n->CalcRTTStartValue < ack64)
1365                        {
1366                            UINT time_span;
1367                            if (v->Now > n->CalcRTTStartTime)
1368                            {
1369                                time_span = (UINT)(v->Now - n->CalcRTTStartTime);
1370                            }
1371                            else
1372                            {
1373                                time_span = 100;
1374                            }
1375                            n->CalcRTTStartTime = 0;
1376
1377                            // 平滑化
1378                            n->CurrentRTT =
1379                                (UINT)
1380                                (
1381                                    ((UINT64)n->CurrentRTT * (UINT64)9 +
1382                                    (UINT64)time_span * (UINT64)1) / (UINT64)10
1383                                );
1384                            n->TcpSendTimeoutSpan = n->CurrentRTT * 2;
1385                        }
1386                    }
1387                    // 送信サイズを減少させる
1388                    n->SendMissionSize -= slide_offset;
1389                    if (n->SendMissionSize == 0)
1390                    {
1391                        // 今回送信する予定であったすべてのセグメントの送受信が完了した
1392                        // より送信セグメントサイズを大きくしてみる
1393                        if (n->TcpSendCWnd < 65536)
1394                        {
1395                            n->TcpSendCWnd++;
1396                        }
1397                        n->CurrentSendingMission = false;
1398                        n->TcpLastSentTime = 0;
1399                        n->RetransmissionUsedFlag = false;
1400                    }
1401                    // バッファをスライディングする
1402                    n->SendSeq += slide_offset;
1403                    ReadFifo(n->SendFifo, NULL, slide_offset);
1404                    // 今回 ACK によって送信完了が確認できたサイズだけ、さらに送信を実行する
1405                    if (n->SendMissionSize != 0 && false)
1406                    {
1407                        UINT notice_window_size_value = 0;
1408                        UINT send_data_size;
1409                        UINT buf_free_bytes;
1410                        UINT send_offset = n->SendMissionSize;
1411                        // 通知するウインドウサイズの値を決定する
1412                        if (FifoSize(n->RecvFifo) < NAT_RECV_BUF_SIZE)
1413                        {
1414                            buf_free_bytes = NAT_RECV_BUF_SIZE - FifoSize(n->RecvFifo);
1415                        }
1416                        notice_window_size_value = MIN(n->TcpRecvWindowSize, buf_free_bytes);
1417                        // 送信すべきセグメントサイズを計算する
1418                        send_data_size = n->TcpSendWindowSize;
1419                        if (send_data_size > (n->TcpSendCWnd * n->TcpSendMaxSegmentSize))
1420                        {
1421                            // cwnd 値を適用する
1422                            send_data_size = n->TcpSendCWnd * n->TcpSendMaxSegmentSize;
1423                        }
1424                        if (n->SendFifo->size > send_offset)
1425                        {
1426                            send_data_size = MIN(send_data_size, n->SendFifo->size - send_offset);
1427                            send_data_size = MIN(send_data_size, slide_offset);
1428                        }
1429                        else
1430                        {
1431                            send_data_size = 0;
1432                        }
1433                        if (send_data_size >= 1)
1434                        {
1435                            // セグメントに分割して送信する
1436                            UINT current_pointer = 0;
1437                            while (send_data_size > 0)
1438                            {
1439                                UINT send_segment_size = MIN(n->TcpSendMaxSegmentSize, send_data_size);
1440                                void *send_segment = (void *)((
1441                                    (UCHAR *)n->SendFifo->p) + n->SendFifo->pos +
1442                                    current_pointer + send_offset);
1443
1444                                SendTcp(v, n->DestIp, n->DestPort, n->SrcIp, n->SrcPort,
1445                                    (UINT)(n->SendSeqInit + n->SendSeq + (UINT64)current_pointer
1446                                    + (UINT)send_offset),
1447                                    (UINT)(n->RecvSeqInit + n->RecvSeq),
1448                                    TCP_ACK | TCP_PSH,
1449                                    notice_window_size_value,
1450                                    0,
1451                                    send_segment,
1452                                    send_segment_size);
1453                                current_pointer += send_segment_size;
1454                                send_data_size -= send_segment_size;
1455                            }
1456                            n->SendMissionSize += current_pointer;
1457                            n->CurrentSendingMission = true;
1458                            n->TcpLastSentTime = v->Now;
1459                            // RTT 測定
1460                            if (n->CalcRTTStartTime == 0)
1461                            {
1462                                n->CalcRTTStartTime = v->Now;
1463                                n->CalcRTTStartValue = n->SendSeq + current_pointer - 1;
1464                            }
1465                        }
1466                    }
1467                    // イベント発生
1468                    SetSockEvent(v->SockEvent);
1469                }
1470            }
1471            // 次にデータの受信処理を行う
1472            seq64 = n->RecvSeq + (UINT64)seq - (n->RecvSeqInit + n->RecvSeq) % X32;
1473            if ((n->RecvSeqInit + n->RecvSeq) % X32 > seq)
1474            {
1475                if (((n->RecvSeqInit + n->RecvSeq) % X32 - ack) >= 0x80000000)
1476                {
1477                    seq64 = n->RecvSeq + (UINT64)seq + X32 - (n->RecvSeqInit + n->RecvSeq) % X32;
1478                }
1479            }
1480            // この時点で seq64 にはクライアントからのデータ開始点の位置が入っている
1481            if (seq64 >= n->RecvSeq && (seq64 + size) <= (n->RecvSeq + n->TcpRecvWindowSize))
1482            {
1483                if (size >= 1)
1484                {
1485                    // 受信ウインドウの範囲内に 1 バイト以上のデータが届いた
1486                    UINT offset = (UINT)(seq64 - n->RecvSeq);
1487                    UINT i;
1488                    IP_PART *me;
1489                    if (n->TcpRecvWindow == NULL)
1490                    {
1491                        n->TcpRecvWindow = NewFifo();
1492                    }
1493                    if (n->TcpRecvList == NULL)
1494                    {
1495                        n->TcpRecvList = NewListFast(NULL);
1496                    }
1497                    // 届いたパケットをバッファに上書きしリストに追加する
1498                    if (FifoSize(n->TcpRecvWindow) < (offset + size))
1499                    {
1500                        // バッファサイズ拡張
1501                        WriteFifo(n->TcpRecvWindow, NULL, offset + size - FifoSize(n->TcpRecvWindow));
1502                    }
1503                    Copy(((UCHAR *)n->TcpRecvWindow->p) + n->TcpRecvWindow->pos +
1504                        offset, data, size);
1505                    me = ZeroMalloc(sizeof(IP_PART));
1506                    me->Offset = offset;
1507                    me->Size = size;
1508                    for (i = 0;i < LIST_NUM(n->TcpRecvList);i++)
1509                    {
1510                        IP_PART *p = LIST_DATA(n->TcpRecvList, i);
1511                        // 重なる領域があれば重なっている部分があれば除去する
1512                        if (p->Size != 0)
1513                        {
1514                            if (me->Offset <= p->Offset && (me->Offset + me->Size) >= (p->Offset + p->Size))
1515                            {
1516                                // このパケットが既存パケットを完全に上書きする
1517                                p->Size = 0;
1518                            }
1519                            else if (me->Offset >= p->Offset && (me->Offset + me->Size) <= (p->Offset + p->Size))
1520                            {
1521                                // 既存パケットがこのパケットを完全に上書きする
1522                                me->Size = 0;
1523                            }
1524                            else if (me->Offset > p->Offset && me->Offset < (p->Offset + p->Size) &&
1525                                (me->Offset + me->Size) > (p->Offset + p->Size))
1526                            {
1527                                // 一部重なっている
1528                                p->Size -= p->Offset + p->Size - me->Offset;
1529                            }
1530                            else if (me->Offset < p->Offset && (me->Offset + size) > p->Offset && (me->Offset + size) < (p->Offset + p->Size))
1531                            {
1532                                // 一部重なっている
1533                                me->Size -= me->Offset + me->Size - p->Offset;
1534                            }
1535                        }
1536                    }
1537                    if (me->Size == 0)
1538                    {
1539                        Free(me);
1540                    }
1541                    else
1542                    {
1543                        Add(n->TcpRecvList, me);
1544                    }
1545KILL_NULL_FIRST:
1546                    // 受信リストから中身が空白のものをすべて削除する
1547                    for (i = 0;i < LIST_NUM(n->TcpRecvList);i++)
1548                    {
1549                        IP_PART *p = LIST_DATA(n->TcpRecvList, i);
1550                        if (p->Size == 0)
1551                        {
1552                            Delete(n->TcpRecvList, p);
1553                            Free(p);
1554                            goto KILL_NULL_FIRST;
1555                        }
1556                    }
1557SCAN_FIRST:
1558                    // 受信リストのうちオフセット 0 から始まるものがあれば抽出する
1559                    for (i = 0;i < LIST_NUM(n->TcpRecvList);i++)
1560                    {
1561                        IP_PART *p = LIST_DATA(n->TcpRecvList, i);
1562                        UINT sz;
1563                        if (p->Offset == 0)
1564                        {
1565                            // 0 から始まるデータブロックを発見したので
1566                            // この分だけ左側にスライドさせてデータを抜き出す
1567                            // バッファを FIFO に書き出す
1568                            sz = p->Size;
1569                            WriteFifo(n->RecvFifo, ((UCHAR *)n->TcpRecvWindow->p) + n->TcpRecvWindow->pos, sz);
1570                            // リストから解放する
1571                            Delete(n->TcpRecvList, p);
1572                            Free(p);
1573                            ReadFifo(n->TcpRecvWindow, NULL, sz);
1574                            // すべての項目を左側にスライドする
1575                            for (i = 0;i < LIST_NUM(n->TcpRecvList);i++)
1576                            {
1577                                p = LIST_DATA(n->TcpRecvList, i);
1578                                p->Offset -= sz;
1579                            }
1580                            // TCB のパラメータを更新
1581                            n->RecvSeq += (UINT64)sz;
1582                            SetSockEvent(v->SockEvent);
1583                            n->SendAckNext = true;
1584                            // 最初からスキャンし直す
1585                            goto SCAN_FIRST;
1586                        }
1587                    }
1588                }
1589            }
1590        }
1591        break;
1592    }
1593
1594    SetSockEvent(v->SockEvent);
1595}
1596
1597// TCP オプションのパース
1598void ParseTcpOption(TCP_OPTION *o, void *data, UINT size)
1599{
1600    UCHAR *buf = (UCHAR *)data;
1601    UINT i;
1602    UINT value_size = 0;
1603    UINT value_id = 0;
1604    UCHAR value[128];
1605    // 引数チェック
1606    if (o == NULL || data == NULL)
1607    {
1608        return;
1609    }
1610
1611    Zero(o, sizeof(TCP_OPTION));
1612
1613    for (i = 0;i < size;i++)
1614    {
1615        if (buf[i] == 0)
1616        {
1617            return;
1618        }
1619        if (buf[i] != 1)
1620        {
1621            value_id = buf[i];
1622            i++;
1623            if (i >= size)
1624            {
1625                return;
1626            }
1627            value_size = buf[i];
1628            if (value_size <= 1 || value_size > sizeof(value))
1629            {
1630                return;
1631            }
1632            i++;
1633            if (i >= size)
1634            {
1635                return;
1636            }
1637            value_size -= 2;
1638            Copy(value, &buf[i], value_size);
1639            i += value_size;
1640            if (i >= size)
1641            {
1642                return;
1643            }
1644            switch (value_id)
1645            {
1646            case 2: // MSS
1647                if (value_size == 2)
1648                {
1649                    USHORT *mss = (USHORT *)value;
1650                    o->MaxSegmentSize = Endian16(*mss);
1651                }
1652                break;
1653
1654            case 3: // WSS
1655                if (value_size == 1)
1656                {
1657                    UCHAR *wss = (UCHAR *)value;
1658                    o->WindowScaling = Endian16(*wss);
1659                }
1660                break;
1661
1662            }
1663        }
1664    }
1665
1666}
1667
1668// 新しい NAT TCP セッションの作成
1669NAT_ENTRY *CreateNatTcp(VH *v, UINT src_ip, UINT src_port, UINT dest_ip, UINT dest_port)
1670{
1671    NAT_ENTRY *n;
1672    // 引数チェック
1673    if (v == NULL)
1674    {
1675        return NULL;
1676    }
1677
1678    if (CanCreateNewNatEntry(v) == false)
1679    {
1680        return NULL;
1681    }
1682
1683    // NAT エントリの作成
1684    n = ZeroMalloc(sizeof(NAT_ENTRY));
1685    n->Id = Inc(v->Counter);
1686    n->v = v;
1687    n->lock = NewLock();
1688    n->Protocol = NAT_TCP;
1689    n->SrcIp = src_ip;
1690    n->SrcPort = src_port;
1691    n->DestIp = dest_ip;
1692    n->DestPort = dest_port;
1693    n->CreatedTime = n->LastCommTime = v->Now;
1694    n->Sock = NULL;
1695    n->DisconnectNow = false;
1696    n->TcpSendMaxSegmentSize = n->TcpRecvMaxSegmentSize = v->TcpMss;
1697
1698    n->SendFifo = NewFifo();
1699    n->RecvFifo = NewFifo();
1700
1701    n->TcpStatus = NAT_TCP_CONNECTING;
1702
1703    n->SendSeqInit = Rand32();
1704    n->CurrentRTT = NAT_INITIAL_RTT_VALUE;
1705    n->TcpSendTimeoutSpan = n->CurrentRTT * 2;
1706
1707    // NAT テーブルに追加
1708    Add(v->NatTable, n);
1709
1710
1711#if 1
1712    {
1713        IP ip1, ip2;
1714        char s1[MAX_SIZE], s2[MAX_SIZE];
1715        UINTToIP(&ip1, src_ip);
1716        UINTToIP(&ip2, dest_ip);
1717        IPToStr(s1, 0, &ip1);
1718        IPToStr(s2, 0, &ip2);
1719        Debug("NAT_ENTRY: CreateNatTcp %s %u -> %s %u\n", s1, src_port, s2, dest_port);
1720
1721        NLog(v, "LH_NAT_TCP_CREATED", n->Id, s1, src_port, s2, dest_port);
1722    }
1723#endif
1724
1725    return n;
1726}
1727
1728// TCP パケットを仮想ネットワークから受信した
1729void VirtualTcpReceived(VH *v, UINT src_ip, UINT dest_ip, void *data, UINT size)
1730{
1731    TCP_HEADER *tcp;
1732    UINT src_port, dest_port;
1733    UINT header_size, buf_size;
1734    void *buf;
1735    IP ip1, ip2;
1736    // 引数チェック
1737    if (v == NULL || data == NULL)
1738    {
1739        return;
1740    }
1741
1742    // ヘッダを取得
1743    if (size < TCP_HEADER_SIZE)
1744    {
1745        // サイズが小さすぎる
1746        return;
1747    }
1748    tcp = (TCP_HEADER *)data;
1749    src_port = Endian16(tcp->SrcPort);
1750    dest_port = Endian16(tcp->DstPort);
1751    if (src_port == 0 || dest_port == 0)
1752    {
1753        // ポート番号が不正
1754        return;
1755    }
1756    if (src_ip == dest_ip || src_ip == 0 || src_ip == 0xffffffff || dest_ip == 0 || dest_ip == 0xffffffff)
1757    {
1758        // IP アドレスが不正
1759        return;
1760    }
1761    UINTToIP(&ip1, src_ip);
1762    UINTToIP(&ip2, dest_ip);
1763    if (ip1.addr[0] == 127 || ip2.addr[0] == 127)
1764    {
1765        // ループバック IP アドレスは指定できない
1766        return;
1767    }
1768    if (IsInNetwork(dest_ip, v->HostIP, v->HostMask))
1769    {
1770        // 仮想 LAN 側のネットワーク向けのパケットは無視する
1771        return;
1772    }
1773    // ヘッダサイズを取得
1774    header_size = TCP_GET_HEADER_SIZE(tcp) * 4;
1775    if (size < header_size)
1776    {
1777        // ヘッダサイズが不正
1778        return;
1779    }
1780    // バッファのサイズとアドレスを取得
1781    buf_size = size - header_size;
1782    buf = (void *)(((UCHAR *)data) + header_size);
1783
1784    TcpRecvForInternet(v, src_ip, src_port, dest_ip, dest_port, tcp, buf, buf_size);
1785}
1786
1787// NAT UDP ポーリング
1788void PoolingNatUdp(VH *v, NAT_ENTRY *n)
1789{
1790    // 引数チェック
1791    if (v == NULL || n == NULL)
1792    {
1793        return;
1794    }
1795
1796    // 受信キューにパケットが 1 つ以上あれば処理する
1797    if (n->UdpRecvQueue->num_item != 0)
1798    {
1799        BLOCK *block;
1800
1801        // すべての UDP パケットを仮想ネットワークに送信する
1802        while (block = GetNext(n->UdpRecvQueue))
1803        {
1804            SendUdp(v, n->SrcIp, n->SrcPort, n->DestIp, n->DestPort,
1805                block->Buf, block->Size);
1806
1807            FreeBlock(block);
1808        }
1809    }
1810}
1811
1812// NAT ポーリング
1813void PoolingNat(VH *v)
1814{
1815    UINT i;
1816    // 引数チェック
1817    if (v == NULL)
1818    {
1819        return;
1820    }
1821
1822    // すべての NAT エントリを走査し処理を行う
1823    for (i = 0;i < LIST_NUM(v->NatTable);i++)
1824    {
1825        NAT_ENTRY *n = LIST_DATA(v->NatTable, i);
1826
1827        switch (n->Protocol)
1828        {
1829        case NAT_TCP:
1830            PollingNatTcp(v, n);
1831            break;
1832
1833        case NAT_UDP:
1834            PoolingNatUdp(v, n);
1835            break;
1836
1837        case NAT_DNS:
1838            PollingNatDns(v, n);
1839            break;
1840        }
1841    }
1842}
1843
1844// NAT テーブルの比較関数
1845int CompareNat(void *p1, void *p2)
1846{
1847    NAT_ENTRY *n1, *n2;
1848    if (p1 == NULL || p2 == NULL)
1849    {
1850        return 0;
1851    }
1852    n1 = *(NAT_ENTRY **)p1;
1853    n2 = *(NAT_ENTRY **)p2;
1854    if (n1 == n2)
1855    {
1856        return 0;
1857    }
1858
1859    if (n1->SrcIp > n2->SrcIp) return 1;
1860    else if (n1->SrcIp < n2->SrcIp) return -1;
1861    else if (n1->DestIp > n2->DestIp) return 1;
1862    else if (n1->DestIp < n2->DestIp) return -1;
1863    else if (n1->SrcPort > n2->SrcPort) return 1;
1864    else if (n1->SrcPort < n2->SrcPort) return -1;
1865    else if (n1->DestPort > n2->DestPort) return 1;
1866    else if (n1->DestPort < n2->DestPort) return -1;
1867    else if (n1->Protocol > n2->Protocol) return 1;
1868    else if (n1->Protocol < n2->Protocol) return -1;
1869    else return 0;
1870}
1871
1872// NAT 構造体の設定
1873void SetNat(NAT_ENTRY *n, UINT protocol, UINT src_ip, UINT src_port, UINT dest_ip, UINT dest_port, UINT public_ip, UINT public_port)
1874{
1875    // 引数チェック
1876    if (n == NULL)
1877    {
1878        return;
1879    }
1880
1881    n->Protocol = protocol;
1882    n->SrcIp = src_ip;
1883    n->SrcPort = src_port;
1884    n->DestIp = dest_ip;
1885    n->DestPort = dest_port;
1886    n->PublicIp = public_ip;
1887    n->PublicPort = public_port;
1888}
1889
1890// NAT の初期化
1891void InitNat(VH *v)
1892{
1893    // 引数チェック
1894    if (v == NULL)
1895    {
1896        return;
1897    }
1898
1899    // NAT テーブルの作成
1900    v->NatTable = NewList(CompareNat);
1901
1902    // ソケットイベントの作成
1903    v->SockEvent = NewSockEvent();
1904
1905    // NAT 用スレッドの作成
1906    v->HaltNat = false;
1907    v->NatThread = NewThread(NatThread, (void *)v);
1908    WaitThreadInit(v->NatThread);
1909}
1910
1911// NAT の解放
1912void FreeNat(VH *v)
1913{
1914    // 引数チェック
1915    if (v == NULL)
1916    {
1917        return;
1918    }
1919
1920    // NAT 用スレッドの停止
1921    v->HaltNat = true;
1922    SetSockEvent(v->SockEvent);
1923    WaitThread(v->NatThread, INFINITE);
1924    ReleaseThread(v->NatThread);
1925    v->NatThread = NULL;
1926    ReleaseSockEvent(v->SockEvent);
1927    v->SockEvent = NULL;
1928
1929    // NAT テーブルの解放
1930    ReleaseList(v->NatTable);
1931}
1932
1933// NAT テーブルの検索
1934NAT_ENTRY *SearchNat(VH *v, NAT_ENTRY *target)
1935{
1936    NAT_ENTRY *n;
1937    // 引数チェック
1938    if (v == NULL || target == NULL)
1939    {
1940        return NULL;
1941    }
1942
1943    // バイナリサーチ
1944    n = (NAT_ENTRY *)Search(v->NatTable, target);
1945
1946    return n;
1947}
1948
1949// UDP NAT エントリの削除
1950void DeleteNatUdp(VH *v, NAT_ENTRY *n)
1951{
1952    BLOCK *block;
1953    // 引数チェック
1954    if (v == NULL || n == NULL)
1955    {
1956        return;
1957    }
1958
1959    NLog(v, "LH_NAT_UDP_DELETED", n->Id);
1960
1961    // すべてのキューを解放
1962    while (block = GetNext(n->UdpRecvQueue))
1963    {
1964        FreeBlock(block);
1965    }
1966    ReleaseQueue(n->UdpRecvQueue);
1967    while (block = GetNext(n->UdpSendQueue))
1968    {
1969        FreeBlock(block);
1970    }
1971    ReleaseQueue(n->UdpSendQueue);
1972
1973    // ソケットを解放
1974    if (n->Sock != NULL)
1975    {
1976        Disconnect(n->Sock);
1977        ReleaseSock(n->Sock);
1978        n->Sock = NULL;
1979    }
1980
1981    DeleteLock(n->lock);
1982
1983    // テーブルから削除
1984    Delete(v->NatTable, n);
1985
1986    // メモリ解放
1987    Free(n);
1988
1989    Debug("NAT: DeleteNatUdp\n");
1990
1991}
1992
1993// NAT UDP エントリを作成
1994NAT_ENTRY *CreateNatUdp(VH *v, UINT src_ip, UINT src_port, UINT dest_ip, UINT dest_port, UINT dns_proxy_ip)
1995{
1996    NAT_ENTRY *n;
1997    // 引数チェック
1998    if (v == NULL)
1999    {
2000        return NULL;
2001    }
2002
2003    if (CanCreateNewNatEntry(v) == false)
2004    {
2005        return NULL;
2006    }
2007
2008    n = ZeroMalloc(sizeof(NAT_ENTRY));
2009    n->Id = Inc(v->Counter);
2010    n->v = v;
2011    n->lock = NewLock();
2012    n->Protocol = NAT_UDP;
2013    n->SrcIp = src_ip;
2014    n->SrcPort = src_port;
2015    n->DestIp = dest_ip;
2016    n->DestPort = dest_port;
2017
2018    if (dns_proxy_ip != 0)
2019    {
2020        n->ProxyDns = true;
2021        n->DestIpProxy = dns_proxy_ip;
2022    }
2023
2024    n->CreatedTime = n->LastCommTime = v->Now;
2025
2026    n->UdpSendQueue = NewQueue();
2027    n->UdpRecvQueue = NewQueue();
2028
2029    n->UdpSocketCreated = false;
2030
2031    SetSockEvent(v->SockEvent);
2032
2033#if 1
2034    {
2035        IP ip1, ip2;
2036        char s1[MAX_SIZE], s2[MAX_SIZE];
2037        UINTToIP(&ip1, src_ip);
2038        UINTToIP(&ip2, dest_ip);
2039        IPToStr(s1, 0, &ip1);
2040        IPToStr(s2, 0, &ip2);
2041        Debug("NAT_ENTRY: CreateNatUdp %s %u -> %s %u\n", s1, src_port, s2, dest_port);
2042
2043        NLog(v, "LH_NAT_UDP_CREATED", n->Id, s1, src_port, s2, dest_port);
2044    }
2045#endif
2046
2047    Add(v->NatTable, n);
2048
2049    return n;
2050}
2051
2052// インターネットへの UDP パケットの処理
2053void UdpRecvForInternet(VH *v, UINT src_ip, UINT src_port, UINT dest_ip, UINT dest_port, void *data, UINT size, bool dns_proxy)
2054{
2055    NAT_ENTRY *n, t;
2056    BLOCK *block;
2057    void *buf;
2058    UINT dns_ip = 0;
2059    // 引数チェック
2060    if (data == NULL || v == NULL)
2061    {
2062        return;
2063    }
2064
2065    if (dns_proxy)
2066    {
2067        // プロキシ接続先の DNS サーバーを取得する
2068        IP ip;
2069        char tmp[MAX_SIZE];
2070        if (GetDefaultDns(&ip) == false)
2071        {
2072            // 失敗
2073            Debug("Failed to GetDefaultDns()\n");
2074            return;
2075        }
2076        dns_ip = IPToUINT(&ip);
2077        IPToStr(tmp, sizeof(tmp), &ip);
2078        Debug("Redirect to DNS Server %s\n", tmp);
2079    }
2080
2081    // このパケットに関する NAT エントリがすでに作成されているかどうかを調べる
2082    SetNat(&t, NAT_UDP, src_ip, src_port, dest_ip, dest_port, 0, 0);
2083    n = SearchNat(v, &t);
2084
2085    if (n == NULL)
2086    {
2087        // 最初のパケットなので NAT エントリを作成する
2088        n = CreateNatUdp(v, src_ip, src_port, dest_ip, dest_port, dns_proxy ? dns_ip : 0);
2089        if (n == NULL)
2090        {
2091            // エントリ作成失敗
2092            return;
2093        }
2094
2095        if (dns_proxy)
2096        {
2097            n->ProxyDns = true;
2098            n->DestIpProxy = dns_ip;
2099        }
2100    }
2101
2102    // キューにパケットを挿入してイベントを呼び出す
2103    buf = Malloc(size);
2104    Copy(buf, data, size);
2105    block = NewBlock(buf, size, 0);
2106    InsertQueue(n->UdpSendQueue, block);
2107
2108    SetSockEvent(v->SockEvent);
2109}
2110
2111// DNS パケットの解釈を試行する
2112bool ParseDnsPacket(VH *v, UINT src_ip, UINT src_port, UINT dest_ip, UINT dest_port, void *data, UINT size)
2113{
2114    DNSV4_HEADER *dns;
2115    NAT_ENTRY *nat;
2116    UINT transaction_id;
2117    void *query_data;
2118    UINT query_data_size;
2119    char hostname[256];
2120    // 引数チェック
2121    if (v == NULL || data == NULL || size == 0)
2122    {
2123        return false;
2124    }
2125
2126    // ヘッダサイズのチェック
2127    if (size < sizeof(DNSV4_HEADER))
2128    {
2129        // サイズ不足
2130        return false;
2131    }
2132
2133    // DNS ヘッダ取得
2134    dns = (DNSV4_HEADER *)data;
2135    transaction_id = Endian16(dns->TransactionId);
2136    if ((dns->Flag1 & 78) != 0 || (dns->Flag1 & 0x80) != 0)
2137    {
2138        // オペコード不正
2139        return false;
2140    }
2141    if (Endian16(dns->NumQuery) != 1)
2142    {
2143        // クエリ数不正
2144        return false;
2145    }
2146
2147    query_data = ((UCHAR *)dns) + sizeof(DNSV4_HEADER);
2148    query_data_size = size - sizeof(DNSV4_HEADER);
2149
2150    // クエリの解釈
2151    if (ParseDnsQuery(hostname, sizeof(hostname), query_data, query_data_size) == false)
2152    {
2153        // 解釈失敗
2154        return false;
2155    }
2156
2157    // DNS エントリの作成
2158    nat = CreateNatDns(v, src_ip, src_port, dest_ip, dest_port, transaction_id,
2159        false, hostname);
2160
2161    if (nat == false)
2162    {
2163        return false;
2164    }
2165
2166    return true;
2167}
2168
2169// NAT DNS 応答パケットの送信
2170void SendNatDnsResponse(VH *v, NAT_ENTRY *n)
2171{
2172    BUF *b;
2173    UINT dns_header_size;
2174    DNSV4_HEADER *dns;
2175    // 引数チェック
2176    if (n == NULL || v == NULL)
2177    {
2178        return;
2179    }
2180
2181    // データの生成
2182    b = NewBuf();
2183
2184    // Query の追加
2185    if (n->DnsGetIpFromHost == false)
2186    {
2187        BuildDnsQueryPacket(b, n->DnsTargetHostName, false);
2188    }
2189    else
2190    {
2191        BuildDnsQueryPacket(b, n->DnsTargetHostName, true);
2192    }
2193
2194    // Response の追加
2195    if (n->DnsOk)
2196    {
2197        if (n->DnsGetIpFromHost == false)
2198        {
2199            BuildDnsResponsePacketA(b, &n->DnsResponseIp);
2200        }
2201        else
2202        {
2203            BuildDnsResponsePacketPtr(b, n->DnsResponseHostName);
2204        }
2205    }
2206
2207    // DNS ヘッダの生成
2208    dns_header_size = sizeof(DNSV4_HEADER) + b->Size;
2209
2210    dns = ZeroMalloc(dns_header_size);
2211    dns->TransactionId = Endian16((USHORT)n->DnsTransactionId);
2212
2213    // 応答フラグの生成
2214    if (n->DnsOk)
2215    {
2216        dns->Flag1 = 0x85;
2217        dns->Flag2 = 0x80;
2218    }
2219    else
2220    {
2221        dns->Flag1 = 0x85;
2222        dns->Flag2 = 0x83;
2223    }
2224
2225    dns->NumQuery = Endian16(1);
2226    dns->AnswerRRs = Endian16(n->DnsOk != false ? 1 : 0);
2227    dns->AuthorityRRs = 0;
2228    dns->AdditionalRRs = 0;
2229
2230    // データのコピー
2231    Copy(((UCHAR *)dns) + sizeof(DNSV4_HEADER), b->Buf, b->Size);
2232
2233    // このパケットを送信
2234    SendUdp(v, n->SrcIp, n->SrcPort, n->DestIp, n->DestPort, dns, dns_header_size);
2235
2236    // メモリ解放
2237    Free(dns);
2238    FreeBuf(b);
2239}
2240
2241// DNS 応答パケット (ホスト名) の生成
2242void BuildDnsResponsePacketPtr(BUF *b, char *hostname)
2243{
2244    USHORT magic;
2245    USHORT type, clas;
2246    UINT ttl;
2247    USHORT len;
2248    BUF *c;
2249    // 引数チェック
2250    if (b == NULL || hostname == NULL)
2251    {
2252        return;
2253    }
2254
2255    magic = Endian16(0xc00c);
2256    type = Endian16(0x000c);
2257    clas = Endian16(0x0001);
2258    ttl = Endian32(NAT_DNS_RESPONSE_TTL);
2259
2260    c = BuildDnsHostName(hostname);
2261    if (c == NULL)
2262    {
2263        return;
2264    }
2265    len = Endian16((USHORT)c->Size);
2266
2267    WriteBuf(b, &magic, 2);
2268    WriteBuf(b, &type, 2);
2269    WriteBuf(b, &clas, 2);
2270    WriteBuf(b, &ttl, 4);
2271    WriteBuf(b, &len, 2);
2272    WriteBuf(b, c->Buf, c->Size);
2273    FreeBuf(c);
2274}
2275
2276// DNS 応答パケット (ホスト IP アドレス) の生成
2277void BuildDnsResponsePacketA(BUF *b, IP *ip)
2278{
2279    UINT ip_addr;
2280    USHORT magic;
2281    USHORT type, clas;
2282    UINT ttl;
2283    USHORT len;
2284    // 引数チェック
2285    if (b == NULL || ip == NULL)
2286    {
2287        return;
2288    }
2289
2290    ip_addr = IPToUINT(ip);
2291    magic = Endian16(0xc00c);
2292    type = Endian16(0x0001);
2293    clas = Endian16(0x0001);
2294    ttl = Endian32(NAT_DNS_RESPONSE_TTL);
2295    len = Endian16((USHORT)sizeof(ttl));
2296
2297    WriteBuf(b, &magic, sizeof(magic));
2298    WriteBuf(b, &type, sizeof(type));
2299    WriteBuf(b, &clas, sizeof(clas));
2300    WriteBuf(b, &ttl, sizeof(ttl));
2301    WriteBuf(b, &len, sizeof(len));
2302    WriteBuf(b, &ip_addr, sizeof(ip_addr));
2303}
2304
2305// DNS クエリデータパケットの生成
2306void BuildDnsQueryPacket(BUF *b, char *hostname, bool ptr)
2307{
2308    USHORT val;
2309    BUF *c;
2310    // 引数チェック
2311    if (b == NULL || hostname == NULL)
2312    {
2313        return;
2314    }
2315
2316    // ホスト名をバッファに変換
2317    c = BuildDnsHostName(hostname);
2318    if (c == NULL)
2319    {
2320        return;
2321    }
2322
2323    WriteBuf(b, c->Buf, c->Size);
2324    FreeBuf(c);
2325
2326    // 種類とクラス
2327    if (ptr == false)
2328    {
2329        val = Endian16(0x0001);
2330    }
2331    else
2332    {
2333        val = Endian16(0x000c);
2334    }
2335    WriteBuf(b, &val, 2);
2336
2337    val = Endian16(0x0001);
2338    WriteBuf(b, &val, 2);
2339}
2340
2341// DNS ホスト名バッファの生成
2342BUF *BuildDnsHostName(char *hostname)
2343{
2344    UINT i;
2345    UCHAR size;
2346    TOKEN_LIST *token;
2347    BUF *b;
2348    // 引数チェック
2349    if (hostname == NULL)
2350    {
2351        return NULL;
2352    }
2353
2354    // ホスト名をトークンに分割
2355    token = ParseToken(hostname, ".");
2356    if (token == NULL)
2357    {
2358        return NULL;
2359    }
2360
2361    b = NewBuf();
2362
2363    // ホスト文字列を追加
2364    for (i = 0;i < token->NumTokens;i++)
2365    {
2366        size = (UCHAR)StrLen(token->Token[i]);
2367        WriteBuf(b, &size, 1);
2368        WriteBuf(b, token->Token[i], size);
2369    }
2370
2371    // NULL 文字
2372    size = 0;
2373    WriteBuf(b, &size, 1);
2374
2375    SeekBuf(b, 0, 0);
2376
2377    FreeToken(token);
2378
2379    return b;
2380}
2381
2382// NAT DNS エントリの処理
2383void PollingNatDns(VH *v, NAT_ENTRY *n)
2384{
2385    // 引数チェック
2386    if (v == NULL || n == NULL)
2387    {
2388        return;
2389    }
2390
2391    if (n->DnsFinished)
2392    {
2393        if (n->DnsPollingFlag == false)
2394        {
2395            n->DnsPollingFlag = true;
2396            // 処理が完了した
2397            SendNatDnsResponse(v, n);
2398
2399            // 終了処理
2400            n->DisconnectNow = true;
2401        }
2402    }
2403}
2404
2405// NAT DNS エントリの作成
2406NAT_ENTRY *CreateNatDns(VH *v, UINT src_ip, UINT src_port, UINT dest_ip, UINT dest_port,
2407                  UINT transaction_id, bool dns_get_ip_from_host, char *dns_target_host_name)
2408{
2409    NAT_ENTRY *n;
2410    // 引数チェック
2411    if (v == NULL || dns_target_host_name == NULL)
2412    {
2413        return NULL;
2414    }
2415
2416    if (CanCreateNewNatEntry(v) == false)
2417    {
2418        return NULL;
2419    }
2420
2421    n = ZeroMalloc(sizeof(NAT_ENTRY));
2422    n->Id = Inc(v->Counter);
2423    n->v = v;
2424    n->lock = NewLock();
2425    n->Protocol = NAT_DNS;
2426    n->SrcIp = src_ip;
2427    n->SrcPort = src_port;
2428    n->DestIp = dest_ip;
2429    n->DestPort = dest_port;
2430    n->DnsTransactionId = transaction_id;
2431    n->CreatedTime = n->LastCommTime = v->Now;
2432    n->DisconnectNow = false;
2433
2434    n->DnsGetIpFromHost = false;
2435    n->DnsTargetHostName = CopyStr(dns_target_host_name);
2436
2437    Add(v->NatTable, n);
2438
2439#if 1
2440    {
2441        IP ip1, ip2;
2442        char s1[MAX_SIZE], s2[MAX_SIZE];
2443        UINTToIP(&ip1, src_ip);
2444        UINTToIP(&ip2, dest_ip);
2445        IPToStr(s1, 0, &ip1);
2446        IPToStr(s2, 0, &ip2);
2447        Debug("NAT_ENTRY: CreateNatDns %s %u -> %s %u\n", s1, src_port, s2, dest_port);
2448    }
2449#endif
2450
2451
2452    return n;
2453}
2454
2455// 次のバイトを取得
2456UCHAR GetNextByte(BUF *b)
2457{
2458    UCHAR c = 0;
2459    // 引数チェック
2460    if (b == NULL)
2461    {
2462        return 0;
2463    }
2464
2465    if (ReadBuf(b, &c, 1) != 1)
2466    {
2467        return 0;
2468    }
2469
2470    return c;
2471}
2472
2473// DNS クエリの解釈
2474bool ParseDnsQuery(char *name, UINT name_size, void *data, UINT data_size)
2475{
2476    BUF *b;
2477    char tmp[257];
2478    bool ok = true;
2479    USHORT val;
2480    // 引数チェック
2481    if (name == NULL || data == NULL || data_size == 0)
2482    {
2483        return false;
2484    }
2485    StrCpy(name, name_size, "");
2486
2487    b = NewBuf();
2488    WriteBuf(b, data, data_size);
2489    SeekBuf(b, 0, 0);
2490
2491    while (true)
2492    {
2493        UINT next_len = (UINT)GetNextByte(b);
2494        if (next_len > 0)
2495        {
2496            // 指定した文字だけ読む
2497            Zero(tmp, sizeof(tmp));
2498            if (ReadBuf(b, tmp, next_len) != next_len)
2499            {
2500                ok = false;
2501                break;
2502            }
2503            // 追記
2504            if (StrLen(name) != 0)
2505            {
2506                StrCat(name, name_size, ".");
2507            }
2508            StrCat(name, name_size, tmp);
2509        }
2510        else
2511        {
2512            // すべて読み終えた
2513            break;
2514        }
2515    }
2516
2517    if (ReadBuf(b, &val, sizeof(val)) != sizeof(val))
2518    {
2519        ok = false;
2520    }
2521    else
2522    {
2523        if (Endian16(val) != 0x01 && Endian16(val) != 0x0c)
2524        {
2525            ok = false;
2526        }
2527    }
2528
2529    if (ReadBuf(b, &val, sizeof(val)) != sizeof(val))
2530    {
2531        ok = false;
2532    }
2533    else
2534    {
2535        if (Endian16(val) != 0x01)
2536        {
2537            ok = false;
2538        }
2539    }
2540
2541    FreeBuf(b);
2542
2543    if (ok == false || StrLen(name) == 0)
2544    {
2545        return false;
2546    }
2547    else
2548    {
2549        return true;
2550    }
2551}
2552
2553// DNS プロキシとして動作する
2554void DnsProxy(VH *v, UINT src_ip, UINT src_port, UINT dest_ip, UINT dest_port, void *data, UINT size)
2555{
2556    // 引数チェック
2557    if (v == NULL || data == NULL || size == 0)
2558    {
2559        return;
2560    }
2561
2562    // まず DNS クエリを解釈することができるかどうか試してみる
2563    //if (ParseDnsPacket(v, src_ip, src_port, dest_ip, dest_port, data, size) == false)
2564    {
2565        // うまくいかない場合は要求をそのまま投げる
2566        UdpRecvForInternet(v, src_ip, src_port, dest_ip, dest_port, data, size, true);
2567    }
2568}
2569
2570// 仮想ホストへの UDP パケットの処理
2571void UdpRecvForMe(VH *v, UINT src_ip, UINT src_port, UINT dest_ip, UINT dest_port, void *data, UINT size)
2572{
2573    // 引数チェック
2574    if (data == NULL || v == NULL)
2575    {
2576        return;
2577    }
2578
2579    if (dest_port == NAT_DNS_PROXY_PORT)
2580    {
2581        // DNS プロキシ起動
2582        DnsProxy(v, src_ip, src_port, dest_ip, dest_port, data, size);
2583    }
2584}
2585
2586// ブロードキャスト UDP パケットの処理
2587void UdpRecvForBroadcast(VH *v, UINT src_ip, UINT src_port, UINT dest_ip, UINT dest_port, void *data, UINT size)
2588{
2589    // 引数チェック
2590    if (data == NULL || v == NULL)
2591    {
2592        return;
2593    }
2594}
2595
2596// UDP パケットを受信した
2597void VirtualUdpReceived(VH *v, UINT src_ip, UINT dest_ip, void *data, UINT size, bool mac_broadcast)
2598{
2599    UDP_HEADER *udp;
2600    UINT packet_length;
2601    void *buf;
2602    UINT buf_size;
2603    UINT src_port, dest_port;
2604    // 引数チェック
2605    if (v == NULL || data == NULL)
2606    {
2607        return;
2608    }
2609
2610    // ヘッダのチェック
2611    udp = (UDP_HEADER *)data;
2612    if (size < UDP_HEADER_SIZE)
2613    {
2614        return;
2615    }
2616    packet_length = Endian16(udp->PacketLength);
2617    if (packet_length != size)
2618    {
2619        return;
2620    }
2621    buf = ((UCHAR *)data) + UDP_HEADER_SIZE;
2622    buf_size = size - UDP_HEADER_SIZE;
2623    src_port = Endian16(udp->SrcPort);
2624    dest_port = Endian16(udp->DstPort);
2625    // ポート番号をチェック
2626    if (dest_port == 0)
2627    {
2628        // ポート番号が不正
2629        return;
2630    }
2631
2632    // 自分宛のパケットまたはブロードキャストパケットかどうか判別する
2633    if (dest_ip == v->HostIP)
2634    {
2635        // 自分宛のパケットが届いた
2636        UdpRecvForMe(v, src_ip, src_port, dest_ip, dest_port, buf, buf_size);
2637    }
2638    else if (mac_broadcast || dest_ip == 0xffffffff || dest_ip == GetBroadcastAddress(v->HostIP, v->HostMask))
2639    {
2640        // ブロードキャストパケットが届いた
2641        UdpRecvForBroadcast(v, src_ip, src_port, dest_ip, dest_port, buf, buf_size);
2642    }
2643    else if (IsInNetwork(dest_ip, v->HostIP, v->HostMask) == false)
2644    {
2645        // ローカルアドレス以外 (つまりインターネット上) へのパケットが届いた
2646        UdpRecvForInternet(v, src_ip, src_port, dest_ip, dest_port, buf, buf_size, false);
2647    }
2648    else
2649    {
2650        // ローカルアドレスが届いた。無視
2651    }
2652}
2653
2654// 指定した IP アドレスの属するサブネットのネットワークアドレスを求める
2655UINT GetNetworkAddress(UINT addr, UINT mask)
2656{
2657    return (addr & mask);
2658}
2659
2660// 指定した IP アドレスの属するサブネットのブロードキャストアドレスを求める
2661UINT GetBroadcastAddress(UINT addr, UINT mask)
2662{
2663    return ((addr & mask) | (~mask));
2664}
2665
2666// 指定した IP アドレスが別の指定したアドレスとサブネットマスクによって表現される
2667// サブネットワークに所属しているかどうか判別する
2668bool IsInNetwork(UINT uni_addr, UINT network_addr, UINT mask)
2669{
2670    if (GetNetworkAddress(uni_addr, mask) == GetNetworkAddress(network_addr, mask))
2671    {
2672        return true;
2673    }
2674    return false;
2675}
2676
2677// UDP パケットの送信
2678void SendUdp(VH *v, UINT dest_ip, UINT dest_port, UINT src_ip, UINT src_port, void *data, UINT size)
2679{
2680    UDPV4_PSEUDO_HEADER *vh;
2681    UDP_HEADER *udp;
2682    UINT udp_packet_length = UDP_HEADER_SIZE + size;
2683    USHORT checksum;
2684    // 引数チェック
2685    if (v == NULL || data == NULL)
2686    {
2687        return;
2688    }
2689    if (udp_packet_length > 65536)
2690    {
2691        return;
2692    }
2693
2694    // 仮想ヘッダを生成
2695    vh = Malloc(sizeof(UDPV4_PSEUDO_HEADER) + size);
2696    udp = (UDP_HEADER *)(((UCHAR *)vh) + 12);
2697
2698    vh->SrcIP = src_ip;
2699    vh->DstIP = dest_ip;
2700    vh->Reserved = 0;
2701    vh->Protocol = IP_PROTO_UDP;
2702    vh->PacketLength1 = Endian16((USHORT)udp_packet_length);
2703    udp->SrcPort = Endian16((USHORT)src_port);
2704    udp->DstPort = Endian16((USHORT)dest_port);
2705    udp->PacketLength = Endian16((USHORT)udp_packet_length);
2706    udp->Checksum = 0;
2707
2708    // データをコピー
2709    Copy(((UCHAR *)udp) + UDP_HEADER_SIZE, data, size);
2710
2711    // チェックサムを計算
2712    checksum = IpChecksum(vh, udp_packet_length + 12);
2713    if (checksum == 0x0000)
2714    {
2715        checksum = 0xffff;
2716    }
2717    udp->Checksum = checksum;
2718
2719    // パケットを送信
2720    SendIp(v, dest_ip, src_ip, IP_PROTO_UDP, udp, udp_packet_length);
2721
2722    // メモリ解放
2723    Free(vh);
2724}
2725
2726// IP 結合オブジェクトのポーリング
2727void PollingIpCombine(VH *v)
2728{
2729    LIST *o;
2730    UINT i;
2731    // 引数チェック
2732    if (v == NULL)
2733    {
2734        return;
2735    }
2736
2737    // 古い結合オブジェクトを破棄する
2738    o = NULL;
2739    for (i = 0;i < LIST_NUM(v->IpCombine);i++)
2740    {
2741        IP_COMBINE *c = LIST_DATA(v->IpCombine, i);
2742
2743        if (c->Expire < v->Now)
2744        {
2745            if (o == NULL)
2746            {
2747                o = NewListFast(NULL);
2748            }
2749            Add(o, c);
2750        }
2751    }
2752
2753    if (o != NULL)
2754    {
2755        for (i = 0;i < LIST_NUM(o);i++)
2756        {
2757            IP_COMBINE *c = LIST_DATA(o, i);
2758
2759            // リストから削除
2760            Delete(v->IpCombine, c);
2761
2762            // メモリ解放
2763            FreeIpCombine(v, c);
2764        }
2765        ReleaseList(o);
2766    }
2767}
2768
2769// ICMP パケットを送信する
2770void VirtualIcmpSend(VH *v, UINT src_ip, UINT dst_ip, void *data, UINT size)
2771{
2772    ICMP_HEADER *icmp;
2773    void *data_buf;
2774    // 引数チェック
2775    if (v == NULL || data == NULL)
2776    {
2777        return;
2778    }
2779
2780    // ヘッダ組み立て
2781    icmp = ZeroMalloc(sizeof(ICMP_HEADER) + size);
2782    // データコピー
2783    data_buf = ((UCHAR *)icmp) + sizeof(ICMP_HEADER);
2784    Copy(data_buf, data, size);
2785    // その他
2786    icmp->Checksum = 0;
2787    icmp->Code = 0;
2788    icmp->Type = ICMP_TYPE_ECHO_RESPONSE;
2789    // チェックサム
2790    icmp->Checksum = IpChecksum(icmp, sizeof(ICMP_HEADER) + size);
2791
2792    // IP パケット送信
2793    SendIp(v, dst_ip, src_ip, IP_PROTO_ICMPV4, icmp, sizeof(ICMP_HEADER) + size);
2794
2795    // メモリ解放
2796    Free(icmp);
2797}
2798
2799// ICMP Echo Response パケットを送信する
2800void VirtualIcmpEchoSendResponse(VH *v, UINT src_ip, UINT dst_ip, USHORT id, USHORT seq_no, void *data, UINT size)
2801{
2802    ICMP_ECHO *e;
2803    // 引数チェック
2804    if (v == NULL || data == NULL)
2805    {
2806        return;
2807    }
2808
2809    // ヘッダ組み立て
2810    e = ZeroMalloc(sizeof(ICMP_ECHO) + size);
2811    e->Identifier = Endian16(id);
2812    e->SeqNo = Endian16(seq_no);
2813
2814    // データコピー
2815    Copy(((UCHAR *)e) + sizeof(ICMP_ECHO), data, size);
2816
2817    // ICMP 送信
2818    VirtualIcmpSend(v, src_ip, dst_ip, e, sizeof(ICMP_ECHO) + size);
2819
2820    // メモリ解放
2821    Free(e);
2822}
2823
2824// ICMP Echo Request パケットを受信した
2825void VirtualIcmpEchoRequestReceived(VH *v, UINT src_ip, UINT dst_ip, void *data, UINT size)
2826{
2827    ICMP_ECHO *echo;
2828    UINT data_size;
2829    void *data_buf;
2830    USHORT id, seq_no;
2831    // 引数チェック
2832    if (v == NULL || data == NULL)
2833    {
2834        return;
2835    }
2836
2837    echo = (ICMP_ECHO *)data;
2838
2839    // エコーサイズチェック
2840    if (size < sizeof(ICMP_ECHO))
2841    {
2842        // データが足らない
2843        return;
2844    }
2845
2846    id = Endian16(echo->Identifier);
2847    seq_no = Endian16(echo->SeqNo);
2848
2849    // データサイズ
2850    data_size = size - sizeof(ICMP_ECHO);
2851
2852    // データ本体
2853    data_buf = ((UCHAR *)data) + sizeof(ICMP_ECHO);
2854
2855    // ICMP Echo Response を返す
2856    VirtualIcmpEchoSendResponse(v, dst_ip, src_ip, id, seq_no, data_buf, data_size);
2857}
2858
2859// ICMP パケットを受信した
2860void VirtualIcmpReceived(VH *v, UINT src_ip, UINT dst_ip, void *data, UINT size)
2861{
2862    ICMP_HEADER *icmp;
2863    UINT msg_size;
2864    USHORT checksum_calc, checksum_original;
2865    // 引数チェック
2866    if (v == NULL || data == NULL)
2867    {
2868        return;
2869    }
2870
2871    // サイズチェック
2872    if (size < sizeof(ICMP_HEADER))
2873    {
2874        return;
2875    }
2876
2877    // ICMP ヘッダ
2878    icmp = (ICMP_HEADER *)data;
2879
2880    // ICMP メッセージサイズの取得
2881    msg_size = size - sizeof(ICMP_HEADER);
2882
2883    // ICMP ヘッダのチェックサムをチェックする
2884    checksum_original = icmp->Checksum;
2885    icmp->Checksum = 0;
2886    checksum_calc = IpChecksum(data, size);
2887    icmp->Checksum = checksum_original;
2888
2889    if (checksum_calc != checksum_original)
2890    {
2891        // チェックサムが不正
2892        Debug("ICMP CheckSum Failed.\n");
2893        return;
2894    }
2895
2896    // オペコードによって識別
2897    switch (icmp->Type)
2898    {
2899    case ICMP_TYPE_ECHO_REQUEST:    // ICMP Echo 要求
2900        VirtualIcmpEchoRequestReceived(v, src_ip, dst_ip, ((UCHAR *)data) + sizeof(ICMP_HEADER), msg_size);
2901        break;
2902
2903    case ICMP_TYPE_ECHO_RESPONSE:   // ICMP Echo 応答
2904        // 何もしない
2905        break;
2906    }
2907}
2908
2909// IP パケットを受信した
2910void IpReceived(VH *v, UINT src_ip, UINT dest_ip, UINT protocol, void *data, UINT size, bool mac_broadcast)
2911{
2912    // 引数チェック
2913    if (v == NULL || data == NULL)
2914    {
2915        return;
2916    }
2917
2918    // サポートされている上位プロトコルにデータを渡す
2919    switch (protocol)
2920    {
2921    case IP_PROTO_ICMPV4:   // ICMPv4
2922        VirtualIcmpReceived(v, src_ip, dest_ip, data, size);
2923        break;
2924
2925    case IP_PROTO_TCP:      // TCP
2926        if (mac_broadcast == false)
2927        {
2928            VirtualTcpReceived(v, src_ip, dest_ip, data, size);
2929        }
2930        break;
2931
2932    case IP_PROTO_UDP:      // UDP
2933        VirtualUdpReceived(v, src_ip, dest_ip, data, size, mac_broadcast);
2934        break;
2935    }
2936}
2937
2938// IP ヘッダのチェックサムを確認する
2939bool IpCheckChecksum(IPV4_HEADER *ip)
2940{
2941    UINT header_size;
2942    USHORT checksum_original, checksum_calc;
2943    // 引数チェック
2944    if (ip == NULL)
2945    {
2946        return false;
2947    }
2948
2949    header_size = IPV4_GET_HEADER_LEN(ip) * 4;
2950    checksum_original = ip->Checksum;
2951    ip->Checksum = 0;
2952    checksum_calc = IpChecksum(ip, header_size);
2953    ip->Checksum = checksum_original;
2954
2955    if (checksum_original == checksum_calc)
2956    {
2957        return true;
2958    }
2959    else
2960    {
2961        return false;
2962    }
2963}
2964
2965// チェックサムを計算する
2966USHORT IpChecksum(void *buf, UINT size)
2967{
2968    int sum = 0;
2969    USHORT *addr = (USHORT *)buf;
2970    int len = (int)size;
2971    USHORT *w = addr;
2972    int nleft = len;
2973    USHORT answer = 0;
2974
2975    while (nleft > 1)
2976    {
2977        sum += *w++;
2978        nleft -= 2;
2979    }
2980
2981    if (nleft == 1)
2982    {
2983        *(UCHAR *)(&answer) = *(UCHAR *)w;
2984        sum += answer;
2985    }
2986
2987    sum = (sum >> 16) + (sum & 0xffff);
2988    sum += (sum >> 16);
2989
2990    answer = ~sum;
2991   
2992    return answer;
2993}
2994
2995// IP 結合オブジェクトに新しく受信した IP パケットを結合する
2996void CombineIp(VH *v, IP_COMBINE *c, UINT offset, void *data, UINT size, bool last_packet)
2997{
2998    UINT i;
2999    IP_PART *p;
3000    UINT need_size;
3001    UINT data_size_delta;
3002    // 引数チェック
3003    if (c == NULL || data == NULL)
3004    {
3005        return;
3006    }
3007
3008    // オフセットとサイズをチェック
3009    if ((offset + size) > 65535)
3010    {
3011        // 64Kbytes を超えるパケットは処理しない
3012        return;
3013    }
3014
3015    if (last_packet == false && c->Size != 0)
3016    {
3017        if ((offset + size) > c->Size)
3018        {
3019            // パケットサイズより大きいパケットは処理しない
3020            return;
3021        }
3022    }
3023
3024    need_size = offset + size;
3025    data_size_delta = c->DataReserved;
3026    // バッファが不足している場合は十分確保する
3027    while (c->DataReserved < need_size)
3028    {
3029        c->DataReserved = c->DataReserved * 4;
3030        c->Data = ReAlloc(c->Data, c->DataReserved);
3031    }
3032    data_size_delta = c->DataReserved - data_size_delta;
3033    v->CurrentIpQuota += data_size_delta;
3034
3035    // データをバッファに上書きする
3036    Copy(((UCHAR *)c->Data) + offset, data, size);
3037
3038    if (last_packet)
3039    {
3040        // No More Flagment パケットが届いた場合、このデータグラムのサイズが確定する
3041        c->Size = offset + size;
3042    }
3043
3044    // オフセットとサイズによって表現されている領域と既存の受信済みリストの
3045    // オフセットとサイズによって表現されている領域との間の重複をチェックする
3046    for (i = 0;i < LIST_NUM(c->IpParts);i++)
3047    {
3048        UINT moving_size;
3049        IP_PART *p = LIST_DATA(c->IpParts, i);
3050
3051        // 先頭領域と既存領域との重複をチェック
3052        if ((p->Offset <= offset) && ((p->Offset + p->Size) > offset))
3053        {
3054            // このパケットと既存パケットとの間で先頭部分に重複が見つかったので
3055            // このパケットのオフセットを後方に圧縮する
3056
3057            if ((offset + size) <= (p->Offset + p->Size))
3058            {
3059                // このパケットは既存のパケットの中に埋もれている
3060                size = 0;
3061            }
3062            else
3063            {
3064                // 後方領域は重なっていない
3065                moving_size = p->Offset + p->Size - offset;
3066                offset += moving_size;
3067                size -= moving_size;
3068            }
3069        }
3070        if ((p->Offset < (offset + size)) && ((p->Offset + p->Size) >= (offset + size)))
3071        {
3072            // このパケットと既存パケットとの間で後方部分に重複が見つかったので
3073            // このパケットのサイズを前方に圧縮する
3074
3075            moving_size = p->Offset + p->Size - offset - size;
3076            size -= moving_size;
3077        }
3078
3079        if ((p->Offset >= offset) && ((p->Offset + p->Size) <= (offset + size)))
3080        {
3081            // このパケットが既存のパケットを完全に覆いかぶさるように上書きされた
3082            p->Size = 0;
3083        }
3084    }
3085
3086    if (size != 0)
3087    {
3088        // このパケットを登録する
3089        p = ZeroMalloc(sizeof(IP_PART));
3090
3091        p->Offset = offset;
3092        p->Size = size;
3093
3094        Add(c->IpParts, p);
3095    }
3096
3097    if (c->Size != 0)
3098    {
3099        // すでに受信したデータ部分リストの合計サイズを取得する
3100        UINT total_size = 0;
3101        UINT i;
3102
3103        for (i = 0;i < LIST_NUM(c->IpParts);i++)
3104        {
3105            IP_PART *p = LIST_DATA(c->IpParts, i);
3106
3107            total_size += p->Size;
3108        }
3109
3110        if (total_size == c->Size)
3111        {
3112            // IP パケットをすべて受信した
3113            IpReceived(v, c->SrcIP, c->DestIP, c->Protocol, c->Data, c->Size, c->MacBroadcast);
3114
3115            // 結合オブジェクトの解放
3116            FreeIpCombine(v, c);
3117
3118            // 結合オブジェクトをリストから削除
3119            Delete(v->IpCombine, c);
3120        }
3121    }
3122}
3123
3124// IP 結合オブジェクトの解放
3125void FreeIpCombine(VH *v, IP_COMBINE *c)
3126{
3127    UINT i;
3128    // 引数チェック
3129    if (c == NULL)
3130    {
3131        return;
3132    }
3133
3134    // データ解放
3135    v->CurrentIpQuota -= c->DataReserved;
3136    Free(c->Data);
3137
3138    // 部分リスト解放
3139    for (i = 0;i < LIST_NUM(c->IpParts);i++)
3140    {
3141        IP_PART *p = LIST_DATA(c->IpParts, i);
3142
3143        Free(p);
3144    }
3145
3146    ReleaseList(c->IpParts);
3147    Free(c);
3148}
3149
3150// IP 結合リストを検索
3151IP_COMBINE *SearchIpCombine(VH *v, UINT src_ip, UINT dest_ip, USHORT id, UCHAR protocol)
3152{
3153    IP_COMBINE *c, t;
3154    // 引数チェック
3155    if (v == NULL)
3156    {
3157        return NULL;
3158    }
3159
3160    t.DestIP = dest_ip;
3161    t.SrcIP = src_ip;
3162    t.Id = id;
3163    t.Protocol = protocol;
3164
3165    c = Search(v->IpCombine, &t);
3166
3167    return c;
3168}
3169
3170// IP 結合リストに新しいオブジェクトを作成して挿入
3171IP_COMBINE *InsertIpCombine(VH *v, UINT src_ip, UINT dest_ip, USHORT id, UCHAR protocol, bool mac_broadcast)
3172{
3173    IP_COMBINE *c;
3174    // 引数チェック
3175    if (v == NULL)
3176    {
3177        return NULL;
3178    }
3179
3180    // クォータを調べる
3181    if ((v->CurrentIpQuota + IP_COMBINE_INITIAL_BUF_SIZE) > IP_COMBINE_WAIT_QUEUE_SIZE_QUOTA)
3182    {
3183        // これ以上 IP パケットを格納できない
3184        return NULL;
3185    }
3186
3187    c = ZeroMalloc(sizeof(IP_COMBINE));
3188    c->DestIP = dest_ip;
3189    c->SrcIP = src_ip;
3190    c->Id = id;
3191    c->Expire = v->Now + (UINT64)IP_COMBINE_TIMEOUT;
3192    c->Size = 0;
3193    c->IpParts = NewList(NULL);
3194    c->Protocol = protocol;
3195    c->MacBroadcast = mac_broadcast;
3196
3197    // メモリを確保
3198    c->DataReserved = IP_COMBINE_INITIAL_BUF_SIZE;
3199    c->Data = Malloc(c->DataReserved);
3200    v->CurrentIpQuota += c->DataReserved;
3201
3202    Insert(v->IpCombine, c);
3203
3204    return c;
3205}
3206
3207// IP 結合リストの初期化
3208void InitIpCombineList(VH *v)
3209{
3210    // 引数チェック
3211    if (v == NULL)
3212    {
3213        return;
3214    }
3215
3216    v->IpCombine = NewList(CompareIpCombine);
3217}
3218
3219// IP 結合リストの解放
3220void FreeIpCombineList(VH *v)
3221{
3222    UINT i;
3223    // 引数チェック
3224    if (v == NULL)
3225    {
3226        return;
3227    }
3228
3229    for (i = 0;i < LIST_NUM(v->IpCombine);i++)
3230    {
3231        IP_COMBINE *c = LIST_DATA(v->IpCombine, i);
3232
3233        FreeIpCombine(v, c);
3234    }
3235
3236    ReleaseList(v->IpCombine);
3237}
3238
3239// IP 結合リストの比較
3240int CompareIpCombine(void *p1, void *p2)
3241{
3242    IP_COMBINE *c1, *c2;
3243    if (p1 == NULL || p2 == NULL)
3244    {
3245        return 0;
3246    }
3247    c1 = *(IP_COMBINE **)p1;
3248    c2 = *(IP_COMBINE **)p2;
3249    if (c1 == NULL || c2 == NULL)
3250    {
3251        return 0;
3252    }
3253    if (c1->Id > c2->Id)
3254    {
3255        return 1;
3256    }
3257    else if (c1->Id < c2->Id)
3258    {
3259        return -1;
3260    }
3261    else if (c1->DestIP > c2->DestIP)
3262    {
3263        return 1;
3264    }
3265    else if (c1->DestIP < c2->DestIP)
3266    {
3267        return -1;
3268    }
3269    else if (c1->SrcIP > c2->SrcIP)
3270    {
3271        return 1;
3272    }
3273    else if (c1->SrcIP < c2->SrcIP)
3274    {
3275        return -1;
3276    }
3277    else if (c1->Protocol > c2->Protocol)
3278    {
3279        return 1;
3280    }
3281    else if (c1->Protocol < c2->Protocol)
3282    {
3283        return -1;
3284    }
3285    return 0;
3286}
3287
3288// IP パケットを受信した
3289void VirtualIpReceived(VH *v, PKT *packet)
3290{
3291    IPV4_HEADER *ip;
3292    void *data;
3293    UINT data_size_recved;
3294    UINT size;
3295    UINT ipv4_header_size;
3296    bool last_packet;
3297    // 引数チェック
3298    if (v == NULL || packet == NULL)
3299    {
3300        return;
3301    }
3302
3303    ip = packet->L3.IPv4Header;
3304
3305    // IPv4 ヘッダのサイズを取得する
3306    ipv4_header_size = IPV4_GET_HEADER_LEN(packet->L3.IPv4Header) * 4;
3307
3308    // IPv4 ヘッダのチェックサムを計算する
3309    if (IpCheckChecksum(ip) == false)
3310    {
3311        return;
3312    }
3313
3314    // データへのポインタを取得する
3315    data = ((UCHAR *)packet->L3.PointerL3) + ipv4_header_size;
3316
3317    // ARP テーブルに登録しておく
3318    ArpIpWasKnown(v, packet->L3.IPv4Header->SrcIP, packet->MacAddressSrc);
3319
3320    // データサイズを取得する
3321    size = Endian16(ip->TotalLength);
3322    if (size <= ipv4_header_size)
3323    {
3324        // データが無い
3325        return;
3326    }
3327    size -= ipv4_header_size;
3328
3329    // 実際に受信したデータサイズを取得する
3330    data_size_recved = packet->PacketSize - (ipv4_header_size + MAC_HEADER_SIZE);
3331    if (data_size_recved < size)
3332    {
3333        // データが足りない (途中で欠落しているかも知れない)
3334        return;
3335    }
3336
3337    if (IPV4_GET_OFFSET(ip) == 0 && (IPV4_GET_FLAGS(ip) & 0x01) == 0)
3338    {
3339        // このパケットは分割されていないので直ちに上位層に渡すことができる
3340        IpReceived(v, ip->SrcIP, ip->DstIP, ip->Protocol, data, size, packet->BroadcastPacket);
3341    }
3342    else
3343    {
3344        // このパケットは分割されているので結合する必要がある
3345
3346        UINT offset = IPV4_GET_OFFSET(ip) * 8;
3347        IP_COMBINE *c = SearchIpCombine(v, ip->SrcIP, ip->DstIP, Endian16(ip->Identification), ip->Protocol);
3348
3349        last_packet = ((IPV4_GET_FLAGS(ip) & 0x01) == 0 ? true : false);
3350
3351        if (c != NULL)
3352        {
3353            // 2 個目移行のパケットである
3354            CombineIp(v, c, offset, data, size, last_packet);
3355        }
3356        else
3357        {
3358            // 最初のパケットなので結合オブジェクトを作成する
3359            c = InsertIpCombine(
3360                v, ip->SrcIP, ip->DstIP, Endian16(ip->Identification), ip->Protocol, packet->BroadcastPacket);
3361            if (c != NULL)
3362            {
3363                CombineIp(v, c, offset, data, size, last_packet);
3364            }
3365        }
3366    }
3367}
3368
3369// 待機している IP パケットのうち指定した IP アドレスからのものを送信する
3370void SendWaitingIp(VH *v, UCHAR *mac, UINT dest_ip)
3371{
3372    UINT i;
3373    LIST *o = NULL;
3374    // 引数チェック
3375    if (v == NULL || mac == NULL)
3376    {
3377        return;
3378    }
3379
3380    // 対象リストを取得する
3381    for (i = 0;i < LIST_NUM(v->IpWaitTable);i++)
3382    {
3383        IP_WAIT *w = LIST_DATA(v->IpWaitTable, i);
3384
3385        if (w->DestIP == dest_ip)
3386        {
3387            if (o == NULL)
3388            {
3389                o = NewListFast(NULL);
3390            }
3391            Add(o, w);
3392        }
3393    }
3394
3395    // 対象となったパケットを一気に送信する
3396    if (o != NULL)
3397    {
3398        for (i = 0;i < LIST_NUM(o);i++)
3399        {
3400            IP_WAIT *w = LIST_DATA(o, i);
3401
3402            // 送信処理
3403            VirtualIpSend(v, mac, w->Data, w->Size);
3404
3405            // リストから削除
3406            Delete(v->IpWaitTable, w);
3407
3408            // メモリ解放
3409            Free(w->Data);
3410            Free(w);
3411        }
3412
3413        ReleaseList(o);
3414    }
3415}
3416
3417// 古い IP 待ちテーブルを削除する
3418void DeleteOldIpWaitTable(VH *v)
3419{
3420    UINT i;
3421    LIST *o = NULL;
3422    // 引数チェック
3423    if (v == NULL)
3424    {
3425        return;
3426    }
3427
3428    // 削除対象リストを取得する
3429    for (i = 0;i < LIST_NUM(v->IpWaitTable);i++)
3430    {
3431        IP_WAIT *w = LIST_DATA(v->IpWaitTable, i);
3432
3433        if (w->Expire < v->Now)
3434        {
3435            if (o == NULL)
3436            {
3437                o = NewListFast(NULL);
3438            }
3439            Add(o, w);
3440        }
3441    }
3442
3443    // 一気に削除する
3444    if (o != NULL)
3445    {
3446        for (i = 0;i < LIST_NUM(o);i++)
3447        {
3448            IP_WAIT *w = LIST_DATA(o, i);
3449
3450            // リストから削除
3451            Delete(v->IpWaitTable, w);
3452
3453            // メモリ解放
3454            Free(w->Data);
3455            Free(w);
3456        }
3457        ReleaseList(o);
3458    }
3459}
3460
3461// IP 待ちテーブルのポーリング
3462void PollingIpWaitTable(VH *v)
3463{
3464    // 古いテーブルの削除
3465    DeleteOldIpWaitTable(v);
3466}
3467
3468// IP 待ちテーブルに IP パケットを挿入する
3469void InsertIpWaitTable(VH *v, UINT dest_ip, UINT src_ip, void *data, UINT size)
3470{
3471    IP_WAIT *w;
3472    // 引数チェック
3473    if (v == NULL || data == NULL || size == 0)
3474    {
3475        return;
3476    }
3477
3478    w = ZeroMalloc(sizeof(IP_WAIT));
3479    w->Data = data;
3480    w->Size = size;
3481    w->SrcIP = src_ip;
3482    w->DestIP = dest_ip;
3483    w->Expire = v->Now + (UINT64)IP_WAIT_FOR_ARP_TIMEOUT;
3484
3485    Add(v->IpWaitTable, w);
3486}
3487
3488// IP 待ちテーブルを初期化する
3489void InitIpWaitTable(VH *v)
3490{
3491    // 引数チェック
3492    if (v == NULL)
3493    {
3494        return;
3495    }
3496
3497    v->IpWaitTable = NewList(NULL);
3498}
3499
3500// IP 待ちテーブルを解放する
3501void FreeIpWaitTable(VH *v)
3502{
3503    UINT i;
3504    // 引数チェック
3505    if (v == NULL)
3506    {
3507        return;
3508    }
3509
3510    for (i = 0;i < LIST_NUM(v->IpWaitTable);i++)
3511    {
3512        IP_WAIT *w = LIST_DATA(v->IpWaitTable, i);
3513
3514        Free(w->Data);
3515        Free(w);
3516    }
3517
3518    ReleaseList(v->IpWaitTable);
3519}
3520
3521// ARP Response が到着するなどして IP アドレスに対する MAC アドレスが判明した
3522void ArpIpWasKnown(VH *v, UINT ip, UCHAR *mac)
3523{
3524    // 引数チェック
3525    if (v == NULL || mac == NULL)
3526    {
3527        return;
3528    }
3529
3530    // ARP 待ち行列にこの IP アドレスに対する問い合わせがあった場合は削除する
3531    DeleteArpWaitTable(v, ip);
3532
3533    // ARP テーブルに登録または更新する
3534    InsertArpTable(v, mac, ip);
3535
3536    // IP 待機リストで待機している IP パケットを送信する
3537    SendWaitingIp(v, mac, ip);
3538}
3539
3540// ARP 待ちリストをチェックし適時 ARP を再発行する
3541void PollingArpWaitTable(VH *v)
3542{
3543    UINT i;
3544    LIST *o;
3545    // 引数チェック
3546    if (v == NULL)
3547    {
3548        return;
3549    }
3550
3551    // 削除リストの初期化
3552    o = NULL;
3553
3554    // すべての ARP 待ちリストを走査
3555    for (i = 0;i < LIST_NUM(v->ArpWaitTable);i++)
3556    {
3557        ARP_WAIT *w = LIST_DATA(v->ArpWaitTable, i);
3558
3559        if (w->GiveupTime < v->Now || (w->GiveupTime - 100 * 1000) > v->Now)
3560        {
3561            // ARP の送信を諦める
3562            if (o == NULL)
3563            {
3564                o = NewListFast(NULL);
3565            }
3566            Add(o, w);
3567        }
3568        else
3569        {
3570            if (w->TimeoutTime < v->Now)
3571            {
3572                // ARP を再度送信する
3573                VirtualArpSendRequest(v, w->IpAddress);
3574
3575                // 次のタイムアウト時刻をセット
3576                w->TimeoutTime = v->Now + (UINT64)w->NextTimeoutTimeValue;
3577                // 2 回目以降の ARP 送信間隔は増やしていく
3578                w->NextTimeoutTimeValue = w->NextTimeoutTimeValue + ARP_REQUEST_TIMEOUT;
3579            }
3580        }
3581    }
3582
3583    // 削除対象の ARP 待ちレコードがある場合は削除する
3584    if (o != NULL)
3585    {
3586        for (i = 0;i < LIST_NUM(o);i++)
3587        {
3588            ARP_WAIT *w = LIST_DATA(o, i);
3589
3590            DeleteArpWaitTable(v, w->IpAddress);
3591        }
3592        ReleaseList(o);
3593    }
3594}
3595
3596// ARP を発行する
3597void SendArp(VH *v, UINT ip)
3598{
3599    ARP_WAIT *w;
3600    // 引数チェック
3601    if (v == NULL)
3602    {
3603        return;
3604    }
3605
3606    // まず ARP 待ちリストに宛先 IP アドレスが登録されているかどうか調べる
3607    w = SearchArpWaitTable(v, ip);
3608    if (w != NULL)
3609    {
3610        // すでに登録されているので何もしない
3611        return;
3612    }
3613
3614    // まず ARP パケットを送信する
3615    VirtualArpSendRequest(v, ip);
3616
3617    // ARP 待ちリストに登録する
3618    w = ZeroMalloc(sizeof(ARP_WAIT));
3619    w->GiveupTime = v->Now + (UINT64)ARP_REQUEST_GIVEUP;
3620    w->TimeoutTime = v->Now + (UINT64)ARP_REQUEST_TIMEOUT;
3621    w->NextTimeoutTimeValue = ARP_REQUEST_TIMEOUT;
3622    w->IpAddress = ip;
3623
3624    InsertArpWaitTable(v, w);
3625}
3626
3627// ARP 待ちテーブルの削除
3628void DeleteArpWaitTable(VH *v, UINT ip)
3629{
3630    ARP_WAIT *w;
3631    // 引数チェック
3632    if (v == NULL)
3633    {
3634        return;
3635    }
3636
3637    w = SearchArpWaitTable(v, ip);
3638    if (w == NULL)
3639    {
3640        return;
3641    }
3642    Delete(v->ArpWaitTable, w);
3643
3644    Free(w);
3645}
3646
3647// ARP 待ちテーブルの検索
3648ARP_WAIT *SearchArpWaitTable(VH *v, UINT ip)
3649{
3650    ARP_WAIT *w, t;
3651    // 引数チェック
3652    if (v == NULL)
3653    {
3654        return NULL;
3655    }
3656
3657    t.IpAddress = ip;
3658    w = Search(v->ArpWaitTable, &t);
3659
3660    return w;
3661}
3662
3663// ARP 待ちテーブルに登録
3664void InsertArpWaitTable(VH *v, ARP_WAIT *w)
3665{
3666    // 引数チェック
3667    if (v == NULL || w == NULL)
3668    {
3669        return;
3670    }
3671
3672    Add(v->ArpWaitTable, w);
3673}
3674
3675// ARP 待ちテーブルの初期化
3676void InitArpWaitTable(VH *v)
3677{
3678    // 引数チェック
3679    if (v == NULL)
3680    {
3681        return;
3682    }
3683
3684    v->ArpWaitTable = NewList(CompareArpWaitTable);
3685}
3686
3687// ARP 待ちテーブルの解放
3688void FreeArpWaitTable(VH *v)
3689{
3690    UINT i;
3691    // 引数チェック
3692    if (v == NULL)
3693    {
3694        return;
3695    }
3696
3697    for (i = 0;i < LIST_NUM(v->ArpWaitTable);i++)
3698    {
3699        ARP_WAIT *w = LIST_DATA(v->ArpWaitTable, i);
3700
3701        Free(w);
3702    }
3703
3704    ReleaseList(v->ArpWaitTable);
3705}
3706
3707// MAC アドレスが不正かどうかチェック
3708bool IsMacInvalid(UCHAR *mac)
3709{
3710    UINT i;
3711    // 引数チェック
3712    if (mac == NULL)
3713    {
3714        return false;
3715    }
3716
3717    for (i = 0;i < 6;i++)
3718    {
3719        if (mac[i] != 0x00)
3720        {
3721            return false;
3722        }
3723    }
3724    return true;
3725}
3726
3727// MAC アドレスがブロードキャストアドレスかどうかチェック
3728bool IsMacBroadcast(UCHAR *mac)
3729{
3730    UINT i;
3731    // 引数チェック
3732    if (mac == NULL)
3733    {
3734        return false;
3735    }
3736
3737    for (i = 0;i < 6;i++)
3738    {
3739        if (mac[i] != 0xff)
3740        {
3741            return false;
3742        }
3743    }
3744    return true;
3745}
3746
3747// ARP テーブルにエントリを挿入する
3748void InsertArpTable(VH *v, UCHAR *mac, UINT ip)
3749{
3750    ARP_ENTRY *e, t;
3751    // 引数チェック
3752    if (v == NULL || mac == NULL || ip == 0 || ip == 0xffffffff || IsMacBroadcast(mac) || IsMacInvalid(mac))
3753    {
3754        return;
3755    }
3756
3757    // すでに同じ IP アドレスが登録されていないかどうかチェック
3758    t.IpAddress = ip;
3759    e = Search(v->ArpTable, &t);
3760    if (e != NULL)
3761    {
3762        // 登録されていたのでこれを上書きするだけ
3763        if (Cmp(e->MacAddress, mac, 6) != 0)
3764        {
3765            e->Created = v->Now;
3766            Copy(e->MacAddress, mac, 6);
3767        }
3768        e->Expire = v->Now + (UINT64)ARP_ENTRY_EXPIRES;
3769    }
3770    else
3771    {
3772        // 新しくエントリを作成する
3773        e = ZeroMalloc(sizeof(ARP_ENTRY));
3774
3775        e->Created = v->Now;
3776        e->Expire = v->Now + (UINT64)ARP_ENTRY_EXPIRES;
3777        Copy(e->MacAddress, mac, 6);
3778        e->IpAddress = ip;
3779
3780        Add(v->ArpTable, e);
3781    }
3782}
3783
3784// ARP テーブルのポーリング
3785void PollingArpTable(VH *v)
3786{
3787    // 引数チェック
3788    if (v == NULL)
3789    {
3790        return;
3791    }
3792
3793    if (v->Now > v->NextArpTablePolling)
3794    {
3795        v->NextArpTablePolling = v->Now + (UINT64)ARP_ENTRY_POLLING_TIME;
3796        RefreshArpTable(v);
3797    }
3798}
3799
3800// 古い ARP エントリを削除する
3801void RefreshArpTable(VH *v)
3802{
3803    UINT i;
3804    LIST *o;
3805    // 引数チェック
3806    if (v == NULL)
3807    {
3808        return;
3809    }
3810
3811    o = NewListFast(NULL);
3812    for (i = 0;i < LIST_NUM(v->ArpTable);i++)
3813    {
3814        ARP_ENTRY *e = LIST_DATA(v->ArpTable, i);
3815
3816        // 有効期限が切れたものを調べる
3817        if (e->Expire < v->Now)
3818        {
3819            // 有効期限が切れている
3820            Add(o, e);
3821        }
3822    }
3823
3824    // 有効期限が切れているものを一括して削除する
3825    for (i = 0;i < LIST_NUM(o);i++)
3826    {
3827        ARP_ENTRY *e = LIST_DATA(o, i);
3828
3829        Delete(v->ArpTable, e);
3830        Free(e);
3831    }
3832
3833    ReleaseList(o);
3834}
3835
3836// ARP テーブルの検索
3837ARP_ENTRY *SearchArpTable(VH *v, UINT ip)
3838{
3839    ARP_ENTRY *e, t;
3840    // 引数チェック
3841    if (v == NULL)
3842    {
3843        return NULL;
3844    }
3845
3846    t.IpAddress = ip;
3847    e = Search(v->ArpTable, &t);
3848
3849    return e;
3850}
3851
3852// ARP テーブルの初期化
3853void InitArpTable(VH *v)
3854{
3855    // 引数チェック
3856    if (v == NULL)
3857    {
3858        return;
3859    }
3860
3861    v->ArpTable = NewList(CompareArpTable);
3862}
3863
3864// ARP テーブルの解放
3865void FreeArpTable(VH *v)
3866{
3867    UINT i;
3868    // 引数チェック
3869    if (v == NULL)
3870    {
3871        return;
3872    }
3873
3874    // すべてのエントリを削除する
3875    for (i = 0;i < LIST_NUM(v->ArpTable);i++)
3876    {
3877        ARP_ENTRY *e = LIST_DATA(v->ArpTable, i);
3878        Free(e);
3879    }
3880    ReleaseList(v->ArpTable);
3881}
3882
3883// ARP 待ちテーブルの比較
3884int CompareArpWaitTable(void *p1, void *p2)
3885{
3886    ARP_WAIT *e1, *e2;
3887    if (p1 == NULL || p2 == NULL)
3888    {
3889        return 0;
3890    }
3891    e1 = *(ARP_WAIT **)p1;
3892    e2 = *(ARP_WAIT **)p2;
3893    if (e1 == NULL || e2 == NULL)
3894    {
3895        return 0;
3896    }
3897
3898    if (e1->IpAddress > e2->IpAddress)
3899    {
3900        return 1;
3901    }
3902    else if (e1->IpAddress < e2->IpAddress)
3903    {
3904        return -1;
3905    }
3906    return 0;
3907}
3908
3909// ARP テーブルの比較
3910int CompareArpTable(void *p1, void *p2)
3911{
3912    ARP_ENTRY *e1, *e2;
3913    if (p1 == NULL || p2 == NULL)
3914    {
3915        return 0;
3916    }
3917    e1 = *(ARP_ENTRY **)p1;
3918    e2 = *(ARP_ENTRY **)p2;
3919    if (e1 == NULL || e2 == NULL)
3920    {
3921        return 0;
3922    }
3923
3924    if (e1->IpAddress > e2->IpAddress)
3925    {
3926        return 1;
3927    }
3928    else if (e1->IpAddress < e2->IpAddress)
3929    {
3930        return -1;
3931    }
3932    return 0;
3933}
3934
3935// 仮想ホストの初期化
3936bool VirtualInit(VH *v)
3937{
3938    // ログ初期化
3939    v->Logger = NULL;
3940
3941    LockVirtual(v);
3942    {
3943        // 初期化
3944        v->Cancel = NewCancel();
3945        v->SendQueue = NewQueue();
3946    }
3947    UnlockVirtual(v);
3948
3949    // カウンタリセット
3950    v->Counter->c = 0;
3951    v->DhcpId = 0;
3952
3953    // ARP テーブルの初期化
3954    InitArpTable(v);
3955
3956    // ARP 待ちテーブルの初期化
3957    InitArpWaitTable(v);
3958
3959    // IP 待ちテーブルの初期化
3960    InitIpWaitTable(v);
3961
3962    // IP 結合リストの初期化
3963    InitIpCombineList(v);
3964
3965    // NAT の初期化
3966    InitNat(v);
3967
3968    // DHCP サーバーの初期化
3969    InitDhcpServer(v);
3970
3971    // その他初期化
3972    v->flag1 = false;
3973    v->NextArpTablePolling = Tick64() + (UINT64)ARP_ENTRY_POLLING_TIME;
3974    v->CurrentIpQuota = 0;
3975    v->Active = true;
3976
3977    return true;
3978}
3979bool VirtualPaInit(SESSION *s)
3980{
3981    VH *v;
3982    // 引数チェック
3983    if (s == NULL || (v = (VH *)s->PacketAdapter->Param) == NULL)
3984    {
3985        return false;
3986    }
3987
3988    return VirtualInit(v);
3989}
3990
3991// 仮想ホストのキャンセルオブジェクトを取得
3992CANCEL *VirtualPaGetCancel(SESSION *s)
3993{
3994    VH *v;
3995    // 引数チェック
3996    if (s == NULL || (v = (VH *)s->PacketAdapter->Param) == NULL)
3997    {
3998        return NULL;
3999    }
4000
4001    AddRef(v->Cancel->ref);
4002    return v->Cancel;
4003}
4004
4005// 仮想ホストから次のパケットを取得
4006UINT VirtualGetNextPacket(VH *v, void **data)
4007{
4008    UINT ret = 0;
4009
4010START:
4011    // 送信キューを調べる
4012    LockQueue(v->SendQueue);
4013    {
4014        BLOCK *block = GetNext(v->SendQueue);
4015
4016        if (block != NULL)
4017        {
4018            // パケットがあった
4019            ret = block->Size;
4020            *data = block->Buf;
4021            // 構造体は破棄する
4022            Free(block);
4023        }
4024    }
4025    UnlockQueue(v->SendQueue);
4026
4027    if (ret == 0)
4028    {
4029        LockVirtual(v);
4030        {
4031            v->Now = Tick64();
4032            // ポーリング処理
4033            VirtualPolling(v);
4034        }
4035        UnlockVirtual(v);
4036        if (v->SendQueue->num_item != 0)
4037        {
4038            goto START;
4039        }
4040    }
4041
4042    return ret;
4043}
4044UINT VirtualPaGetNextPacket(SESSION *s, void **data)
4045{
4046    VH *v;
4047    // 引数チェック
4048    if (s == NULL || (v = (VH *)s->PacketAdapter->Param) == NULL)
4049    {
4050        return INFINITE;
4051    }
4052
4053    return VirtualGetNextPacket(v, data);
4054}
4055
4056// ポーリング処理 (SessionMain ループ中に 1 回必ず呼ばれる)
4057void VirtualPolling(VH *v)
4058{
4059    // 引数チェック
4060    if (v == NULL)
4061    {
4062        return;
4063    }
4064
4065    // DHCP ポーリング
4066    PollingDhcpServer(v);
4067
4068    // NAT ポーリング
4069    PoolingNat(v);
4070
4071    // 古い ARP テーブルの清掃
4072    PollingArpTable(v);
4073
4074    // ARP 待ちリストのポーリング
4075    PollingArpWaitTable(v);
4076
4077    // IP 待ちリストのポーリング
4078    PollingIpWaitTable(v);
4079
4080    // IP 結合リストのポーリング
4081    PollingIpCombine(v);
4082
4083    // ビーコン送信プロシージャ
4084    PollingBeacon(v);
4085}
4086
4087// ビーコン送信プロシージャ
4088void PollingBeacon(VH *v)
4089{
4090    // 引数チェック
4091    if (v == NULL)
4092    {
4093        return;
4094    }
4095
4096    if (v->LastSendBeacon == 0 ||
4097        ((v->LastSendBeacon + BEACON_SEND_INTERVAL) <= Tick64()))
4098    {
4099        v->LastSendBeacon = Tick64();
4100
4101        SendBeacon(v);
4102    }
4103}
4104
4105// Layer-2 パケットを送信する
4106void VirtualLayer2Send(VH *v, UCHAR *dest_mac, UCHAR *src_mac, USHORT protocol, void *data, UINT size)
4107{
4108    MAC_HEADER *mac_header;
4109    UCHAR *buf;
4110    BLOCK *block;
4111    // 引数チェック
4112    if (v == NULL || dest_mac == NULL || src_mac == NULL || data == NULL || size > (MAX_PACKET_SIZE - sizeof(MAC_HEADER)))
4113    {
4114        return;
4115    }
4116
4117    // バッファ生成
4118    buf = Malloc(MAC_HEADER_SIZE + size);
4119
4120    // MAC ヘッダ
4121    mac_header = (MAC_HEADER *)&buf[0];
4122    Copy(mac_header->DestAddress, dest_mac, 6);
4123    Copy(mac_header->SrcAddress, src_mac, 6);
4124    mac_header->Protocol = Endian16(protocol);
4125
4126    // データのコピー
4127    Copy(&buf[sizeof(MAC_HEADER)], data, size);
4128
4129    // サイズ
4130    size += sizeof(MAC_HEADER);
4131
4132    // パケット生成
4133    block = NewBlock(buf, size, 0);
4134
4135    // キューに挿入する
4136    LockQueue(v->SendQueue);
4137    {
4138        InsertQueue(v->SendQueue, block);
4139    }
4140    UnlockQueue(v->SendQueue);
4141
4142    // キャンセル
4143    Cancel(v->Cancel);
4144}
4145
4146// IP パケットを送信する (自動的に分割処理を行う)
4147void SendIp(VH *v, UINT dest_ip, UINT src_ip, UCHAR protocol, void *data, UINT size)
4148{
4149    UINT mss;
4150    UCHAR *buf;
4151    USHORT offset;
4152    USHORT id;
4153    USHORT total_size;
4154    UINT size_of_this_packet;
4155    // 引数チェック
4156    if (v == NULL || data == NULL || size == 0 || size > MAX_IP_DATA_SIZE_TOTAL)
4157    {
4158        return;
4159    }
4160
4161    // 最大セグメントサイズ
4162    mss = v->IpMss;
4163
4164    // バッファ
4165    buf = (UCHAR *)data;
4166
4167    // ID
4168    id = (v->NextId++);
4169
4170    // 合計サイズ
4171    total_size = (USHORT)size;
4172
4173    // 分割作業を開始
4174    offset = 0;
4175
4176    while (true)
4177    {
4178        bool last_packet = false;
4179        // このパケットのサイズを取得
4180        size_of_this_packet = MIN((USHORT)mss, (total_size - offset));
4181        if ((offset + (USHORT)size_of_this_packet) == total_size)
4182        {
4183            last_packet = true;
4184        }
4185
4186        // 分割されたパケットの送信処理
4187        SendFragmentedIp(v, dest_ip, src_ip, id,
4188            total_size, offset, protocol, buf + offset, size_of_this_packet, NULL);
4189        if (last_packet)
4190        {
4191            break;
4192        }
4193
4194        offset += (USHORT)size_of_this_packet;
4195    }
4196}
4197
4198// 分割済みの IP パケットを送信予約する
4199void SendFragmentedIp(VH *v, UINT dest_ip, UINT src_ip, USHORT id, USHORT total_size, USHORT offset, UCHAR protocol, void *data, UINT size, UCHAR *dest_mac)
4200{
4201    UCHAR *buf;
4202    IPV4_HEADER *ip;
4203    ARP_ENTRY *arp;
4204    // 引数チェック
4205    if (v == NULL || data == NULL || size == 0)
4206    {
4207        return;
4208    }
4209
4210    // メモリ確保
4211    buf = Malloc(size + IP_HEADER_SIZE);
4212    ip = (IPV4_HEADER *)&buf[0];
4213
4214    // IP ヘッダ構築
4215    ip->VersionAndHeaderLength = 0;
4216    IPV4_SET_VERSION(ip, 4);
4217    IPV4_SET_HEADER_LEN(ip, (IP_HEADER_SIZE / 4));
4218    ip->TypeOfService = DEFAULT_IP_TOS;
4219    ip->TotalLength = Endian16((USHORT)(size + IP_HEADER_SIZE));
4220    ip->Identification = Endian16(id);
4221    ip->FlagsAndFlagmentOffset[0] = ip->FlagsAndFlagmentOffset[1] = 0;
4222    IPV4_SET_OFFSET(ip, (offset / 8));
4223    if ((offset + size) >= total_size)
4224    {
4225        IPV4_SET_FLAGS(ip, 0x00);
4226    }
4227    else
4228    {
4229        IPV4_SET_FLAGS(ip, 0x01);
4230    }
4231    ip->TimeToLive = DEFAULT_IP_TTL;
4232    ip->Protocol = protocol;
4233    ip->Checksum = 0;
4234    ip->SrcIP = src_ip;
4235    ip->DstIP = dest_ip;
4236
4237    // チェックサム計算
4238    ip->Checksum = IpChecksum(ip, IP_HEADER_SIZE);
4239
4240    // データコピー
4241    Copy(buf + IP_HEADER_SIZE, data, size);
4242
4243    if (dest_mac == NULL)
4244    {
4245        if (ip->DstIP == 0xffffffff ||
4246            (IsInNetwork(ip->DstIP, v->HostIP, v->HostMask) && (ip->DstIP & (~v->HostMask)) == (~v->HostMask)))
4247        {
4248            // ブロードキャストアドレス
4249            dest_mac = broadcast;
4250        }
4251        else
4252        {
4253            // 宛先 MAC アドレスが不明な場合は ARP 問い合わせ
4254            arp = SearchArpTable(v, dest_ip);
4255            if (arp != NULL)
4256            {
4257                dest_mac = arp->MacAddress;
4258            }
4259        }
4260    }
4261    if (dest_mac != NULL)
4262    {
4263        // 直ちにパケットを送信する
4264        VirtualIpSend(v, dest_mac, buf, size + IP_HEADER_SIZE);
4265
4266        // パケットデータは解放して良い
4267        Free(buf);
4268    }
4269    else
4270    {
4271        // このパケットはまだ転送できないので IP 待ちテーブルに追加する
4272        InsertIpWaitTable(v, dest_ip, src_ip, buf, size + IP_HEADER_SIZE);
4273
4274        // ARP を発行する
4275        SendArp(v, dest_ip);
4276    }
4277}
4278
4279// IP パケット (分割済み) を送信する
4280void VirtualIpSend(VH *v, UCHAR *dest_mac, void *data, UINT size)
4281{
4282    // 引数チェック
4283    if (v == NULL || dest_mac == NULL || data == NULL || size == 0)
4284    {
4285        return;
4286    }
4287
4288    // 送信
4289    VirtualLayer2Send(v, dest_mac, v->MacAddress, MAC_PROTO_IPV4, data, size);
4290}
4291
4292// ARP リクエストパケットを送信する
4293void VirtualArpSendRequest(VH *v, UINT dest_ip)
4294{
4295    ARPV4_HEADER arp;
4296    // 引数チェック
4297    if (v == NULL)
4298    {
4299        return;
4300    }
4301
4302    // ARP ヘッダを構築
4303    arp.HardwareType = Endian16(ARP_HARDWARE_TYPE_ETHERNET);
4304    arp.ProtocolType = Endian16(MAC_PROTO_IPV4);
4305    arp.HardwareSize = 6;
4306    arp.ProtocolSize = 4;
4307    arp.Operation = Endian16(ARP_OPERATION_REQUEST);
4308    Copy(arp.SrcAddress, v->MacAddress, 6);
4309    arp.SrcIP = v->HostIP;
4310    Zero(&arp.TargetAddress, 6);
4311    arp.TargetIP = dest_ip;
4312
4313    // 送信
4314    VirtualLayer2Send(v, broadcast, v->MacAddress, MAC_PROTO_ARPV4, &arp, sizeof(arp));
4315}
4316
4317// ARP レスポンスパケットを送信する
4318void VirtualArpSendResponse(VH *v, UCHAR *dest_mac, UINT dest_ip, UINT src_ip)
4319{
4320    ARPV4_HEADER arp;
4321    // 引数チェック
4322    if (v == NULL || dest_mac == NULL)
4323    {
4324        return;
4325    }
4326
4327    // ARP ヘッダを構築
4328    arp.HardwareType = Endian16(ARP_HARDWARE_TYPE_ETHERNET);
4329    arp.ProtocolType = Endian16(MAC_PROTO_IPV4);
4330    arp.HardwareSize = 6;
4331    arp.ProtocolSize = 4;
4332    arp.Operation = Endian16(ARP_OPERATION_RESPONSE);
4333    Copy(arp.SrcAddress, v->MacAddress, 6);
4334    Copy(arp.TargetAddress, dest_mac, 6);
4335    arp.SrcIP = src_ip;
4336    arp.TargetIP = dest_ip;
4337
4338    // 送信
4339    VirtualLayer2Send(v, dest_mac, v->MacAddress, MAC_PROTO_ARPV4, &arp, sizeof(ARPV4_HEADER));
4340}
4341
4342// ARP リクエストパケットを受信した
4343void VirtualArpResponseRequest(VH *v, PKT *packet)
4344{
4345    ARPV4_HEADER *arp;
4346    // 引数チェック
4347    if (v == NULL || packet == NULL)
4348    {
4349        return;
4350    }
4351
4352    arp = packet->L3.ARPv4Header;
4353
4354    // 相手のホスト IP アドレスと MAC アドレスを既知の情報とする
4355    ArpIpWasKnown(v, arp->SrcIP, arp->SrcAddress);
4356
4357    // 自分のホスト IP アドレスと一致するかどうか検索
4358    if (v->HostIP == arp->TargetIP)
4359    {
4360        // 一致したので応答する
4361        VirtualArpSendResponse(v, arp->SrcAddress, arp->SrcIP, v->HostIP);
4362        return;
4363    }
4364    // 一致しない場合は何もしない
4365}
4366
4367// ARP レスポンスパケットを受信した
4368void VirtualArpResponseReceived(VH *v, PKT *packet)
4369{
4370    ARPV4_HEADER *arp;
4371    // 引数チェック
4372    if (v == NULL || packet == NULL)
4373    {
4374        return;
4375    }
4376
4377    arp = packet->L3.ARPv4Header;
4378
4379    // この情報を既知の情報とする
4380    ArpIpWasKnown(v, arp->SrcIP, arp->SrcAddress);
4381}
4382
4383// ARP パケットを受信した
4384void VirtualArpReceived(VH *v, PKT *packet)
4385{
4386    ARPV4_HEADER *arp;
4387    // 引数チェック
4388    if (v == NULL || packet == NULL)
4389    {
4390        return;
4391    }
4392
4393    arp = packet->L3.ARPv4Header;
4394
4395    if (Endian16(arp->HardwareType) != ARP_HARDWARE_TYPE_ETHERNET)
4396    {
4397        // ハードウェア種類が Ethernet 以外の場合は無視
4398        return;
4399    }
4400    if (Endian16(arp->ProtocolType) != MAC_PROTO_IPV4)
4401    {
4402        // プロトコル種類が IPv4 以外の場合は無視
4403        return;
4404    }
4405    if (arp->HardwareSize != 6 || arp->ProtocolSize != 4)
4406    {
4407        // ハードウェアアドレスまたはプロトコルアドレスのサイズが不正なので無視
4408        return;
4409    }
4410    // 送信元 MAC アドレスをチェック
4411    if (Cmp(arp->SrcAddress, packet->MacAddressSrc, 6) != 0)
4412    {
4413        // ARP パケットの MAC アドレスと MAC ヘッダの MAC アドレスが異なる
4414        return;
4415    }
4416
4417    switch (Endian16(arp->Operation))
4418    {
4419    case ARP_OPERATION_REQUEST:     // ARP リクエスト
4420        VirtualArpResponseRequest(v, packet);
4421        break;
4422
4423    case ARP_OPERATION_RESPONSE:    // ARP レスポンス
4424        VirtualArpResponseReceived(v, packet);
4425        break;
4426    }
4427}
4428
4429// DHCP サーバーの解放
4430void FreeDhcpServer(VH *v)
4431{
4432    UINT i;
4433    // 引数チェック
4434    if (v == NULL)
4435    {
4436        return;
4437    }
4438
4439    // すべてのリースエントリを削除する
4440    for (i = 0;i < LIST_NUM(v->DhcpLeaseList);i++)
4441    {
4442        DHCP_LEASE *d = LIST_DATA(v->DhcpLeaseList, i);
4443        FreeDhcpLease(d);
4444    }
4445
4446    ReleaseList(v->DhcpLeaseList);
4447    v->DhcpLeaseList = NULL;
4448}
4449
4450// DHCP サーバーの初期化
4451void InitDhcpServer(VH *v)
4452{
4453    // 引数チェック
4454    if (v == NULL)
4455    {
4456        return;
4457    }
4458
4459    // リスト作成
4460    v->DhcpLeaseList = NewList(CompareDhcpLeaseList);
4461}
4462
4463// DHCP リース項目を IP アドレスで検索
4464DHCP_LEASE *SearchDhcpLeaseByIp(VH *v, UINT ip)
4465{
4466    UINT i;
4467    // 引数チェック
4468    if (v == NULL)
4469    {
4470        return NULL;
4471    }
4472
4473    for (i = 0;i < LIST_NUM(v->DhcpLeaseList);i++)
4474    {
4475        DHCP_LEASE *d = LIST_DATA(v->DhcpLeaseList, i);
4476        if (d->IpAddress == ip)
4477        {
4478            return d;
4479        }
4480    }
4481
4482    return NULL;
4483}
4484
4485// DHCP リース項目を MAC アドレスで検索
4486DHCP_LEASE *SearchDhcpLeaseByMac(VH *v, UCHAR *mac)
4487{
4488    DHCP_LEASE *d, t;
4489    // 引数チェック
4490    if (v == NULL || mac == NULL)
4491    {
4492        return NULL;
4493    }
4494
4495    Copy(&t.MacAddress, mac, 6);
4496    d = Search(v->DhcpLeaseList, &t);
4497
4498    return d;
4499}
4500
4501// DHCP リース項目の解放
4502void FreeDhcpLease(DHCP_LEASE *d)
4503{
4504    // 引数チェック
4505    if (d == NULL)
4506    {
4507        return;
4508    }
4509
4510    Free(d->Hostname);
4511    Free(d);
4512}
4513
4514// DHCP リース項目の作成
4515DHCP_LEASE *NewDhcpLease(UINT expire, UCHAR *mac_address, UINT ip, UINT mask, char *hostname)
4516{
4517    DHCP_LEASE *d;
4518    // 引数チェック
4519    if (mac_address == NULL || hostname == NULL)
4520    {
4521        return NULL;
4522    }
4523
4524    d = ZeroMalloc(sizeof(DHCP_LEASE));
4525    d->LeasedTime = (UINT64)Tick64();
4526    if (expire == INFINITE)
4527    {
4528        d->ExpireTime = INFINITE;
4529    }
4530    else
4531    {
4532        d->ExpireTime = d->LeasedTime + (UINT64)expire;
4533    }
4534    d->IpAddress = ip;
4535    d->Mask = mask;
4536    d->Hostname = CopyStr(hostname);
4537    Copy(d->MacAddress, mac_address, 6);
4538
4539
4540    return d;
4541}
4542
4543// DHCP リストの項目の比較
4544int CompareDhcpLeaseList(void *p1, void *p2)
4545{
4546    DHCP_LEASE *d1, *d2;
4547    // 引数チェック
4548    if (p1 == NULL || p2 == NULL)
4549    {
4550        return 0;
4551    }
4552    d1 = *(DHCP_LEASE **)p1;
4553    d2 = *(DHCP_LEASE **)p2;
4554    if (d1 == NULL || d2 == NULL)
4555    {
4556        return 0;
4557    }
4558
4559    return Cmp(d1->MacAddress, d2->MacAddress, 6);
4560}
4561
4562// DHCP サーバーのポーリング
4563void PollingDhcpServer(VH *v)
4564{
4565    UINT i;
4566    // 引数チェック
4567    if (v == NULL)
4568    {
4569        return;
4570    }
4571
4572    if (v->LastDhcpPolling != 0)
4573    {
4574        if ((v->LastDhcpPolling + (UINT64)DHCP_POLLING_INTERVAL) < v->Now ||
4575            v->LastDhcpPolling > v->Now)
4576        {
4577            return;
4578        }
4579    }
4580    v->LastDhcpPolling = v->Now;
4581
4582    // 有効期限の切れたエントリを削除
4583FIRST_LIST:
4584    for (i = 0;i < LIST_NUM(v->DhcpLeaseList);i++)
4585    {
4586        DHCP_LEASE *d = LIST_DATA(v->DhcpLeaseList, i);
4587
4588        if (d->ExpireTime < v->Now)
4589        {
4590            FreeDhcpLease(d);
4591            Delete(v->DhcpLeaseList, d);
4592            goto FIRST_LIST;
4593        }
4594    }
4595}
4596
4597// DHCP REQUEST に対応する
4598UINT ServeDhcpRequest(VH *v, UCHAR *mac, UINT request_ip)
4599{
4600    UINT ret;
4601    // 引数チェック
4602    if (v == NULL || mac == NULL)
4603    {
4604        return 0;
4605    }
4606
4607    ret = ServeDhcpDiscover(v, mac, request_ip);
4608    if (ret != request_ip)
4609    {
4610        if (request_ip != 0)
4611        {
4612            // 要求されている IP アドレスを割り当てることができない場合はエラー
4613            return 0;
4614        }
4615    }
4616
4617    return ret;
4618}
4619
4620// DHCP DISCOVER に対応する
4621UINT ServeDhcpDiscover(VH *v, UCHAR *mac, UINT request_ip)
4622{
4623    UINT ret = 0;
4624    // 引数チェック
4625    if (v == NULL || mac == NULL)
4626    {
4627        return 0;
4628    }
4629
4630    if (request_ip != 0)
4631    {
4632        // IP アドレスが指定されている
4633        DHCP_LEASE *d = SearchDhcpLeaseByIp(v, request_ip);
4634        if (d != NULL)
4635        {
4636            // 同じ IP アドレスのエントリがすでに存在している場合は
4637            // 同じ MAC アドレスからの要求であることを調べる
4638            if (Cmp(mac, d->MacAddress, 6) == 0)
4639            {
4640                // 指定された IP アドレスが割り当て範囲内にあるかどうか調べる
4641                if (Endian32(v->DhcpIpStart) <= Endian32(request_ip) &&
4642                    Endian32(request_ip) <= Endian32(v->DhcpIpEnd))
4643                {
4644                    // 範囲内にあるなら承諾する
4645                    ret = request_ip;
4646                }
4647            }
4648        }
4649        else
4650        {
4651            // 指定された IP アドレスが割り当て範囲内にあるかどうか調べる
4652            if (Endian32(v->DhcpIpStart) <= Endian32(request_ip) &&
4653                Endian32(request_ip) <= Endian32(v->DhcpIpEnd))
4654            {
4655                // 範囲内にあるなら承諾する
4656                ret = request_ip;
4657            }
4658            else
4659            {
4660                // 範囲外であるが Discover なので範囲内の IP を 1 つ提案する
4661            }
4662        }
4663    }
4664
4665    if (ret == 0)
4666    {
4667        // すでに登録されているエントリで同じ MAC アドレスのものがあれば
4668        // それを優先して使用する
4669        DHCP_LEASE *d = SearchDhcpLeaseByMac(v, mac);
4670        if (d != NULL)
4671        {
4672            // 見つかった IP アドレスが割り当て範囲内にあるかどうか調べる
4673            if (Endian32(v->DhcpIpStart) <= Endian32(d->IpAddress) &&
4674                Endian32(d->IpAddress) <= Endian32(v->DhcpIpEnd))
4675            {
4676                // 範囲内にあるなら見つかったIPアドレスを使用する
4677                ret = d->IpAddress;
4678            }
4679        }
4680    }
4681
4682    if (ret == 0)
4683    {
4684        // 新しく割り当てることが可能な IP アドレスを適当に取る
4685        ret = GetFreeDhcpIpAddress(v);
4686    }
4687
4688    return ret;
4689}
4690
4691// 新しく割り当てることが可能な IP アドレスを適当に 1 つ取る
4692UINT GetFreeDhcpIpAddress(VH *v)
4693{
4694    UINT ip_start, ip_end;
4695    UINT i;
4696    // 引数チェック
4697    if (v == NULL)
4698    {
4699        return 0;
4700    }
4701
4702    ip_start = Endian32(v->DhcpIpStart);
4703    ip_end = Endian32(v->DhcpIpEnd);
4704
4705    for (i = ip_start; i <= ip_end;i++)
4706    {
4707        UINT ip = Endian32(i);
4708        if (SearchDhcpLeaseByIp(v, ip) == NULL)
4709        {
4710            // 空き IP アドレスを発見した
4711            return ip;
4712        }
4713    }
4714
4715    // 空きが無い
4716    return 0;
4717}
4718
4719// 仮想 DHCP サーバー
4720void VirtualDhcpServer(VH *v, PKT *p)
4721{
4722    DHCPV4_HEADER *dhcp;
4723    UCHAR *data;
4724    UINT size;
4725    UINT dhcp_header_size;
4726    UINT dhcp_data_offset;
4727    UINT tran_id;
4728    UINT magic_cookie = Endian32(DHCP_MAGIC_COOKIE);
4729    bool ok;
4730    DHCP_OPTION_LIST *opt;
4731    // 引数チェック
4732    if (v == NULL || p == NULL)
4733    {
4734        return;
4735    }
4736
4737    dhcp = p->L7.DHCPv4Header;
4738
4739    tran_id = Endian32(dhcp->TransactionId);
4740
4741    // DHCP データとサイズを取得する
4742    dhcp_header_size = sizeof(DHCPV4_HEADER);
4743    dhcp_data_offset = (UINT)(((UCHAR *)p->L7.DHCPv4Header) - ((UCHAR *)p->MacHeader) + dhcp_header_size);
4744    data = ((UCHAR *)dhcp) + dhcp_header_size;
4745    size = p->PacketSize - dhcp_data_offset;
4746    if (dhcp_header_size < 5)
4747    {
4748        // データサイズが不正
4749        return;
4750    }
4751
4752    // Magic Cookie を検索する
4753    ok = false;
4754    while (size >= 5)
4755    {
4756        if (Cmp(data, &magic_cookie, sizeof(magic_cookie)) == 0)
4757        {
4758            // 発見
4759            data += 4;
4760            size -= 4;
4761            ok = true;
4762            break;
4763        }
4764        data++;
4765        size--;
4766    }
4767
4768    if (ok == false)
4769    {
4770        // パケット不正
4771        return;
4772    }
4773
4774    // DHCP オプションリストのパース
4775    opt = ParseDhcpOptionList(data, size);
4776    if (opt == NULL)
4777    {
4778        // パケット不正
4779        return;
4780    }
4781
4782    if (dhcp->OpCode == 1 && (opt->Opcode == DHCP_DISCOVER || opt->Opcode == DHCP_REQUEST))
4783    {
4784        // サーバーとしての動作を行う
4785        UINT ip;
4786        if (opt->RequestedIp == 0)
4787        {
4788            opt->RequestedIp = p->L3.IPv4Header->SrcIP;
4789        }
4790        if (opt->Opcode == DHCP_DISCOVER)
4791        {
4792            // 利用できる IP アドレスを 1 つ返す
4793            ip = ServeDhcpDiscover(v, p->MacAddressSrc, opt->RequestedIp);
4794        }
4795        else
4796        {
4797            // IP アドレスを確定する
4798            ip = ServeDhcpRequest(v, p->MacAddressSrc, opt->RequestedIp);
4799        }
4800        if (ip != 0)
4801        {
4802            // 提供可能な IP アドレスがある場合は応答してやる
4803
4804            if (opt->Opcode == DHCP_REQUEST)
4805            {
4806                DHCP_LEASE *d;
4807                char mac[MAX_SIZE];
4808                char str[MAX_SIZE];
4809                // 同じ IP アドレスで古いレコードがあれば削除する
4810                d = SearchDhcpLeaseByIp(v, ip);
4811                if (d != NULL)
4812                {
4813                    FreeDhcpLease(d);
4814                    Delete(v->DhcpLeaseList, d);
4815                }
4816
4817                // 新しいエントリを作成する
4818                d = NewDhcpLease(v->DhcpExpire, p->MacAddressSrc,
4819                    ip, v->DhcpMask,
4820                    opt->Hostname);
4821                d->Id = ++v->DhcpId;
4822                Add(v->DhcpLeaseList, d);
4823                MacToStr(mac, sizeof(mac), d->MacAddress);
4824
4825                IPToStr32(str, sizeof(str), d->IpAddress);
4826
4827                NLog(v, "LH_NAT_DHCP_CREATED", d->Id, mac, str, d->Hostname, v->DhcpExpire / 1000);
4828            }
4829
4830            // 応答する
4831            if (ip != 0)
4832            {
4833                DHCP_OPTION_LIST ret;
4834                LIST *o;
4835                Zero(&ret, sizeof(ret));
4836
4837                ret.Opcode = (opt->Opcode == DHCP_DISCOVER ? DHCP_OFFER : DHCP_ACK);
4838                ret.ServerAddress = v->HostIP;
4839                if (v->DhcpExpire == INFINITE)
4840                {
4841                    ret.LeaseTime = INFINITE;
4842                }
4843                else
4844                {
4845                    ret.LeaseTime = Endian32(v->DhcpExpire / 1000);
4846                }
4847                StrCpy(ret.DomainName, sizeof(ret.DomainName), v->DhcpDomain);
4848                ret.SubnetMask = v->DhcpMask;
4849                ret.DnsServer = v->DhcpDns;
4850                ret.Gateway = v->DhcpGateway;
4851
4852                if (1)
4853                {
4854                    char client_mac[MAX_SIZE];
4855                    char client_ip[64];
4856                    IP ips;
4857                    BinToStr(client_mac, sizeof(client_mac), p->MacAddressSrc, 6);
4858                    UINTToIP(&ips, ip);
4859                    IPToStr(client_ip, sizeof(client_ip), &ips);
4860                    Debug("DHCP %s : %s given %s\n",
4861                        ret.Opcode == DHCP_OFFER ? "DHCP_OFFER" : "DHCP_ACK",
4862                        client_mac, client_ip);
4863                }
4864
4865                // DHCP オプションのビルド
4866                o = BuildDhcpOption(&ret);
4867                if (o != NULL)
4868                {
4869                    BUF *b = BuildDhcpOptionsBuf(o);
4870                    if (b != NULL)
4871                    {
4872                        UINT dest_ip = p->L3.IPv4Header->SrcIP;
4873                        if (dest_ip == 0)
4874                        {
4875                            dest_ip = 0xffffffff;
4876                        }
4877                        // 送信
4878                        VirtualDhcpSend(v, tran_id, dest_ip, Endian16(p->L4.UDPHeader->SrcPort),
4879                            ip, dhcp->ClientMacAddress, b);
4880
4881                        // メモリ解放
4882                        FreeBuf(b);
4883                    }
4884                    FreeDhcpOptions(o);
4885                }
4886            }
4887        }
4888        else
4889        {
4890            // 提供できる IP アドレスが無い
4891            DHCP_OPTION_LIST ret;
4892            LIST *o;
4893            Zero(&ret, sizeof(ret));
4894
4895            ret.Opcode = DHCP_NACK;
4896            ret.ServerAddress = v->HostIP;
4897            StrCpy(ret.DomainName, sizeof(ret.DomainName), v->DhcpDomain);
4898            ret.SubnetMask = v->DhcpMask;
4899
4900            // DHCP オプションのビルド
4901            o = BuildDhcpOption(&ret);
4902            if (o != NULL)
4903            {
4904                BUF *b = BuildDhcpOptionsBuf(o);
4905                if (b != NULL)
4906                {
4907                    UINT dest_ip = p->L3.IPv4Header->SrcIP;
4908                    if (dest_ip == 0)
4909                    {
4910                        dest_ip = 0xffffffff;
4911                    }
4912                    // 送信
4913                    VirtualDhcpSend(v, tran_id, dest_ip, Endian16(p->L4.UDPHeader->SrcPort),
4914                        ip, dhcp->ClientMacAddress, b);
4915
4916                    // メモリ解放
4917                    FreeBuf(b);
4918                }
4919                FreeDhcpOptions(o);
4920            }
4921        }
4922    }
4923
4924    // メモリ解放
4925    Free(opt);
4926}
4927
4928// DHCP 応答パケットの送信
4929void VirtualDhcpSend(VH *v, UINT tran_id, UINT dest_ip, UINT dest_port,
4930                     UINT new_ip, UCHAR *client_mac, BUF *b)
4931{
4932    UINT blank_size = 128 + 64;
4933    UINT dhcp_packet_size;
4934    UINT magic = Endian32(DHCP_MAGIC_COOKIE);
4935    DHCPV4_HEADER *dhcp;
4936    void *magic_cookie_addr;
4937    void *buffer_addr;
4938    // 引数チェック
4939    if (v == NULL || b == NULL)
4940    {
4941        return;
4942    }
4943
4944    // DHCP パケットサイズを求める
4945    dhcp_packet_size = blank_size + sizeof(DHCPV4_HEADER) + sizeof(magic) + b->Size;
4946
4947    // ヘッダ作成
4948    dhcp = ZeroMalloc(dhcp_packet_size);
4949
4950    dhcp->OpCode = 2;
4951    dhcp->HardwareType = 1;
4952    dhcp->HardwareAddressSize = 6;
4953    dhcp->Hops = 0;
4954    dhcp->TransactionId = Endian32(tran_id);
4955    dhcp->Seconds = 0;
4956    dhcp->Flags = 0;
4957    dhcp->YourIP = new_ip;
4958    dhcp->ServerIP = v->HostIP;
4959    Copy(dhcp->ClientMacAddress, client_mac, 6);
4960
4961    // アドレスを求める
4962    magic_cookie_addr = (((UCHAR *)dhcp) + sizeof(DHCPV4_HEADER) + blank_size);
4963    buffer_addr = ((UCHAR *)magic_cookie_addr) + sizeof(magic);
4964
4965    // Magic Cookie
4966    Copy(magic_cookie_addr, &magic, sizeof(magic));
4967
4968    // Buffer
4969    Copy(buffer_addr, b->Buf, b->Size);
4970
4971    // 送信
4972    SendUdp(v, dest_ip, dest_port, v->HostIP, NAT_DHCP_SERVER_PORT, dhcp, dhcp_packet_size);
4973
4974    Free(dhcp);
4975}
4976
4977// DHCP オプション リストをバッファに変換する
4978BUF *BuildDhcpOptionsBuf(LIST *o)
4979{
4980    BUF *b;
4981    UINT i;
4982    UCHAR id;
4983    UCHAR sz;
4984    // 引数チェック
4985    if (o == NULL)
4986    {
4987        return NULL;
4988    }
4989
4990    b = NewBuf();
4991    for (i = 0;i < LIST_NUM(o);i++)
4992    {
4993        DHCP_OPTION *d = LIST_DATA(o, i);
4994        id = (UCHAR)d->Id;
4995        sz = (UCHAR)d->Size;
4996        WriteBuf(b, &id, 1);
4997        WriteBuf(b, &sz, 1);
4998        WriteBuf(b, d->Data, d->Size);
4999    }
5000
5001    id = 0xff;
5002    WriteBuf(b, &id, 1);
5003
5004    return b;
5005}
5006
5007// DHCP オプション リストを DHCP オプションに変換する
5008LIST *BuildDhcpOption(DHCP_OPTION_LIST *opt)
5009{
5010    LIST *o;
5011    UCHAR opcode;
5012    // 引数チェック
5013    if (opt == NULL)
5014    {
5015        return NULL;
5016    }
5017
5018    o = NewListFast(NULL);
5019
5020    // オペコード
5021    opcode = (UCHAR)opt->Opcode;
5022    Add(o, NewDhcpOption(DHCP_ID_MESSAGE_TYPE, &opcode, sizeof(opcode)));
5023    Add(o, NewDhcpOption(DHCP_ID_SERVER_ADDRESS, &opt->ServerAddress, sizeof(opt->ServerAddress)));
5024    Add(o, NewDhcpOption(DHCP_ID_LEASE_TIME, &opt->LeaseTime, sizeof(opt->LeaseTime)));
5025    if (StrLen(opt->DomainName) != 0 && opt->DnsServer != 0)
5026    {
5027        Add(o, NewDhcpOption(DHCP_ID_DOMAIN_NAME, opt->DomainName, StrLen(opt->DomainName)));
5028    }
5029    if (opt->SubnetMask != 0)
5030    {
5031        Add(o, NewDhcpOption(DHCP_ID_SUBNET_MASK, &opt->SubnetMask, sizeof(opt->SubnetMask)));
5032    }
5033    if (opt->Gateway != 0)
5034    {
5035        Add(o, NewDhcpOption(DHCP_ID_GATEWAY_ADDR, &opt->Gateway, sizeof(opt->Gateway)));
5036    }
5037    if (opt->DnsServer != 0)
5038    {
5039        Add(o, NewDhcpOption(DHCP_ID_DNS_ADDR, &opt->DnsServer, sizeof(opt->DnsServer)));
5040    }
5041
5042    return o;
5043}
5044
5045// 新しい DHCP オプション項目の作成
5046DHCP_OPTION *NewDhcpOption(UINT id, void *data, UINT size)
5047{
5048    DHCP_OPTION *ret;
5049    if (size != 0 && data == NULL)
5050    {
5051        return NULL;
5052    }
5053
5054    ret = ZeroMalloc(sizeof(DHCP_OPTION));
5055    ret->Data = ZeroMalloc(size);
5056    Copy(ret->Data, data, size);
5057    ret->Size = (UCHAR)size;
5058    ret->Id = (UCHAR)id;
5059
5060    return ret;
5061}
5062
5063// DHCP オプションリストのパース
5064DHCP_OPTION_LIST *ParseDhcpOptionList(void *data, UINT size)
5065{
5066    DHCP_OPTION_LIST *ret;
5067    LIST *o;
5068    DHCP_OPTION *a;
5069    // 引数チェック
5070    if (data == NULL)
5071    {
5072        return NULL;
5073    }
5074
5075    // リストのパース
5076    o = ParseDhcpOptions(data, size);
5077    if (o == NULL)
5078    {
5079        return NULL;
5080    }
5081
5082    ret = ZeroMalloc(sizeof(DHCP_OPTION_LIST));
5083
5084    // オペコードの取得
5085    a = GetDhcpOption(o, DHCP_ID_MESSAGE_TYPE);
5086    if (a != NULL)
5087    {
5088        if (a->Size == 1)
5089        {
5090            ret->Opcode = *((UCHAR *)a->Data);
5091        }
5092    }
5093
5094    switch (ret->Opcode)
5095    {
5096    case DHCP_DISCOVER:
5097    case DHCP_REQUEST:
5098        // クライアント要求なのでより細かくパースする
5099        // 要求された IP アドレス
5100        a = GetDhcpOption(o, DHCP_ID_REQUEST_IP_ADDRESS);
5101        if (a != NULL && a->Size == 4)
5102        {
5103            Copy(&ret->RequestedIp, a->Data, 4);
5104        }
5105        // ホスト名
5106        a = GetDhcpOption(o, DHCP_ID_HOST_NAME);
5107        if (a != NULL)
5108        {
5109            if (a->Size > 1)
5110            {
5111                Copy(ret->Hostname, a->Data, MIN(a->Size, sizeof(ret->Hostname) - 1));
5112            }
5113        }
5114        break;
5115
5116    case DHCP_OFFER:
5117    case DHCP_ACK:
5118        // 今のところこの 2 つのオプションをパースする必要は無い
5119        break;
5120    }
5121
5122    // リストの解放
5123    FreeDhcpOptions(o);
5124
5125    return ret;
5126}
5127
5128// DHCP オプションの検索
5129DHCP_OPTION *GetDhcpOption(LIST *o, UINT id)
5130{
5131    UINT i;
5132    DHCP_OPTION *ret = NULL;
5133    // 引数チェック
5134    if (o == NULL)
5135    {
5136        return NULL;
5137    }
5138
5139    for (i = 0;i < LIST_NUM(o);i++)
5140    {
5141        DHCP_OPTION *opt = LIST_DATA(o, i);
5142        if (opt->Id == id)
5143        {
5144            ret = opt;
5145        }
5146    }
5147
5148    return ret;
5149}
5150
5151// DHCP オプションの解放
5152void FreeDhcpOptions(LIST *o)
5153{
5154    UINT i;
5155    // 引数チェック
5156    if (o == NULL)
5157    {
5158        return;
5159    }
5160
5161    for (i = 0;i < LIST_NUM(o);i++)
5162    {
5163        DHCP_OPTION *opt = LIST_DATA(o, i);
5164        Free(opt->Data);
5165        Free(opt);
5166    }
5167
5168    ReleaseList(o);
5169}
5170
5171// DHCP オプションのパース
5172LIST *ParseDhcpOptions(void *data, UINT size)
5173{
5174    BUF *b;
5175    LIST *o;
5176    // 引数チェック
5177    if (data == NULL)
5178    {
5179        return NULL;
5180    }
5181
5182    b = NewBuf();
5183    WriteBuf(b, data, size);
5184    SeekBuf(b, 0, 0);
5185
5186    o = NewListFast(NULL);
5187
5188    while (true)
5189    {
5190        UCHAR c = 0;
5191        UCHAR sz = 0;
5192        DHCP_OPTION *opt;
5193        if (ReadBuf(b, &c, 1) != 1)
5194        {
5195            break;
5196        }
5197        if (c == 0xff)
5198        {
5199            break;
5200        }
5201        if (ReadBuf(b, &sz, 1) != 1)
5202        {
5203            break;
5204        }
5205
5206        opt = ZeroMalloc(sizeof(DHCP_OPTION));
5207        opt->Id = (UINT)c;
5208        opt->Size = (UINT)sz;
5209        opt->Data = ZeroMalloc((UINT)sz);
5210        ReadBuf(b, opt->Data, sz);
5211        Add(o, opt);
5212    }
5213
5214    FreeBuf(b);
5215
5216    return o;
5217}
5218
5219// 仮想ホスト - Layer2 の処理
5220void VirtualLayer2(VH *v, PKT *packet)
5221{
5222    bool ok;
5223    // 引数チェック
5224    if (packet == NULL || v == NULL)
5225    {
5226        return;
5227    }
5228
5229    // パケットフィルタ
5230    if (VirtualLayer2Filter(v, packet) == false)
5231    {
5232        // パケットは無視された
5233        return;
5234    }
5235
5236    ok = false;
5237    if (packet->TypeL3 == L3_IPV4 && packet->TypeL4 == L4_UDP && packet->TypeL7 == L7_DHCPV4)
5238    {
5239        if (v->UseDhcp)
5240        {
5241            // DHCP パケットに関する特殊な処理
5242            if (packet->BroadcastPacket || Cmp(packet->MacAddressDest, v->MacAddress, 6) == 0)
5243            {
5244                // 仮想 DHCP サーバー処理
5245                VirtualDhcpServer(v, packet);
5246                ok = true;
5247            }
5248        }
5249    }
5250
5251    if (ok == false)
5252    {
5253        // サポートしているプロトコルごとに処理
5254        switch (packet->TypeL3)
5255        {
5256        case L3_ARPV4:  // ARPv4
5257            VirtualArpReceived(v, packet);
5258            break;
5259
5260        case L3_IPV4:   // IPv4
5261            VirtualIpReceived(v, packet);
5262            break;
5263        }
5264    }
5265}
5266
5267// パケットフィルタ (自分以外へのパケットを遮断)
5268bool VirtualLayer2Filter(VH *v, PKT *packet)
5269{
5270    // 引数チェック
5271    if (v == NULL || packet == NULL)
5272    {
5273        return false;
5274    }
5275
5276    // ブロードキャストパケットなら通過
5277    if (packet->BroadcastPacket)
5278    {
5279        return true;
5280    }
5281
5282    // 送信元が自分のパケットなら無視
5283    if (Cmp(packet->MacAddressSrc, v->MacAddress, 6) == 0)
5284    {
5285        return false;
5286    }
5287    // 自分宛のパケットなら通過
5288    if (Cmp(packet->MacAddressDest, v->MacAddress, 6) == 0)
5289    {
5290        return true;
5291    }
5292
5293    // それ以外のパケットなら破棄
5294    return false;
5295}
5296
5297// 仮想ホストにパケットを受信させる
5298bool VirtualPutPacket(VH *v, void *data, UINT size)
5299{
5300    if (data == NULL)
5301    {
5302        // フラッシュ
5303        v->flag1 = false;
5304    }
5305    else
5306    {
5307        // 受信したパケットを解釈する
5308        PKT *packet = ParsePacket(data, size);
5309
5310        if (v->flag1 == false)
5311        {
5312            v->flag1 = true;
5313            v->Now = Tick64();
5314        }
5315
5316        // ここの中は仮想マシン全体をロックする
5317        LockVirtual(v);
5318        {
5319            if (packet != NULL)
5320            {
5321                // Layer-2 の処理を行う
5322                VirtualLayer2(v, packet);
5323
5324                // パケット構造体の解放
5325                FreePacket(packet);
5326            }
5327        }
5328        UnlockVirtual(v);
5329
5330        Free(data);
5331    }
5332
5333    return true;
5334}
5335bool VirtualPaPutPacket(SESSION *s, void *data, UINT size)
5336{
5337    VH *v;
5338    // 引数チェック
5339    if (s == NULL || (v = (VH *)s->PacketAdapter->Param) == NULL)
5340    {
5341        return false;
5342    }
5343
5344    return VirtualPutPacket(v, data, size);
5345}
5346
5347// 仮想ホストのオプションを取得する
5348void GetVirtualHostOption(VH *v, VH_OPTION *o)
5349{
5350    // 引数チェック
5351    if (v == NULL)
5352    {
5353        return;
5354    }
5355
5356    LockVirtual(v);
5357    {
5358        Zero(o, sizeof(VH_OPTION));
5359
5360        // MAC アドレス
5361        Copy(o->MacAddress, v->MacAddress, 6);
5362
5363        // ホスト情報
5364        UINTToIP(&o->Ip, v->HostIP);
5365        UINTToIP(&o->Mask, v->HostMask);
5366
5367        o->Mtu = v->Mtu;
5368
5369        // NAT タイムアウト情報
5370        o->NatTcpTimeout = v->NatTcpTimeout / 1000;
5371        o->NatUdpTimeout = v->NatUdpTimeout / 1000;
5372
5373        // NAT 使用フラグ
5374        o->UseNat = v->UseNat;
5375
5376        // DHCP 使用フラグ
5377        o->UseDhcp = v->UseDhcp;
5378
5379        // DHCP 配布 IP アドレス範囲
5380        UINTToIP(&o->DhcpLeaseIPStart, v->DhcpIpStart);
5381        UINTToIP(&o->DhcpLeaseIPEnd, v->DhcpIpEnd);
5382
5383        // サブネットマスク
5384        UINTToIP(&o->DhcpSubnetMask, v->DhcpMask);
5385
5386        // 有効期限
5387        if (v->DhcpExpire != INFINITE)
5388        {
5389            o->DhcpExpireTimeSpan = v->DhcpExpire / 1000;
5390        }
5391        else
5392        {
5393            o->DhcpExpireTimeSpan = INFINITE;
5394        }
5395
5396        // ゲートウェイアドレス
5397        UINTToIP(&o->DhcpGatewayAddress, v->DhcpGateway);
5398
5399        // DNS サーバーアドレス
5400        UINTToIP(&o->DhcpDnsServerAddress, v->DhcpDns);
5401
5402        // ドメイン名
5403        StrCpy(o->DhcpDomainName, sizeof(o->DhcpDomainName), v->DhcpDomain);
5404
5405        // ログの保存
5406        o->SaveLog = v->SaveLog;
5407    }
5408    UnlockVirtual(v);
5409}
5410
5411// 仮想ホストにオプションを設定する
5412void SetVirtualHostOption(VH *v, VH_OPTION *vo)
5413{
5414    UINT i;
5415    // 引数チェック
5416    if (v == NULL || vo == NULL)
5417    {
5418        return;
5419    }
5420
5421    LockVirtual(v);
5422    {
5423        // MAC アドレスを設定する
5424        for (i = 0;i < 6;i++)
5425        {
5426            if (vo->MacAddress[i] != 0)
5427            {
5428                Copy(v->MacAddress, vo->MacAddress, 6);
5429                break;
5430            }
5431        }
5432
5433        // ホスト情報リストを設定する
5434        v->HostIP = IPToUINT(&vo->Ip);
5435        v->HostMask = IPToUINT(&vo->Mask);
5436
5437        // MTU, MMS を設定する
5438        v->Mtu = MIN(vo->Mtu, MAX_L3_DATA_SIZE);
5439        if (v->Mtu == 0)
5440        {
5441            v->Mtu = MAX_L3_DATA_SIZE;
5442        }
5443        v->Mtu = MAX(v->Mtu, TCP_HEADER_SIZE + IP_HEADER_SIZE + MAC_HEADER_SIZE + 8);
5444        v->IpMss = ((v->Mtu - IP_HEADER_SIZE) / 8) * 8;
5445        v->TcpMss = ((v->IpMss - TCP_HEADER_SIZE) / 8) * 8;
5446        v->UdpMss = ((v->IpMss - UDP_HEADER_SIZE) / 8) * 8;
5447
5448        if (vo->NatTcpTimeout != 0)
5449        {
5450            v->NatTcpTimeout = MIN(vo->NatTcpTimeout, 4000000) * 1000;
5451        }
5452        if (vo->NatUdpTimeout != 0)
5453        {
5454            v->NatUdpTimeout = MIN(vo->NatUdpTimeout, 4000000) * 1000;
5455        }
5456        v->NatTcpTimeout = MAKESURE(v->NatTcpTimeout, NAT_TCP_MIN_TIMEOUT, NAT_TCP_MAX_TIMEOUT);
5457        v->NatUdpTimeout = MAKESURE(v->NatUdpTimeout, NAT_UDP_MIN_TIMEOUT, NAT_UDP_MAX_TIMEOUT);
5458        Debug("Timeout: %d , %d\n", v->NatTcpTimeout, v->NatUdpTimeout);
5459
5460        // NAT 使用フラグ
5461        v->UseNat = vo->UseNat;
5462
5463        // DHCP 使用フラグ
5464        v->UseDhcp = vo->UseDhcp;
5465
5466        // 有効期限
5467        if (vo->DhcpExpireTimeSpan == 0 || vo->DhcpExpireTimeSpan == INFINITE)
5468        {
5469            v->DhcpExpire = INFINITE;
5470        }
5471        else
5472        {
5473            v->DhcpExpire = MAKESURE(DHCP_MIN_EXPIRE_TIMESPAN,
5474                MIN(vo->DhcpExpireTimeSpan * 1000, 2000000000),
5475                INFINITE);
5476        }
5477
5478        // 配布するアドレス範囲
5479        v->DhcpIpStart = IPToUINT(&vo->DhcpLeaseIPStart);
5480        v->DhcpIpEnd = IPToUINT(&vo->DhcpLeaseIPEnd);
5481        if (Endian32(v->DhcpIpEnd) < Endian32(v->DhcpIpStart))
5482        {
5483            v->DhcpIpEnd = v->DhcpIpStart;
5484        }
5485
5486        // サブネットマスク
5487        v->DhcpMask = IPToUINT(&vo->DhcpSubnetMask);
5488
5489        // ゲートウェイアドレス
5490        v->DhcpGateway = IPToUINT(&vo->DhcpGatewayAddress);
5491
5492        // DNS サーバーアドレス
5493        v->DhcpDns = IPToUINT(&vo->DhcpDnsServerAddress);
5494
5495        // ドメイン名
5496        StrCpy(v->DhcpDomain, sizeof(v->DhcpDomain), vo->DhcpDomainName);
5497
5498        // ログの保存
5499        v->SaveLog = vo->SaveLog;
5500    }
5501    UnlockVirtual(v);
5502}
5503
5504// 仮想ホストの解放
5505void Virtual_Free(VH *v)
5506{
5507    // DHCP サーバー解放
5508    FreeDhcpServer(v);
5509
5510    // NAT 解放
5511    FreeNat(v);
5512
5513    LockVirtual(v);
5514    {
5515        // IP 結合リスト解放
5516        FreeIpCombineList(v);
5517
5518        // IP 待ちテーブル解放
5519        FreeIpWaitTable(v);
5520
5521        // ARP 待ちテーブル解放
5522        FreeArpWaitTable(v);
5523
5524        // ARP テーブル解放
5525        FreeArpTable(v);
5526
5527        // 送信キュー解放
5528        LockQueue(v->SendQueue);
5529        {
5530            BLOCK *block;
5531
5532            // すべてのキューを解放する
5533            while (block = GetNext(v->SendQueue))
5534            {
5535                FreeBlock(block);
5536            }
5537        }
5538        UnlockQueue(v->SendQueue);
5539        ReleaseQueue(v->SendQueue);
5540        v->SendQueue = NULL;
5541
5542        // キャンセルオブジェクト解放
5543        ReleaseCancel(v->Cancel);
5544
5545        v->Active = false;
5546    }
5547    UnlockVirtual(v);
5548
5549    // ロガー解放
5550    FreeLog(v->Logger);
5551}
5552void VirtualPaFree(SESSION *s)
5553{
5554    VH *v;
5555    // 引数チェック
5556    if (s == NULL || (v = (VH *)s->PacketAdapter->Param) == NULL)
5557    {
5558        return;
5559    }
5560
5561    Virtual_Free(v);
5562}
5563
5564// 仮想ホストの解放
5565void ReleaseVirtual(VH *v)
5566{
5567    // 引数チェック
5568    if (v == NULL)
5569    {
5570        return;
5571    }
5572
5573    if (Release(v->ref) == 0)
5574    {
5575        CleanupVirtual(v);
5576    }
5577}
5578
5579// 仮想ホストのロック
5580void LockVirtual(VH *v)
5581{
5582    // 引数チェック
5583    if (v == NULL)
5584    {
5585        return;
5586    }
5587
5588    Lock(v->lock);
5589}
5590
5591// 仮想ホストのロック解除
5592void UnlockVirtual(VH *v)
5593{
5594    // 引数チェック
5595    if (v == NULL)
5596    {
5597        return;
5598    }
5599
5600    Unlock(v->lock);
5601}
5602
5603// 仮想ホストのクリーンアップ
5604void CleanupVirtual(VH *v)
5605{
5606    // 引数チェック
5607    if (v == NULL)
5608    {
5609        return;
5610    }
5611
5612    if (v->Session != NULL)
5613    {
5614        ReleaseSession(v->Session);
5615    }
5616
5617    DeleteCounter(v->Counter);
5618    DeleteLock(v->lock);
5619
5620    Free(v);
5621}
5622
5623// 仮想ホストの停止
5624void StopVirtualHost(VH *v)
5625{
5626    SESSION *s;
5627    // 引数チェック
5628    if (v == NULL)
5629    {
5630        return;
5631    }
5632
5633    // 仮想ホストに対応したセッションの取得
5634    LockVirtual(v);
5635    {
5636        s = v->Session;
5637        if (s != NULL)
5638        {
5639            AddRef(s->ref);
5640        }
5641    }
5642    UnlockVirtual(v);
5643
5644    if (s == NULL)
5645    {
5646        // すでにこのセッションは停止している
5647        return;
5648    }
5649
5650    // セッションの停止
5651    StopSession(s);
5652
5653    ReleaseSession(s);
5654}
5655
5656// 新しい仮想ホストの作成
5657VH *NewVirtualHost(CEDAR *cedar, CLIENT_OPTION *option, CLIENT_AUTH *auth, VH_OPTION *vh_option)
5658{
5659    return NewVirtualHostEx(cedar, option, auth, vh_option, NULL);
5660}
5661VH *NewVirtualHostEx(CEDAR *cedar, CLIENT_OPTION *option, CLIENT_AUTH *auth, VH_OPTION *vh_option, NAT *nat)
5662{
5663    VH *v;
5664    // 引数チェック
5665    if (vh_option == NULL)
5666    {
5667        return NULL;
5668    }
5669
5670    // VH の作成
5671    v = ZeroMalloc(sizeof(VH));
5672    v->ref = NewRef();
5673    v->lock = NewLock();
5674    v->Counter = NewCounter();
5675
5676    v->nat = nat;
5677
5678    // オプションの設定
5679    SetVirtualHostOption(v, vh_option);
5680
5681    return v;
5682}
5683
5684// ランダムな MAC アドレスを生成する
5685void GenMacAddress(UCHAR *mac)
5686{
5687    UCHAR rand_data[32];
5688    UINT64 now;
5689    BUF *b;
5690    UCHAR hash[SHA1_SIZE];
5691    // 引数チェック
5692    if (mac == NULL)
5693    {
5694        return;
5695    }
5696
5697    // 現在時刻を取得
5698    now = SystemTime64();
5699
5700    // 乱数を生成
5701    Rand(rand_data, sizeof(rand_data));
5702
5703    // バッファに追加
5704    b = NewBuf();
5705    WriteBuf(b, &now, sizeof(now));
5706    WriteBuf(b, rand_data, sizeof(rand_data));
5707
5708    // ハッシュ
5709    Hash(hash, b->Buf, b->Size, true);
5710
5711    // MAC アドレスを生成
5712    mac[0] = 0x00;
5713    mac[1] = 0xAC;      // AC 万歳
5714    mac[2] = hash[0];
5715    mac[3] = hash[1];
5716    mac[4] = hash[2];
5717    mac[5] = hash[3];
5718
5719    FreeBuf(b);
5720}
5721
5722// 仮想ホストのパケットアダプタを取得
5723PACKET_ADAPTER *VirtualGetPacketAdapter()
5724{
5725    return NewPacketAdapter(VirtualPaInit, VirtualPaGetCancel,
5726        VirtualPaGetNextPacket, VirtualPaPutPacket, VirtualPaFree);
5727}
5728
5729
Note: See TracBrowser for help on using the repository browser.