source: azure_iot_hub/trunk/asp3_dcre/tinet/netinet6/icmp6.c@ 388

Last change on this file since 388 was 388, checked in by coas-nagasima, 5 years ago

Azure IoT Hub Device C SDK を使ったサンプルの追加

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
  • Property svn:mime-type set to text/x-csrc
File size: 22.3 KB
Line 
1/*
2 * TINET (TCP/IP Protocol Stack)
3 *
4 * Copyright (C) 2001-2017 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 388 2019-05-22 11:25:18Z 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#include "tinet_cfg.h"
121
122#endif /* of #ifdef TARGET_KERNEL_ASP */
123
124#ifdef TARGET_KERNEL_JSP
125
126#include <s_services.h>
127#include <t_services.h>
128#include "tinet_id.h"
129
130#endif /* of #ifdef TARGET_KERNEL_JSP */
131
132#include <tinet_defs.h>
133#include <tinet_config.h>
134
135#include <net/if.h>
136#include <net/if_loop.h>
137#include <net/if_ppp.h>
138#include <net/ethernet.h>
139#include <net/net.h>
140#include <net/net_endian.h>
141#include <net/net_buf.h>
142#include <net/net_timer.h>
143#include <net/net_count.h>
144
145#include <netinet/in.h>
146#include <netinet/in_var.h>
147#include <netinet/ip.h>
148#include <netinet/ip_var.h>
149#include <netinet/ip_icmp.h>
150#include <netinet/tcp.h>
151#include <netinet/tcp_var.h>
152#include <netinet/udp_var.h>
153
154#include <netinet6/nd6.h>
155
156#ifdef _IP6_CFG
157
158/*
159 * 変数
160 */
161
162#ifdef SUPPORT_MIB
163
164/*
165 * SNMP の 管理情
166報ベース (MIB)
167 */
168
169T_ICMP6_IFSTAT icmp6_ifstat;
170
171#endif /* of #ifdef SUPPORT_MIB */
172
173/*
174 * icmp6_output -- ICMP6 パケットを送信する。
175 */
176
177static void
178icmp6_output (T_NET_BUF *output, uint_t off)
179{
180 T_IN6_IFADDR *ia;
181 T_IFNET *ifp = IF_GET_IFNET();
182 T_IP6_HDR *ip6h;
183 T_ICMP6_HDR *icmp6h;
184
185 /*
186 * 宛å…
187ˆã‚¢ãƒ‰ãƒ¬ã‚¹ã«ãµã•ã‚ã—い送信å…
188ƒã‚¢ãƒ‰ãƒ¬ã‚¹ã‚’、
189 * ネットワークインタフェースから探索して利用する。
190 */
191 ip6h = GET_IP6_HDR(output);
192 if ((ia = in6_ifawithifp(ifp, &ip6h->dst)) == NULL) {
193 NET_COUNT_MIB(icmp6_ifstat.ipv6IfIcmpOutErrors, 1);
194 syscall(rel_net_buf(output));
195 return;
196 }
197 memcpy(&ip6h->src, &ia->addr, sizeof(T_IN6_ADDR));
198
199 icmp6h = GET_ICMP6_HDR(output, off);
200
201 /* チェックサムを計算する。*/
202 icmp6h->sum = 0;
203 icmp6h->sum = in6_cksum(output, IPPROTO_ICMPV6, (uint8_t*)icmp6h - output->buf,
204 ntohs(ip6h->plen) - (off - IF_IP6_HDR_SIZE));
205
206 /* 送信する。*/
207 NET_COUNT_ICMP6(net_count_icmp6[NC_ICMP6_OUT_OCTETS],
208 output->len - GET_IF_IP6_HDR_SIZE(output));
209 NET_COUNT_ICMP6(net_count_icmp6[NC_ICMP6_OUT_PACKETS], 1);
210 NET_COUNT_MIB(icmp6_ifstat.ipv6IfIcmpOutMsgs, 1);
211 ip6_output(output, 0, TMO_ICMP_OUTPUT);
212 }
213
214/*
215 * icmp6_echo_request -- エコー要求を受信したときの処理
216 */
217
218static void
219icmp6_echo_request (T_NET_BUF *input, uint_t off)
220{
221 T_IP6_HDR *ip6h;
222 T_ICMP6_HDR *icmp6h;
223 T_IFNET *ifp = IF_GET_IFNET();
224 T_IN6_IFADDR *ia;
225 T_IN6_ADDR dst;
226 uint_t diff;
227
228 NET_COUNT_MIB(icmp6_ifstat.ipv6IfIcmpInEchos, 1);
229
230 ip6h = GET_IP6_HDR(input);
231
232 /*
233 * IPv6 ヘッダと ICMPv6 ヘッダ間の拡張ヘッダを除去する。
234 */
235 diff = off - IF_IP6_HDR_SIZE;
236 if (diff > 0) {
237 /* ICMPv6 ヘッダを前に詰める。*/
238 memmove(input->buf + IF_IP6_HDR_SIZE, input->buf + off, input->len - off);
239 off = IF_IP6_HDR_SIZE;
240
241 /* ペイロード長を調整する。*/
242 ip6h->plen = htons(ntohs(ip6h->plen) - diff);
243 input->len -= diff;
244 }
245
246 icmp6h = GET_ICMP6_HDR(input, off);
247 if (icmp6h->code != 0) {
248 NET_COUNT_ICMP6(net_count_icmp6[NC_ICMP6_IN_ERR_PACKETS], 1);
249 syscall(rel_net_buf(input));
250 return;
251 }
252
253 /*
254 * メッセージの型をエコー要求 (128) から
255 * エコー応答 (129) に変更して送り返す。
256 */
257 icmp6h->type = ICMP6_ECHO_REPLY;
258
259 /* IPv6 ヘッダの発信å…
260ƒã‚¢ãƒ‰ãƒ¬ã‚¹ã¨å®›å…
261ˆã‚¢ãƒ‰ãƒ¬ã‚¹ã‚’å…
262¥æ›¿ãˆã‚‹ã€‚*/
263 memcpy(&dst, &ip6h->dst, sizeof(T_IN6_ADDR));
264 memcpy(&ip6h->dst, &ip6h->src, sizeof(T_IN6_ADDR));
265 memcpy(&ip6h->src, &dst, sizeof(T_IN6_ADDR));
266
267 /*
268 * å…
269ƒã®å®›å…
270ˆã‚¢ãƒ‰ãƒ¬ã‚¹ãŒãƒžãƒ«ãƒã‚­ãƒ£ã‚¹ãƒˆã®å ´åˆã¯ã€
271 * 宛å…
272ˆã‚¢ãƒ‰ãƒ¬ã‚¹ã«ãµã•ã‚ã—い送信å…
273ƒã‚¢ãƒ‰ãƒ¬ã‚¹ã‚’、
274 * ネットワークインタフェースから探索して利用する。
275 */
276 if (IN6_IS_ADDR_MULTICAST(&dst)) {
277 if ((ia = in6_ifawithifp(ifp, &ip6h->dst)) == NULL) {
278 syscall(rel_net_buf(input));
279 return;
280 }
281 else
282 memcpy(&ip6h->src, &ia->addr, sizeof(T_IN6_ADDR));
283 }
284
285 /* 次ヘッダとホップリミットを設定する。*/
286 ip6h->next = IPPROTO_ICMPV6;
287 ip6h->hlim = IP6_DEFTTL;
288
289 /* チェックサムを計算する。*/
290 icmp6h->sum = 0;
291 icmp6h->sum = in6_cksum(input, IPPROTO_ICMPV6, (uint8_t*)icmp6h - input->buf,
292 ntohs(ip6h->plen) - (off - IF_IP6_HDR_SIZE));
293
294 /* 送信する。*/
295 NET_COUNT_ICMP6(net_count_icmp6[NC_ICMP6_OUT_OCTETS],
296 input->len - GET_IF_IP6_HDR_SIZE(input));
297 NET_COUNT_ICMP6(net_count_icmp6[NC_ICMP6_OUT_PACKETS], 1);
298 NET_COUNT_MIB(icmp6_ifstat.ipv6IfIcmpOutMsgs, 1);
299 NET_COUNT_MIB(icmp6_ifstat.ipv6IfIcmpOutEchoReplies, 1);
300 ip6_output(input, 0, TMO_ICMP_OUTPUT);
301 }
302
303/*
304 * icmp6_notify_error -- エラーを通知する。
305 */
306
307static void
308icmp6_notify_error(T_NET_BUF *input, uint_t poff)
309{
310 T_ICMP6_HDR *icmp6h;
311 ER_UINT loff;
312 uint_t len, next;
313
314 len = input->len - poff;
315
316 /* データグラム長が ICMP6 ヘッダ長 + IP6 ヘッダ長以下なら何もしない。*/
317 if (len < ICMP6_HDR_SIZE + IP6_HDR_SIZE)
318 return;
319
320 icmp6h = GET_ICMP6_HDR(input, poff);
321
322 /* 最終ヘッダを探索する。*/
323 loff = ip6_lasthdr(input, poff + ICMP6_HDR_SIZE, IPPROTO_IPV6, &next);
324
325 /* 最終ヘッダが TCP/UDP のみ対応する。*/
326 if (loff >= 0 && (next == IPPROTO_TCP || next == IPPROTO_UDP)) {
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
332#if defined(SUPPORT_TCP)
333
334 if (next == IPPROTO_TCP)
335
336 tcp_notify(input, icmp6h->code == ICMP6_DST_UNREACH_NOPORT ? EV_CNNRF : EV_HURCH);
337
338#endif /* of #if defined(SUPPORT_TCP) */
339
340#if defined(SUPPORT_UDP) && TNUM_UDP6_CEPID > 0
341
342 if (next == IPPROTO_UDP)
343
344 udp6_notify(input, icmp6h->code == ICMP6_DST_UNREACH_NOPORT ? EV_CNNRF : EV_HURCH);
345
346#endif /* of #if defined(SUPPORT_UDP) && TNUM_UDP6_CEPID > 0 */
347
348 }
349 else
350 syslog(LOG_NOTICE, "[ICMP6] error code: %d.", icmp6h->code);
351 }
352
353#if NUM_IN6_HOSTCACHE_ENTRY > 0
354
355/*
356 * icmp6_mtudisc_update -- Path MTU を更新する。
357 */
358
359static void
360icmp6_mtudisc_update(T_NET_BUF *input, uint_t off, uint32_t mtu)
361{
362 T_IP6_HDR *pip6h;
363
364 pip6h = (T_IP6_HDR*)GET_ICMP6_SDU(input, off);
365
366 if (mtu < IP6_HDR_SIZE + sizeof(T_IP6_FRAG_HDR) + 8)
367 return;
368
369 if (mtu > IF_MTU)
370 return;
371
372 in6_hostcache_update(&pip6h->dst, mtu);
373 }
374
375#endif /* of #if NUM_IN6_HOSTCACHE_ENTRY > 0 */
376
377#if defined(NUM_IN6_REDIRECT_ROUTE_ENTRY)
378#if NUM_IN6_REDIRECT_ROUTE_ENTRY > 0
379
380/*
381 * icmp6_redirect_input -- 向け直しメッセージの処理
382 */
383
384static void
385icmp6_redirect_input (T_NET_BUF *input, uint_t off)
386{
387 T_IP6_HDR *ip6h;
388 const T_IN6_ADDR *gw;
389 T_ND_REDIRECT_HDR *rdh;
390 T_ND_OPT_HDR *opth;
391 T_IFNET *ifp = IF_GET_IFNET();
392 bool_t router, onlink;
393 uint_t lladdr_len = 0;
394 uint8_t *lladdr = NULL;
395 uint8_t nd_opt_off[ND_OPT_OFF_ARRAY_SIZE];
396
397 ip6h = GET_IP6_HDR(input);
398
399 /*
400 * IP ヘッダのチェック、以下の場合は破棄する。
401 * ・リンクローカル以外から送られてきたメッセージ
402 * ・ホップリミットが IPV6_MAXHLIM (255) 以外
403 */
404 if (!IN6_IS_ADDR_LINKLOCAL(&ip6h->src) || ip6h->hlim != IPV6_MAXHLIM)
405 goto err_ret;
406
407 rdh = (T_ND_REDIRECT_HDR *)(input->buf + off);
408
409 /* 向け直しの終点アドレスがマルチキャストアドレスの場合は破棄する。*/
410 if (IN6_IS_ADDR_MULTICAST(&rdh->dst))
411 goto err_ret;
412
413 /* ターゲットアドレスが経路表に登録されているかチェックする。*/
414 if ((gw = in6_rtalloc(ifp, &rdh->dst)) != NULL) {
415 /* GW アドレスと送信å…
416ƒã‚¢ãƒ‰ãƒ¬ã‚¹ãŒç•°ãªã£ã¦ã„れば破棄する。*/
417 if (!IN6_ARE_ADDR_EQUAL(gw, &ip6h->src))
418 goto err_ret;
419 }
420 else /* 経路表になければ破棄する。*/
421 goto err_ret;
422
423 router = onlink = false;
424
425 /*
426 * ターゲットアドレスがリンクローカルアドレスであれば、
427 * ターゲットはルータ
428 */
429 if (IN6_IS_ADDR_LINKLOCAL(&rdh->target))
430 router = true;
431
432 /*
433 * ターゲットアドレスと終点アドレスが同一であれば、オンリンク
434 */
435 if (IN6_ARE_ADDR_EQUAL(&rdh->target, &rdh->dst))
436 onlink = true;
437
438 /*
439 * ルータでも、オンリンクでもなければエラー
440 */
441 if (!router && !onlink)
442 goto err_ret;
443
444 /* 近隣探索オプションのオフセットを記録する。*/
445 if (nd6_options(nd_opt_off, input->buf + off + ND_REDIRECT_HDR_SIZE,
446 input->len - (off + ND_REDIRECT_HDR_SIZE)) != E_OK)
447 goto err_ret;
448
449 /* 近隣探索オプション (向け直しのルータのリンクアドレス) */
450 if (nd_opt_off[ND_OPT_OFF_ARRAY_IX(ND_OPT_TARGET_LINKADDR)]) {
451 opth = (T_ND_OPT_HDR *)((uint8_t *)(input->buf + off + ND_REDIRECT_HDR_SIZE) +
452 nd_opt_off[ND_OPT_OFF_ARRAY_IX(ND_OPT_TARGET_LINKADDR)] - 8);
453 /* 注意: オプションオフセットé…
454åˆ—には、オフセット + 8 が設定されている。*/
455 lladdr = (uint8_t *)(opth + 1);
456 lladdr_len = (opth->len << 3);
457 }
458
459 /*
460 * ネットワークインタフェースのアドレス長が一致しなければエラー
461 */
462 if (lladdr && lladdr_len != ((sizeof(T_IF_ADDR) + sizeof(T_ND_OPT_HDR) + 7) & ~7))
463 goto err_ret;
464
465 /* 向け直しのルータのリンクアドレスを近隣キャッシュに登録する。*/
466 nd6_cache_lladdr(ifp, &rdh->target, (T_IF_ADDR *)lladdr, ND_REDIRECT,
467 onlink ? ND_REDIRECT_ONLINK : ND_REDIRECT_ROUTER);
468
469 /* ルーティング表に登録する。*/
470 in6_rtredirect(&rdh->target, &rdh->dst, 128, IN_RTF_REDIRECT, TMO_IN_REDIRECT);
471
472 syscall(rel_net_buf(input));
473 return;
474
475err_ret:
476 NET_COUNT_ICMP6(net_count_nd6[NC_ICMP6_IN_ERR_PACKETS], 1);
477 syscall(rel_net_buf(input));
478 }
479
480#endif /* of #if NUM_IN6_REDIRECT_ROUTE_ENTRY > 0 */
481#endif /* of #if defined(NUM_IN6_REDIRECT_ROUTE_ENTRY) */
482
483/*
484 * icmp6_input -- ICMP6 のå…
485¥åŠ›é–¢æ•°
486 */
487
488uint_t
489icmp6_input (T_NET_BUF **inputp, uint_t *offp, uint_t *nextp)
490{
491 T_NET_BUF *input = *inputp;
492 T_IP6_HDR *ip6h;
493 T_ICMP6_HDR *icmp6h;
494 uint_t len, off = *offp;
495 uint8_t code;
496
497 NET_COUNT_ICMP6(net_count_icmp6[NC_ICMP6_IN_OCTETS],
498 input->len - GET_IF_IP6_HDR_SIZE(input));
499 NET_COUNT_ICMP6(net_count_icmp6[NC_ICMP6_IN_PACKETS], 1);
500 NET_COUNT_MIB(icmp6_ifstat.ipv6IfIcmpInMsgs, 1);
501
502 /* ICMP6 ヘッダの長さをチェックする。*/
503 len = input->len - off;
504 if (len < ICMP6_HDR_SIZE) {
505 NET_COUNT_ICMP6(net_count_icmp6[NC_ICMP6_IN_ERR_PACKETS], 1);
506 NET_COUNT_MIB(icmp6_ifstat.ipv6IfIcmpInErrors, 1);
507 goto buf_rel;
508 }
509
510 ip6h = GET_IP6_HDR(input);
511 icmp6h = GET_ICMP6_HDR(input, off);
512
513 /* チェックサムを計算する。*/
514 if ((in6_cksum(input, IPPROTO_ICMPV6, off, ntohs(ip6h->plen) - (off - IF_IP6_HDR_SIZE)) & 0xffff) != 0) {
515 NET_COUNT_ICMP6(net_count_icmp6[NC_ICMP6_IN_ERR_PACKETS], 1);
516 NET_COUNT_MIB(icmp6_ifstat.ipv6IfIcmpInErrors, 1);
517 goto buf_rel;
518 }
519
520 code = icmp6h->code;
521
522 /* メッセージの型により分岐する。*/
523 switch (icmp6h->type) {
524
525 case ICMP6_DST_UNREACH: /* 宛å…
526ˆåˆ°é”不可能 */
527 NET_COUNT_MIB(icmp6_ifstat.ipv6IfIcmpInDestUnreachs, 1);
528 icmp6_notify_error(input, off);
529 break;
530
531 case ICMP6_ECHO_REQUEST: /* エコー要求 */
532 icmp6_echo_request(input, off);
533 return IPPROTO_DONE;
534 break;
535
536 case ICMP6_ECHO_REPLY: /* エコー応答 */
537
538#ifdef ICMP_CFG_CALLBACK_ECHO_REPLY
539
540 icmp6_echo_reply(input, off);
541
542#endif /* of #ifdef ICMP_CFG_CALLBACK_ECHO_REPLY */
543
544 break;
545
546 case ND_ROUTER_ADVERT: /* ルータ通知 */
547 NET_COUNT_MIB(icmp6_ifstat.ipv6IfIcmpInRouterAdvertisements, 1);
548 if (code != 0 || len < ROUTER_ADVERT_HDR_SIZE)
549 goto buf_rel;
550 nd6_ra_input(input, off);
551 return IPPROTO_DONE;
552 break;
553
554 case ND_NEIGHBOR_SOLICIT: /* 近隣要請 */
555 NET_COUNT_MIB(icmp6_ifstat.ipv6IfIcmpInNeighborSolicits, 1);
556 if (code != 0 || len < NEIGHBOR_SOLICIT_HDR_SIZE)
557 goto buf_rel;
558 nd6_ns_input(input, off);
559 return IPPROTO_DONE;
560 break;
561
562 case ND_NEIGHBOR_ADVERT: /* 近隣通知 */
563 NET_COUNT_MIB(icmp6_ifstat.ipv6IfIcmpInNeighborAdvertisements, 1);
564 if (code != 0 || len < NEIGHBOR_ADVERT_HDR_SIZE)
565 goto buf_rel;
566 nd6_na_input(input, off);
567 return IPPROTO_DONE;
568 break;
569
570 case ND_REDIRECT: /* 向け直し */
571 NET_COUNT_MIB(icmp6_ifstat.ipv6IfIcmpInRedirects, 1);
572
573#if defined(NUM_IN6_REDIRECT_ROUTE_ENTRY)
574#if NUM_IN6_REDIRECT_ROUTE_ENTRY > 0
575
576 if (code != 0 || len < ND_REDIRECT_HDR_SIZE)
577 goto buf_rel;
578 icmp6_redirect_input(input, off);
579 return IPPROTO_DONE;
580
581#else /* of #if NUM_IN6_REDIRECT_ROUTE_ENTRY > 0 */
582
583 syslog(LOG_WARNING, "[ICMP6] redirect ignored.");
584
585#endif /* of #if NUM_IN6_REDIRECT_ROUTE_ENTRY > 0 */
586#else /* of #if defined(NUM_IN6_REDIRECT_ROUTE_ENTRY) */
587
588 syslog(LOG_WARNING, "[ICMP6] redirect ignored.");
589
590#endif /* of #if defined(NUM_IN6_REDIRECT_ROUTE_ENTRY) */
591
592 break;
593
594 case ICMP6_PACKET_TOO_BIG: /* パケットが大きすぎる。 */
595
596#if NUM_IN6_HOSTCACHE_ENTRY > 0
597
598 icmp6_mtudisc_update(input, off, ntohl(icmp6h->icmp6_mtu));
599
600#endif /* of #if NUM_IN6_HOSTCACHE_ENTRY > 0 */
601
602 NET_COUNT_MIB(icmp6_ifstat.ipv6IfIcmpInPktTooBigs, 1);
603 break;
604
605 case ICMP6_TIME_EXCEEDED: /* TTL を超
606過した。 */
607 NET_COUNT_MIB(icmp6_ifstat.ipv6IfIcmpInTimeExcds, 1);
608 break;
609
610 case ICMP6_PARAM_PROB: /* IPv6 ヘッダが不正。 */
611 NET_COUNT_MIB(icmp6_ifstat.ipv6IfIcmpInParmProblems, 1);
612 break;
613
614 case MLD_LISTENER_QUERY: /* マルチキャスト受信者
615ç…
616§ä¼š */
617 case MLD_LISTENER_REPORT: /* マルチキャスト受信者
618報告 */
619 case MLD_LISTENER_DONE: /* マルチキャスト受信者
620終了 */
621 case ND_ROUTER_SOLICIT: /* ルータ要請 */
622 case ICMP6_ROUTER_RENUMBERING: /* ルータ番号再設定 */
623 case ICMP6_FQDN_QUERY: /* FQDN ç…
624§ä¼š */
625 case ICMP6_FQDN_REPLY: /* FQDN 応答 */
626 syslog(LOG_INFO, "[ICMP6] unsupported type: %d.", icmp6h->type);
627 break;
628
629 default:
630 syslog(LOG_WARNING, "[ICMP6] unknown type: %d.", icmp6h->type);
631 NET_COUNT_ICMP6(net_count_icmp6[NC_ICMP6_IN_ERR_PACKETS], 1);
632 NET_COUNT_MIB(icmp6_ifstat.ipv6IfIcmpInErrors, 1);
633 break;
634 }
635
636buf_rel:
637 syscall(rel_net_buf(input));
638 return IPPROTO_DONE;
639 }
640
641/*
642 * icmp6_error -- ICMP6 エラー送信関数
643 */
644
645void
646icmp6_error (T_NET_BUF *input, uint8_t type, uint8_t code, uint32_t param)
647{
648 T_NET_BUF *output;
649 T_IP6_HDR *ip6h;
650 T_ICMP6_HDR *icmp6h;
651 ER_UINT off;
652 uint_t next, len;
653
654 ip6h = GET_IP6_HDR(input);
655
656 /*
657 * 宛å…
658ˆã‚¢ãƒ‰ãƒ¬ã‚¹ãŒã€ãƒžãƒ«ãƒã‚­ãƒ£ã‚¹ãƒˆã®å ´åˆã¯ã€
659 * 以下の条件以外のときは処理を行わない。
660 *
661 * ・データグラムが大きすぎる。
662 * ・IPv6 ヘッダの不正で、オプションが認識できない。
663 */
664 if (IN6_IS_ADDR_MULTICAST(&ip6h->dst) &&
665 !((type == ICMP6_PACKET_TOO_BIG) ||
666 (type == ICMP6_PARAM_PROB && code == ICMP6_PARAMPROB_OPTION)))
667 goto buf_rel;
668
669 /*
670 * 始点アドレスが、以下の場合は処理を行わない。
671 *
672 * ・無指定
673 * ・マルチキャスト
674 */
675 if (IN6_IS_ADDR_UNSPECIFIED(&ip6h->src) ||
676 IN6_IS_ADDR_MULTICAST (&ip6h->src))
677 goto buf_rel;
678
679 /* 最後のヘッダを探索する。*/
680 off = ip6_lasthdr(input, 0, IPPROTO_IPV6, &next);
681
682 /*
683 * タイプが、エラーか向け直しの ICMP6 パケットのエラーには返答しない。
684 */
685 if (off >= 0 && next == IPPROTO_ICMPV6) {
686 T_ICMP6_HDR *icmp6h;
687
688 if (input->len - off < ICMP6_HDR_SIZE)
689 goto buf_rel;
690
691 icmp6h = GET_ICMP6_HDR(input, off);
692 if (icmp6h->type < ICMP6_ECHO_REQUEST ||
693 icmp6h->type == ND_REDIRECT)
694 goto buf_rel;
695 }
696
697 /* DoS 攻撃に対する防御は未実装
698 */
699
700 /*
701 * 送り返すメッセージ長を、ICMPv6 の最大ペイロード長に調整する。
702 * IPV6_MMTU - (IP6_HDR_SIZE + ICMP6_HDR_SIZE)
703 */
704 if (input->len - IF_HDR_SIZE > IPV6_MMTU - (IP6_HDR_SIZE + ICMP6_HDR_SIZE))
705 len = IPV6_MMTU - (IP6_HDR_SIZE + ICMP6_HDR_SIZE);
706 else
707 len = input->len - IF_HDR_SIZE;
708
709 /* 送信用のネットワークバッファを獲得する。*/
710 if (in6_get_datagram(&output, len + ICMP6_HDR_SIZE, 0,
711 &ip6h->src, &in6_addr_unspecified,
712 IPPROTO_ICMPV6, IPV6_MAXHLIM,
713 NBA_SEARCH_ASCENT, TMO_ICMP_OUTPUT) != E_OK)
714 goto buf_rel;
715
716 /* ICMP6 ヘッダを設定する。*/
717 icmp6h = GET_ICMP6_HDR(output, IF_IP6_ICMP6_HDR_OFFSET);
718 icmp6h->type = type;
719 icmp6h->code = code;
720 icmp6h->icmp6_pptr = htonl(param);
721
722 /* エラーデータを設定する。*/
723 memcpy(GET_ICMP6_SDU(output, IF_IP6_ICMP6_HDR_OFFSET), (uint8_t *)ip6h, len);
724
725#ifdef SUPPORT_MIB
726
727 switch (type) {
728 case ICMP6_DST_UNREACH:
729 NET_COUNT_MIB(icmp6_ifstat.ipv6IfIcmpOutDestUnreachs, 1);
730 break;
731
732 case ICMP6_PARAM_PROB:
733 NET_COUNT_MIB(icmp6_ifstat.ipv6IfIcmpOutParmProblems, 1);
734 break;
735
736 default:
737 break;
738
739 }
740
741#endif /* of #ifdef SUPPORT_MIB */
742
743 /* 送信する。*/
744 icmp6_output(output, IF_IP6_HDR_SIZE);
745
746buf_rel:
747 syscall(rel_net_buf(input));
748 }
749
750#endif /* of #ifdef _IP6_CFG */
Note: See TracBrowser for help on using the repository browser.