source: azure_iot_hub/trunk/asp3_dcre/tinet/netinet6/in6_subr.c@ 388

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

Azure IoT Hub Device C SDK を使ったサンプルの追加

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