source: asp3_tinet_ecnl_arm/trunk/asp3_dcre/tinet/netinet6/in6_subr.c@ 364

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

TINETとSocket APIなどを更新

  • 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 syscall(rel_net_buf(*nbuf));
373 *nbuf = NULL;
374 return error;
375 }
376
377 /* 4 オクテット境界までパディングで埋める。*/
378 if (align > len)
379 memset(GET_IP6_SDU(*nbuf) + len, 0, align - len);
380
381 return E_OK;
382 }
383
384/*
385 * in6_get_maxnum_ifaddr -- インタフェースに設定可能な最大アドレス数を返す。
386 */
387
388uint_t
389in6_get_maxnum_ifaddr (void)
390{
391 return NUM_IN6_IFADDR_ENTRY;
392 }
393
394/*
395 * in6_get_ifaddr -- インタフェースに設定されているアドレスを返す。
396 */
397
398const T_IN6_ADDR *
399in6_get_ifaddr (int_t index)
400{
401 T_IFNET *ifp = IF_GET_IFNET();
402
403 if (index < NUM_IN6_IFADDR_ENTRY &&
404 (ifp->in6_ifaddrs[index].flags & IN6_IFF_DEFINED))
405 return &ifp->in6_ifaddrs[index].addr;
406 else
407 return NULL;
408 }
409
410/*
411 * ipv62str -- IPv6 アドレスを文字列に変換する。
412 */
413
414char *
415ipv62str (char *buf, const T_IN6_ADDR *p_addr)
416{
417 static char addr_sbuf[NUM_IPV6ADDR_STR_BUFF][sizeof("0123:4567:89ab:cdef:0123:4567:255.255.255.255")];
418 static int_t bix = NUM_IPV6ADDR_STR_BUFF;
419
420 bool_t omit = false, zero = false;
421 char *start;
422 int_t ix, len6;
423
424 if (buf == NULL) {
425 syscall(wai_sem(SEM_IP2STR_BUFF_LOCK));
426 buf = addr_sbuf[-- bix];
427 if (bix <= 0)
428 bix = NUM_IPV6ADDR_STR_BUFF;
429 syscall(sig_sem(SEM_IP2STR_BUFF_LOCK));
430 }
431
432 start = buf;
433 if (p_addr == NULL || IN6_IS_ADDR_UNSPECIFIED(p_addr)) {
434 *buf ++ = '0';
435 *buf ++ = ':';
436 *buf ++ = ':';
437 *buf ++ = '0';
438 }
439 else {
440 if (IN6_IS_ADDR_V4MAPPED(p_addr))
441 len6 = sizeof(T_IN6_ADDR) / 2 - 2;
442 else
443 len6 = sizeof(T_IN6_ADDR) / 2;
444 for (ix = 0; ix < len6; ix ++) {
445 if (omit) {
446 buf += convert_hexdigit(buf, ntohs(p_addr->s6_addr16[ix]), 16, 0, ' ');
447 if (ix < 7)
448 *buf ++ = ':';
449 }
450 else if (ix > 0 && ix < 7 && p_addr->s6_addr16[ix] == 0)
451 zero = true;
452 else {
453 if (zero) {
454 omit = true;
455 *buf ++ = ':';
456 }
457 buf += convert_hexdigit(buf, ntohs(p_addr->s6_addr16[ix]), 16, 0, ' ');
458 if (ix < 7)
459 *buf ++ = ':';
460 }
461 }
462
463 if (len6 == sizeof(T_IN6_ADDR) / 2 - 2) {
464 T_IN4_ADDR ipv4addr;
465
466 ipv4addr = ntohl(p_addr->s6_addr32[3]);
467 buf += convert_hexdigit(buf, (uint_t)((ipv4addr >> 24) & 0xff), 10, 0, ' ');
468 *(buf ++) = '.';
469 buf += convert_hexdigit(buf, (uint_t)((ipv4addr >> 16) & 0xff), 10, 0, ' ');
470 *(buf ++) = '.';
471 buf += convert_hexdigit(buf, (uint_t)((ipv4addr >> 8) & 0xff), 10, 0, ' ');
472 *(buf ++) = '.';
473 buf += convert_hexdigit(buf, (uint_t)((ipv4addr ) & 0xff), 10, 0, ' ');
474 }
475 }
476 *buf = '\0';
477 return start;
478 }
479
480/*
481 * in6_cksum -- IPv6 のトランスポート層ヘッダのチェックサムを計算する。
482 *
483 * 注意: 戻り値はネットワークバイトオーダ
484 */
485
486uint16_t
487in6_cksum (T_NET_BUF *nbuf, uint8_t proto, uint_t off, uint_t len)
488{
489 uint32_t sum;
490 uint_t align;
491
492 /* 4 オクテット境界のデータ長 */
493 align = (len + 3) >> 2 << 2;
494
495 /* 4 オクテット境界までパディングで埋める。*/
496 if (align > len)
497 memset((uint8_t*)nbuf->buf + off + len, 0, align - len);
498
499 sum = in_cksum_sum(nbuf->buf + off, align)
500 + in_cksum_sum(&GET_IP6_HDR(nbuf)->src, sizeof(T_IN6_ADDR) * 2)
501 + len + proto;
502 sum = in_cksum_carry(sum);
503
504 return ~htons((uint16_t)sum);
505 }
506
507/*
508 * get_ip6_hdr_size -- 拡張ヘッダも含めた IPv6 ヘッダ長を返す。
509 */
510
511uint_t
512get_ip6_hdr_size (T_NET_BUF *nbuf)
513{
514 T_IP6_HDR *iph = GET_IP6_HDR(nbuf);
515 uint_t size = IP6_HDR_SIZE, hsize;
516 uint8_t curr = iph->next, next;
517 uint8_t *hdr = ((uint8_t *)iph) + IP6_HDR_SIZE;
518
519 while (1) {
520 next = *hdr;
521 if (curr ==IPPROTO_NONE) /* 次ヘッダ無し */
522 break;
523 else if (curr == IPPROTO_FRAGMENT) /* 断片化 */
524 hsize = sizeof(T_IP6_FRAG_HDR);
525 else if (curr == IPPROTO_AH) /* IPv6 認証 */
526 hsize = (((T_IP6_AH_HDR *)hdr)->len + 2) * 4;
527 else if (curr == IPPROTO_HOPOPTS || /* 中継点 (Hop-by-Hop) オプション */
528 curr == IPPROTO_DSTOPTS || /* IPv6 終点オプション */
529 curr == IPPROTO_ROUTING) /* 経路制御 */
530 hsize = (((T_IP6_EXT_HDR *)hdr)->len + 1) * 8;
531 else
532 break;
533 size += hsize;
534 hdr += hsize;
535 curr = next;
536 }
537 return size;
538 }
539
540/*
541 * in6_plen2pmask -- プレフィックス長からマスクを生成する。
542 */
543
544void
545in6_plen2pmask (T_IN6_ADDR *mask, uint_t prefix_len)
546{
547 uint8_t *ptr, bit;
548
549 memset(mask->s6_addr + prefix_len / 8, 0, (128 - prefix_len + 7) / 8);
550 for (ptr = mask->s6_addr; prefix_len > 0; ptr ++) {
551 for (bit = 0x80; bit && (prefix_len > 0); prefix_len --) {
552 *ptr |= bit;
553 bit >>= 1;
554 }
555 }
556 }
557
558/*
559 * in6_rtalloc -- ルーティング表を探索する。
560 */
561
562const T_IN6_ADDR *
563in6_rtalloc (T_IFNET *ifp, const T_IN6_ADDR *dst)
564{
565 if (IN6_IS_ADDR_LINKLOCAL(dst) || IN6_IS_ADDR_MULTICAST(dst))
566 return dst;
567 else {
568 T_IN6_IFADDR *ia;
569 SYSTIM now;
570 int_t ix;
571
572 /*
573 * サイトローカルアドレスか集約可能(グローバル)アドレスの場合は、
574 * 同一リンク内のノードであるかをチェックする。
575 */
576
577 syscall(get_tim(&now));
578 now /= SYSTIM_HZ;
579
580 /* 推奨有効時間内のアドレスを探索する。*/
581 for (ix = NUM_IN6_IFADDR_ENTRY; ix -- > 0; ) {
582 ia = &ifp->in6_ifaddrs[ix];
583 if (IFA6_IS_READY(ia) &&
584 in6_are_prefix_equal(dst, &ia->addr, ia->prefix_len) &&
585 (int32_t)(ia->lifetime.preferred - now) > 0) {
586 /* ia->lifetime.preferred > now */
587 return dst;
588 }
589 }
590
591 /* 有効時間内のアドレスを探索する。*/
592 for (ix = NUM_IN6_IFADDR_ENTRY; ix -- > 0; ) {
593 ia = &ifp->in6_ifaddrs[ix];
594 if (IFA6_IS_READY(ia) &&
595 in6_are_prefix_equal(dst, &ia->addr, ia->prefix_len) &&
596 (int32_t)(ia->lifetime.expire - now) > 0)
597 /* ia->lifetime.expire > now */
598 return dst;
599 }
600
601 /*
602 * プレフィックスを探索する。
603 */
604 if (nd6_onlink_prefix_lookup (dst) != NULL)
605 return dst;
606
607 /*
608 * 静的経路表を探索する。
609 */
610
611#if NUM_IN6_ROUTE_ENTRY > 0
612
613 syscall(wai_sem(SEM_IN6_ROUTING_TBL));
614 for (ix = NUM_IN6_ROUTE_ENTRY; ix --; ) {
615 if ((routing6_tbl[ix].flags & IN_RTF_DEFINED) &&
616 in6_are_prefix_equal(dst, &routing6_tbl[ix].target,
617 routing6_tbl[ix].prefix_len)) {
618
619 /*
620 * 向け直しによるエントリは、有効時間が切れる時刻を延長する。
621 * expire の単位は [s]。
622 * TMO_IN_REDIRECT の単位は [ms]。
623 */
624 if (ix > NUM_IN6_STATIC_ROUTE_ENTRY) {
625 SYSTIM now;
626
627 syscall(get_tim(&now));
628 routing6_tbl[ix].expire = now / SYSTIM_HZ + TMO_IN_REDIRECT / 1000;
629 }
630
631 syscall(sig_sem(SEM_IN6_ROUTING_TBL));
632 return &routing6_tbl[ix].gateway;
633 }
634 }
635 syscall(sig_sem(SEM_IN6_ROUTING_TBL));
636
637#endif /* of #if NUM_IN6_ROUTE_ENTRY > 0 */
638
639 /*
640 * ディフォルトルータ・リストを探索する。
641 */
642 return nd6_router_lookup();
643 }
644 }
645
646#if NUM_IN6_REDIRECT_ROUTE_ENTRY > 0
647
648/*
649 * in6_gateway_lookup -- ルーティング表のルータを探索する。
650 */
651
652T_IN6_RTENTRY *
653in6_gateway_lookup (const T_IN6_ADDR *gw)
654{
655 int_t ix;
656
657 for (ix = NUM_IN6_ROUTE_ENTRY; ix --; )
658 if ((routing6_tbl[ix].flags & IN_RTF_DEFINED) &&
659 IN6_ARE_ADDR_EQUAL(&routing6_tbl[ix].gateway, gw))
660 return &routing6_tbl[ix];
661 return NULL;
662 }
663
664/*
665 * in6_rtredirect -- ルーティング表にエントリを登録する。
666 *
667 * 注意: 引数 tmo の単位は [us]。
668 */
669
670void
671in6_rtredirect (const T_IN6_ADDR *gateway, const T_IN6_ADDR *target, uint_t prefix_len, uint8_t flags, uint32_t tmo)
672{
673 T_IN6_RTENTRY *frt;
674
675 frt = in6_rtnewentry(flags, tmo);
676 memcpy(&frt->gateway, gateway, sizeof(T_IN6_ADDR));
677 memcpy(&frt->target, target, sizeof(T_IN6_ADDR));
678 frt->prefix_len = prefix_len;
679 }
680
681#endif /* of #if NUM_IN6_REDIRECT_ROUTE_ENTRY > 0 */
682
683#if NUM_IN6_HOSTCACHE_ENTRY > 0
684
685/*
686 * in6_hostcache_lookup -- IPv6 ホストキャッシュを探索する。
687 */
688
689static T_IN6_HOSTCACHE_ENTRY*
690in6_hostcache_lookup (const T_IN6_ADDR *dst)
691{
692 int_t ix;
693
694 for (ix = NUM_IN6_HOSTCACHE_ENTRY; ix -- > 0; ) {
695 if (IN6_ARE_ADDR_EQUAL(dst, &in6_hostcache[ix].dst))
696 return &in6_hostcache[ix];
697 }
698 return NULL;
699 }
700
701/*
702 * in6_hostcache_update -- IPv6 ホストキャッシュを更新する。
703 */
704
705void
706in6_hostcache_update (T_IN6_ADDR *dst, uint32_t mtu)
707{
708 T_IN6_HOSTCACHE_ENTRY *hc;
709 SYSTIM now, old;
710 int_t ix, oix;
711
712 syscall(get_tim(&now));
713
714 /* 既に登録されているか探索する。*/
715 if ((hc = in6_hostcache_lookup (dst)) == NULL) {
716
717 /* 空きのホストキャッシュを探す。*/
718 for (ix = NUM_IN6_HOSTCACHE_ENTRY; ix -- > 0; ) {
719 if (IN6_IS_HOSTCACHE_FREE(&in6_hostcache[ix]))
720 break;
721 }
722
723 if (ix < 0) {
724 /*
725 * 空きが無い時は、有効時間の切れる時間が、
726 * 最も短いホストキャッシュを置換する。
727 */
728 old = now - 1;
729 oix = 0;
730 for (ix = NUM_IN6_HOSTCACHE_ENTRY; ix -- > 0; ) {
731 hc = &in6_hostcache[ix];
732 if (IN6_IS_HOSTCACHE_BUSY(hc) && (int32_t)(hc->expire - old) < 0) {
733 /* hc->expire < old */
734 oix = ix;
735 old = hc->expire;
736 }
737 }
738 ix = oix;
739 }
740 hc = &in6_hostcache[ix];
741 }
742 else if (mtu > hc->mtu &&
743 (int32_t)(hc->expire - now) >= (IN6_HOSTCACHE_EXPIRE - IN6_HOSTCACHE_INCREASE)) {
744
745 /*
746 * 既に登録されていて、新しい MTU が、登録されている MTU より大きいとき、
747 * IN6_HOSTCACHE_INCREASE(推奨 10 分)間は更新しない。
748 */
749 return;
750 }
751 memcpy(&hc->dst, dst, sizeof(T_IN6_ADDR));
752 hc->expire = now + IN6_HOSTCACHE_EXPIRE;
753 hc->mtu = mtu;
754 }
755
756/*
757 * in6_hostcache_getmtu -- IPv6 ホストキャッシュをから MTU を取得する。
758 *
759 * 戻り値が 0 であれば、ホストキャッシュに登録されていない。
760 */
761
762uint32_t
763in6_hostcache_getmtu (const T_IN6_ADDR *dst)
764{
765 T_IN6_HOSTCACHE_ENTRY *hc;
766
767 /* 既に登録されているか探索する。*/
768 if ((hc = in6_hostcache_lookup(dst)) == NULL)
769 return 0;
770 else
771 return hc->mtu;
772 }
773
774/*
775 * in6_hostcache_timer -- IPv6 ホストキャッシュ更新タイマー
776 *
777 * 1秒周期で起動される。
778 */
779
780static void
781in6_hostcache_timer (void)
782{
783 static int_t interval = IN6_HOSTCACHE_PRUNE / SYSTIM_HZ;
784
785 SYSTIM now;
786
787 interval --;
788 if (interval <= 0) {
789 syscall(get_tim(&now));
790 interval = IN6_HOSTCACHE_PRUNE / SYSTIM_HZ;
791 }
792 }
793
794#endif /* of #if NUM_IN6_HOSTCACHE_ENTRY > 0 */
795
796/*
797 * in6_timer -- IPv6 共通タイマー
798 *
799 * 1秒周期で起動される。
800 */
801
802static void
803in6_timer (void)
804{
805#if NUM_IN6_REDIRECT_ROUTE_ENTRY > 0
806
807 in6_rttimer();
808
809#endif /* of #if NUM_IN6_REDIRECT_ROUTE_ENTRY > 0 */
810
811#ifdef IP6_CFG_FRAGMENT
812
813 frag6_timer();
814
815#endif /* of #ifdef IP6_CFG_FRAGMENT */
816
817#if NUM_IN6_HOSTCACHE_ENTRY > 0
818
819 in6_hostcache_timer();
820
821#endif /* of #if NUM_IN6_HOSTCACHE_ENTRY > 0 */
822
823 timeout((callout_func)in6_timer, NULL, IN_TIMER_TMO);
824 }
825
826/*
827 * in6_init -- IPv6 共通機能を初期化する。
828 */
829
830void
831in6_init (void)
832{
833#if NUM_IN6_REDIRECT_ROUTE_ENTRY > 0
834
835 in6_rtinit();
836
837#endif /* of #if NUM_IN6_REDIRECT_ROUTE_ENTRY > 0 */
838
839 timeout((callout_func)nd6_timer, NULL, ND6_TIMER_TMO);
840 timeout((callout_func)in6_timer, NULL, IN_TIMER_TMO);
841 }
842
843/*
844 * in6_is_dstaddr_accept -- 宛先アドレスとして正しいかチェックする。
845 */
846
847bool_t
848in6_is_dstaddr_accept (const T_IN6_ADDR *myaddr, const T_IN6_ADDR *dstaddr)
849{
850 if (IN6_IS_ADDR_UNSPECIFIED(myaddr))
851 return in6_lookup_ifaddr(IF_GET_IFNET(), dstaddr) != NULL;
852 else
853 return IN6_ARE_ADDR_EQUAL(dstaddr, myaddr);
854 }
855
856#if defined(DHCP6_CLI_CFG)
857
858/*
859 * in6_add_ifaddr -- インタフェースに IPv6 アドレスを設定する。
860 *
861 * vltime と pltime の単位は[s]
862 */
863
864static ER
865in6_add_ifaddr (T_IN6_ADDR *addr, uint_t prefix_len,
866 uint32_t vltime, uint32_t pltime)
867{
868 T_IFNET *ifp = IF_GET_IFNET();
869 T_IN6_IFADDR *ia = NULL;
870 int_t ix;
871
872 /* 空きのエントリーを探す。*/
873 ix = 0;
874 while (true) {
875 ia = in6ifa_ifpwithix(ifp, ix ++);
876
877 /* 空きが無ければエラー */
878 if (ia == NULL)
879 return E_OBJ;
880
881 if ((ia->flags & IN6_IFF_DEFINED) == 0)
882 break;
883 }
884
885 /* 登録する。*/
886 return in6_update_ifa(ifp, ia, addr, prefix_len, vltime, pltime,
887 IN6_RTR_IX_UNREACH, ND6_PREFIX_IX_INVALID, 0);
888 }
889
890/*
891 * in6_upd_ifaddr -- インタフェースに設定されている IPv6 アドレスを更新する。
892 *
893 * 登録されていなければ、追加する。
894 * vltime と pltime の単位は[s]
895 */
896
897ER
898in6_upd_ifaddr (T_IN6_ADDR *addr, uint_t prefix_len,
899 uint32_t vltime, uint32_t pltime)
900{
901 T_IFNET *ifp = IF_GET_IFNET();
902 T_IN6_IFADDR *ia;
903 int_t ix;
904
905 /*
906 * アドレスが一致するエントリーを探す。
907 * 無ければ登録する。
908 */
909 if ((ix = in6_addr2ifaix(addr)) == IPV6_IFADDR_IX_INVALID)
910 return in6_add_ifaddr(addr, prefix_len, vltime, pltime);
911
912 /*
913 * インデックス番号から、エントリーに変換する。
914 * エラーにならないはずであるが、確認する。
915 */
916 if ((ia = in6ifa_ifpwithix (ifp, ix)) == NULL)
917 return E_OBJ;
918
919 /* 更新する。*/
920 return in6_update_ifa(ifp, ia, addr, prefix_len, vltime, pltime,
921 IN6_RTR_IX_UNREACH, ND6_PREFIX_IX_INVALID, 0);
922 }
923
924/*
925 * in6_del_ifaddr -- インタフェースに設定されている IPv6 アドレスを削除する。
926 */
927
928ER
929in6_del_ifaddr (T_IN6_ADDR *addr)
930{
931 T_IFNET *ifp = IF_GET_IFNET();
932 int_t ix;
933
934 /* アドレスが一致するエントリーを探す。*/
935 if ((ix = in6_addr2ifaix(addr)) != IPV6_IFADDR_IX_INVALID) {
936
937 /* エントリーを無効にする。*/
938 ifp->in6_ifaddrs[ix].flags &= ~IN6_IFF_DEFINED;
939 return E_OK;
940 }
941 return E_PAR;
942 }
943
944#endif /* of #if defined(DHCP6_CLI_CFG) */
945
946#endif /* of #ifdef _IP6_CFG */
Note: See TracBrowser for help on using the repository browser.