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