source: lab.git/Dev/utvpn/utvpn-unix-v101-7101-public/src/Cedar/TcpIp.c @ 89fbc5d

trunk
Last change on this file since 89fbc5d 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: 40.3 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// TcpIp.c
79// TCP/IP プロトコル パケットアナライザ
80
81#include "CedarPch.h"
82
83// パケットに VLAN タグを埋め込む
84void VLanInsertTag(void **packet_data, UINT *packet_size, UINT vlan_id)
85{
86    UINT dest_size;
87    UCHAR *dest_data;
88    UINT src_size;
89    UCHAR *src_data;
90    USHORT vlan_ushort = Endian16(((USHORT)vlan_id) & 0xFFF);
91    // 引数チェック
92    if (packet_data == NULL || *packet_data == NULL || packet_size == NULL ||
93        *packet_size < 14 || vlan_id == 0)
94    {
95        return;
96    }
97
98    src_size = *packet_size;
99    src_data = (UCHAR *)(*packet_data);
100
101    dest_size = src_size + 4;
102    dest_data = Malloc(dest_size);
103
104    dest_data[12] = 0x81;
105    dest_data[13] = 0x00;
106    Copy(&dest_data[14], &vlan_ushort, sizeof(USHORT));
107
108    Copy(&dest_data[0], &src_data[0], 12);
109    Copy(&dest_data[16], &src_data[12], src_size - 12);
110
111    *packet_size = dest_size;
112    *packet_data = dest_data;
113
114    Free(src_data);
115}
116
117// パケットから VLAN タグを取り除く
118bool VLanRemoveTag(void **packet_data, UINT *packet_size, UINT vlan_id)
119{
120    bool has_vlan_tag = false;
121    UCHAR *src_data;
122    UINT src_size;
123    // 引数チェック
124    if (packet_data == NULL || *packet_data == NULL || packet_size == NULL ||
125        *packet_size < 14)
126    {
127        return false;
128    }
129
130    src_data = (UCHAR *)(*packet_data);
131    src_size = *packet_size;
132
133    if (src_data[12] == 0x81 && src_data[13] == 0x00)
134    {
135        if (src_size >= 18)
136        {
137            USHORT vlan_ushort;
138
139            vlan_ushort = Endian16(*((USHORT *)&src_data[14]));
140            vlan_ushort = vlan_ushort & 0xFFF;
141
142            if (vlan_id == 0 || (vlan_ushort == vlan_id))
143            {
144                UINT dest_size = src_size - 4;
145                UINT i;
146
147                for (i = 12;i < dest_size;i++)
148                {
149                    src_data[i] = src_data[i + 4];
150                }
151
152                *packet_size = dest_size;
153
154                return true;
155            }
156        }
157    }
158
159    return false;
160}
161
162// ICMPv6 パケットの送信
163BUF *BuildICMPv6(IPV6_ADDR *src_ip, IPV6_ADDR *dest_ip, UCHAR hop_limit, UCHAR type, UCHAR code, void *data, UINT size, UINT id)
164{
165    ICMP_HEADER *icmp;
166    void *data_buf;
167    BUF *ret;
168    // 引数チェック
169    if (src_ip == NULL || dest_ip == NULL || data == NULL)
170    {
171        return NULL;
172    }
173
174    // ヘッダの組み立て
175    icmp = ZeroMalloc(sizeof(ICMP_HEADER) + size);
176    data_buf = ((UCHAR *)icmp) + sizeof(ICMP_HEADER);
177    Copy(data_buf, data, size);
178
179    icmp->Type = type;
180    icmp->Code = code;
181    icmp->Checksum = CalcChecksumForIPv6(src_ip, dest_ip, IP_PROTO_ICMPV6, icmp,
182        sizeof(ICMP_HEADER) + size);
183
184    ret = BuildIPv6(dest_ip, src_ip, id, IP_PROTO_ICMPV6, hop_limit, icmp,
185        sizeof(ICMP_HEADER) + size);
186
187    Free(icmp);
188
189    return ret;
190}
191
192// ICMPv6 近隣要請パケットのビルド
193BUF *BuildICMPv6NeighborSoliciation(IPV6_ADDR *src_ip, IPV6_ADDR *target_ip, UCHAR *my_mac_address, UINT id)
194{
195    ICMPV6_OPTION_LIST opt;
196    ICMPV6_OPTION_LINK_LAYER link;
197    ICMPV6_NEIGHBOR_SOLICIATION_HEADER header;
198    BUF *b;
199    BUF *b2;
200    BUF *ret;
201    // 引数チェック
202    if (src_ip == NULL || target_ip == NULL || my_mac_address == NULL)
203    {
204        return NULL;
205    }
206
207    Zero(&link, sizeof(link));
208    Copy(link.Address, my_mac_address, 6);
209
210    Zero(&opt, sizeof(opt));
211    opt.SourceLinkLayer = &link;
212
213    b = BuildICMPv6Options(&opt);
214
215    Zero(&header, sizeof(header));
216    Copy(&header.TargetAddress, target_ip, sizeof(IPV6_ADDR));
217
218    b2 = NewBuf();
219
220    WriteBuf(b2, &header, sizeof(header));
221    WriteBufBuf(b2, b);
222
223    ret = BuildICMPv6(src_ip, target_ip, 255,
224        ICMPV6_TYPE_NEIGHBOR_SOLICIATION, 0, b2->Buf, b2->Size, id);
225
226    FreeBuf(b);
227    FreeBuf(b2);
228
229    return ret;
230}
231
232// キューから次のヘッダ番号を取得
233UCHAR IPv6GetNextHeaderFromQueue(QUEUE *q)
234{
235    UINT *p;
236    UCHAR v;
237    // 引数チェック
238    if (q == NULL)
239    {
240        return IPV6_HEADER_NONE;
241    }
242
243    p = (UINT *)GetNext(q);
244    v = (UCHAR)(*p);
245    Free(p);
246
247    return v;
248}
249
250// IPv6 拡張オプションヘッダ (可変長) の追加
251void BuildAndAddIPv6PacketOptionHeader(BUF *b, IPV6_OPTION_HEADER *opt, UCHAR next_header, UINT size)
252{
253    IPV6_OPTION_HEADER *h;
254    UINT total_size;
255    // 引数チェック
256    if (b == NULL || opt == NULL)
257    {
258        return;
259    }
260
261    total_size = size;
262    if ((total_size % 8) != 0)
263    {
264        total_size = ((total_size / 8) + 1) * 8;
265    }
266
267    h = ZeroMalloc(total_size);
268    Copy(h, opt, size);
269    h->Size = (total_size / 8) - 1;
270    h->NextHeader = next_header;
271
272    WriteBuf(b, h, total_size);
273
274    Free(h);
275}
276
277// IPv6 パケットのビルド
278BUF *BuildIPv6(IPV6_ADDR *dest_ip, IPV6_ADDR *src_ip, UINT id, UCHAR protocol, UCHAR hop_limit, void *data,
279               UINT size)
280{
281    IPV6_HEADER_PACKET_INFO info;
282    IPV6_HEADER ip_header;
283    BUF *buf;
284    UINT size_for_headers;
285    // 引数チェック
286    if (dest_ip == NULL || src_ip == NULL || data == NULL)
287    {
288        return NULL;
289    }
290    if (hop_limit == 0)
291    {
292        hop_limit = 255;
293    }
294
295    // IPv6 ヘッダ
296    Zero(&ip_header, sizeof(ip_header));
297    IPV6_SET_VERSION(&ip_header, 6);
298    ip_header.HopLimit = hop_limit;
299    Copy(&ip_header.SrcAddress, src_ip, sizeof(IPV6_ADDR));
300    Copy(&ip_header.DestAddress, dest_ip, sizeof(IPV6_ADDR));
301
302    // ヘッダパケット情報の整理
303    Zero(&info, sizeof(info));
304    info.IPv6Header = &ip_header;
305    info.Protocol = protocol;
306    info.Payload = data;
307    info.PayloadSize = size;
308
309    buf = BuildIPv6PacketHeader(&info, &size_for_headers);
310    if (buf == NULL)
311    {
312        return NULL;
313    }
314
315    return buf;
316}
317
318// IPv6 パケットヘッダ部のビルド
319BUF *BuildIPv6PacketHeader(IPV6_HEADER_PACKET_INFO *info, UINT *bytes_before_payload)
320{
321    BUF *b;
322    QUEUE *q;
323    UINT bbp = 0;
324    // 引数チェック
325    if (info == NULL)
326    {
327        return NULL;
328    }
329
330    b = NewBuf();
331    q = NewQueueFast();
332
333    // オプションヘッダの一覧を作成
334    if (info->HopHeader != NULL)
335    {
336        InsertQueueInt(q, IPV6_HEADER_HOP);
337    }
338    if (info->EndPointHeader != NULL)
339    {
340        InsertQueueInt(q, IPV6_HEADER_ENDPOINT);
341    }
342    if (info->RoutingHeader != NULL)
343    {
344        InsertQueueInt(q, IPV6_HEADER_ROUTING);
345    }
346    if (info->FragmentHeader != NULL)
347    {
348        InsertQueueInt(q, IPV6_HEADER_FRAGMENT);
349    }
350    InsertQueueInt(q, info->Protocol);
351
352    // IPv6 ヘッダ
353    info->IPv6Header->NextHeader = IPv6GetNextHeaderFromQueue(q);
354    WriteBuf(b, info->IPv6Header, sizeof(IPV6_HEADER));
355
356    // ホップバイホップオプションヘッダ
357    if (info->HopHeader != NULL)
358    {
359        BuildAndAddIPv6PacketOptionHeader(b, info->HopHeader,
360            IPv6GetNextHeaderFromQueue(q), info->HopHeaderSize);
361    }
362
363    // 終点オプションヘッダ
364    if (info->EndPointHeader != NULL)
365    {
366        BuildAndAddIPv6PacketOptionHeader(b, info->EndPointHeader,
367            IPv6GetNextHeaderFromQueue(q), info->EndPointHeaderSize);
368    }
369
370    // ルーティングヘッダ
371    if (info->RoutingHeader != NULL)
372    {
373        BuildAndAddIPv6PacketOptionHeader(b, info->RoutingHeader,
374            IPv6GetNextHeaderFromQueue(q), info->RoutingHeaderSize);
375    }
376
377    // フラグメントヘッダ
378    if (info->FragmentHeader != NULL)
379    {
380        info->FragmentHeader->NextHeader = IPv6GetNextHeaderFromQueue(q);
381        WriteBuf(b, info->FragmentHeader, sizeof(IPV6_FRAGMENT_HEADER));
382    }
383
384    bbp = b->Size;
385    if (info->FragmentHeader == NULL)
386    {
387        bbp += sizeof(IPV6_FRAGMENT_HEADER);
388    }
389
390    // ペイロード
391    if (info->Protocol != IPV6_HEADER_NONE)
392    {
393        WriteBuf(b, info->Payload, info->PayloadSize);
394    }
395
396    ReleaseQueue(q);
397
398    SeekBuf(b, 0, 0);
399
400    // ペイロード長さ
401    ((IPV6_HEADER *)b->Buf)->PayloadLength = Endian16(b->Size - (USHORT)sizeof(IPV6_HEADER));
402
403    if (bytes_before_payload != NULL)
404    {
405        // ペイロードの直前までの長さ (ただしフラグメントヘッダは必ず含まれると仮定)
406        // を計算する
407        *bytes_before_payload = bbp;
408    }
409
410    return b;
411}
412
413// ICMPv6 パケットのオプション値のビルド
414void BuildICMPv6OptionValue(BUF *b, UCHAR type, void *header_pointer, UINT total_size)
415{
416    UINT packet_size;
417    UCHAR *packet;
418    ICMPV6_OPTION *opt;
419    // 引数チェック
420    if (b == NULL || header_pointer == NULL)
421    {
422        return;
423    }
424
425    packet_size = ((total_size + 7) / 8) * 8;
426    packet = ZeroMalloc(packet_size);
427
428    Copy(packet, header_pointer, total_size);
429    opt = (ICMPV6_OPTION *)packet;
430    opt->Length = (UCHAR)(packet_size / 8);
431    opt->Type = type;
432
433    WriteBuf(b, packet, packet_size);
434
435    Free(packet);
436}
437
438// ICMPv6 パケットのオプションのビルド
439BUF *BuildICMPv6Options(ICMPV6_OPTION_LIST *o)
440{
441    BUF *b;
442    // 引数チェック
443    if (o == NULL)
444    {
445        return NULL;
446    }
447
448    b = NewBuf();
449
450    if (o->SourceLinkLayer != NULL)
451    {
452        BuildICMPv6OptionValue(b, ICMPV6_OPTION_TYPE_SOURCE_LINK_LAYER, o->SourceLinkLayer, sizeof(ICMPV6_OPTION_LINK_LAYER));
453    }
454    if (o->TargetLinkLayer != NULL)
455    {
456        BuildICMPv6OptionValue(b, ICMPV6_OPTION_TYPE_TARGET_LINK_LAYER, o->TargetLinkLayer, sizeof(ICMPV6_OPTION_LINK_LAYER));
457    }
458    if (o->Prefix != NULL)
459    {
460        BuildICMPv6OptionValue(b, ICMPV6_OPTION_TYPE_PREFIX, o->Prefix, sizeof(ICMPV6_OPTION_PREFIX));
461    }
462    if (o->Mtu != NULL)
463    {
464        BuildICMPv6OptionValue(b, ICMPV6_OPTION_TYPE_MTU, o->Mtu, sizeof(ICMPV6_OPTION_MTU));
465    }
466
467    SeekBuf(b, 0, 0);
468
469    return b;
470}
471
472// チェックサム計算
473USHORT CalcChecksumForIPv6(IPV6_ADDR *src_ip, IPV6_ADDR *dest_ip, UCHAR protocol, void *data, UINT size)
474{
475    UCHAR *tmp;
476    UINT tmp_size;
477    IPV6_PSEUDO_HEADER *ph;
478    USHORT ret;
479    // 引数チェック
480    if (data == NULL && size != 0)
481    {
482        return 0;
483    }
484
485    tmp_size = size + sizeof(IPV6_PSEUDO_HEADER);
486    tmp = ZeroMalloc(tmp_size);
487
488    ph = (IPV6_PSEUDO_HEADER *)tmp;
489    Copy(&ph->SrcAddress, src_ip, sizeof(IPV6_ADDR));
490    Copy(&ph->DestAddress, dest_ip, sizeof(IPV6_ADDR));
491    ph->UpperLayerPacketSize = Endian32(size);
492    ph->NextHeader = protocol;
493
494    Copy(((UCHAR *)tmp) + sizeof(IPV6_PSEUDO_HEADER), data, size);
495
496    ret = IpChecksum(tmp, tmp_size);
497
498    Free(tmp);
499
500    return ret;
501}
502
503// クローンされたパケットを解放する
504void FreeClonePacket(PKT *p)
505{
506    // 引数チェック
507    if (p == NULL)
508    {
509        return;
510    }
511
512    Free(p->IPv6HeaderPacketInfo.IPv6Header);
513    Free(p->IPv6HeaderPacketInfo.HopHeader);
514    Free(p->IPv6HeaderPacketInfo.EndPointHeader);
515    Free(p->IPv6HeaderPacketInfo.RoutingHeader);
516    Free(p->IPv6HeaderPacketInfo.FragmentHeader);
517    Free(p->IPv6HeaderPacketInfo.Payload);
518    Free(p->ICMPv6HeaderPacketInfo.Data);
519    Free(p->ICMPv6HeaderPacketInfo.EchoData);
520    Free(p->ICMPv6HeaderPacketInfo.Headers.HeaderPointer);
521    FreeCloneICMPv6Options(&p->ICMPv6HeaderPacketInfo.OptionList);
522    Free(p->L3.PointerL3);
523    Free(p->L4.PointerL4);
524    Free(p->L7.PointerL7);
525    Free(p->PacketData);
526    Free(p->MacHeader);
527    Free(p);
528}
529
530// パケットヘッダをコピーする
531PKT *ClonePacket(PKT *p, bool copy_data)
532{
533    PKT *ret;
534    // 引数チェック
535    if (p == NULL)
536    {
537        return NULL;
538    }
539
540    ret = ZeroMallocFast(sizeof(PKT));
541    ret->PacketSize = p->PacketSize;
542
543    // MAC ヘッダのコピー
544    ret->MacHeader = MallocFast(sizeof(MAC_HEADER));
545    Copy(ret->MacHeader, p->MacHeader, sizeof(MAC_HEADER));
546
547    // MAC フラグのコピー
548    ret->BroadcastPacket = p->BroadcastPacket;
549    ret->InvalidSourcePacket = p->InvalidSourcePacket;
550
551    // IPv6 関係構造体のコピー
552    Copy(&ret->IPv6HeaderPacketInfo, &p->IPv6HeaderPacketInfo, sizeof(IPV6_HEADER_PACKET_INFO));
553    Copy(&ret->ICMPv6HeaderPacketInfo, &p->ICMPv6HeaderPacketInfo, sizeof(ICMPV6_HEADER_INFO));
554
555    // Layer 3
556    ret->TypeL3 = p->TypeL3;
557    switch (ret->TypeL3)
558    {
559    case L3_ARPV4:
560        // ARP パケット
561        ret->L3.ARPv4Header = MallocFast(sizeof(ARPV4_HEADER));
562        Copy(ret->L3.ARPv4Header, p->L3.ARPv4Header, sizeof(ARPV4_HEADER));
563        break;
564
565    case L3_IPV4:
566        // IPv4 パケット
567        ret->L3.IPv4Header = MallocFast(sizeof(IPV4_HEADER));
568        Copy(ret->L3.IPv4Header, p->L3.IPv4Header, sizeof(IPV4_HEADER));
569        break;
570
571    case L3_IPV6:
572        // IPv6 パケット
573        ret->L3.IPv6Header = MallocFast(sizeof(IPV6_HEADER));
574        Copy(ret->L3.IPv6Header, p->L3.IPv6Header, sizeof(IPV6_HEADER));
575
576        ret->IPv6HeaderPacketInfo.IPv6Header = Clone(p->IPv6HeaderPacketInfo.IPv6Header,
577            sizeof(IPV6_HEADER));
578
579        ret->IPv6HeaderPacketInfo.HopHeader = Clone(p->IPv6HeaderPacketInfo.HopHeader,
580            sizeof(IPV6_OPTION_HEADER));
581
582        ret->IPv6HeaderPacketInfo.EndPointHeader = Clone(p->IPv6HeaderPacketInfo.EndPointHeader,
583            sizeof(IPV6_OPTION_HEADER));
584
585        ret->IPv6HeaderPacketInfo.RoutingHeader = Clone(p->IPv6HeaderPacketInfo.RoutingHeader,
586            sizeof(IPV6_OPTION_HEADER));
587
588        ret->IPv6HeaderPacketInfo.FragmentHeader = Clone(p->IPv6HeaderPacketInfo.FragmentHeader,
589            sizeof(IPV6_FRAGMENT_HEADER));
590
591        ret->IPv6HeaderPacketInfo.Payload = Clone(p->IPv6HeaderPacketInfo.Payload,
592            p->IPv6HeaderPacketInfo.PayloadSize);
593        break;
594    }
595
596    // Layer 4
597    ret->TypeL4 = p->TypeL4;
598    switch (ret->TypeL4)
599    {
600    case L4_ICMPV4:
601        // ICMPv4 パケット
602        ret->L4.ICMPHeader = MallocFast(sizeof(ICMP_HEADER));
603        Copy(ret->L4.ICMPHeader, p->L4.ICMPHeader, sizeof(ICMP_HEADER));
604        break;
605
606    case L4_ICMPV6:
607        // ICMPv6 パケット
608        ret->L4.ICMPHeader = MallocFast(sizeof(ICMP_HEADER));
609        Copy(ret->L4.ICMPHeader, p->L4.ICMPHeader, sizeof(ICMP_HEADER));
610
611        ret->ICMPv6HeaderPacketInfo.Data = Clone(p->ICMPv6HeaderPacketInfo.Data,
612            p->ICMPv6HeaderPacketInfo.DataSize);
613
614        ret->ICMPv6HeaderPacketInfo.EchoData = Clone(p->ICMPv6HeaderPacketInfo.EchoData,
615            p->ICMPv6HeaderPacketInfo.EchoDataSize);
616
617        switch (ret->ICMPv6HeaderPacketInfo.Type)
618        {
619        case ICMPV6_TYPE_ECHO_REQUEST:
620        case ICMPV6_TYPE_ECHO_RESPONSE:
621            break;
622
623        case ICMPV6_TYPE_ROUTER_SOLICIATION:
624            ret->ICMPv6HeaderPacketInfo.Headers.RouterSoliciationHeader =
625                Clone(p->ICMPv6HeaderPacketInfo.Headers.RouterSoliciationHeader,
626                sizeof(ICMPV6_ROUTER_SOLICIATION_HEADER));
627            break;
628
629        case ICMPV6_TYPE_ROUTER_ADVERTISEMENT:
630            ret->ICMPv6HeaderPacketInfo.Headers.RouterAdvertisementHeader =
631                Clone(p->ICMPv6HeaderPacketInfo.Headers.RouterAdvertisementHeader,
632                sizeof(ICMPV6_ROUTER_ADVERTISEMENT_HEADER));
633            break;
634
635        case ICMPV6_TYPE_NEIGHBOR_SOLICIATION:
636            ret->ICMPv6HeaderPacketInfo.Headers.NeighborSoliciationHeader =
637                Clone(p->ICMPv6HeaderPacketInfo.Headers.NeighborSoliciationHeader,
638                sizeof(ICMPV6_NEIGHBOR_SOLICIATION_HEADER));
639            break;
640
641        case ICMPV6_TYPE_NEIGHBOR_ADVERTISEMENT:
642            ret->ICMPv6HeaderPacketInfo.Headers.NeighborAdvertisementHeader =
643                Clone(p->ICMPv6HeaderPacketInfo.Headers.NeighborAdvertisementHeader,
644                sizeof(ICMPV6_NEIGHBOR_ADVERTISEMENT_HEADER));
645            break;
646        }
647
648        CloneICMPv6Options(&ret->ICMPv6HeaderPacketInfo.OptionList,
649            &p->ICMPv6HeaderPacketInfo.OptionList);
650        break;
651
652    case L4_TCP:
653        // TCP パケット
654        ret->L4.TCPHeader = MallocFast(sizeof(TCP_HEADER));
655        Copy(ret->L4.TCPHeader, p->L4.TCPHeader, sizeof(TCP_HEADER));
656        break;
657
658    case L4_UDP:
659        // UDP パケット
660        ret->L4.UDPHeader = MallocFast(sizeof(UDP_HEADER));
661        Copy(ret->L4.UDPHeader, p->L4.UDPHeader, sizeof(UDP_HEADER));
662        break;
663    }
664
665    // Layer 7
666    ret->TypeL7 = p->TypeL7;
667    switch (ret->TypeL7)
668    {
669    case L7_DHCPV4:
670        // DHCP パケット
671        ret->L7.DHCPv4Header = MallocFast(sizeof(DHCPV4_HEADER));
672        Copy(ret->L7.DHCPv4Header, p->L7.DHCPv4Header, sizeof(DHCPV4_HEADER));
673        break;
674    }
675
676    // アドレスデータ
677    ret->MacAddressSrc = ret->MacHeader->SrcAddress;
678    ret->MacAddressDest = ret->MacHeader->DestAddress;
679
680    if (copy_data)
681    {
682        // パケット本体もコピー
683        ret->PacketData = MallocFast(p->PacketSize);
684        Copy(ret->PacketData, p->PacketData, p->PacketSize);
685    }
686
687    return ret;
688}
689
690// パケットの中身をパースする
691PKT *ParsePacket(UCHAR *buf, UINT size)
692{
693    return ParsePacketEx(buf, size, false);
694}
695PKT *ParsePacketEx(UCHAR *buf, UINT size, bool no_l3)
696{
697    return ParsePacketEx2(buf, size, no_l3, 0);
698}
699PKT *ParsePacketEx2(UCHAR *buf, UINT size, bool no_l3, UINT vlan_type_id)
700{
701    return ParsePacketEx3(buf, size, no_l3, vlan_type_id, true);
702}
703PKT *ParsePacketEx3(UCHAR *buf, UINT size, bool no_l3, UINT vlan_type_id, bool bridge_id_as_mac_address)
704{
705    PKT *p;
706    // 引数チェック
707    if (buf == NULL || size == 0)
708    {
709        return NULL;
710    }
711
712    if (vlan_type_id == 0)
713    {
714        vlan_type_id = MAC_PROTO_TAGVLAN;
715    }
716
717    p = ZeroMallocFast(sizeof(PKT));
718
719    p->VlanTypeID = vlan_type_id;
720
721    // パース実行
722    if (ParsePacketL2Ex(p, buf, size, no_l3) == false)
723    {
724        // パース失敗
725        FreePacket(p);
726        return NULL;
727    }
728
729    p->PacketData = buf;
730    p->PacketSize = size;
731
732    p->MacAddressSrc = p->MacHeader->SrcAddress;
733    p->MacAddressDest = p->MacHeader->DestAddress;
734
735    if (bridge_id_as_mac_address)
736    {
737        if (p->TypeL3 == L3_BPDU)
738        {
739            if (p->L3.BpduHeader != NULL)
740            {
741                p->MacAddressSrc = p->L3.BpduHeader->BridgeMacAddress;
742            }
743        }
744    }
745
746    // パース成功
747    return p;
748}
749
750
751// Layer-2 パース
752bool ParsePacketL2(PKT *p, UCHAR *buf, UINT size)
753{
754    return ParsePacketL2Ex(p, buf, size, false);
755}
756bool ParsePacketL2Ex(PKT *p, UCHAR *buf, UINT size, bool no_l3)
757{
758    UINT i;
759    bool b1, b2;
760    USHORT type_id_16;
761    // 引数チェック
762    if (p == NULL || buf == NULL)
763    {
764        return false;
765    }
766
767    // サイズをチェック
768    if (size < sizeof(MAC_HEADER))
769    {
770        return false;
771    }
772
773    // MAC ヘッダ
774    p->MacHeader = (MAC_HEADER *)buf;
775
776    buf += sizeof(MAC_HEADER);
777    size -= sizeof(MAC_HEADER);
778
779    // MAC ヘッダの解析
780    p->BroadcastPacket = true;
781    b1 = true;
782    b2 = true;
783    for (i = 0;i < 6;i++)
784    {
785        if (p->MacHeader->DestAddress[i] != 0xff)
786        {
787            p->BroadcastPacket = false;
788        }
789        if (p->MacHeader->SrcAddress[i] != 0xff)
790        {
791            b1 = false;
792        }
793        if (p->MacHeader->SrcAddress[i] != 0x00)
794        {
795            b2 = false;
796        }
797    }
798    if (b1 || b2 || (Cmp(p->MacHeader->SrcAddress, p->MacHeader->DestAddress, 6) == 0))
799    {
800        p->InvalidSourcePacket = true;
801    }
802    else
803    {
804        p->InvalidSourcePacket = false;
805    }
806
807    if (p->MacHeader->DestAddress[0] & 0x01)
808    {
809        p->BroadcastPacket = true;
810    }
811
812    // L3 パケットのパース
813    type_id_16 = Endian16(p->MacHeader->Protocol);
814
815    if (type_id_16 > 1500)
816    {
817        // 通常の Ethernet フレーム
818        switch (type_id_16)
819        {
820        case MAC_PROTO_ARPV4:   // ARPv4
821            if (no_l3)
822            {
823                return true;
824            }
825
826            return ParsePacketARPv4(p, buf, size);
827
828        case MAC_PROTO_IPV4:    // IPv4
829            if (no_l3)
830            {
831                return true;
832            }
833
834            return ParsePacketIPv4(p, buf, size);
835
836        case MAC_PROTO_IPV6:    // IPv6
837            if (no_l3)
838            {
839                return true;
840            }
841
842            return ParsePacketIPv6(p, buf, size);
843
844        default:                // 不明
845            if (type_id_16 == p->VlanTypeID)
846            {
847                // VLAN
848                return ParsePacketTAGVLAN(p, buf, size);
849            }
850            else
851            {
852                return true;
853            }
854        }
855    }
856    else
857    {
858        // IEEE 802.3 の古い (パケットのペイロード長が書いてある) フレーム
859        // (BPDU 等で使われていることがある)
860        UINT length = (UINT)type_id_16;
861        LLC_HEADER *llc;
862
863        // 長さが残っているかどうかチェック
864        if (size < length || size < sizeof(LLC_HEADER))
865        {
866            return true;
867        }
868
869        // LLC ヘッダを読む
870        llc = (LLC_HEADER *)buf;
871        buf += sizeof(LLC_HEADER);
872        size -= sizeof(LLC_HEADER);
873
874        // DSAP, SSAP の値によってプロトコルを判定する
875        if (llc->Dsap == LLC_DSAP_BPDU && llc->Ssap == LLC_SSAP_BPDU)
876        {
877            // BPDU (Spanning Tree) である
878            return ParsePacketBPDU(p, buf, size);
879        }
880        else
881        {
882            // 不明なプロトコルである
883            return true;
884        }
885    }
886}
887
888// TAG VLAN パース
889bool ParsePacketTAGVLAN(PKT *p, UCHAR *buf, UINT size)
890{
891    USHORT vlan_ushort;
892    // 引数チェック
893    if (p == NULL || buf == NULL)
894    {
895        return false;
896    }
897
898    // サイズをチェック
899    if (size < sizeof(TAGVLAN_HEADER))
900    {
901        return false;
902    }
903
904    // TAG VLAN ヘッダ
905    p->L3.TagVlanHeader = (TAGVLAN_HEADER *)buf;
906    p->TypeL3 = L3_TAGVLAN;
907
908    buf += sizeof(TAGVLAN_HEADER);
909    size -= sizeof(TAGVLAN_HEADER);
910
911    vlan_ushort = Endian16(*((USHORT *)p->L3.TagVlanHeader->Data));
912    vlan_ushort = vlan_ushort & 0xFFF;
913
914    p->VlanId = vlan_ushort;
915
916    return true;
917}
918
919// BPDU パース
920bool ParsePacketBPDU(PKT *p, UCHAR *buf, UINT size)
921{
922    // 引数チェック
923    if (p == NULL || buf == NULL)
924    {
925        return false;
926    }
927
928    // サイズをチェック
929    if (size < sizeof(BPDU_HEADER))
930    {
931        return true;
932    }
933
934    // BPDU ヘッダ
935    p->L3.BpduHeader = (BPDU_HEADER *)buf;
936    p->TypeL3 = L3_BPDU;
937
938    buf += sizeof(BPDU_HEADER);
939    size -= sizeof(BPDU_HEADER);
940
941    return true;
942}
943
944// ARPv4 パース
945bool ParsePacketARPv4(PKT *p, UCHAR *buf, UINT size)
946{
947    // 引数チェック
948    if (p == NULL || buf == NULL)
949    {
950        return false;
951    }
952
953    // サイズをチェック
954    if (size < sizeof(ARPV4_HEADER))
955    {
956        return false;
957    }
958
959    // ARPv4 ヘッダ
960    p->L3.ARPv4Header = (ARPV4_HEADER *)buf;
961    p->TypeL3 = L3_ARPV4;
962
963    buf += sizeof(ARPV4_HEADER);
964    size -= sizeof(ARPV4_HEADER);
965
966    return true;
967}
968
969// IPv6 拡張ヘッダの解析
970bool ParseIPv6ExtHeader(IPV6_HEADER_PACKET_INFO *info, UCHAR next_header, UCHAR *buf, UINT size)
971{
972    bool ret = false;
973    IPV6_OPTION_HEADER *option_header;
974    UINT option_header_size;
975    UCHAR next_header_2 = IPV6_HEADER_NONE;
976    // 引数チェック
977    if (info == NULL || buf == NULL)
978    {
979        return false;
980    }
981
982    info->IsFragment = false;
983
984    while (true)
985    {
986        if (size > 8)
987        {
988            next_header_2 = *((UCHAR *)buf);
989        }
990
991        switch (next_header)
992        {
993        case IPV6_HEADER_HOP:
994        case IPV6_HEADER_ENDPOINT:
995        case IPV6_HEADER_ROUTING:
996            // 可変長ヘッダ
997            if (size < 8)
998            {
999                return false;
1000            }
1001
1002            option_header = (IPV6_OPTION_HEADER *)buf;
1003            option_header_size = (option_header->Size + 1) * 8;
1004            if (size < option_header_size)
1005            {
1006                return false;
1007            }
1008
1009            switch (next_header)
1010            {
1011            case IPV6_HEADER_HOP:
1012                info->HopHeader = (IPV6_OPTION_HEADER *)buf;
1013                info->HopHeaderSize = option_header_size;
1014                break;
1015
1016            case IPV6_HEADER_ENDPOINT:
1017                info->EndPointHeader = (IPV6_OPTION_HEADER *)buf;
1018                info->EndPointHeaderSize = option_header_size;
1019                break;
1020
1021            case IPV6_HEADER_ROUTING:
1022                info->RoutingHeader = (IPV6_OPTION_HEADER *)buf;
1023                info->RoutingHeaderSize = option_header_size;
1024                break;
1025            }
1026
1027            buf += option_header_size;
1028            size -= option_header_size;
1029            break;
1030
1031        case IPV6_HEADER_FRAGMENT:
1032            // フラグメントヘッダ (固定長)
1033            if (size < sizeof(IPV6_FRAGMENT_HEADER))
1034            {
1035                return false;
1036            }
1037
1038            info->FragmentHeader = (IPV6_FRAGMENT_HEADER *)buf;
1039
1040            if (IPV6_GET_FRAGMENT_OFFSET(info->FragmentHeader) != 0)
1041            {
1042                info->IsFragment = true;
1043            }
1044
1045            buf += sizeof(IPV6_FRAGMENT_HEADER);
1046            size -= sizeof(IPV6_FRAGMENT_HEADER);
1047            break;
1048
1049        default:
1050            // 後にペイロードが続くとみなす
1051            if (next_header != IPV6_HEADER_NONE)
1052            {
1053                info->Payload = buf;
1054                info->PayloadSize = size;
1055            }
1056            else
1057            {
1058                info->Payload = NULL;
1059                info->PayloadSize = 0;
1060            }
1061            info->Protocol = next_header;
1062            return true;
1063        }
1064
1065        next_header = next_header_2;
1066    }
1067}
1068
1069// IPv6 ヘッダの解析
1070bool ParsePacketIPv6Header(IPV6_HEADER_PACKET_INFO *info, UCHAR *buf, UINT size)
1071{
1072    // 引数チェック
1073    if (info == NULL || buf == NULL)
1074    {
1075        return false;
1076    }
1077
1078    Zero(info, sizeof(IPV6_HEADER_PACKET_INFO));
1079
1080    // IPv6 ヘッダ
1081    if (size < sizeof(IPV6_HEADER))
1082    {
1083        // サイズ不正
1084        return false;
1085    }
1086
1087    info->IPv6Header = (IPV6_HEADER *)buf;
1088    buf += sizeof(IPV6_HEADER);
1089    size -= sizeof(IPV6_HEADER);
1090
1091    if (IPV6_GET_VERSION(info->IPv6Header) != 6)
1092    {
1093        // バージョン不正
1094        return false;
1095    }
1096
1097    // 拡張ヘッダの解析
1098    return ParseIPv6ExtHeader(info, info->IPv6Header->NextHeader, buf, size);
1099}
1100
1101// ICMPv6 パケットのオプションの解析
1102bool ParseICMPv6Options(ICMPV6_OPTION_LIST *o, UCHAR *buf, UINT size)
1103{
1104    // 引数チェック
1105    if (o == NULL || buf == NULL)
1106    {
1107        return false;
1108    }
1109
1110    Zero(o, sizeof(ICMPV6_OPTION_LIST));
1111
1112    // ヘッダ部分の読み込み
1113    while (true)
1114    {
1115        ICMPV6_OPTION *option_header;
1116        UINT header_total_size;
1117        UCHAR *header_pointer;
1118        if (size < sizeof(ICMPV6_OPTION))
1119        {
1120            // サイズ不足
1121            return true;
1122        }
1123
1124        option_header = (ICMPV6_OPTION *)buf;
1125        // ヘッダ全体サイズの計算
1126        header_total_size = option_header->Length * 8;
1127        if (header_total_size == 0)
1128        {
1129            // サイズがゼロ
1130            return true;
1131        }
1132        if (size < header_total_size)
1133        {
1134            // サイズ不足
1135            return true;
1136        }
1137
1138        header_pointer = buf;
1139        buf += header_total_size;
1140        size -= header_total_size;
1141
1142        switch (option_header->Type)
1143        {
1144        case ICMPV6_OPTION_TYPE_SOURCE_LINK_LAYER:
1145        case ICMPV6_OPTION_TYPE_TARGET_LINK_LAYER:
1146            // ソース or ターゲットリンクレイヤオプション
1147            if (header_total_size >= sizeof(ICMPV6_OPTION_LINK_LAYER))
1148            {
1149                if (option_header->Type == ICMPV6_OPTION_TYPE_SOURCE_LINK_LAYER)
1150                {
1151                    o->SourceLinkLayer = (ICMPV6_OPTION_LINK_LAYER *)header_pointer;
1152                }
1153                else
1154                {
1155                    o->TargetLinkLayer = (ICMPV6_OPTION_LINK_LAYER *)header_pointer;
1156                }
1157            }
1158            else
1159            {
1160                // ICMPv6 パケット破損?
1161                return false;
1162            }
1163            break;
1164
1165        case ICMPV6_OPTION_TYPE_PREFIX:
1166            // プレフィックス情報
1167            if (header_total_size >= sizeof(ICMPV6_OPTION_PREFIX))
1168            {
1169                o->Prefix = (ICMPV6_OPTION_PREFIX *)header_pointer;
1170            }
1171            else
1172            {
1173                // ICMPv6 パケット破損?
1174            }
1175            break;
1176
1177        case ICMPV6_OPTION_TYPE_MTU:
1178            // MTU
1179            if (header_total_size >= sizeof(ICMPV6_OPTION_MTU))
1180            {
1181                o->Mtu = (ICMPV6_OPTION_MTU *)header_pointer;
1182            }
1183            else
1184            {
1185                // ICMPv6 パケット破損?
1186            }
1187            break;
1188        }
1189    }
1190}
1191
1192// ICMPv6 パース
1193bool ParseICMPv6(PKT *p, UCHAR *buf, UINT size)
1194{
1195    ICMPV6_HEADER_INFO icmp_info;
1196    ICMP_HEADER *icmp;
1197    ICMP_ECHO *echo;
1198    UINT msg_size;
1199    // 引数チェック
1200    if (p == NULL || buf == NULL)
1201    {
1202        return false;
1203    }
1204
1205    Zero(&icmp_info, sizeof(icmp_info));
1206
1207    if (size < sizeof(ICMP_HEADER))
1208    {
1209        return false;
1210    }
1211
1212    icmp = (ICMP_HEADER *)buf;
1213    p->L4.ICMPHeader = icmp;
1214
1215    msg_size = size - sizeof(ICMP_HEADER);
1216
1217    icmp_info.Type = icmp->Type;
1218    icmp_info.Code = icmp->Code;
1219    icmp_info.Data = ((UCHAR *)buf) + sizeof(ICMP_HEADER);
1220    icmp_info.DataSize = msg_size;
1221
1222    switch (icmp_info.Type)
1223    {
1224    case ICMPV6_TYPE_ECHO_REQUEST:
1225    case ICMPV6_TYPE_ECHO_RESPONSE:
1226        // ICMP Echo Request / Response
1227        if (icmp_info.DataSize < sizeof(ICMP_ECHO))
1228        {
1229            return false;
1230        }
1231
1232        echo = (ICMP_ECHO *)icmp_info.Data;
1233
1234        icmp_info.EchoHeader.Identifier = Endian16(echo->Identifier);
1235        icmp_info.EchoHeader.SeqNo = Endian16(echo->SeqNo);
1236        icmp_info.EchoData = (UCHAR *)echo + sizeof(ICMP_ECHO);
1237        icmp_info.EchoDataSize = icmp_info.DataSize - sizeof(ICMP_ECHO);
1238
1239        break;
1240
1241    case ICMPV6_TYPE_ROUTER_SOLICIATION:
1242        // ルータ要請
1243        if (icmp_info.DataSize < sizeof(ICMPV6_ROUTER_SOLICIATION_HEADER))
1244        {
1245            return false;
1246        }
1247
1248        icmp_info.Headers.RouterSoliciationHeader =
1249            (ICMPV6_ROUTER_SOLICIATION_HEADER *)(((UCHAR *)icmp_info.Data));
1250
1251        if (ParseICMPv6Options(&icmp_info.OptionList, ((UCHAR *)icmp_info.Headers.HeaderPointer) + sizeof(ICMPV6_ROUTER_SOLICIATION_HEADER),
1252            icmp_info.DataSize - sizeof(ICMPV6_ROUTER_SOLICIATION_HEADER)) == false)
1253        {
1254            return false;
1255        }
1256
1257        break;
1258
1259    case ICMPV6_TYPE_ROUTER_ADVERTISEMENT:
1260        // ルータ広告
1261        if (icmp_info.DataSize < sizeof(ICMPV6_ROUTER_ADVERTISEMENT_HEADER))
1262        {
1263            return false;
1264        }
1265
1266        icmp_info.Headers.RouterAdvertisementHeader =
1267            (ICMPV6_ROUTER_ADVERTISEMENT_HEADER *)(((UCHAR *)icmp_info.Data));
1268
1269        if (ParseICMPv6Options(&icmp_info.OptionList, ((UCHAR *)icmp_info.Headers.HeaderPointer) + sizeof(ICMPV6_ROUTER_ADVERTISEMENT_HEADER),
1270            icmp_info.DataSize - sizeof(ICMPV6_ROUTER_ADVERTISEMENT_HEADER)) == false)
1271        {
1272            return false;
1273        }
1274
1275        break;
1276
1277    case ICMPV6_TYPE_NEIGHBOR_SOLICIATION:
1278        // 近隣要請
1279        if (icmp_info.DataSize < sizeof(ICMPV6_NEIGHBOR_SOLICIATION_HEADER))
1280        {
1281            return false;
1282        }
1283
1284        icmp_info.Headers.NeighborSoliciationHeader =
1285            (ICMPV6_NEIGHBOR_SOLICIATION_HEADER *)(((UCHAR *)icmp_info.Data));
1286
1287        if (ParseICMPv6Options(&icmp_info.OptionList, ((UCHAR *)icmp_info.Headers.HeaderPointer) + sizeof(ICMPV6_NEIGHBOR_SOLICIATION_HEADER),
1288            icmp_info.DataSize - sizeof(ICMPV6_NEIGHBOR_SOLICIATION_HEADER)) == false)
1289        {
1290            return false;
1291        }
1292
1293        break;
1294
1295    case ICMPV6_TYPE_NEIGHBOR_ADVERTISEMENT:
1296        // 近隣広告
1297        if (icmp_info.DataSize < sizeof(ICMPV6_NEIGHBOR_ADVERTISEMENT_HEADER))
1298        {
1299            return false;
1300        }
1301
1302        icmp_info.Headers.NeighborAdvertisementHeader =
1303            (ICMPV6_NEIGHBOR_ADVERTISEMENT_HEADER *)(((UCHAR *)icmp_info.Data));
1304
1305        if (ParseICMPv6Options(&icmp_info.OptionList, ((UCHAR *)icmp_info.Headers.HeaderPointer) + sizeof(ICMPV6_NEIGHBOR_ADVERTISEMENT_HEADER),
1306            icmp_info.DataSize - sizeof(ICMPV6_NEIGHBOR_ADVERTISEMENT_HEADER)) == false)
1307        {
1308            return false;
1309        }
1310
1311        break;
1312    }
1313
1314    p->TypeL4 = L4_ICMPV6;
1315    Copy(&p->ICMPv6HeaderPacketInfo, &icmp_info, sizeof(ICMPV6_HEADER_INFO));
1316
1317    return true;
1318}
1319
1320// ICMPv6 オプションの解放
1321void FreeCloneICMPv6Options(ICMPV6_OPTION_LIST *o)
1322{
1323    // 引数チェック
1324    if (o == NULL)
1325    {
1326        return;
1327    }
1328
1329    Free(o->SourceLinkLayer);
1330    Free(o->TargetLinkLayer);
1331    Free(o->Prefix);
1332    Free(o->Mtu);
1333}
1334
1335// ICMPv6 オプションのクローン
1336void CloneICMPv6Options(ICMPV6_OPTION_LIST *dst, ICMPV6_OPTION_LIST *src)
1337{
1338    // 引数チェック
1339    if (dst == NULL || src == NULL)
1340    {
1341        return;
1342    }
1343
1344    Zero(dst, sizeof(ICMPV6_OPTION_LIST));
1345
1346    dst->SourceLinkLayer = Clone(src->SourceLinkLayer, sizeof(ICMPV6_OPTION_LINK_LAYER));
1347    dst->TargetLinkLayer = Clone(src->TargetLinkLayer, sizeof(ICMPV6_OPTION_LINK_LAYER));
1348    dst->Prefix = Clone(src->Prefix, sizeof(ICMPV6_OPTION_PREFIX));
1349    dst->Mtu = Clone(src->Mtu, sizeof(ICMPV6_OPTION_MTU));
1350}
1351
1352// IPv6 パース
1353bool ParsePacketIPv6(PKT *p, UCHAR *buf, UINT size)
1354{
1355    // 引数チェック
1356    if (p == NULL || buf == NULL)
1357    {
1358        return false;
1359    }
1360
1361    if (ParsePacketIPv6Header(&p->IPv6HeaderPacketInfo, buf, size) == false)
1362    {
1363        return false;
1364    }
1365
1366    p->TypeL3 = L3_IPV6;
1367    p->L3.IPv6Header = p->IPv6HeaderPacketInfo.IPv6Header;
1368
1369    if (p->IPv6HeaderPacketInfo.Payload == NULL)
1370    {
1371        // ペイロードなし
1372        return true;
1373    }
1374
1375    buf = p->IPv6HeaderPacketInfo.Payload;
1376    size = p->IPv6HeaderPacketInfo.PayloadSize;
1377
1378    if (p->IPv6HeaderPacketInfo.IsFragment)
1379    {
1380        // フラグメントパケットであるからこれ以上解釈しない
1381        p->TypeL4 = L4_FRAGMENT;
1382        return true;
1383    }
1384
1385    // L4 パケットのパース
1386    switch (p->IPv6HeaderPacketInfo.Protocol)
1387    {
1388    case IP_PROTO_ICMPV6:   // ICMPv6
1389        if (ParseICMPv6(p, buf, size) == false)
1390        {
1391            // ICMPv6 のパースに失敗しても true を返す
1392            return true;
1393        }
1394        else
1395        {
1396            return true;
1397        }
1398
1399    case IP_PROTO_TCP:      // TCP
1400        return ParseTCP(p, buf, size);
1401
1402    case IP_PROTO_UDP:      // UDP
1403        return ParseUDP(p, buf, size);
1404
1405    default:                // 不明
1406        return true;
1407    }
1408
1409    return true;
1410}
1411
1412// IPv4 パース
1413bool ParsePacketIPv4(PKT *p, UCHAR *buf, UINT size)
1414{
1415    UINT header_size;
1416    // 引数チェック
1417    if (p == NULL || buf == NULL)
1418    {
1419        return false;
1420    }
1421
1422    // サイズをチェック
1423    if (size < sizeof(IPV4_HEADER))
1424    {
1425        return false;
1426    }
1427
1428    // IPv4 ヘッダ
1429    p->L3.IPv4Header = (IPV4_HEADER *)buf;
1430    p->TypeL3 = L3_IPV4;
1431
1432    // ヘッダのチェック
1433    header_size = IPV4_GET_HEADER_LEN(p->L3.IPv4Header) * 4;
1434    if (header_size < sizeof(IPV4_HEADER) || size < header_size)
1435    {
1436        // ヘッダサイズが不正
1437        p->L3.IPv4Header = NULL;
1438        p->TypeL3= L3_UNKNOWN;
1439        return true;
1440    }
1441
1442    if (IPV4_GET_OFFSET(p->L3.IPv4Header) != 0)
1443    {
1444        // フラグメント化されているからこれ以上解析しない
1445        p->TypeL4 = L4_FRAGMENT;
1446        return true;
1447    }
1448
1449    buf += header_size;
1450    size -= header_size;
1451
1452    // L4 パケットのパース
1453    switch (p->L3.IPv4Header->Protocol)
1454    {
1455    case IP_PROTO_ICMPV4:   // ICMPv4
1456        return ParseICMPv4(p, buf, size);
1457
1458    case IP_PROTO_UDP:      // UDP
1459        return ParseUDP(p, buf, size);
1460
1461    case IP_PROTO_TCP:      // TCP
1462        return ParseTCP(p, buf, size);
1463
1464    default:                // 不明
1465        return true;
1466    }
1467}
1468
1469// ICMPv4 パース
1470bool ParseICMPv4(PKT *p, UCHAR *buf, UINT size)
1471{
1472    // 引数チェック
1473    if (p == NULL || buf == NULL)
1474    {
1475        return false;
1476    }
1477
1478    // サイズをチェック
1479    if (size < sizeof(ICMP_HEADER))
1480    {
1481        // サイズが不正
1482        return false;
1483    }
1484
1485    // ICMPv4 ヘッダ
1486    p->L4.ICMPHeader = (ICMP_HEADER *)buf;
1487    p->TypeL4 = L4_ICMPV4;
1488
1489    buf += sizeof(ICMP_HEADER);
1490    size -= sizeof(ICMP_HEADER);
1491
1492    return true;
1493}
1494
1495// TCP パース
1496bool ParseTCP(PKT *p, UCHAR *buf, UINT size)
1497{
1498    UINT header_size;
1499    // 引数チェック
1500    if (p == NULL || buf == NULL)
1501    {
1502        return false;
1503    }
1504
1505    // サイズをチェック
1506    if (size < sizeof(TCP_HEADER))
1507    {
1508        // サイズが不正
1509        return false;
1510    }
1511
1512    // TCP ヘッダ
1513    p->L4.TCPHeader = (TCP_HEADER *)buf;
1514    p->TypeL4 = L4_TCP;
1515
1516    // ヘッダサイズをチェック
1517    header_size = TCP_GET_HEADER_SIZE(p->L4.TCPHeader) * 4;
1518    if (header_size < sizeof(TCP_HEADER) || size < header_size)
1519    {
1520        // ヘッダサイズが不正
1521        p->L4.TCPHeader = NULL;
1522        p->TypeL4 = L4_UNKNOWN;
1523        return true;
1524    }
1525
1526    buf += header_size;
1527    size -= header_size;
1528
1529    return true;
1530}
1531
1532// UDP パース
1533bool ParseUDP(PKT *p, UCHAR *buf, UINT size)
1534{
1535    USHORT src_port, dst_port;
1536    // 引数チェック
1537    if (p == NULL || buf == NULL)
1538    {
1539        return false;
1540    }
1541
1542    // サイズをチェック
1543    if (size < sizeof(UDP_HEADER))
1544    {
1545        // サイズが不正
1546        return false;
1547    }
1548
1549    // UDP ヘッダ
1550    p->L4.UDPHeader = (UDP_HEADER *)buf;
1551    p->TypeL4 = L4_UDP;
1552
1553    buf += sizeof(UDP_HEADER);
1554    size -= sizeof(UDP_HEADER);
1555
1556    // ポート番号をチェック
1557    src_port = Endian16(p->L4.UDPHeader->SrcPort);
1558    dst_port = Endian16(p->L4.UDPHeader->DstPort);
1559
1560    if ((src_port == 67 && dst_port == 68) ||
1561        (src_port == 68 && dst_port == 67))
1562    {
1563        if (p->TypeL3 == L3_IPV4)
1564        {
1565            // DHCP パケットを発見
1566            ParseDHCPv4(p, buf, size);
1567        }
1568    }
1569
1570    return true;
1571}
1572
1573// DHCPv4 パース
1574void ParseDHCPv4(PKT *p, UCHAR *buf, UINT size)
1575{
1576    // 引数チェック
1577    if (p == NULL || buf == NULL)
1578    {
1579        return;
1580    }
1581
1582    // サイズをチェック
1583    if (size < sizeof(DHCPV4_HEADER))
1584    {
1585        // サイズが不正
1586        return;
1587    }
1588
1589    // DHCPv4 ヘッダ
1590    p->L7.DHCPv4Header = (DHCPV4_HEADER *)buf;
1591    p->TypeL7 = L7_DHCPV4;
1592}
1593
1594// パケットのメモリを解放する
1595void FreePacket(PKT *p)
1596{
1597    // 引数チェック
1598    if (p == NULL)
1599    {
1600        return;
1601    }
1602
1603    if (p->MacHeader != NULL)
1604    {
1605        switch (p->TypeL3)
1606        {
1607        case L3_IPV4:
1608            FreePacketIPv4(p);
1609            break;
1610
1611        case L3_ARPV4:
1612            FreePacketARPv4(p);
1613            break;
1614
1615        case L3_TAGVLAN:
1616            FreePacketTagVlan(p);
1617            break;
1618        }
1619    }
1620
1621    Free(p);
1622}
1623
1624// IPv4 パケットのメモリを解放する
1625void FreePacketIPv4(PKT *p)
1626{
1627    // 引数チェック
1628    if (p == NULL)
1629    {
1630        return;
1631    }
1632
1633    switch (p->TypeL4)
1634    {
1635    case L4_ICMPV4:
1636        FreePacketICMPv4(p);
1637        break;
1638
1639    case L4_TCP:
1640        FreePacketTCPv4(p);
1641        break;
1642
1643    case L4_UDP:
1644        FreePacketUDPv4(p);
1645        break;
1646    }
1647
1648    p->L3.IPv4Header = NULL;
1649    p->TypeL3 = L3_UNKNOWN;
1650}
1651
1652// タグ VLAN パケットのメモリを解放する
1653void FreePacketTagVlan(PKT *p)
1654{
1655    // 引数チェック
1656    if (p == NULL)
1657    {
1658        return;
1659    }
1660
1661    p->L3.TagVlanHeader = NULL;
1662    p->TypeL3 = L3_UNKNOWN;
1663}
1664
1665// ARPv4 パケットのメモリを解放する
1666void FreePacketARPv4(PKT *p)
1667{
1668    // 引数チェック
1669    if (p == NULL)
1670    {
1671        return;
1672    }
1673
1674    p->L3.ARPv4Header = NULL;
1675    p->TypeL3 = L3_UNKNOWN;
1676}
1677
1678// UDPv4 パケットのメモリを解放する
1679void FreePacketUDPv4(PKT *p)
1680{
1681    // 引数チェック
1682    if (p == NULL)
1683    {
1684        return;
1685    }
1686
1687    switch (p->TypeL7)
1688    {
1689    case L7_DHCPV4:
1690        FreePacketDHCPv4(p);
1691        break;
1692    }
1693
1694    p->L4.UDPHeader = NULL;
1695    p->TypeL4 = L4_UNKNOWN;
1696}
1697
1698// TCPv4 パケットのメモリを解放する
1699void FreePacketTCPv4(PKT *p)
1700{
1701    // 引数チェック
1702    if (p == NULL)
1703    {
1704        return;
1705    }
1706
1707    p->L4.TCPHeader = NULL;
1708    p->TypeL4 = L4_UNKNOWN;
1709}
1710
1711// ICMPv4 パケットのメモリを解放する
1712void FreePacketICMPv4(PKT *p)
1713{
1714    // 引数チェック
1715    if (p == NULL)
1716    {
1717        return;
1718    }
1719
1720    p->L4.ICMPHeader = NULL;
1721    p->TypeL4 = L4_UNKNOWN;
1722}
1723
1724// DHCPv4 パケットのメモリを解放する
1725void FreePacketDHCPv4(PKT *p)
1726{
1727    // 引数チェック
1728    if (p == NULL)
1729    {
1730        return;
1731    }
1732
1733    p->L7.DHCPv4Header = NULL;
1734    p->TypeL7 = L7_UNKNOWN;
1735}
1736
Note: See TracBrowser for help on using the repository browser.