source: EcnlProtoTool/trunk/asp3_dcre/tinet/netinet6/ip6_input.c@ 321

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

文字コードを設定

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc;charset=UTF-8
File size: 19.8 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 * 上記著作権者は,以下の (1)~(4) の条件か,Free Software Foundation
8 * によって公表されている GNU General Public License の Version 2 に記
9 * 述されている条件を満たす場合に限り,本ソフトウェア(本ソフトウェア
10 * を改変したものを含む.以下同じ)を使用・複製・改変・再配布(以下,
11 * 利用と呼ぶ)することを無償で許諾する.
12 * (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
13 * 権表示,この利用条件および下記の無保証規定が,そのままの形でソー
14 * スコード中に含まれていること.
15 * (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
16 * 用できる形で再配布する場合には,再配布に伴うドキュメント(利用
17 * 者マニュアルなど)に,上記の著作権表示,この利用条件および下記
18 * の無保証規定を掲載すること.
19 * (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
20 * 用できない形で再配布する場合には,次の条件を満たすこと.
21 * (a) 再配布に伴うドキュメント(利用者マニュアルなど)に,上記の著
22 * 作権表示,この利用条件および下記の無保証規定を掲載すること.
23 * (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
24 * 害からも,上記著作権者およびTOPPERSプロジェクトを免責すること.
25 *
26 * 本ソフトウェアは,無保証で提供されているものである.上記著作権者お
27 * よびTOPPERSプロジェクトは,本ソフトウェアに関して,その適用可能性も
28 * 含めて,いかなる保証も行わない.また,本ソフトウェアの利用により直
29 * 接的または間接的に生じたいかなる損害に関しても,その責任を負わない.
30 *
31 * @(#) $Id$
32 */
33
34/* $FreeBSD: src/sys/netinet6/ip6_input.c,v 1.11.2.10 2001/07/24 19:10:18 brooks Exp $ */
35/* $KAME: ip6_input.c,v 1.194 2001/05/27 13:28:35 itojun Exp $ */
36
37/*
38 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
39 * All rights reserved.
40 *
41 * Redistribution and use in source and binary forms, with or without
42 * modification, are permitted provided that the following conditions
43 * are met:
44 * 1. Redistributions of source code must retain the above copyright
45 * notice, this list of conditions and the following disclaimer.
46 * 2. Redistributions in binary form must reproduce the above copyright
47 * notice, this list of conditions and the following disclaimer in the
48 * documentation and/or other materials provided with the distribution.
49 * 3. Neither the name of the project nor the names of its contributors
50 * may be used to endorse or promote products derived from this software
51 * without specific prior written permission.
52 *
53 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
54 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
55 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
56 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
57 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
58 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
59 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
60 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
61 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
62 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
63 * SUCH DAMAGE.
64 */
65
66/*
67 * Copyright (c) 1982, 1986, 1988, 1993
68 * The Regents of the University of California. All rights reserved.
69 *
70 * Redistribution and use in source and binary forms, with or without
71 * modification, are permitted provided that the following conditions
72 * are met:
73 * 1. Redistributions of source code must retain the above copyright
74 * notice, this list of conditions and the following disclaimer.
75 * 2. Redistributions in binary form must reproduce the above copyright
76 * notice, this list of conditions and the following disclaimer in the
77 * documentation and/or other materials provided with the distribution.
78 * 3. All advertising materials mentioning features or use of this software
79 * must display the following acknowledgement:
80 * This product includes software developed by the University of
81 * California, Berkeley and its contributors.
82 * 4. Neither the name of the University nor the names of its contributors
83 * may be used to endorse or promote products derived from this software
84 * without specific prior written permission.
85 *
86 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
87 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
88 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
89 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
90 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
91 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
92 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
93 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
94 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
95 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
96 * SUCH DAMAGE.
97 *
98 * @(#)ip_input.c 8.2 (Berkeley) 1/4/94
99 */
100
101#include <string.h>
102
103#ifdef TARGET_KERNEL_ASP
104
105#include <kernel.h>
106#include <sil.h>
107
108#endif /* of #ifdef TARGET_KERNEL_ASP */
109
110#ifdef TARGET_KERNEL_JSP
111
112#include <s_services.h>
113#include <t_services.h>
114
115#endif /* of #ifdef TARGET_KERNEL_JSP */
116
117#include <tinet_defs.h>
118#include <tinet_config.h>
119
120#include <net/if.h>
121#include <net/if_loop.h>
122#include <net/if_ppp.h>
123#include <net/ethernet.h>
124#include <net/ppp_ipcp.h>
125#include <net/net.h>
126#include <net/net_buf.h>
127#include <net/net_count.h>
128
129#include <netinet/in.h>
130#include <netinet6/in6.h>
131#include <netinet6/in6_var.h>
132#include <netinet6/nd6.h>
133#include <netinet/ip6.h>
134#include <netinet6/ip6_var.h>
135#include <netinet/icmp6.h>
136#include <netinet6/ah6.h>
137#include <netinet6/esp6.h>
138#include <netinet/tcp.h>
139#include <netinet/tcp_timer.h>
140#include <netinet/tcp_var.h>
141#include <netinet/udp_var.h>
142
143#include <net/if6_var.h>
144
145#ifdef SUPPORT_INET6
146
147/*
148 * 関数
149 */
150
151static uint_t ip6_no_header_input (T_NET_BUF **inputp, uint_t *offp, uint_t *nextp);
152
153/*
154 * 上位プロトコル選択構造体
155 */
156
157typedef struct t_proto_switch {
158 uint_t (*func)(T_NET_BUF **, uint_t *, uint_t *); /* 入力関数 */
159 uint_t proto; /* プロトコル番号 */
160 } T_PROTO_SWITCH;
161
162static const T_PROTO_SWITCH proto_switch[] = {
163 { esp6_input, IPPROTO_ESP }, /* IPv6 暗号化ヘッダ */
164 { ah6_input, IPPROTO_AH }, /* IPv6 認証ヘッダ */
165 { frag6_input, IPPROTO_FRAGMENT }, /* 断片ヘッダ */
166 { route6_input, IPPROTO_ROUTING }, /* 経路制御ヘッダ */
167 { dest6_input, IPPROTO_DSTOPTS }, /* IPv6 終点オプション */
168 { ip6_no_header_input,
169 IPPROTO_NONE }, /* 次ヘッダ無し */
170 { icmp6_input, IPPROTO_ICMPV6 },
171
172#ifdef SUPPORT_UDP
173
174 { udp_input, IPPROTO_UDP },
175
176#endif /* of #ifdef SUPPORT_UDP */
177
178#ifdef SUPPORT_TCP
179
180 { tcp_input, IPPROTO_TCP },
181
182#endif /* of #ifdef SUPPORT_TCP */
183
184 };
185
186#ifdef SUPPORT_MIB
187
188T_IN6_IFSTAT in6_ifstat;
189
190#endif /* of #ifdef SUPPORT_MIB */
191
192/*
193 * get_upper_proto -- 上位プロトコル処理関数を返す。
194 */
195
196static uint_t (*
197get_upper_proto(uint_t proto))(T_NET_BUF **, uint_t *, uint_t *)
198{
199 int_t ix;
200
201 for (ix = sizeof(proto_switch) / sizeof(T_PROTO_SWITCH); ix -- > 0; )
202 if (proto_switch[ix].proto == proto)
203 return proto_switch[ix].func;
204 return NULL;
205 }
206
207/*
208 * ip6_no_header_input -- 次ヘッダが無しの場合の入力処理
209 */
210
211static uint_t
212ip6_no_header_input (T_NET_BUF **input, uint_t *offp, uint_t *nextp)
213{
214 syscall(rel_net_buf(*input));
215 return IPPROTO_DONE;
216 }
217
218/*
219 * ip6_hopopts_input -- 中継点オプション入力処理
220 *
221 * 本実装では、パディング以外のオプションを全て未知オプションとして処理する。
222 *
223 * 戻り値:
224 *
225 * 0 以上 正常
226 * IP6_OPT_RET_ERR (-1) エラー、呼出側でネットワークバッファを開放する。
227 * IP6_OPT_RET_REL (-2) エラー、ネットワークバッファは開放されている。
228 */
229
230static ER_UINT
231ip6_hopopts_input (T_NET_BUF *input, uint_t *offp, uint_t *nextp)
232{
233 T_IP6_HBH_HDR *hbh;
234 ER_UINT optlen;
235 uint_t len;
236 uint8_t *opt;
237
238 hbh = (T_IP6_HBH_HDR *)(input->buf + *offp);
239 len = (hbh->len + 1) << 3;
240 *nextp = *offp - IF_HDR_SIZE + offsetof(T_IP6_HBH_HDR, next);
241 *offp += len;
242 opt = (uint8_t *)hbh + sizeof(T_IP6_HBH_HDR);
243
244 for (len -= sizeof(T_IP6_HBH_HDR); len > 0; len -= optlen) {
245 switch (*opt) {
246 case IP6OPT_PAD1:
247 optlen = 1;
248 break;
249 case IP6OPT_PADN:
250 if (len < IP6OPT_MINLEN)
251 return IP6_OPT_RET_ERR;
252 optlen = *(opt + 1) + 2;
253 break;
254 case IP6OPT_JUMBO:
255 case IP6OPT_NSAP_ADDR:
256 case IP6OPT_TUNNEL_LIMIT:
257 case IP6OPT_RTR_ALERT:
258 default:
259 if (len < IP6OPT_MINLEN)
260 return IP6_OPT_RET_ERR;
261 optlen = ip6_unknown_opt(input, opt);
262 if (optlen < 0)
263 return optlen;
264 optlen += 2;
265 break;
266 }
267
268 opt += optlen;
269 }
270
271 return *offp;
272 }
273
274/*
275 * ip6_get_prev_hdr -- 直前の拡張ヘッダの next フィールドのアドレスを返す。
276 *
277 * 注意: off には IF_HDR_SIZE も含まれている。
278 */
279
280uint8_t *
281ip6_get_prev_hdr (T_NET_BUF *nbuf, uint_t off)
282{
283 T_IP6_HDR *ip6h;
284 T_IP6_EXT_HDR *ip6eh;
285 uint_t len;
286 uint8_t next;
287
288 ip6h = GET_IP6_HDR(nbuf);
289 if (off == IF_HDR_SIZE + sizeof(T_IP6_HDR))
290 return &ip6h->next;
291 else {
292 next = ip6h->next;
293 len = IF_HDR_SIZE + sizeof(T_IP6_HDR);
294 ip6eh = NULL;
295
296 while (len < off) {
297 ip6eh = (T_IP6_EXT_HDR *)(nbuf->buf + len);
298
299 switch (next) {
300 case IPPROTO_FRAGMENT:
301 len += sizeof(T_IP6_FRAG_HDR);
302 break;
303 case IPPROTO_AH:
304 len += (ip6eh->len + 2) << 2;
305 break;
306 default:
307 len += (ip6eh->len + 2) << 3;
308 break;
309 }
310 next = ip6eh->next;
311 }
312
313 if (ip6eh == NULL)
314 return NULL;
315 else
316 return &ip6eh->next;
317 }
318 }
319
320/*
321 * ip6_init -- IPv6 の初期化関数
322 */
323
324void
325ip6_init (void)
326{
327 in6_init();
328 in6_ifainit();
329 }
330
331/*
332 * ip6_input -- IPv6 の入力関数
333 */
334
335void
336ip6_input (T_NET_BUF *input)
337{
338 T_IP6_HDR *ip6h;
339 T_IN6_IFADDR *ia6;
340 T_IFNET *ifp;
341 ER_UINT noff;
342 uint_t next, nest, plen, offp, nextp;
343 uint_t (*func)(T_NET_BUF **, uint_t *, uint_t *);
344
345 NET_COUNT_IP6(net_count_ip6[NC_IP6_IN_OCTETS], input->len - IF_HDR_SIZE);
346 NET_COUNT_IP6(net_count_ip6[NC_IP6_IN_PACKETS], 1);
347 NET_COUNT_MIB(in6_ifstat.ipv6IfStatsInReceives, 1);
348
349 /* IP ヘッダの長さをチェックする。*/
350 if (input->len < IF_IP6_HDR_SIZE) {
351 NET_COUNT_IP6(net_count_ip6[NC_IP6_IN_ERR_SHORT], 1);
352 NET_COUNT_MIB(in6_ifstat.ipv6IfStatsInHdrErrors, 1);
353 goto buf_rel;
354 }
355
356 ip6h = GET_IP6_HDR(input);
357
358 /* バージョンをチェックする。*/
359 if (IP6_VCF_V(ntohl(ip6h->vcf)) != IPV6_VERSION) {
360 NET_COUNT_IP6(net_count_ip6[NC_IP6_IN_ERR_VER], 1);
361 NET_COUNT_MIB(in6_ifstat.ipv6IfStatsInHdrErrors, 1);
362 goto buf_rel;
363 }
364
365 /*
366 * 次のデータグラムは破棄する。
367 *
368 * ・始点アドレスがマルチキャスト
369 * ・終点アドレスが未定義
370 *
371 * ネットワークインタフェースがループバックでないとき、
372 * 次のデータグラムも破棄する。
373 *
374 * ・始点アドレスがループバック
375 * ・終点アドレスがループバック
376 *
377 * 悪意のあるユーザが TCP/UDP スタックの混乱や
378 * セキュリティチェックをバイパスするため、IPv4
379 * マップアドレスを悪用することを防ぐため
380 * 以下のデータグラムは破棄する。
381 *
382 * ・始点アドレスが ::ffff:127.0.0.1
383 * ・終点アドレスが ::ffff:127.0.0.1
384 */
385
386 if (IN6_IS_ADDR_MULTICAST(&ip6h->src) ||
387 IN6_IS_ADDR_UNSPECIFIED(&ip6h->dst)) {
388 NET_COUNT_IP6(net_count_ip6[NC_IP6_IN_ERR_ADDR], 1);
389 NET_COUNT_MIB(in6_ifstat.ipv6IfStatsInAddrErrors, 1);
390 goto buf_rel;
391 }
392
393 if (IN6_IS_ADDR_V4MAPPED(&ip6h->src) ||
394 IN6_IS_ADDR_V4MAPPED(&ip6h->dst)) {
395 NET_COUNT_IP6(net_count_ip6[NC_IP6_IN_ERR_ADDR], 1);
396 NET_COUNT_MIB(in6_ifstat.ipv6IfStatsInAddrErrors, 1);
397 goto buf_rel;
398 }
399
400#ifdef SUPPORT_LOOP
401
402#else /* of #ifdef SUPPORT_LOOP */
403
404 if (IN6_IS_ADDR_LOOPBACK(&ip6h->src) ||
405 IN6_IS_ADDR_LOOPBACK(&ip6h->dst)) {
406 NET_COUNT_IP6(net_count_ip6[NC_IP6_IN_ERR_ADDR], 1);
407 NET_COUNT_MIB(in6_ifstat.ipv6IfStatsInAddrErrors, 1);
408 goto buf_rel;
409 }
410
411#endif /* of #ifdef SUPPORT_LOOP */
412
413 ifp = IF_GET_IFNET();
414
415 if (IN6_IS_ADDR_MULTICAST(&ip6h->dst)) {
416 /* 宛先がマルチキャストの場合の処理 */
417 NET_COUNT_MIB(in6_ifstat.ipv6IfStatsInMcastPkts, 1);
418 if (!in6_lookup_multi(ifp, &ip6h->dst)) {
419 NET_COUNT_IP6(net_count_ip6[NC_IP6_IN_ERR_ADDR], 1);
420 NET_COUNT_MIB(in6_ifstat.ipv6IfStatsInAddrErrors, 1);
421 goto buf_rel;
422 }
423 }
424 else {
425 if ((ia6 = in6_lookup_ifaddr(ifp, &ip6h->dst)) == NULL) {
426 NET_COUNT_IP6(net_count_ip6[NC_IP6_IN_ERR_ADDR], 1);
427 NET_COUNT_MIB(in6_ifstat.ipv6IfStatsInAddrErrors, 1);
428 goto buf_rel;
429 }
430
431 /* アドレスが未解決の場合はデータグラムを破棄する。*/
432 if (IFA6_IS_NOTREADY(ia6)) {
433 NET_COUNT_IP6(net_count_ip6[NC_IP6_IN_ERR_ADDR], 1);
434 NET_COUNT_MIB(in6_ifstat.ipv6IfStatsInAddrErrors, 1);
435 goto buf_rel;
436 }
437 }
438
439 /* オフセットを設定する。*/
440 offp = GET_IP6_NEXT_HDR(input) - input->buf;
441
442 /* ペイロード長を取り出す。*/
443 plen = ntohs(ip6h->plen);
444
445
446 /* 次ヘッダの位置を初期化する。*/
447 nextp = offsetof(T_IP6_HDR, next);
448
449 /*
450 * 中継点 (Hop-by-Hop) オプションヘッダのチェック
451 */
452 if (ip6h->next == IPPROTO_HOPOPTS) {
453
454 /* 中継点ヘッダの長さをチェックする。*/
455 if (plen < sizeof(T_IP6_HBH_HDR)) {
456 NET_COUNT_IP6(net_count_ip6[NC_IP6_IN_ERR_SHORT], 1);
457 NET_COUNT_MIB(in6_ifstat.ipv6IfStatsInHdrErrors, 1);
458 goto buf_rel;
459 }
460
461 if ((noff = ip6_hopopts_input(input, &offp, &nextp)) < 0) {
462 if (noff == IP6_OPT_RET_ERR) {
463 NET_COUNT_IP6(net_count_ip6[NC_IP6_IN_ERR_PACKETS], 1);
464 NET_COUNT_MIB(in6_ifstat.ipv6IfStatsInHdrErrors, 1);
465 goto buf_rel;
466 }
467 else if (noff == IP6_OPT_RET_REL) {
468 NET_COUNT_IP6(net_count_ip6[NC_IP6_IN_ERR_PACKETS], 1);
469 NET_COUNT_MIB(in6_ifstat.ipv6IfStatsInHdrErrors, 1);
470 return;
471 }
472 }
473
474 /*
475 * ペイロード長が 0 で、中継点オプションがあるときは、
476 * 巨大ペイロード・オプションが含まれなければならない。
477 * このとき、巨大ペイロード・オプションにある
478 * ペイロード長をチェックする必要があるが、本実装では、
479 * 巨大ペイロード・オプションを未知のオプションとして
480 * 扱うので、何もしない。
481 */
482 next = ((T_IP6_HBH_HDR *)(ip6h + 1))->next;
483 }
484 else
485 next = ip6h->next;
486
487 /* IPv6 データグラム長をチェックする。*/
488 if (input->len - IF_IP6_HDR_SIZE < plen) {
489 NET_COUNT_IP6(net_count_ip6[NC_IP6_IN_ERR_SHORT], 1);
490 NET_COUNT_MIB(in6_ifstat.ipv6IfStatsInTruncatedPkts, 1);
491 goto buf_rel;
492 }
493 else if (input->len > IF_IP6_HDR_SIZE + plen)
494 input->len = IF_IP6_HDR_SIZE + plen;
495
496 /* 上位プロトコル処理関数を呼び出す。*/
497 nest = 0;
498 while (next != IPPROTO_DONE) {
499 if (++ nest > IP6_HDR_NEST_LIMIT) {
500 NET_COUNT_IP6(net_count_ip6[NC_IP6_IN_ERR_PROTO], 1);
501 NET_COUNT_MIB(in6_ifstat.ipv6IfStatsInUnknownProtos, 1);
502 goto buf_rel;
503 }
504 else if ((func = get_upper_proto(next)) == NULL) {
505 NET_COUNT_IP6(net_count_ip6[NC_IP6_IN_ERR_PROTO], 1);
506 NET_COUNT_IP6(net_count_ip6[NC_IP6_IN_ERR_PACKETS], 1);
507 NET_COUNT_MIB(in6_ifstat.ipv6IfStatsInUnknownProtos, 1);
508
509 /* icmp6_error でネットワークバッファを開放する。*/
510 icmp6_error(input, ICMP6_PARAM_PROB,
511 ICMP6_PARAMPROB_NEXT_HEADER, nextp);
512 return;
513 }
514 else {
515 next = (*func)(&input, &offp, &nextp);
516 }
517 }
518 return;
519
520buf_rel:
521 NET_COUNT_IP6(net_count_ip6[NC_IP6_IN_ERR_PACKETS], 1);
522 syscall(rel_net_buf(input));
523 }
524
525/*
526 * ip6_nexthdr -- 次のヘッダのオフセットを返す。
527 *
528 * 戻り値 == -1 : 最後のヘッダ、またはエラー。
529 * 戻り値 > 0 : さらにヘッダが続く。
530 */
531
532ER_UINT
533ip6_nexthdr (T_NET_BUF *nbuf, uint_t off, uint_t proto, uint_t *nextp)
534{
535 T_IP6_FRAG_HDR *ip6fh;
536 T_IP6_EXT_HDR *ip6eh;
537
538 switch (proto) {
539
540 case IPPROTO_IPV6: /* IPv6 */
541 if (nbuf->len < off + IP6_HDR_SIZE)
542 return (ER_UINT)-1;
543 *nextp = ((T_IP6_HDR *)(nbuf->buf + off))->next;
544 return off + IP6_HDR_SIZE;
545 break;
546
547 case IPPROTO_FRAGMENT: /* 断片ヘッダ */
548 if (nbuf->len < off + sizeof(T_IP6_FRAG_HDR))
549 return (ER_UINT)-1;
550
551 /* 中間のフラグメントの場合は処理をやめる。*/
552 ip6fh = (T_IP6_FRAG_HDR *)(nbuf->buf + off);
553 if (ntohs(ip6fh->off_flag) & IP6F_MORE_FRAG)
554 return (ER_UINT)-1;
555
556 *nextp = ip6fh->next;
557 return off + sizeof(T_IP6_FRAG_HDR);
558 break;
559
560 case IPPROTO_AH: /* IPv6 認証ヘッダ */
561 case IPPROTO_HOPOPTS: /* IPv6 中継点 (Hop-by-Hop) オプション */
562 case IPPROTO_ROUTING: /* 経路制御ヘッダ */
563 case IPPROTO_DSTOPTS: /* IPv6 終点オプション */
564 if (nbuf->len < off + sizeof(T_IP6_EXT_HDR))
565 return (ER_UINT)-1;
566
567 ip6eh = (T_IP6_EXT_HDR *)(nbuf->buf + off);
568 *nextp = ip6eh->next;
569 if (proto == IPPROTO_AH)
570 return off + ((ip6eh->len + 2) << 2);
571 else
572 return off + ((ip6eh->len + 1) << 3);
573 break;
574 }
575
576 return (ER_UINT)-1;
577 }
578
579/*
580 * ip6_lasthdr -- 最後のヘッダのオフセットを返す。
581 */
582
583ER_UINT
584ip6_lasthdr (T_NET_BUF *nbuf, uint_t off, uint_t proto, uint_t *nextp)
585{
586 ER_UINT newoff;
587
588 while (1) {
589 newoff = ip6_nexthdr(nbuf, off, proto, nextp);
590 if (newoff < 0)
591 return (ER_UINT)off;
592 off = newoff;
593 proto = *nextp;
594 }
595 return (ER_UINT)0u;
596 }
597
598/*
599 * ip6_unknown_opt -- 未知のオプションの処理
600 *
601 * 戻り値:
602 *
603 * 0 以上 正常、オプション長。
604 * IP6_OPT_RET_ERR (-1) エラー、呼出側でネットワークバッファを開放する。
605 * IP6_OPT_RET_REL (-2) エラー、ネットワークバッファは開放されている。
606 */
607
608ER_UINT
609ip6_unknown_opt (T_NET_BUF *input, uint8_t *opt)
610{
611 switch (IP6OPT_TYPE(*opt)) {
612 case IP6OPT_TYPE_SKIP: /* 無視する。 */
613 return *(opt + 1);
614 break;
615 case IP6OPT_TYPE_ICMP: /* 破棄して、マルチキャストでなければ ICMP を返送する。 */
616 if (IN6_IS_ADDR_MULTICAST(&GET_IP6_HDR(input)->dst))
617 return IP6_OPT_RET_ERR;
618 /* no break; */
619 case IP6OPT_TYPE_FORCEICMP: /* 破棄して、ICMP を返送する。 */
620 icmp6_error(input, ICMP6_PARAM_PROB,
621 ICMP6_PARAMPROB_OPTION,
622 (opt - input->buf) - IF_HDR_SIZE);
623 return IP6_OPT_RET_REL;
624 break;
625 /*case IP6OPT_TYPE_DISCARD: データグラムを破棄する。 */
626 }
627
628 return IP6_OPT_RET_ERR;
629 }
630
631/*
632 * ip6_remove_exthdrs -- IPv6 拡張ヘッダを削除し、以降を前に詰める。
633 */
634
635ER
636ip6_remove_exthdrs (T_NET_BUF *nbuf)
637{
638 ER_UINT off;
639 uint_t next;
640
641 /* 開始オフセットを IP ヘッダに設定する。*/
642 off = ((uint8_t *)GET_IP_HDR(nbuf)) - nbuf->buf;
643
644 /* 最終ヘッダを探索する。*/
645 off = ip6_lasthdr(nbuf, off, IPPROTO_IPV6, &next);
646
647 if (off <= 0)
648 return E_OBJ;
649 else {
650 uint_t sdu;
651
652 sdu = GET_IP_SDU(nbuf) - nbuf->buf;
653 if (off > sdu) {
654 memmove(nbuf->buf + sdu, nbuf->buf + off, off - sdu);
655 GET_IP_HDR(nbuf)->plen -= off - sdu;
656 nbuf->len -= off - sdu;
657 }
658 }
659 return E_OK;
660 }
661
662#endif /* of #ifdef SUPPORT_INET6 */
Note: See TracBrowser for help on using the repository browser.