source: asp3_tinet_ecnl_arm/trunk/asp3_dcre/tinet/netinet6/ip6_input.c@ 352

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

arm向けASP3版ECNLを追加

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc;charset=UTF-8
File size: 19.9 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 * 上記著作権者は,以下の (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#include <t_syslog.h>
108#include "tinet_cfg.h"
109
110#endif /* of #ifdef TARGET_KERNEL_ASP */
111
112#ifdef TARGET_KERNEL_JSP
113
114#include <s_services.h>
115#include <t_services.h>
116#include "tinet_id.h"
117
118#endif /* of #ifdef TARGET_KERNEL_JSP */
119
120#include <tinet_defs.h>
121#include <tinet_config.h>
122
123#include <net/if.h>
124#include <net/if_loop.h>
125#include <net/if_ppp.h>
126#include <net/ethernet.h>
127#include <net/ppp_ipcp.h>
128#include <net/net.h>
129#include <net/net_endian.h>
130#include <net/net_buf.h>
131#include <net/net_count.h>
132
133#include <netinet/in.h>
134#include <netinet/in_var.h>
135#include <netinet/ip.h>
136#include <netinet/ip_var.h>
137#include <netinet/ip_icmp.h>
138#include <netinet/tcp.h>
139#include <netinet/tcp_var.h>
140#include <netinet/udp_var.h>
141
142#include <netinet6/nd6.h>
143#include <netinet6/ah6.h>
144#include <netinet6/esp6.h>
145
146#include <net/if_var.h>
147
148#ifdef _IP6_CFG
149
150/*
151 * 関数
152 */
153
154static uint_t ip6_no_header_input (T_NET_BUF **inputp, uint_t *offp, uint_t *nextp);
155
156/*
157 * 上位プロトコル選択構造体
158 */
159
160typedef struct t_proto_switch {
161 uint_t (*func)(T_NET_BUF **, uint_t *, uint_t *); /* 入力関数 */
162 uint_t proto; /* プロトコル番号 */
163 } T_PROTO_SWITCH;
164
165static const T_PROTO_SWITCH proto_switch[] = {
166 { esp6_input, IPPROTO_ESP }, /* IPv6 暗号化ヘッダ */
167 { ah6_input, IPPROTO_AH }, /* IPv6 認証ヘッダ */
168 { frag6_input, IPPROTO_FRAGMENT }, /* 断片ヘッダ */
169 { route6_input, IPPROTO_ROUTING }, /* 経路制御ヘッダ */
170 { dest6_input, IPPROTO_DSTOPTS }, /* IPv6 終点オプション */
171 { ip6_no_header_input,
172 IPPROTO_NONE }, /* 次ヘッダ無し */
173 { icmp6_input, IPPROTO_ICMPV6 },
174
175#if defined(SUPPORT_TCP)
176
177 { tcp_input, IPPROTO_TCP },
178
179#endif /* of #if defined(SUPPORT_TCP) */
180
181#if defined(SUPPORT_UDP) && TNUM_UDP6_CEPID > 0
182
183 { udp6_input, IPPROTO_UDP },
184
185#endif /* of #if defined(SUPPORT_UDP) && TNUM_UDP6_CEPID > 0 */
186
187 };
188
189#ifdef SUPPORT_MIB
190
191T_IN6_IFSTAT in6_ifstat;
192
193#endif /* of #ifdef SUPPORT_MIB */
194
195/*
196 * get_upper_proto -- 上位プロトコル処理関数を返す。
197 */
198
199static uint_t (*
200get_upper_proto(uint_t proto))(T_NET_BUF **, uint_t *, uint_t *)
201{
202 int_t ix;
203
204 for (ix = sizeof(proto_switch) / sizeof(T_PROTO_SWITCH); ix -- > 0; )
205 if (proto_switch[ix].proto == proto)
206 return proto_switch[ix].func;
207 return NULL;
208 }
209
210/*
211 * ip6_no_header_input -- 次ヘッダが無しの場合の入力処理
212 */
213
214static uint_t
215ip6_no_header_input (T_NET_BUF **input, uint_t *offp, uint_t *nextp)
216{
217 syscall(rel_net_buf(*input));
218 return IPPROTO_DONE;
219 }
220
221/*
222 * ip6_hopopts_input -- 中継点オプション入力処理
223 *
224 * 本実装では、パディング以外のオプションを全て未知オプションとして処理する。
225 *
226 * 戻り値:
227 *
228 * 0 以上 正常
229 * IP6_OPT_RET_ERR (-1) エラー、呼出側でネットワークバッファを開放する。
230 * IP6_OPT_RET_REL (-2) エラー、ネットワークバッファは開放されている。
231 */
232
233static ER_UINT
234ip6_hopopts_input (T_NET_BUF *input, uint_t *offp, uint_t *nextp)
235{
236 T_IP6_HBH_HDR *hbh;
237 ER_UINT optlen;
238 uint_t len;
239 uint8_t *opt;
240
241 hbh = (T_IP6_HBH_HDR *)(input->buf + *offp);
242 len = (hbh->len + 1) << 3;
243 *nextp = *offp - IF_HDR_SIZE + offsetof(T_IP6_HBH_HDR, next);
244 *offp += len;
245 opt = (uint8_t *)hbh + sizeof(T_IP6_HBH_HDR);
246
247 for (len -= sizeof(T_IP6_HBH_HDR); len > 0; len -= optlen) {
248 switch (*opt) {
249 case IP6OPT_PAD1:
250 optlen = 1;
251 break;
252 case IP6OPT_PADN:
253 if (len < IP6OPT_MINLEN)
254 return IP6_OPT_RET_ERR;
255 optlen = *(opt + 1) + 2;
256 break;
257 case IP6OPT_JUMBO:
258 case IP6OPT_NSAP_ADDR:
259 case IP6OPT_TUNNEL_LIMIT:
260 case IP6OPT_RTR_ALERT:
261 default:
262 if (len < IP6OPT_MINLEN)
263 return IP6_OPT_RET_ERR;
264 optlen = ip6_unknown_opt(input, opt);
265 if (optlen < 0)
266 return optlen;
267 optlen += 2;
268 break;
269 }
270
271 opt += optlen;
272 }
273
274 return *offp;
275 }
276
277/*
278 * ip6_get_prev_hdr -- 直前の拡張ヘッダの next フィールドのアドレスを返す。
279 *
280 * 注意: off には IF_HDR_SIZE も含まれている。
281 */
282
283uint8_t *
284ip6_get_prev_hdr (T_NET_BUF *nbuf, uint_t off)
285{
286 T_IP6_HDR *ip6h;
287 T_IP6_EXT_HDR *ip6eh;
288 uint_t len;
289 uint8_t next;
290
291 ip6h = GET_IP6_HDR(nbuf);
292 if (off == IF_HDR_SIZE + sizeof(T_IP6_HDR))
293 return &ip6h->next;
294 else {
295 next = ip6h->next;
296 len = IF_HDR_SIZE + sizeof(T_IP6_HDR);
297 ip6eh = NULL;
298
299 while (len < off) {
300 ip6eh = (T_IP6_EXT_HDR *)(nbuf->buf + len);
301
302 switch (next) {
303 case IPPROTO_FRAGMENT:
304 len += sizeof(T_IP6_FRAG_HDR);
305 break;
306 case IPPROTO_AH:
307 len += (ip6eh->len + 2) << 2;
308 break;
309 default:
310 len += (ip6eh->len + 2) << 3;
311 break;
312 }
313 next = ip6eh->next;
314 }
315
316 if (ip6eh == NULL)
317 return NULL;
318 else
319 return &ip6eh->next;
320 }
321 }
322
323/*
324 * ip6_init -- IPv6 の初期化関数
325 */
326
327void
328ip6_init (void)
329{
330 in6_init();
331 in6_ifainit();
332 }
333
334/*
335 * ip6_input -- IPv6 の入力関数
336 */
337
338void
339ip6_input (T_NET_BUF *input)
340{
341 T_IP6_HDR *ip6h;
342 T_IN6_IFADDR *ia6;
343 T_IFNET *ifp;
344 ER_UINT noff;
345 uint_t next, nest, plen, offp, nextp;
346 uint_t (*func)(T_NET_BUF **, uint_t *, uint_t *);
347
348 NET_COUNT_IP6(net_count_ip6[NC_IP6_IN_OCTETS], input->len - IF_HDR_SIZE);
349 NET_COUNT_IP6(net_count_ip6[NC_IP6_IN_PACKETS], 1);
350 NET_COUNT_MIB(in6_ifstat.ipv6IfStatsInReceives, 1);
351
352 /* IP ヘッダの長さをチェックする。*/
353 if (input->len < IF_IP6_HDR_SIZE) {
354 NET_COUNT_IP6(net_count_ip6[NC_IP6_IN_ERR_SHORT], 1);
355 NET_COUNT_MIB(in6_ifstat.ipv6IfStatsInHdrErrors, 1);
356 goto buf_rel;
357 }
358
359 ip6h = GET_IP6_HDR(input);
360
361 /* バージョンをチェックする。*/
362 if (IP6_VCF_V(ntohl(ip6h->vcf)) != IPV6_VERSION) {
363 NET_COUNT_IP6(net_count_ip6[NC_IP6_IN_ERR_VER], 1);
364 NET_COUNT_MIB(in6_ifstat.ipv6IfStatsInHdrErrors, 1);
365 goto buf_rel;
366 }
367
368 /*
369 * 次のデータグラムは破棄する。
370 *
371 * ・始点アドレスがマルチキャスト
372 * ・終点アドレスが未定義
373 *
374 * ネットワークインタフェースがループバックでないとき、
375 * 次のデータグラムも破棄する。
376 *
377 * ・始点アドレスがループバック
378 * ・終点アドレスがループバック
379 *
380 * 悪意のあるユーザが TCP/UDP スタックの混乱や
381 * セキュリティチェックをバイパスするため、IPv4
382 * マップアドレスを悪用することを防ぐため
383 * 以下のデータグラムは破棄する。
384 *
385 * ・始点アドレスが ::ffff:127.0.0.1
386 * ・終点アドレスが ::ffff:127.0.0.1
387 */
388
389 if (IN6_IS_ADDR_MULTICAST(&ip6h->src) ||
390 IN6_IS_ADDR_UNSPECIFIED(&ip6h->dst)) {
391 NET_COUNT_IP6(net_count_ip6[NC_IP6_IN_ERR_ADDR], 1);
392 NET_COUNT_MIB(in6_ifstat.ipv6IfStatsInAddrErrors, 1);
393 goto buf_rel;
394 }
395
396 if (IN6_IS_ADDR_V4MAPPED(&ip6h->src) ||
397 IN6_IS_ADDR_V4MAPPED(&ip6h->dst)) {
398 NET_COUNT_IP6(net_count_ip6[NC_IP6_IN_ERR_ADDR], 1);
399 NET_COUNT_MIB(in6_ifstat.ipv6IfStatsInAddrErrors, 1);
400 goto buf_rel;
401 }
402
403#ifdef SUPPORT_LOOP
404
405#else /* of #ifdef SUPPORT_LOOP */
406
407 if (IN6_IS_ADDR_LOOPBACK(&ip6h->src) ||
408 IN6_IS_ADDR_LOOPBACK(&ip6h->dst)) {
409 NET_COUNT_IP6(net_count_ip6[NC_IP6_IN_ERR_ADDR], 1);
410 NET_COUNT_MIB(in6_ifstat.ipv6IfStatsInAddrErrors, 1);
411 goto buf_rel;
412 }
413
414#endif /* of #ifdef SUPPORT_LOOP */
415
416 ifp = IF_GET_IFNET();
417
418 if (IN6_IS_ADDR_MULTICAST(&ip6h->dst)) {
419 /* 宛先がマルチキャストの場合の処理 */
420 NET_COUNT_MIB(in6_ifstat.ipv6IfStatsInMcastPkts, 1);
421 if (!in6_lookup_multi(ifp, &ip6h->dst)) {
422 NET_COUNT_IP6(net_count_ip6[NC_IP6_IN_ERR_ADDR], 1);
423 NET_COUNT_MIB(in6_ifstat.ipv6IfStatsInAddrErrors, 1);
424 goto buf_rel;
425 }
426 }
427 else {
428 if ((ia6 = in6_lookup_ifaddr(ifp, &ip6h->dst)) == NULL) {
429 NET_COUNT_IP6(net_count_ip6[NC_IP6_IN_ERR_ADDR], 1);
430 NET_COUNT_MIB(in6_ifstat.ipv6IfStatsInAddrErrors, 1);
431 goto buf_rel;
432 }
433
434 /* アドレスが未解決の場合はデータグラムを破棄する。*/
435 if (IFA6_IS_NOTREADY(ia6)) {
436 NET_COUNT_IP6(net_count_ip6[NC_IP6_IN_ERR_ADDR], 1);
437 NET_COUNT_MIB(in6_ifstat.ipv6IfStatsInAddrErrors, 1);
438 goto buf_rel;
439 }
440 }
441
442 /* オフセットを設定する。*/
443 offp = GET_IP6_NEXT_HDR(input) - input->buf;
444
445 /* ペイロード長を取り出す。*/
446 plen = ntohs(ip6h->plen);
447
448
449 /* 次ヘッダの位置を初期化する。*/
450 nextp = offsetof(T_IP6_HDR, next);
451
452 /*
453 * 中継点 (Hop-by-Hop) オプションヘッダのチェック
454 */
455 if (ip6h->next == IPPROTO_HOPOPTS) {
456
457 /* 中継点ヘッダの長さをチェックする。*/
458 if (plen < sizeof(T_IP6_HBH_HDR)) {
459 NET_COUNT_IP6(net_count_ip6[NC_IP6_IN_ERR_SHORT], 1);
460 NET_COUNT_MIB(in6_ifstat.ipv6IfStatsInHdrErrors, 1);
461 goto buf_rel;
462 }
463
464 if ((noff = ip6_hopopts_input(input, &offp, &nextp)) < 0) {
465 if (noff == IP6_OPT_RET_ERR) {
466 NET_COUNT_IP6(net_count_ip6[NC_IP6_IN_ERR_PACKETS], 1);
467 NET_COUNT_MIB(in6_ifstat.ipv6IfStatsInHdrErrors, 1);
468 goto buf_rel;
469 }
470 else if (noff == IP6_OPT_RET_REL) {
471 NET_COUNT_IP6(net_count_ip6[NC_IP6_IN_ERR_PACKETS], 1);
472 NET_COUNT_MIB(in6_ifstat.ipv6IfStatsInHdrErrors, 1);
473 return;
474 }
475 }
476
477 /*
478 * ペイロード長が 0 で、中継点オプションがあるときは、
479 * 巨大ペイロード・オプションが含まれなければならない。
480 * このとき、巨大ペイロード・オプションにある
481 * ペイロード長をチェックする必要があるが、本実装では、
482 * 巨大ペイロード・オプションを未知のオプションとして
483 * 扱うので、何もしない。
484 */
485 next = ((T_IP6_HBH_HDR *)(ip6h + 1))->next;
486 }
487 else
488 next = ip6h->next;
489
490 /* IPv6 データグラム長をチェックする。*/
491 if (input->len - IF_IP6_HDR_SIZE < plen) {
492 NET_COUNT_IP6(net_count_ip6[NC_IP6_IN_ERR_SHORT], 1);
493 NET_COUNT_MIB(in6_ifstat.ipv6IfStatsInTruncatedPkts, 1);
494 goto buf_rel;
495 }
496 else if (input->len > IF_IP6_HDR_SIZE + plen)
497 input->len = IF_IP6_HDR_SIZE + plen;
498
499 /* 上位プロトコル処理関数を呼び出す。*/
500 nest = 0;
501 while (next != IPPROTO_DONE) {
502 if (++ nest > IP6_HDR_NEST_LIMIT) {
503 NET_COUNT_IP6(net_count_ip6[NC_IP6_IN_ERR_PROTO], 1);
504 NET_COUNT_MIB(in6_ifstat.ipv6IfStatsInUnknownProtos, 1);
505 goto buf_rel;
506 }
507 else if ((func = get_upper_proto(next)) == NULL) {
508 NET_COUNT_IP6(net_count_ip6[NC_IP6_IN_ERR_PROTO], 1);
509 NET_COUNT_IP6(net_count_ip6[NC_IP6_IN_ERR_PACKETS], 1);
510 NET_COUNT_MIB(in6_ifstat.ipv6IfStatsInUnknownProtos, 1);
511
512 /* icmp6_error でネットワークバッファを開放する。*/
513 icmp6_error(input, ICMP6_PARAM_PROB,
514 ICMP6_PARAMPROB_NEXT_HEADER, nextp);
515 return;
516 }
517 else {
518 next = (*func)(&input, &offp, &nextp);
519 }
520 }
521 return;
522
523buf_rel:
524 NET_COUNT_IP6(net_count_ip6[NC_IP6_IN_ERR_PACKETS], 1);
525 syscall(rel_net_buf(input));
526 }
527
528/*
529 * ip6_nexthdr -- 次のヘッダのオフセットを返す。
530 *
531 * 戻り値 == -1 : 最後のヘッダ、またはエラー。
532 * 戻り値 > 0 : さらにヘッダが続く。
533 */
534
535ER_UINT
536ip6_nexthdr (T_NET_BUF *nbuf, uint_t off, uint_t proto, uint_t *nextp)
537{
538 T_IP6_FRAG_HDR *ip6fh;
539 T_IP6_EXT_HDR *ip6eh;
540
541 switch (proto) {
542
543 case IPPROTO_IPV6: /* IPv6 */
544 if (nbuf->len < off + IP6_HDR_SIZE)
545 return (ER_UINT)-1;
546 *nextp = ((T_IP6_HDR *)(nbuf->buf + off))->next;
547 return off + IP6_HDR_SIZE;
548 break;
549
550 case IPPROTO_FRAGMENT: /* 断片ヘッダ */
551 if (nbuf->len < off + sizeof(T_IP6_FRAG_HDR))
552 return (ER_UINT)-1;
553
554 /* 中間のフラグメントの場合は処理をやめる。*/
555 ip6fh = (T_IP6_FRAG_HDR *)(nbuf->buf + off);
556 if (ntohs(ip6fh->off_flag) & IP6F_MORE_FRAG)
557 return (ER_UINT)-1;
558
559 *nextp = ip6fh->next;
560 return off + sizeof(T_IP6_FRAG_HDR);
561 break;
562
563 case IPPROTO_AH: /* IPv6 認証ヘッダ */
564 case IPPROTO_HOPOPTS: /* IPv6 中継点 (Hop-by-Hop) オプション */
565 case IPPROTO_ROUTING: /* 経路制御ヘッダ */
566 case IPPROTO_DSTOPTS: /* IPv6 終点オプション */
567 if (nbuf->len < off + sizeof(T_IP6_EXT_HDR))
568 return (ER_UINT)-1;
569
570 ip6eh = (T_IP6_EXT_HDR *)(nbuf->buf + off);
571 *nextp = ip6eh->next;
572 if (proto == IPPROTO_AH)
573 return off + ((ip6eh->len + 2) << 2);
574 else
575 return off + ((ip6eh->len + 1) << 3);
576 break;
577 }
578
579 return (ER_UINT)-1;
580 }
581
582/*
583 * ip6_lasthdr -- 最後のヘッダのオフセットを返す。
584 */
585
586ER_UINT
587ip6_lasthdr (T_NET_BUF *nbuf, uint_t off, uint_t proto, uint_t *nextp)
588{
589 ER_UINT newoff;
590
591 while (1) {
592 newoff = ip6_nexthdr(nbuf, off, proto, nextp);
593 if (newoff < 0)
594 return (ER_UINT)off;
595 off = newoff;
596 proto = *nextp;
597 }
598 return (ER_UINT)0u;
599 }
600
601/*
602 * ip6_unknown_opt -- 未知のオプションの処理
603 *
604 * 戻り値:
605 *
606 * 0 以上 正常、オプション長。
607 * IP6_OPT_RET_ERR (-1) エラー、呼出側でネットワークバッファを開放する。
608 * IP6_OPT_RET_REL (-2) エラー、ネットワークバッファは開放されている。
609 */
610
611ER_UINT
612ip6_unknown_opt (T_NET_BUF *input, uint8_t *opt)
613{
614 switch (IP6OPT_TYPE(*opt)) {
615 case IP6OPT_TYPE_SKIP: /* 無視する。 */
616 return *(opt + 1);
617 break;
618 case IP6OPT_TYPE_ICMP: /* 破棄して、マルチキャストでなければ ICMP を返送する。 */
619 if (IN6_IS_ADDR_MULTICAST(&GET_IP6_HDR(input)->dst))
620 return IP6_OPT_RET_ERR;
621 /* no break; */
622 case IP6OPT_TYPE_FORCEICMP: /* 破棄して、ICMP を返送する。 */
623 icmp6_error(input, ICMP6_PARAM_PROB,
624 ICMP6_PARAMPROB_OPTION,
625 (opt - input->buf) - IF_HDR_SIZE);
626 return IP6_OPT_RET_REL;
627 break;
628 /*case IP6OPT_TYPE_DISCARD: データグラムを破棄する。 */
629 }
630
631 return IP6_OPT_RET_ERR;
632 }
633
634/*
635 * ip6_remove_exthdrs -- IPv6 拡張ヘッダを削除し、以降を前に詰める。
636 */
637
638ER
639ip6_remove_exthdrs (T_NET_BUF *nbuf)
640{
641 ER_UINT off;
642 uint_t next;
643
644 /* 開始オフセットを IP ヘッダに設定する。*/
645 off = ((uint8_t *)GET_IP6_HDR(nbuf)) - nbuf->buf;
646
647 /* 最終ヘッダを探索する。*/
648 off = ip6_lasthdr(nbuf, off, IPPROTO_IPV6, &next);
649
650 if (off <= 0)
651 return E_OBJ;
652 else {
653 uint_t sdu;
654
655 sdu = GET_IP6_SDU(nbuf) - nbuf->buf;
656 if (off > sdu) {
657 memmove(nbuf->buf + sdu, nbuf->buf + off, off - sdu);
658 GET_IP6_HDR(nbuf)->plen -= off - sdu;
659 nbuf->len -= off - sdu;
660 }
661 }
662 return E_OK;
663 }
664
665#endif /* of #ifdef _IP6_CFG */
Note: See TracBrowser for help on using the repository browser.