source: rubycfg_asp/trunk/asp_dcre/tinet/netinet6/in6_subr.c@ 313

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

ソースを追加

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