source: EcnlProtoTool/trunk/asp3_dcre/tinet/netinet6/in6_subr.c@ 331

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

prototoolに関連するプロジェクトをnewlibからmuslを使うよう変更・更新
ntshellをnewlibの下位の実装から、muslのsyscallの実装に変更・更新
以下のOSSをアップデート
・mruby-1.3.0
・musl-1.1.18
・onigmo-6.1.3
・tcc-0.9.27
以下のOSSを追加
・openssl-1.1.0e
・curl-7.57.0
・zlib-1.2.11
以下のmrbgemsを追加
・iij/mruby-digest
・iij/mruby-env
・iij/mruby-errno
・iij/mruby-iijson
・iij/mruby-ipaddr
・iij/mruby-mock
・iij/mruby-require
・iij/mruby-tls-openssl

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc;charset=UTF-8
File size: 25.4 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/*
35 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
36 * All rights reserved.
37 *
38 * Redistribution and use in source and binary forms, with or without
39 * modification, are permitted provided that the following conditions
40 * are met:
41 * 1. Redistributions of source code must retain the above copyright
42 * notice, this list of conditions and the following disclaimer.
43 * 2. Redistributions in binary form must reproduce the above copyright
44 * notice, this list of conditions and the following disclaimer in the
45 * documentation and/or other materials provided with the distribution.
46 * 3. Neither the name of the project nor the names of its contributors
47 * may be used to endorse or promote products derived from this software
48 * without specific prior written permission.
49 *
50 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
51 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
52 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
53 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
54 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
55 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
56 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
57 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
58 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
59 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
60 * SUCH DAMAGE.
61 */
62
63/*
64 * Copyright (c) 1985, 1986, 1993
65 * The Regents of the University of California. All rights reserved.
66 *
67 * Redistribution and use in source and binary forms, with or without
68 * modification, are permitted provided that the following conditions
69 * are met:
70 * 1. Redistributions of source code must retain the above copyright
71 * notice, this list of conditions and the following disclaimer.
72 * 2. Redistributions in binary form must reproduce the above copyright
73 * notice, this list of conditions and the following disclaimer in the
74 * documentation and/or other materials provided with the distribution.
75 * 3. All advertising materials mentioning features or use of this software
76 * must display the following acknowledgement:
77 * This product includes software developed by the University of
78 * California, Berkeley and its contributors.
79 * 4. Neither the name of the University nor the names of its contributors
80 * may be used to endorse or promote products derived from this software
81 * without specific prior written permission.
82 *
83 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
84 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
85 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
86 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
87 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
88 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
89 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
90 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
91 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
92 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
93 * SUCH DAMAGE.
94 */
95
96#include <string.h>
97
98#ifdef TARGET_KERNEL_ASP
99
100#include <kernel.h>
101#include <sil.h>
102#include "kernel_cfg.h"
103
104#endif /* of #ifdef TARGET_KERNEL_ASP */
105
106#ifdef TARGET_KERNEL_JSP
107
108#include <s_services.h>
109#include <t_services.h>
110#include "kernel_id.h"
111#include "tinet_id.h"
112
113#endif /* of #ifdef TARGET_KERNEL_JSP */
114
115#include <tinet_defs.h>
116#include <tinet_config.h>
117
118#include <net/if.h>
119#include <net/if_loop.h>
120#include <net/if_ppp.h>
121#include <net/ethernet.h>
122#include <net/if_arp.h>
123#include <net/net.h>
124#include <net/net_endian.h>
125#include <net/net_var.h>
126#include <net/net_buf.h>
127#include <net/net_timer.h>
128
129#include <netinet/in.h>
130#include <netinet/in_var.h>
131#include <netinet/ip.h>
132#include <netinet/ip_var.h>
133
134#include <netinet6/nd6.h>
135#include <netinet6/ah.h>
136
137#include <net/if_var.h>
138
139/*
140 * in6_make_ipv4mapped -- IPv4 射影アドレスを生成する。
141 *
142 * 注意:
143 * src はホストバイトオーダー
144 *
145 */
146
147T_IN6_ADDR *
148in6_make_ipv4mapped (T_IN6_ADDR *dst, T_IN4_ADDR src)
149{
150 dst->s6_addr32[0] = ULONG_C(0x00000000);
151 dst->s6_addr32[1] = ULONG_C(0x00000000);
152 dst->s6_addr32[2] = IPV6_ADDR_INT32_0000FFFF;
153 dst->s6_addr32[3] = htonl(src);
154
155 return dst;
156 }
157
158#ifdef _IP6_CFG
159
160#if NUM_IN6_REDIRECT_ROUTE_ENTRY > 0
161
162/*
163 * in6_rtinit -- ルーティング表を初期化する。
164 */
165
166void
167in6_rtinit (void)
168{
169 int_t ix;
170
171 for (ix = 0; ix < NUM_IN6_STATIC_ROUTE_ENTRY; ix ++)
172 routing6_tbl[ix].flags = IN_RTF_DEFINED;
173
174 for ( ; ix < NUM_IN6_ROUTE_ENTRY; ix ++)
175 routing6_tbl[ix].flags = 0;
176 }
177
178/*
179 * in6_rtnewentry -- 新しいエントリを獲得する。
180 */
181
182T_IN6_RTENTRY *
183in6_rtnewentry (uint8_t flags, uint32_t tmo)
184{
185 SYSTIM now;
186 T_IN6_RTENTRY *rt, *frt = NULL;
187 int_t ix;
188
189 /* 空きエントリを探す。*/
190 for (ix = NUM_IN6_STATIC_ROUTE_ENTRY; ix < NUM_IN6_ROUTE_ENTRY; ix ++) {
191 rt = &routing6_tbl[ix];
192 if ((routing6_tbl[ix].flags & IN_RTF_DEFINED) == 0) {
193 frt = rt;
194 break;
195 }
196 }
197
198 /* expire の単位は [s]。*/
199 syscall(get_tim(&now));
200 now /= SYSTIM_HZ;
201
202 if (frt == NULL) {
203 /* 空きがなければ、有効時間がもっとも短いエントリを空きにする。*/
204 T_IN6_RTENTRY *srt = NULL;
205 int_t diff, sdiff = INT_MAX;
206
207 syscall(wai_sem(SEM_IN6_ROUTING_TBL));
208 for (ix = NUM_IN6_STATIC_ROUTE_ENTRY; ix < NUM_IN6_ROUTE_ENTRY; ix ++) {
209 rt = &routing6_tbl[ix];
210 diff = (int_t)(rt->expire - now);
211 if (diff <= 0) { /* rt->expire <= now */
212 /* 既に、有効時間が過ぎている。*/
213 frt = rt;
214 break;
215 }
216 else if (diff < sdiff) {
217 srt = rt;
218 sdiff = diff;
219 }
220 }
221 if (frt == NULL)
222 frt = srt;
223 frt->flags = 0;
224 syscall(sig_sem(SEM_IN6_ROUTING_TBL));
225 }
226
227 frt->flags = (uint8_t)(flags | IN_RTF_DEFINED);
228 frt->expire = now + tmo / SYSTIM_HZ;
229 return frt;
230 }
231
232/*
233 * in6_rttimer -- ルーティング表の管理タイマー
234 */
235
236void
237in6_rttimer (void)
238{
239 SYSTIM now;
240 int_t ix;
241
242 /* expire の単位は [s]。*/
243 syscall(get_tim(&now));
244 now /= SYSTIM_HZ;
245
246 syscall(wai_sem(SEM_IN6_ROUTING_TBL));
247 for (ix = NUM_IN6_STATIC_ROUTE_ENTRY; ix < NUM_IN6_ROUTE_ENTRY; ix ++)
248 if ((routing6_tbl[ix].flags & IN_RTF_DEFINED) &&
249 (int_t)(routing6_tbl[ix].expire - now) <= 0)
250 routing6_tbl[ix].flags = 0;
251 syscall(sig_sem(SEM_IN6_ROUTING_TBL));
252 }
253
254#endif /* of #if NUM_IN6_REDIRECT_ROUTE_ENTRY > 0 */
255
256#if NUM_IN6_HOSTCACHE_ENTRY > 0
257
258/*
259 * ホストキャッシュ
260 */
261
262static T_IN6_HOSTCACHE_ENTRY in6_hostcache[NUM_IN6_HOSTCACHE_ENTRY];
263
264#endif /* of #if NUM_IN6_HOSTCACHE_ENTRY > 0 */
265
266/*
267 * in6_lookup_ifaddr -- ネットワークインタフェースに割り当てられているアドレスを探索する。
268 */
269
270T_IN6_IFADDR *
271in6_lookup_ifaddr (T_IFNET *ifp, const T_IN6_ADDR *addr)
272{
273 int_t ix;
274
275 for (ix = NUM_IN6_IFADDR_ENTRY; ix -- > 0; ) {
276 if ((ifp->in6_ifaddrs[ix].flags & IN6_IFF_DEFINED) &&
277 IN6_ARE_ADDR_EQUAL(addr, &ifp->in6_ifaddrs[ix].addr))
278 return &ifp->in6_ifaddrs[ix];
279 }
280 return NULL;
281 }
282
283/*
284 * in6_lookup_multi -- ネットワークインタフェースのマルチキャストアドレスを検索する。
285 */
286
287bool_t
288in6_lookup_multi (T_IFNET *ifp, const T_IN6_ADDR *maddr)
289{
290 int_t ix;
291
292 for (ix = MAX_IN6_MADDR_CNT; ix -- > 0; )
293 if (IN6_ARE_ADDR_EQUAL(maddr, &ifp->in6_maddrs[ix]))
294 return true;
295 return false;
296 }
297
298/*
299 * in6_set_header -- IPv6 ヘッダを設定する。
300 */
301
302ER
303in6_set_header (T_NET_BUF *nbuf, uint_t len,
304 const T_IN6_ADDR *dstaddr, const T_IN6_ADDR *srcaddr,
305 uint8_t next, uint8_t hlim)
306{
307 T_IFNET *ifp = IF_GET_IFNET();
308 T_IP6_HDR *ip6h;
309 T_IN6_IFADDR *ia;
310
311 /*
312 * 宛先アドレスにふさわしい送信元アドレスを、
313 * ネットワークインタフェースから探索して利用する。
314 */
315 if (srcaddr == NULL || !IN6_IS_ADDR_UNSPECIFIED(srcaddr))
316 ;
317 else if ((ia = in6_ifawithifp(ifp, dstaddr)) == NULL)
318 return E_SYS;
319 else
320 srcaddr = &ia->addr;
321
322 /* IPv6 ヘッダを設定する。*/
323 ip6h = GET_IP6_HDR(nbuf);
324 ip6h->vcf = htonl(IP6_MAKE_VCF(IPV6_VERSION, 0));
325 ip6h->plen = htons(len);
326 ip6h->next = next;
327 ip6h->hlim = hlim;
328
329 if (dstaddr == NULL)
330 memset(&ip6h->dst, 0, sizeof(T_IN6_ADDR));
331 else
332 memcpy(&ip6h->dst, dstaddr, sizeof(T_IN6_ADDR));
333
334 if (srcaddr == NULL)
335 memset(&ip6h->src, 0, sizeof(T_IN6_ADDR));
336 else
337 memcpy(&ip6h->src, srcaddr, sizeof(T_IN6_ADDR));
338
339 return E_OK;
340 }
341
342/*
343 * in6_get_datagram -- IPv6 データグラムを獲得し、ヘッダを設定する。
344 */
345
346ER
347in6_get_datagram (T_NET_BUF **nbuf, uint_t len, uint_t maxlen,
348 const T_IN6_ADDR *dstaddr, const T_IN6_ADDR *srcaddr,
349 uint8_t next, uint8_t hlim, ATR nbatr, TMO tmout)
350{
351 ER error;
352 uint_t align;
353
354 /* データ長は 4 オクテット境界に調整する。 */
355 align = (len + 3) >> 2 << 2;
356
357 /* ネットワークバッファを獲得する。 */
358 if ((error = tget_net_buf_ex(nbuf, IF_IP6_HDR_SIZE + align,
359 IF_IP6_HDR_SIZE + maxlen, nbatr, tmout)) != E_OK)
360 return error;
361
362 /*
363 * より大きなサイズのネットワークバッファを獲得する場合のみ長さを調整する。
364 * より小さなサイズのネットワークバッファの獲得は、送信ウィンドバッファの
365 * 省コピー機能で使用され、実際に送信するまで、データサイズは決定できない。
366 */
367 if ((nbatr & NBA_SEARCH_ASCENT) != 0)
368 (*nbuf)->len = IF_IP6_HDR_SIZE + len;
369
370 /* IPv6 ヘッダを設定する。*/
371 if ((error = in6_set_header(*nbuf, len, dstaddr, srcaddr, next, hlim)) != E_OK)
372 return error;
373
374 /* 4 オクテット境界までパディングで埋める。*/
375 if (align > len)
376 memset(GET_IP6_SDU(*nbuf) + len, 0, align - len);
377
378 return E_OK;
379 }
380
381/*
382 * in6_get_maxnum_ifaddr -- インタフェースに設定可能な最大アドレス数を返す。
383 */
384
385uint_t
386in6_get_maxnum_ifaddr (void)
387{
388 return NUM_IN6_IFADDR_ENTRY;
389 }
390
391/*
392 * in6_get_ifaddr -- インタフェースに設定されているアドレスを返す。
393 */
394
395const T_IN6_ADDR *
396in6_get_ifaddr (int_t index)
397{
398 T_IFNET *ifp = IF_GET_IFNET();
399
400 if (index < NUM_IN6_IFADDR_ENTRY &&
401 (ifp->in6_ifaddrs[index].flags & IN6_IFF_DEFINED))
402 return &ifp->in6_ifaddrs[index].addr;
403 else
404 return NULL;
405 }
406
407/*
408 * ipv62str -- IPv6 アドレスを文字列に変換する。
409 */
410
411char *
412ipv62str (char *buf, const T_IN6_ADDR *p_addr)
413{
414 static char addr_sbuf[NUM_IPV6ADDR_STR_BUFF][sizeof("0123:4567:89ab:cdef:0123:4567:255.255.255.255")];
415 static int_t bix = NUM_IPV6ADDR_STR_BUFF;
416
417 bool_t omit = false, zero = false;
418 char *start;
419 int_t ix, len6;
420
421 if (buf == NULL) {
422 syscall(wai_sem(SEM_IP2STR_BUFF_LOCK));
423 buf = addr_sbuf[-- bix];
424 if (bix <= 0)
425 bix = NUM_IPV6ADDR_STR_BUFF;
426 syscall(sig_sem(SEM_IP2STR_BUFF_LOCK));
427 }
428
429 start = buf;
430 if (p_addr == NULL || IN6_IS_ADDR_UNSPECIFIED(p_addr)) {
431 *buf ++ = '0';
432 *buf ++ = ':';
433 *buf ++ = ':';
434 *buf ++ = '0';
435 }
436 else {
437 if (IN6_IS_ADDR_V4MAPPED(p_addr))
438 len6 = sizeof(T_IN6_ADDR) / 2 - 2;
439 else
440 len6 = sizeof(T_IN6_ADDR) / 2;
441 for (ix = 0; ix < len6; ix ++) {
442 if (omit) {
443 buf += convert_hexdigit(buf, ntohs(p_addr->s6_addr16[ix]), 16, 0, ' ');
444 if (ix < 7)
445 *buf ++ = ':';
446 }
447 else if (ix > 0 && ix < 7 && p_addr->s6_addr16[ix] == 0)
448 zero = true;
449 else {
450 if (zero) {
451 omit = true;
452 *buf ++ = ':';
453 }
454 buf += convert_hexdigit(buf, ntohs(p_addr->s6_addr16[ix]), 16, 0, ' ');
455 if (ix < 7)
456 *buf ++ = ':';
457 }
458 }
459
460 if (len6 == sizeof(T_IN6_ADDR) / 2 - 2) {
461 T_IN4_ADDR ipv4addr;
462
463 ipv4addr = ntohl(p_addr->s6_addr32[3]);
464 buf += convert_hexdigit(buf, (uint_t)((ipv4addr >> 24) & 0xff), 10, 0, ' ');
465 *(buf ++) = '.';
466 buf += convert_hexdigit(buf, (uint_t)((ipv4addr >> 16) & 0xff), 10, 0, ' ');
467 *(buf ++) = '.';
468 buf += convert_hexdigit(buf, (uint_t)((ipv4addr >> 8) & 0xff), 10, 0, ' ');
469 *(buf ++) = '.';
470 buf += convert_hexdigit(buf, (uint_t)((ipv4addr ) & 0xff), 10, 0, ' ');
471 }
472 }
473 *buf = '\0';
474 return start;
475 }
476
477/*
478 * in6_cksum -- IPv6 のトランスポート層ヘッダのチェックサムを計算する。
479 *
480 * 注意: 戻り値はネットワークバイトオーダ
481 */
482
483uint16_t
484in6_cksum (T_NET_BUF *nbuf, uint8_t proto, uint_t off, uint_t len)
485{
486 uint32_t sum;
487 uint_t align;
488
489 /* 4 オクテット境界のデータ長 */
490 align = (len + 3) >> 2 << 2;
491
492 /* 4 オクテット境界までパディングで埋める。*/
493 if (align > len)
494 memset((uint8_t*)nbuf->buf + off + len, 0, align - len);
495
496 sum = in_cksum_sum(nbuf->buf + off, align)
497 + in_cksum_sum(&GET_IP6_HDR(nbuf)->src, sizeof(T_IN6_ADDR) * 2)
498 + len + proto;
499 sum = in_cksum_carry(sum);
500
501 return ~htons((uint16_t)sum);
502 }
503
504/*
505 * get_ip6_hdr_size -- 拡張ヘッダも含めた IPv6 ヘッダ長を返す。
506 */
507
508uint_t
509get_ip6_hdr_size (T_NET_BUF *nbuf)
510{
511 T_IP6_HDR *iph = GET_IP6_HDR(nbuf);
512 uint_t size = IP6_HDR_SIZE, hsize;
513 uint8_t curr = iph->next, next;
514 uint8_t *hdr = ((uint8_t *)iph) + IP6_HDR_SIZE;
515
516 while (1) {
517 next = *hdr;
518 if (curr ==IPPROTO_NONE) /* 次ヘッダ無し */
519 break;
520 else if (curr == IPPROTO_FRAGMENT) /* 断片化 */
521 hsize = sizeof(T_IP6_FRAG_HDR);
522 else if (curr == IPPROTO_AH) /* IPv6 認証 */
523 hsize = (((T_IP6_AH_HDR *)hdr)->len + 2) * 4;
524 else if (curr == IPPROTO_HOPOPTS || /* 中継点 (Hop-by-Hop) オプション */
525 curr == IPPROTO_DSTOPTS || /* IPv6 終点オプション */
526 curr == IPPROTO_ROUTING) /* 経路制御 */
527 hsize = (((T_IP6_EXT_HDR *)hdr)->len + 1) * 8;
528 else
529 break;
530 size += hsize;
531 hdr += hsize;
532 curr = next;
533 }
534 return size;
535 }
536
537/*
538 * in6_plen2pmask -- プレフィックス長からマスクを生成する。
539 */
540
541void
542in6_plen2pmask (T_IN6_ADDR *mask, uint_t prefix_len)
543{
544 uint8_t *ptr, bit;
545
546 memset(mask->s6_addr + prefix_len / 8, 0, (128 - prefix_len + 7) / 8);
547 for (ptr = mask->s6_addr; prefix_len > 0; ptr ++) {
548 for (bit = 0x80; bit && (prefix_len > 0); prefix_len --) {
549 *ptr |= bit;
550 bit >>= 1;
551 }
552 }
553 }
554
555/*
556 * in6_rtalloc -- ルーティング表を探索する。
557 */
558
559const T_IN6_ADDR *
560in6_rtalloc (T_IFNET *ifp, const T_IN6_ADDR *dst)
561{
562 if (IN6_IS_ADDR_LINKLOCAL(dst) || IN6_IS_ADDR_MULTICAST(dst))
563 return dst;
564 else {
565 T_IN6_IFADDR *ia;
566 SYSTIM now;
567 int_t ix;
568
569 /*
570 * サイトローカルアドレスか集約可能(グローバル)アドレスの場合は、
571 * 同一リンク内のノードであるかをチェックする。
572 */
573
574 syscall(get_tim(&now));
575 now /= SYSTIM_HZ;
576
577 /* 推奨有効時間内のアドレスを探索する。*/
578 for (ix = NUM_IN6_IFADDR_ENTRY; ix -- > 0; ) {
579 ia = &ifp->in6_ifaddrs[ix];
580 if (IFA6_IS_READY(ia) &&
581 in6_are_prefix_equal(dst, &ia->addr, ia->prefix_len) &&
582 (int32_t)(ia->lifetime.preferred - now) > 0) {
583 /* ia->lifetime.preferred > now */
584 return dst;
585 }
586 }
587
588 /* 有効時間内のアドレスを探索する。*/
589 for (ix = NUM_IN6_IFADDR_ENTRY; ix -- > 0; ) {
590 ia = &ifp->in6_ifaddrs[ix];
591 if (IFA6_IS_READY(ia) &&
592 in6_are_prefix_equal(dst, &ia->addr, ia->prefix_len) &&
593 (int32_t)(ia->lifetime.expire - now) > 0)
594 /* ia->lifetime.expire > now */
595 return dst;
596 }
597
598 /*
599 * プレフィックスを探索する。
600 */
601 if (nd6_onlink_prefix_lookup (dst) != NULL)
602 return dst;
603
604 /*
605 * 静的経路表を探索する。
606 */
607
608#if NUM_IN6_ROUTE_ENTRY > 0
609
610 syscall(wai_sem(SEM_IN6_ROUTING_TBL));
611 for (ix = NUM_IN6_ROUTE_ENTRY; ix --; ) {
612 if ((routing6_tbl[ix].flags & IN_RTF_DEFINED) &&
613 in6_are_prefix_equal(dst, &routing6_tbl[ix].target,
614 routing6_tbl[ix].prefix_len)) {
615
616 /*
617 * 向け直しによるエントリは、有効時間が切れる時刻を延長する。
618 * expire の単位は [s]。
619 * TMO_IN_REDIRECT の単位は [ms]。
620 */
621 if (ix > NUM_IN6_STATIC_ROUTE_ENTRY) {
622 SYSTIM now;
623
624 syscall(get_tim(&now));
625 routing6_tbl[ix].expire = now / SYSTIM_HZ + TMO_IN_REDIRECT / 1000;
626 }
627
628 syscall(sig_sem(SEM_IN6_ROUTING_TBL));
629 return &routing6_tbl[ix].gateway;
630 }
631 }
632 syscall(sig_sem(SEM_IN6_ROUTING_TBL));
633
634#endif /* of #if NUM_IN6_ROUTE_ENTRY > 0 */
635
636 /*
637 * ディフォルトルータ・リストを探索する。
638 */
639 return nd6_router_lookup();
640 }
641 }
642
643#if NUM_IN6_REDIRECT_ROUTE_ENTRY > 0
644
645/*
646 * in6_gateway_lookup -- ルーティング表のルータを探索する。
647 */
648
649T_IN6_RTENTRY *
650in6_gateway_lookup (const T_IN6_ADDR *gw)
651{
652 int_t ix;
653
654 for (ix = NUM_IN6_ROUTE_ENTRY; ix --; )
655 if ((routing6_tbl[ix].flags & IN_RTF_DEFINED) &&
656 IN6_ARE_ADDR_EQUAL(&routing6_tbl[ix].gateway, gw))
657 return &routing6_tbl[ix];
658 return NULL;
659 }
660
661/*
662 * in6_rtredirect -- ルーティング表にエントリを登録する。
663 *
664 * 注意: 引数 tmo の単位は [ms]。
665 */
666
667void
668in6_rtredirect (const T_IN6_ADDR *gateway, const T_IN6_ADDR *target, uint_t prefix_len, uint8_t flags, uint32_t tmo)
669{
670 T_IN6_RTENTRY *frt;
671
672 frt = in6_rtnewentry(flags, tmo);
673 memcpy(&frt->gateway, gateway, sizeof(T_IN6_ADDR));
674 memcpy(&frt->target, target, sizeof(T_IN6_ADDR));
675 frt->prefix_len = prefix_len;
676 }
677
678#endif /* of #if NUM_IN6_REDIRECT_ROUTE_ENTRY > 0 */
679
680#if NUM_IN6_HOSTCACHE_ENTRY > 0
681
682/*
683 * in6_hostcache_lookup -- IPv6 ホストキャッシュを探索する。
684 */
685
686static T_IN6_HOSTCACHE_ENTRY*
687in6_hostcache_lookup (const T_IN6_ADDR *dst)
688{
689 int_t ix;
690
691 for (ix = NUM_IN6_HOSTCACHE_ENTRY; ix -- > 0; ) {
692 if (IN6_ARE_ADDR_EQUAL(dst, &in6_hostcache[ix].dst))
693 return &in6_hostcache[ix];
694 }
695 return NULL;
696 }
697
698/*
699 * in6_hostcache_update -- IPv6 ホストキャッシュを更新する。
700 */
701
702void
703in6_hostcache_update (T_IN6_ADDR *dst, uint32_t mtu)
704{
705 T_IN6_HOSTCACHE_ENTRY *hc;
706 SYSTIM now, old;
707 int_t ix, oix;
708
709 syscall(get_tim(&now));
710
711 /* 既に登録されているか探索する。*/
712 if ((hc = in6_hostcache_lookup (dst)) == NULL) {
713
714 /* 空きのホストキャッシュを探す。*/
715 for (ix = NUM_IN6_HOSTCACHE_ENTRY; ix -- > 0; ) {
716 if (IN6_IS_HOSTCACHE_FREE(&in6_hostcache[ix]))
717 break;
718 }
719
720 if (ix < 0) {
721 /*
722 * 空きが無い時は、有効時間の切れる時間が、
723 * 最も短いホストキャッシュを置換する。
724 */
725 old = now - 1;
726 oix = 0;
727 for (ix = NUM_IN6_HOSTCACHE_ENTRY; ix -- > 0; ) {
728 hc = &in6_hostcache[ix];
729 if (IN6_IS_HOSTCACHE_BUSY(hc) && (int32_t)(hc->expire - old) < 0) {
730 /* hc->expire < old */
731 oix = ix;
732 old = hc->expire;
733 }
734 }
735 ix = oix;
736 }
737 hc = &in6_hostcache[ix];
738 }
739 else if (mtu > hc->mtu &&
740 (int32_t)(hc->expire - now) >= (IN6_HOSTCACHE_EXPIRE - IN6_HOSTCACHE_INCREASE)) {
741
742 /*
743 * 既に登録されていて、新しい MTU が、登録されている MTU より大きいとき、
744 * IN6_HOSTCACHE_INCREASE(推奨 10 分)間は更新しない。
745 */
746 return;
747 }
748 memcpy(&hc->dst, dst, sizeof(T_IN6_ADDR));
749 hc->expire = now + IN6_HOSTCACHE_EXPIRE;
750 hc->mtu = mtu;
751 }
752
753/*
754 * in6_hostcache_getmtu -- IPv6 ホストキャッシュをから MTU を取得する。
755 *
756 * 戻り値が 0 であれば、ホストキャッシュに登録されていない。
757 */
758
759uint32_t
760in6_hostcache_getmtu (const T_IN6_ADDR *dst)
761{
762 T_IN6_HOSTCACHE_ENTRY *hc;
763
764 /* 既に登録されているか探索する。*/
765 if ((hc = in6_hostcache_lookup(dst)) == NULL)
766 return 0;
767 else
768 return hc->mtu;
769 }
770
771/*
772 * in6_hostcache_timer -- IPv6 ホストキャッシュ更新タイマー
773 *
774 * 1秒周期で起動される。
775 */
776
777static void
778in6_hostcache_timer (void)
779{
780 static int_t interval = IN6_HOSTCACHE_PRUNE / SYSTIM_HZ;
781
782 SYSTIM now;
783
784 interval --;
785 if (interval <= 0) {
786 syscall(get_tim(&now));
787 interval = IN6_HOSTCACHE_PRUNE / SYSTIM_HZ;
788 }
789 }
790
791#endif /* of #if NUM_IN6_HOSTCACHE_ENTRY > 0 */
792
793/*
794 * in6_timer -- IPv6 共通タイマー
795 *
796 * 1秒周期で起動される。
797 */
798
799static void
800in6_timer (void)
801{
802#if NUM_IN6_REDIRECT_ROUTE_ENTRY > 0
803
804 in6_rttimer();
805
806#endif /* of #if NUM_IN6_REDIRECT_ROUTE_ENTRY > 0 */
807
808#ifdef IP6_CFG_FRAGMENT
809
810 frag6_timer();
811
812#endif /* of #ifdef IP6_CFG_FRAGMENT */
813
814#if NUM_IN6_HOSTCACHE_ENTRY > 0
815
816 in6_hostcache_timer();
817
818#endif /* of #if NUM_IN6_HOSTCACHE_ENTRY > 0 */
819
820 timeout((callout_func)in6_timer, NULL, IN_TIMER_TMO);
821 }
822
823/*
824 * in6_init -- IPv6 共通機能を初期化する。
825 */
826
827void
828in6_init (void)
829{
830#if NUM_IN6_REDIRECT_ROUTE_ENTRY > 0
831
832 in6_rtinit();
833
834#endif /* of #if NUM_IN6_REDIRECT_ROUTE_ENTRY > 0 */
835
836 timeout((callout_func)nd6_timer, NULL, ND6_TIMER_TMO);
837 timeout((callout_func)in6_timer, NULL, IN_TIMER_TMO);
838 }
839
840/*
841 * in6_is_dstaddr_accept -- 宛先アドレスとして正しいかチェックする。
842 */
843
844bool_t
845in6_is_dstaddr_accept (const T_IN6_ADDR *myaddr, const T_IN6_ADDR *dstaddr)
846{
847 if (IN6_IS_ADDR_UNSPECIFIED(myaddr))
848 return in6_lookup_ifaddr(IF_GET_IFNET(), dstaddr) != NULL;
849 else
850 return IN6_ARE_ADDR_EQUAL(dstaddr, myaddr);
851 }
852
853#if defined(DHCP6_CLI_CFG)
854
855/*
856 * in6_add_ifaddr -- インタフェースに IPv6 アドレスを設定する。
857 *
858 * vltime と pltime の単位は[s]
859 */
860
861static ER
862in6_add_ifaddr (T_IN6_ADDR *addr, uint_t prefix_len,
863 uint32_t vltime, uint32_t pltime)
864{
865 T_IFNET *ifp = IF_GET_IFNET();
866 T_IN6_IFADDR *ia = NULL;
867 int_t ix;
868
869 /* 空きのエントリーを探す。*/
870 ix = 0;
871 while (true) {
872 ia = in6ifa_ifpwithix(ifp, ix ++);
873
874 /* 空きが無ければエラー */
875 if (ia == NULL)
876 return E_OBJ;
877
878 if ((ia->flags & IN6_IFF_DEFINED) == 0)
879 break;
880 }
881
882 /* 登録する。*/
883 return in6_update_ifa(ifp, ia, addr, prefix_len, vltime, pltime,
884 IN6_RTR_IX_UNREACH, ND6_PREFIX_IX_INVALID, 0);
885 }
886
887/*
888 * in6_upd_ifaddr -- インタフェースに設定されている IPv6 アドレスを更新する。
889 *
890 * 登録されていなければ、追加する。
891 * vltime と pltime の単位は[s]
892 */
893
894ER
895in6_upd_ifaddr (T_IN6_ADDR *addr, uint_t prefix_len,
896 uint32_t vltime, uint32_t pltime)
897{
898 T_IFNET *ifp = IF_GET_IFNET();
899 T_IN6_IFADDR *ia;
900 int_t ix;
901
902 /*
903 * アドレスが一致するエントリーを探す。
904 * 無ければ登録する。
905 */
906 if ((ix = in6_addr2ifaix(addr)) == IPV6_IFADDR_IX_INVALID)
907 return in6_add_ifaddr(addr, prefix_len, vltime, pltime);
908
909 /*
910 * インデックス番号から、エントリーに変換する。
911 * エラーにならないはずであるが、確認する。
912 */
913 if ((ia = in6ifa_ifpwithix (ifp, ix)) == NULL)
914 return E_OBJ;
915
916 /* 更新する。*/
917 return in6_update_ifa(ifp, ia, addr, prefix_len, vltime, pltime,
918 IN6_RTR_IX_UNREACH, ND6_PREFIX_IX_INVALID, 0);
919 }
920
921/*
922 * in6_del_ifaddr -- インタフェースに設定されている IPv6 アドレスを削除する。
923 */
924
925ER
926in6_del_ifaddr (T_IN6_ADDR *addr)
927{
928 T_IFNET *ifp = IF_GET_IFNET();
929 int_t ix;
930
931 /* アドレスが一致するエントリーを探す。*/
932 if ((ix = in6_addr2ifaix(addr)) != IPV6_IFADDR_IX_INVALID) {
933
934 /* エントリーを無効にする。*/
935 ifp->in6_ifaddrs[ix].flags &= ~IN6_IFF_DEFINED;
936 return E_OK;
937 }
938 return E_PAR;
939 }
940
941#endif /* of #if defined(DHCP6_CLI_CFG) */
942
943#endif /* of #ifdef _IP6_CFG */
Note: See TracBrowser for help on using the repository browser.