source: EcnlProtoTool/trunk/asp3_dcre/tinet/netinet6/icmp6.c@ 286

Last change on this file since 286 was 270, checked in by coas-nagasima, 7 years ago

mruby版ECNLプロトタイピング・ツールを追加

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
  • Property svn:mime-type set to text/x-csrc
File size: 21.5 KB
Line 
1/*
2 * TINET (TCP/IP Protocol Stack)
3 *
4 * Copyright (C) 2001-2009 by Dep. of Computer Science and Engineering
5 * Tomakomai National College of Technology, JAPAN
6 *
7 * 上記著作権者
8は,以下の (1)~(4) の条件か,Free Software Foundation
9 * によってå…
10¬è¡¨ã•ã‚Œã¦ã„ã‚‹ GNU General Public License の Version 2 に記
11 * 述されている条件を満たす場合に限り,本ソフトウェア(本ソフトウェア
12 * を改変したものを含む.以下同じ)を使用・複製・改変・再é…
13å¸ƒï¼ˆä»¥ä¸‹ï¼Œ
14 * 利用と呼ぶ)することを無償で許諾する.
15 * (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
16 * 権表示,この利用条件および下記の無保証規定が,そのままの形でソー
17 * スコード中に含まれていること.
18 * (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
19 * 用できる形で再é…
20å¸ƒã™ã‚‹å ´åˆã«ã¯ï¼Œå†é…
21å¸ƒã«ä¼´ã†ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆï¼ˆåˆ©ç”¨
22 * 者
23マニュアルなど)に,上記の著作権表示,この利用条件および下記
24 * の無保証規定を掲載すること.
25 * (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
26 * 用できない形で再é…
27å¸ƒã™ã‚‹å ´åˆã«ã¯ï¼Œæ¬¡ã®æ¡ä»¶ã‚’満たすこと.
28 * (a) 再é…
29å¸ƒã«ä¼´ã†ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆï¼ˆåˆ©ç”¨è€…
30マニュアルなど)に,上記の著
31 * 作権表示,この利用条件および下記の無保証規定を掲載すること.
32 * (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
33 * 害からも,上記著作権者
34およびTOPPERSプロジェクトをå…
35è²¬ã™ã‚‹ã“と.
36 *
37 * 本ソフトウェアは,無保証で提供されているものである.上記著作権者
38お
39 * よびTOPPERSプロジェクトは,本ソフトウェアに関して,その適用可能性も
40 * 含めて,いかなる保証も行わない.また,本ソフトウェアの利用により直
41 * 接的または間接的に生じたいかなる損害に関しても,その責任を負わない.
42 *
43 * @(#) $Id: icmp6.c 270 2017-02-09 04:03:47Z coas-nagasima $
44 */
45
46/* $FreeBSD: src/sys/netinet6/icmp66.c,v 1.6.2.6 2001/07/10 09:44:16 ume Exp $ */
47/* $KAME: icmp66.c,v 1.211 2001/04/04 05:56:20 itojun Exp $ */
48
49/*
50 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
51 * All rights reserved.
52 *
53 * Redistribution and use in source and binary forms, with or without
54 * modification, are permitted provided that the following conditions
55 * are met:
56 * 1. Redistributions of source code must retain the above copyright
57 * notice, this list of conditions and the following disclaimer.
58 * 2. Redistributions in binary form must reproduce the above copyright
59 * notice, this list of conditions and the following disclaimer in the
60 * documentation and/or other materials provided with the distribution.
61 * 3. Neither the name of the project nor the names of its contributors
62 * may be used to endorse or promote products derived from this software
63 * without specific prior written permission.
64 *
65 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
66 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
67 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
68 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
69 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
70 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
71 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
72 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
73 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
74 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
75 * SUCH DAMAGE.
76 */
77
78/*
79 * Copyright (c) 1982, 1986, 1988, 1993
80 * The Regents of the University of California. All rights reserved.
81 *
82 * Redistribution and use in source and binary forms, with or without
83 * modification, are permitted provided that the following conditions
84 * are met:
85 * 1. Redistributions of source code must retain the above copyright
86 * notice, this list of conditions and the following disclaimer.
87 * 2. Redistributions in binary form must reproduce the above copyright
88 * notice, this list of conditions and the following disclaimer in the
89 * documentation and/or other materials provided with the distribution.
90 * 3. All advertising materials mentioning features or use of this software
91 * must display the following acknowledgement:
92 * This product includes software developed by the University of
93 * California, Berkeley and its contributors.
94 * 4. Neither the name of the University nor the names of its contributors
95 * may be used to endorse or promote products derived from this software
96 * without specific prior written permission.
97 *
98 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
99 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
100 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
101 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
102 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
103 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
104 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
105 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
106 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
107 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
108 * SUCH DAMAGE.
109 *
110 * @(#)ip_icmp6.c 8.2 (Berkeley) 1/4/94
111 */
112
113#include <string.h>
114
115#ifdef TARGET_KERNEL_ASP
116
117#include <kernel.h>
118#include <sil.h>
119#include <t_syslog.h>
120
121#endif /* of #ifdef TARGET_KERNEL_ASP */
122
123#ifdef TARGET_KERNEL_JSP
124
125#include <s_services.h>
126#include <t_services.h>
127
128#endif /* of #ifdef TARGET_KERNEL_JSP */
129
130#include <tinet_defs.h>
131#include <tinet_config.h>
132
133#include <net/if.h>
134#include <net/if_loop.h>
135#include <net/if_ppp.h>
136#include <net/ethernet.h>
137#include <net/net.h>
138#include <net/net_buf.h>
139#include <net/net_timer.h>
140#include <net/net_count.h>
141
142#include <netinet/in.h>
143#include <netinet/in_var.h>
144#include <netinet6/in6.h>
145#include <netinet6/in6_var.h>
146#include <netinet/ip6.h>
147#include <netinet6/ip6_var.h>
148#include <netinet/icmp6.h>
149#include <netinet6/nd6.h>
150#include <netinet/tcp.h>
151#include <netinet/tcp_timer.h>
152#include <netinet/tcp_var.h>
153
154#ifdef SUPPORT_INET6
155
156/*
157 * 変数
158 */
159
160#ifdef SUPPORT_MIB
161
162/*
163 * SNMP の 管理情
164報ベース (MIB)
165 */
166
167T_ICMP6_IFSTAT icmp6_ifstat;
168
169#endif /* of #ifdef SUPPORT_MIB */
170
171/*
172 * icmp6_output -- ICMP6 パケットを送信する。
173 */
174
175static void
176icmp6_output (T_NET_BUF *output, uint_t off)
177{
178 T_IN6_IFADDR *ia;
179 T_IFNET *ifp = IF_GET_IFNET();
180 T_IP6_HDR *ip6h;
181 T_ICMP6_HDR *icmp6h;
182
183 /*
184 * 宛å…
185ˆã‚¢ãƒ‰ãƒ¬ã‚¹ã«ãµã•ã‚ã—い送信å…
186ƒã‚¢ãƒ‰ãƒ¬ã‚¹ã‚’、
187 * ネットワークインタフェースから探索して利用する。
188 */
189 ip6h = GET_IP6_HDR(output);
190 if ((ia = in6_ifawithifp(ifp, &ip6h->dst)) == NULL) {
191 NET_COUNT_MIB(icmp6_ifstat.ipv6IfIcmpOutErrors, 1);
192 syscall(rel_net_buf(output));
193 return;
194 }
195 ip6h->src = ia->addr;
196
197 icmp6h = GET_ICMP6_HDR(output, off);
198
199 /* チェックサムを計算する。*/
200 icmp6h->sum = 0;
201 icmp6h->sum = in6_cksum(output, IPPROTO_ICMPV6, (uint8_t*)icmp6h - output->buf,
202 ntohs(ip6h->plen) - (off - IF_IP6_HDR_SIZE));
203
204 /* 送信する。*/
205 NET_COUNT_ICMP6(net_count_icmp6[NC_ICMP6_OUT_OCTETS],
206 output->len - GET_IF_IP6_HDR_SIZE(output));
207 NET_COUNT_ICMP6(net_count_icmp6[NC_ICMP6_OUT_PACKETS], 1);
208 NET_COUNT_MIB(icmp6_ifstat.ipv6IfIcmpOutMsgs, 1);
209 ip6_output(output, 0, TMO_ICMP_OUTPUT);
210 }
211
212/*
213 * icmp6_echo_request -- エコー要求を受信したときの処理
214 */
215
216static void
217icmp6_echo_request (T_NET_BUF *input, uint_t off)
218{
219 T_IP6_HDR *ip6h;
220 T_ICMP6_HDR *icmp6h;
221 T_IFNET *ifp = IF_GET_IFNET();
222 T_IN6_IFADDR *ia;
223 T_IN6_ADDR dst;
224 uint_t diff;
225
226 NET_COUNT_MIB(icmp6_ifstat.ipv6IfIcmpInEchos, 1);
227
228 ip6h = GET_IP6_HDR(input);
229
230 /*
231 * IPv6 ヘッダと ICMPv6 ヘッダ間の拡張ヘッダを除去する。
232 */
233 diff = off - IF_IP6_HDR_SIZE;
234 if (diff > 0) {
235 /* ICMPv6 ヘッダを前に詰める。*/
236 memmove(input->buf + IF_IP6_HDR_SIZE, input->buf + off, input->len - off);
237 off = IF_IP6_HDR_SIZE;
238
239 /* ペイロード長を調整する。*/
240 ip6h->plen = htons(ntohs(ip6h->plen) - diff);
241 input->len -= diff;
242 }
243
244 icmp6h = GET_ICMP6_HDR(input, off);
245 if (icmp6h->code != 0) {
246 NET_COUNT_ICMP6(net_count_icmp6[NC_ICMP6_IN_ERR_PACKETS], 1);
247 syscall(rel_net_buf(input));
248 return;
249 }
250
251 /*
252 * メッセージの型をエコー要求 (128) から
253 * エコー応答 (129) に変更して送り返す。
254 */
255 icmp6h->type = ICMP6_ECHO_REPLY;
256
257 /* IPv6 ヘッダの発信å…
258ƒã‚¢ãƒ‰ãƒ¬ã‚¹ã¨å®›å…
259ˆã‚¢ãƒ‰ãƒ¬ã‚¹ã‚’å…
260¥æ›¿ãˆã‚‹ã€‚*/
261 dst = ip6h->dst;
262 ip6h->dst = ip6h->src;
263 ip6h->src = dst;
264
265 /*
266 * å…
267ƒã®å®›å…
268ˆã‚¢ãƒ‰ãƒ¬ã‚¹ãŒãƒžãƒ«ãƒã‚­ãƒ£ã‚¹ãƒˆã®å ´åˆã¯ã€
269 * 宛å…
270ˆã‚¢ãƒ‰ãƒ¬ã‚¹ã«ãµã•ã‚ã—い送信å…
271ƒã‚¢ãƒ‰ãƒ¬ã‚¹ã‚’、
272 * ネットワークインタフェースから探索して利用する。
273 */
274 if (IN6_IS_ADDR_MULTICAST(&dst)) {
275 if ((ia = in6_ifawithifp(ifp, &ip6h->dst)) == NULL) {
276 syscall(rel_net_buf(input));
277 return;
278 }
279 else
280 ip6h->src = ia->addr;
281 }
282
283 /* 次ヘッダとホップリミットを設定する。*/
284 ip6h->next = IPPROTO_ICMPV6;
285 ip6h->hlim = IP_DEFTTL;
286
287 /* チェックサムを計算する。*/
288 icmp6h->sum = 0;
289 icmp6h->sum = in6_cksum(input, IPPROTO_ICMPV6, (uint8_t*)icmp6h - input->buf,
290 ntohs(ip6h->plen) - (off - IF_IP6_HDR_SIZE));
291
292 /* 送信する。*/
293 NET_COUNT_ICMP6(net_count_icmp6[NC_ICMP6_OUT_OCTETS],
294 input->len - GET_IF_IP6_HDR_SIZE(input));
295 NET_COUNT_ICMP6(net_count_icmp6[NC_ICMP6_OUT_PACKETS], 1);
296 NET_COUNT_MIB(icmp6_ifstat.ipv6IfIcmpOutMsgs, 1);
297 NET_COUNT_MIB(icmp6_ifstat.ipv6IfIcmpOutEchoReplies, 1);
298 ip6_output(input, 0, TMO_ICMP_OUTPUT);
299 }
300
301/*
302 * icmp6_notify_error -- エラーを通知する。
303 */
304
305static void
306icmp6_notify_error(T_NET_BUF *input, uint_t poff)
307{
308 T_ICMP6_HDR *icmp6h;
309 ER_UINT loff;
310 uint_t len, next;
311
312 len = input->len - poff;
313
314 /* データグラム長が ICMP6 ヘッダ長 + IP6 ヘッダ長以下なら何もしない。*/
315 if (len < ICMP6_HDR_SIZE + IP6_HDR_SIZE)
316 return;
317
318 icmp6h = GET_ICMP6_HDR(input, poff);
319
320 /* 最終ヘッダを探索する。*/
321 loff = ip6_lasthdr(input, poff + ICMP6_HDR_SIZE, IPPROTO_IPV6, &next);
322
323 /* 最終ヘッダが TCP のみ対応する。*/
324 if (loff >= 0 && next == IPPROTO_TCP) {
325
326#ifdef SUPPORT_TCP
327
328 memcpy(GET_IP6_HDR(input), input->buf + (loff + ICMP6_HDR_SIZE),
329 input->len - (loff + ICMP6_HDR_SIZE));
330 input->len -= loff + ICMP6_HDR_SIZE;
331 tcp_notify(input, icmp6h->code == ICMP6_DST_UNREACH_NOPORT ? EV_CNNRF : EV_HURCH);
332
333#endif /* of #ifdef SUPPORT_TCP */
334
335 }
336 else
337 syslog(LOG_NOTICE, "[ICMP6] error code: %d.", icmp6h->code);
338 }
339
340#if NUM_IN6_HOSTCACHE_ENTRY > 0
341
342/*
343 * icmp6_mtudisc_update -- Path MTU を更新する。
344 */
345
346static void
347icmp6_mtudisc_update(T_NET_BUF *input, uint_t off, uint32_t mtu)
348{
349 T_IP6_HDR *pip6h;
350
351 pip6h = (T_IP6_HDR*)GET_ICMP6_SDU(input, off);
352
353 if (mtu < IP6_HDR_SIZE + sizeof(T_IP6_FRAG_HDR) + 8)
354 return;
355
356 if (mtu > IF_MTU)
357 return;
358
359 in6_hostcache_update(&pip6h->dst, mtu);
360 }
361
362#endif /* of #if NUM_IN6_HOSTCACHE_ENTRY > 0 */
363
364#if NUM_REDIRECT_ROUTE_ENTRY > 0
365
366/*
367 * icmp6_redirect_input -- 向け直しメッセージの処理
368 */
369
370static void
371icmp6_redirect_input (T_NET_BUF *input, uint_t off)
372{
373 T_IP6_HDR *ip6h;
374 T_IN6_ADDR *gw;
375 T_ND_REDIRECT_HDR *rdh;
376 T_ND_OPT_HDR *opth;
377 T_IFNET *ifp = IF_GET_IFNET();
378 bool_t router, onlink;
379 uint_t lladdr_len = 0;
380 uint8_t *lladdr = NULL;
381 uint8_t nd_opt_off[ND_OPT_OFF_ARRAY_SIZE];
382
383 ip6h = GET_IP6_HDR(input);
384
385 /*
386 * IP ヘッダのチェック、以下の場合は破棄する。
387 * ・リンクローカル以外から送られてきたメッセージ
388 * ・ホップリミットが IPV6_MAXHLIM (255) 以外
389 */
390 if (!IN6_IS_ADDR_LINKLOCAL(&ip6h->src) || ip6h->hlim != IPV6_MAXHLIM)
391 goto err_ret;
392
393 rdh = (T_ND_REDIRECT_HDR *)(input->buf + off);
394
395 /* 向け直しの終点アドレスがマルチキャストアドレスの場合は破棄する。*/
396 if (IN6_IS_ADDR_MULTICAST(&rdh->dst))
397 goto err_ret;
398
399 /* ターゲットアドレスが経路表に登録されているかチェックする。*/
400 if ((gw = in6_rtalloc(ifp, &rdh->dst)) != NULL) {
401 /* GW アドレスと送信å…
402ƒã‚¢ãƒ‰ãƒ¬ã‚¹ãŒç•°ãªã£ã¦ã„れば破棄する。*/
403 if (!IN6_ARE_ADDR_EQUAL(gw, &ip6h->src))
404 goto err_ret;
405 }
406 else /* 経路表になければ破棄する。*/
407 goto err_ret;
408
409 router = onlink = false;
410
411 /*
412 * ターゲットアドレスがリンクローカルアドレスであれば、
413 * ターゲットはルータ
414 */
415 if (IN6_IS_ADDR_LINKLOCAL(&rdh->target))
416 router = true;
417
418 /*
419 * ターゲットアドレスと終点アドレスが同一であれば、オンリンク
420 */
421 if (IN6_ARE_ADDR_EQUAL(&rdh->target, &rdh->dst))
422 onlink = true;
423
424 /*
425 * ルータでも、オンリンクでもなければエラー
426 */
427 if (!router && !onlink)
428 goto err_ret;
429
430 /* 近隣探索オプションのオフセットを記録する。*/
431 if (nd6_options(nd_opt_off, input->buf + off + ND_REDIRECT_HDR_SIZE,
432 input->len - (off + ND_REDIRECT_HDR_SIZE)) != E_OK)
433 goto err_ret;
434
435 /* 近隣探索オプション (向け直しのルータのリンクアドレス) */
436 if (nd_opt_off[ND_OPT_OFF_ARRAY_IX(ND_OPT_TARGET_LINKADDR)]) {
437 opth = (T_ND_OPT_HDR *)((uint8_t *)(input->buf + off + ND_REDIRECT_HDR_SIZE) +
438 nd_opt_off[ND_OPT_OFF_ARRAY_IX(ND_OPT_TARGET_LINKADDR)] - 8);
439 /* 注意: オプションオフセットé…
440åˆ—には、オフセット + 8 が設定されている。*/
441 lladdr = (uint8_t *)(opth + 1);
442 lladdr_len = (opth->len << 3);
443 }
444
445 /*
446 * ネットワークインタフェースのアドレス長が一致しなければエラー
447 */
448 if (lladdr && lladdr_len != ((sizeof(T_IF_ADDR) + sizeof(T_ND_OPT_HDR) + 7) & ~7))
449 goto err_ret;
450
451 /* 向け直しのルータのリンクアドレスを近隣キャッシュに登録する。*/
452 nd6_cache_lladdr(ifp, &rdh->target, (T_IF_ADDR *)lladdr, ND_REDIRECT,
453 onlink ? ND_REDIRECT_ONLINK : ND_REDIRECT_ROUTER);
454
455 /* ルーティング表に登録する。*/
456 in6_rtredirect(&rdh->target, &rdh->dst, 128, IN_RTF_REDIRECT, TMO_IN_REDIRECT);
457
458 syscall(rel_net_buf(input));
459 return;
460
461err_ret:
462 NET_COUNT_ICMP6(net_count_nd6[NC_ICMP6_IN_ERR_PACKETS], 1);
463 syscall(rel_net_buf(input));
464 }
465
466#endif /* of #if NUM_REDIRECT_ROUTE_ENTRY > 0 */
467
468/*
469 * icmp6_input -- ICMP6 のå…
470¥åŠ›é–¢æ•°
471 */
472
473uint_t
474icmp6_input (T_NET_BUF **inputp, uint_t *offp, uint_t *nextp)
475{
476 T_NET_BUF *input = *inputp;
477 T_IP6_HDR *ip6h;
478 T_ICMP6_HDR *icmp6h;
479 uint_t len, off = *offp;
480 uint8_t code;
481
482 NET_COUNT_ICMP6(net_count_icmp6[NC_ICMP6_IN_OCTETS],
483 input->len - GET_IF_IP6_HDR_SIZE(input));
484 NET_COUNT_ICMP6(net_count_icmp6[NC_ICMP6_IN_PACKETS], 1);
485 NET_COUNT_MIB(icmp6_ifstat.ipv6IfIcmpInMsgs, 1);
486
487 /* ICMP6 ヘッダの長さをチェックする。*/
488 len = input->len - off;
489 if (len < ICMP6_HDR_SIZE) {
490 NET_COUNT_ICMP6(net_count_icmp6[NC_ICMP6_IN_ERR_PACKETS], 1);
491 NET_COUNT_MIB(icmp6_ifstat.ipv6IfIcmpInErrors, 1);
492 goto buf_rel;
493 }
494
495 ip6h = GET_IP6_HDR(input);
496 icmp6h = GET_ICMP6_HDR(input, off);
497
498 /* チェックサムを計算する。*/
499 if ((in6_cksum(input, IPPROTO_ICMPV6, off, ntohs(ip6h->plen) - (off - IF_IP_HDR_SIZE)) & 0xffff) != 0) {
500 NET_COUNT_ICMP6(net_count_icmp6[NC_ICMP6_IN_ERR_PACKETS], 1);
501 NET_COUNT_MIB(icmp6_ifstat.ipv6IfIcmpInErrors, 1);
502 goto buf_rel;
503 }
504
505 code = icmp6h->code;
506
507 /* メッセージの型により分岐する。*/
508 switch (icmp6h->type) {
509
510 case ICMP6_DST_UNREACH: /* 宛å…
511ˆåˆ°é”不可能 */
512 NET_COUNT_MIB(icmp6_ifstat.ipv6IfIcmpInDestUnreachs, 1);
513 icmp6_notify_error(input, off);
514 break;
515
516 case ICMP6_ECHO_REQUEST: /* エコー要求 */
517 icmp6_echo_request(input, off);
518 return IPPROTO_DONE;
519 break;
520
521 case ICMP6_ECHO_REPLY: /* エコー応答 */
522
523#ifdef ICMP_CFG_CALLBACK_ECHO_REPLY
524
525 icmp6_echo_reply(input, off);
526
527#endif /* of #ifdef ICMP_CFG_CALLBACK_ECHO_REPLY */
528
529 break;
530
531 case ND_ROUTER_ADVERT: /* ルータ通知 */
532 NET_COUNT_MIB(icmp6_ifstat.ipv6IfIcmpInRouterAdvertisements, 1);
533 if (code != 0 || len < ROUTER_ADVERT_HDR_SIZE)
534 goto buf_rel;
535 nd6_ra_input(input, off);
536 return IPPROTO_DONE;
537 break;
538
539 case ND_NEIGHBOR_SOLICIT: /* 近隣要請 */
540 NET_COUNT_MIB(icmp6_ifstat.ipv6IfIcmpInNeighborSolicits, 1);
541 if (code != 0 || len < NEIGHBOR_SOLICIT_HDR_SIZE)
542 goto buf_rel;
543 nd6_ns_input(input, off);
544 return IPPROTO_DONE;
545 break;
546
547 case ND_NEIGHBOR_ADVERT: /* 近隣通知 */
548 NET_COUNT_MIB(icmp6_ifstat.ipv6IfIcmpInNeighborAdvertisements, 1);
549 if (code != 0 || len < NEIGHBOR_ADVERT_HDR_SIZE)
550 goto buf_rel;
551 nd6_na_input(input, off);
552 return IPPROTO_DONE;
553 break;
554
555 case ND_REDIRECT: /* 向け直し */
556 NET_COUNT_MIB(icmp6_ifstat.ipv6IfIcmpInRedirects, 1);
557
558#if NUM_REDIRECT_ROUTE_ENTRY > 0
559
560 if (code != 0 || len < ND_REDIRECT_HDR_SIZE)
561 goto buf_rel;
562 icmp6_redirect_input(input, off);
563 return IPPROTO_DONE;
564
565#else /* of #if NUM_REDIRECT_ROUTE_ENTRY > 0 */
566
567 syslog(LOG_WARNING, "[ICMP6] redirect ignored.");
568
569#endif /* of #if NUM_REDIRECT_ROUTE_ENTRY > 0 */
570
571 break;
572
573 case ICMP6_PACKET_TOO_BIG: /* パケットが大きすぎる。 */
574
575#if NUM_IN6_HOSTCACHE_ENTRY > 0
576
577 icmp6_mtudisc_update(input, off, ntohl(icmp6h->icmp6_mtu));
578
579#endif /* of #if NUM_IN6_HOSTCACHE_ENTRY > 0 */
580
581 NET_COUNT_MIB(icmp6_ifstat.ipv6IfIcmpInPktTooBigs, 1);
582 break;
583
584 case ICMP6_TIME_EXCEEDED: /* TTL を超
585過した。 */
586 NET_COUNT_MIB(icmp6_ifstat.ipv6IfIcmpInTimeExcds, 1);
587 break;
588
589 case ICMP6_PARAM_PROB: /* IPv6 ヘッダが不正。 */
590 NET_COUNT_MIB(icmp6_ifstat.ipv6IfIcmpInParmProblems, 1);
591 break;
592
593 case MLD_LISTENER_QUERY: /* マルチキャスト受信者
594ç…
595§ä¼š */
596 case MLD_LISTENER_REPORT: /* マルチキャスト受信者
597報告 */
598 case MLD_LISTENER_DONE: /* マルチキャスト受信者
599終了 */
600 case ND_ROUTER_SOLICIT: /* ルータ要請 */
601 case ICMP6_ROUTER_RENUMBERING: /* ルータ番号再設定 */
602 case ICMP6_FQDN_QUERY: /* FQDN ç…
603§ä¼š */
604 case ICMP6_FQDN_REPLY: /* FQDN 応答 */
605 syslog(LOG_WARNING, "[ICMP6] unsupported type: %d.", icmp6h->type);
606 break;
607
608 default:
609 syslog(LOG_WARNING, "[ICMP6] unknown type: %d.", icmp6h->type);
610 NET_COUNT_ICMP6(net_count_icmp6[NC_ICMP6_IN_ERR_PACKETS], 1);
611 NET_COUNT_MIB(icmp6_ifstat.ipv6IfIcmpInErrors, 1);
612 break;
613 }
614
615buf_rel:
616 syscall(rel_net_buf(input));
617 return IPPROTO_DONE;
618 }
619
620/*
621 * icmp6_error -- ICMP6 エラー送信関数
622 */
623
624void
625icmp6_error (T_NET_BUF *input, uint8_t type, uint8_t code, uint32_t param)
626{
627 T_NET_BUF *output;
628 T_IP6_HDR *ip6h;
629 T_ICMP6_HDR *icmp6h;
630 ER_UINT off;
631 uint_t next, len;
632
633 ip6h = GET_IP6_HDR(input);
634
635 /*
636 * 宛å…
637ˆã‚¢ãƒ‰ãƒ¬ã‚¹ãŒã€ãƒžãƒ«ãƒã‚­ãƒ£ã‚¹ãƒˆã®å ´åˆã¯ã€
638 * 以下の条件以外のときは処理を行わない。
639 *
640 * ・データグラムが大きすぎる。
641 * ・IPv6 ヘッダの不正で、オプションが認識できない。
642 */
643 if (IN6_IS_ADDR_MULTICAST(&ip6h->dst) &&
644 !((type == ICMP6_PACKET_TOO_BIG) ||
645 (type == ICMP6_PARAM_PROB && code == ICMP6_PARAMPROB_OPTION)))
646 goto buf_rel;
647
648 /*
649 * 始点アドレスが、以下の場合は処理を行わない。
650 *
651 * ・無指定
652 * ・マルチキャスト
653 */
654 if (IN6_IS_ADDR_UNSPECIFIED(&ip6h->src) ||
655 IN6_IS_ADDR_MULTICAST (&ip6h->src))
656 goto buf_rel;
657
658 /* 最後のヘッダを探索する。*/
659 off = ip6_lasthdr(input, 0, IPPROTO_IPV6, &next);
660
661 /*
662 * タイプが、エラーか向け直しの ICMP6 パケットのエラーには返答しない。
663 */
664 if (off >= 0 && next == IPPROTO_ICMPV6) {
665 T_ICMP6_HDR *icmp6h;
666
667 if (input->len - off < ICMP6_HDR_SIZE)
668 goto buf_rel;
669
670 icmp6h = GET_ICMP6_HDR(input, off);
671 if (icmp6h->type < ICMP6_ECHO_REQUEST ||
672 icmp6h->type == ND_REDIRECT)
673 goto buf_rel;
674 }
675
676 /* DoS 攻撃に対する防御は未実装
677 */
678
679 /*
680 * 送り返すメッセージ長を、ICMPv6 の最大ペイロード長に調整する。
681 * IPV6_MMTU - (IP6_HDR_SIZE + ICMP6_HDR_SIZE)
682 */
683 if (input->len - IF_HDR_SIZE > IPV6_MMTU - (IP6_HDR_SIZE + ICMP6_HDR_SIZE))
684 len = IPV6_MMTU - (IP6_HDR_SIZE + ICMP6_HDR_SIZE);
685 else
686 len = input->len - IF_HDR_SIZE;
687
688 /* 送信用のネットワークバッファを獲得する。*/
689 if (in6_get_datagram(&output, len + ICMP6_HDR_SIZE, 0,
690 &ip6h->src, &in6_addr_unspecified,
691 IPPROTO_ICMPV6, IPV6_MAXHLIM,
692 NBA_SEARCH_ASCENT, TMO_ICMP_OUTPUT) != E_OK)
693 goto buf_rel;
694
695 /* ICMP6 ヘッダを設定する。*/
696 icmp6h = GET_ICMP6_HDR(output, IF_IP6_ICMP6_HDR_OFFSET);
697 icmp6h->type = type;
698 icmp6h->code = code;
699 icmp6h->icmp6_pptr = htonl(param);
700
701 /* エラーデータを設定する。*/
702 memcpy(GET_ICMP6_SDU(output, IF_IP6_ICMP6_HDR_OFFSET), (uint8_t *)ip6h, len);
703
704#ifdef SUPPORT_MIB
705
706 switch (type) {
707 case ICMP6_DST_UNREACH:
708 NET_COUNT_MIB(icmp6_ifstat.ipv6IfIcmpOutDestUnreachs, 1);
709 break;
710
711 case ICMP6_PARAM_PROB:
712 NET_COUNT_MIB(icmp6_ifstat.ipv6IfIcmpOutParmProblems, 1);
713 break;
714
715 default:
716 break;
717
718 }
719
720#endif /* of #ifdef SUPPORT_MIB */
721
722 /* 送信する。*/
723 icmp6_output(output, IF_IP6_HDR_SIZE);
724
725buf_rel:
726 syscall(rel_net_buf(input));
727 }
728
729#endif /* of #ifdef SUPPORT_INET6 */
Note: See TracBrowser for help on using the repository browser.