source: azure_iot_hub/trunk/asp3_dcre/tinet/netinet6/nd6_rtr.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: 41.5 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: nd6_rtr.c 388 2019-05-22 11:25:18Z coas-nagasima $
44 */
45
46/* $FreeBSD: src/sys/netinet6/nd6_rtr.c,v 1.11 2002/04/19 04:46:23 suz Exp $ */
47/* $KAME: nd6_rtr.c,v 1.111 2001/04/27 01:37:15 jinmei Exp $ */
48
49/*
50 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
51 * All rights reserved.
52 *
53 * Redistribution and use in source and binary forms, with or without
54 * modification, are permitted provided that the following conditions
55 * are met:
56 * 1. Redistributions of source code must retain the above copyright
57 * notice, this list of conditions and the following disclaimer.
58 * 2. Redistributions in binary form must reproduce the above copyright
59 * notice, this list of conditions and the following disclaimer in the
60 * documentation and/or other materials provided with the distribution.
61 * 3. Neither the name of the project nor the names of its contributors
62 * may be used to endorse or promote products derived from this software
63 * without specific prior written permission.
64 *
65 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
66 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
67 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
68 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
69 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
70 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
71 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
72 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
73 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
74 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
75 * SUCH DAMAGE.
76 */
77
78#include <string.h>
79
80#ifdef TARGET_KERNEL_ASP
81
82#include <kernel.h>
83#include <sil.h>
84#include <t_syslog.h>
85#include "kernel_cfg.h"
86
87#endif /* of #ifdef TARGET_KERNEL_ASP */
88
89#ifdef TARGET_KERNEL_JSP
90
91#include <s_services.h>
92#include <t_services.h>
93#include "kernel_id.h"
94
95#endif /* of #ifdef TARGET_KERNEL_JSP */
96
97#include <tinet_defs.h>
98#include <tinet_config.h>
99
100#include <net/if.h>
101#include <net/if_ppp.h>
102#include <net/if_loop.h>
103#include <net/ethernet.h>
104#include <net/if_arp.h>
105#include <net/ppp_ipcp.h>
106#include <net/net.h>
107#include <net/net_endian.h>
108#include <net/net_var.h>
109#include <net/net_buf.h>
110#include <net/net_timer.h>
111#include <net/net_count.h>
112
113#include <netinet/in.h>
114#include <netinet/in_var.h>
115#include <netinet/ip.h>
116#include <netinet/ip_var.h>
117#include <netinet/ip_icmp.h>
118
119#include <netinet6/nd6.h>
120#include <netinet6/in6_ifattach.h>
121
122#include <net/if_var.h>
123
124/*
125 * 外部関数の定義
126 */
127
128extern const char *itron_strerror (ER ercd);
129
130#ifdef _IP6_CFG
131
132#if NUM_ND6_DEF_RTR_ENTRY > 0
133
134/*
135 * å…
136¨åŸŸå¤‰æ•°
137 */
138
139SYSTIM nd6_base_reachable_time = ND6_DEF_REACHABLE_TIME; /* ルータから通知された値 */
140SYSTIM nd6_reachable_time = ND6_DEF_REACHABLE_TIME; /* ルータから通知された値の補正値 */
141SYSTIM nd6_recalc_reachtm_interval = ND6_RECALC_REACHTM_INTERVAL; /* 到達可能状æ…
142‹ã®æœ‰åŠ¹æ™‚間再計算間隔 */
143SYSTIM nd6_retrans_time = ND6_DEF_RETRANS_TIME; /* 近隣探索の送信間隔 */
144uint8_t ip6_defhlim = IPV6_DEFHLIM; /* ホップリミットの規定値 */
145
146/*
147 * 局所変数
148 */
149
150/*
151 * プレフィックス・リスト
152 */
153
154static T_ND6_PREFIX nd6_prefix[NUM_ND6_PREFIX_ENTRY];
155
156/*
157 * ディフォルトルータ・リスト
158 */
159
160static T_DEF_ROUTER nd6_def_router[NUM_ND6_DEF_RTR_ENTRY];
161static uint_t def_router_count = 0; /* リストにあるルータ数 */
162
163/*
164 * make_mask -- マップ用のマスクを生成する。
165 */
166
167static uint_t
168make_mask (int_t index)
169{
170 uint_t mask;
171 int_t ix;
172
173 /* マスクを生成する。*/
174 mask = 1;
175 for (ix = index; ix -- > 0; )
176 mask <<= 1;
177
178 return mask;
179 }
180
181/*
182 * find_pfxlist_reachable_router --
183 * 指定したプレフィックスを通知したルータがリンク上に存在するかチェックする。
184 */
185
186static T_DEF_ROUTER *
187find_pfxlist_reachable_router (T_ND6_PREFIX *pr)
188{
189 T_DEF_ROUTER *dr = NULL;
190 T_LLINFO_ND6 *ln;
191 uint_t mask;
192 int_t ix;
193
194 mask = 1;
195 for (ix = 0; ix < def_router_count; ix ++) {
196 if ((pr->routermap & mask) != 0) {
197 if ((ln = nd6_lookup(&nd6_def_router[ix].addr, false)) != NULL &&
198 ND6_IS_LLINFO_PROBREACH(ln))
199 return dr;
200 }
201 mask <<= 1;
202 }
203 return NULL;
204 }
205
206/*
207 * pfxlist_onlink_check -- プレフィックス・リストのオンリンク状æ…
208‹ã‚’チェックする。
209 *
210 * 注意: この関数を呼び出すときは、SEM_ND6_DEFRTRLIST で、
211 * ロックしてから呼び出すこと。
212 */
213
214static void
215pfxlist_onlink_check (void)
216{
217 T_IFNET *ifp = IF_GET_IFNET();
218 T_ND6_PREFIX *pr = NULL;
219 T_IN6_IFADDR *ia;
220 ER error;
221 int_t ix;
222
223 for (ix = NUM_ND6_PREFIX_ENTRY; ix -- > 0; ) {
224 pr = &nd6_prefix[ix];
225 if ((pr->flags & ND6_PREFIX_FLAG_ONLINK) != 0 &&
226 find_pfxlist_reachable_router(pr))
227 break;
228 }
229
230 if (ix >= 0) {
231 /*
232 * オンリンク状æ…
233‹ã®ãƒ—レフィックスが最低一つ存在するときの処理。
234 * 各プレフィックスのオンリンク状æ…
235‹ã‚’、それらを通知してきたルータの
236 * 状æ…
237‹ã«å¾“って設定する。
238 */
239
240
241 for (ix = NUM_ND6_PREFIX_ENTRY; ix -- > 0; ) {
242 pr = &nd6_prefix[ix];
243
244 if ((pr->flags & ND6_PREFIX_FLAG_ONLINK) == 0)
245 continue;
246
247 if ((pr->flags & ND6_PREFIX_STATE_DETACHED) == 0 &&
248 find_pfxlist_reachable_router(pr) == NULL)
249 pr->flags |= ND6_PREFIX_STATE_DETACHED;
250
251 if ((pr->flags & ND6_PREFIX_STATE_DETACHED) != 0 &&
252 find_pfxlist_reachable_router(pr) != NULL)
253 pr->flags &= ~ND6_PREFIX_STATE_DETACHED;
254 }
255 }
256 else {
257 /*
258 * どのプレフィックスもオンリンクではなく、
259 * ディフォルトルータも存在しないときの処理。
260 * すべてのプレフィックスを使用可能状æ…
261‹ã«è¨­å®šã™ã‚‹ã€‚
262 */
263
264
265 for (ix = NUM_ND6_PREFIX_ENTRY; ix -- > 0; ) {
266 pr = &nd6_prefix[ix];
267
268 if ((pr->flags & ND6_PREFIX_FLAG_ONLINK) == 0)
269 continue;
270
271 if ((pr->flags & ND6_PREFIX_STATE_DETACHED) != 0)
272 pr->flags &= ~ND6_PREFIX_STATE_DETACHED;
273 }
274 }
275
276 /*
277 * 各プレフィックス毎に、通知してきたルータの状æ…
278‹ã¨
279 * オンリンクの状æ…
280‹ãŒä¸€è‡´ã—なければ、オンリンク状æ…
281‹ã‚’更新する。
282 */
283 for (ix = NUM_ND6_PREFIX_ENTRY; ix -- > 0; ) {
284 pr = &nd6_prefix[ix];
285
286 if ((pr->flags & ND6_PREFIX_FLAG_ONLINK) == 0)
287 continue;
288
289 if ((pr->flags & ND6_PREFIX_STATE_DETACHED) != 0 &&
290 (pr->flags & ND6_PREFIX_STATE_ONLINK ) != 0) {
291 if ((error = nd6_prefix_offlink(pr)) != E_OK)
292 syslog(LOG_ERROR, "[ND6 RTR] prefix offlink failed: %s", itron_strerror(error));
293 }
294
295 if ((pr->flags & ND6_PREFIX_STATE_DETACHED) == 0 &&
296 (pr->flags & ND6_PREFIX_STATE_ONLINK ) == 0 &&
297 (pr->flags & ND6_PREFIX_FLAG_ONLINK ) == 0) {
298 if ((error = nd6_prefix_onlink(pr)) != E_OK)
299 syslog(LOG_ERROR, "[ND6 RTR] prefix onlink failed: %s", itron_strerror(error));
300 }
301 }
302
303 /*
304 * リンク上にプレフィックスを通知しているルータが
305 * 少なくとも 1 台存在するか確認する。
306 */
307 for (ix = NUM_IN6_IFADDR_ENTRY; ix -- > 0; ) {
308 ia = &ifp->in6_ifaddrs[ix];
309 if ((ia->flags & (IN6_IFF_DEFINED | IN6_IFF_AUTOCONF)) != 0 &&
310 ia->prefix_index != ND6_PREFIX_IX_INVALID) {
311 pr = &nd6_prefix[ia->prefix_index];
312 if (find_pfxlist_reachable_router(pr) != NULL)
313 break;
314 }
315 }
316
317 if (ix >= 0) {
318 /*
319 * リンク上にプレフィックスを通知しているルータが
320 * 少なくとも 1 台存在する時の処理。
321 */
322 for (ix = NUM_IN6_IFADDR_ENTRY; ix -- > 0; ) {
323 ia = &ifp->in6_ifaddrs[ix];
324 if ((ia->flags & (IN6_IFF_DEFINED | IN6_IFF_AUTOCONF)) != 0 &&
325 ia->prefix_index != ND6_PREFIX_IX_INVALID) {
326 pr = &nd6_prefix[ia->prefix_index];
327 if (find_pfxlist_reachable_router(pr) != NULL)
328 ia->flags &= ~IN6_IFF_DETACHED;
329 else
330 ia->flags |= IN6_IFF_DETACHED;
331 }
332 }
333 }
334 else {
335 /*
336 * リンク上にプレフィックスを通知しているルータが
337 * 1 台存在しない時はå…
338¨ã¦ã®ã‚¢ãƒ‰ãƒ¬ã‚¹ã‚’利用できるようにする。
339 */
340 for (ix = NUM_IN6_IFADDR_ENTRY; ix -- > 0; ) {
341 ia = &ifp->in6_ifaddrs[ix];
342 if ((ia->flags & (IN6_IFF_DEFINED | IN6_IFF_AUTOCONF)) != 0)
343 ia->flags &= ~IN6_IFF_DETACHED;
344 }
345 }
346 }
347
348/*
349 * pfxrtr_add -- プレフィックスエントリとディフォルトルータ・エントリをリンクする。
350 *
351 * 注意: この関数を呼び出すときは、SEM_ND6_DEFRTRLIST で、
352 * ロックしてから呼び出すこと。
353 */
354
355static void
356pfxrtr_add (int_t prefix_index, int_t rtr_index)
357{
358 /* プレフィックスエントリとディフォルトルータ・エントリをリンクする。*/
359 nd6_prefix[prefix_index].routermap |= make_mask(rtr_index);
360 nd6_def_router[rtr_index].plistmap |= make_mask(prefix_index);
361
362 pfxlist_onlink_check();
363 }
364
365/*
366 * nd6_pfxrtr_lookup -- プレフィックスエントリからルータを探索する。
367 */
368
369static uint_t
370pfxrtr_lookup (const T_ND6_PREFIX *pr, int_t rtr_index)
371{
372 return (pr->routermap & make_mask(rtr_index)) == 0 ? IN6_RTR_IX_UNREACH : rtr_index;
373 }
374
375/*
376 * defrouter_select -- 優å…
377ˆãƒ‡ã‚£ãƒ•ã‚©ãƒ«ãƒˆãƒ»ãƒ«ãƒ¼ã‚¿ã‚’選択しなおす。
378 *
379 * 注意: この関数を呼び出すときは、SEM_ND6_DEFRTRLIST で、
380 * ロックしてから呼び出すこと。
381 */
382
383static void
384defrouter_select (void)
385{
386 T_DEF_ROUTER *dr = NULL, router;
387 T_LLINFO_ND6 *ln;
388 int_t ix, tix;
389
390 for (ix = 0; ix < def_router_count; ix ++) {
391 dr = &nd6_def_router[ix];
392 if ((ln = nd6_lookup(&dr->addr, false)) != NULL && ND6_IS_LLINFO_PROBREACH(ln)) {
393
394 /* 選択したルータをå…
395ˆé ­ã«ç§»ã™ã€‚*/
396 router = *dr;
397 for (tix = ix; tix > 0; tix --)
398 nd6_def_router[tix] = nd6_def_router[tix - 1];
399 nd6_def_router[0] = router;
400 break;
401 }
402 }
403 }
404
405/*
406 * defrtrlist_update -- ディフォルトルータ・リストを更新する。
407 *
408 * 戻り値は、ルータのインデックス。
409 * ただし、値が -1 なら、プレフィックス・リストは更新しない。
410 */
411
412static int_t
413defrtrlist_update (T_IN6_ADDR *src, uint32_t lifetime, uint8_t flags)
414{
415 T_DEF_ROUTER *dr, *fdr = NULL;
416 SYSTIM now;
417 int_t ix;
418
419 syscall(get_tim(&now));
420 syscall(wai_sem(SEM_ND6_DEFRTRLIST));
421
422 /* 登録済か調べる。*/
423 if ((fdr = nd6_defrtrlist_lookup(src)) != NULL) {
424 /* 登録済みの場合の処理 */
425 if (lifetime == 0) {
426 nd6_defrtrlist_del(fdr);
427 syscall(sig_sem(SEM_ND6_DEFRTRLIST));
428 return -1;
429 }
430 else {
431 fdr->lifetime = lifetime * SYSTIM_HZ; /* lifetime の単位は秒 */
432 fdr->flags = flags;
433 fdr->expire = now + fdr->lifetime;
434 syscall(sig_sem(SEM_ND6_DEFRTRLIST));
435 return fdr - nd6_def_router;
436 }
437 }
438 else if (lifetime == 0) {
439 syscall(sig_sem(SEM_ND6_DEFRTRLIST));
440 return -1;
441 }
442
443 if (fdr == NULL && def_router_count < NUM_ND6_DEF_RTR_ENTRY) {
444 /*
445 * def_router_count < NUM_ND6_DEF_RTR_ENTRY であれば、
446 * nd6_def_router[def_router_count]; が空きエントリ
447 */
448 fdr = &nd6_def_router[def_router_count];
449 }
450
451 /* 空きエントリがなければ、有効時間が短いエントリを削除する。*/
452 if (fdr == NULL) {
453 T_DEF_ROUTER *sdr = NULL;
454 int32_t diff, sdiff = 0xffffffff;
455
456 for (ix = def_router_count; ix -- > 0; ) {
457 dr = &nd6_def_router[ix];
458 diff = (int32_t)(dr->expire - now);
459 if (diff <= 0) { /* dr->expire <= now */
460 /* 既に、有効時間が過ぎている。*/
461 sdr = dr;
462 break;
463 }
464 else if (diff < sdiff)
465 sdr = dr;
466 }
467 if (sdr != NULL) {
468 fdr = sdr;
469 nd6_defrtrlist_del(fdr);
470 }
471 }
472
473 /* 各メンバに値を設定する。*/
474 fdr->plistmap = 0;
475 memcpy(&fdr->addr, src, sizeof(T_IN6_ADDR));
476 fdr->lifetime = lifetime * SYSTIM_HZ; /* lifetime の単位は秒 */
477 fdr->flags = flags;
478 fdr->expire = now + fdr->lifetime;
479 fdr->state = ND6_DEF_RTR_BUSY;
480 def_router_count ++;
481
482 /*
483 * ディフォルトルータとして登録するが、
484 * 既にディフォルトルータがあれば選択しなおさない。
485 */
486 if (fdr - nd6_def_router != 0)
487 defrouter_select();
488
489 syscall(sig_sem(SEM_ND6_DEFRTRLIST));
490 return fdr - nd6_def_router;
491 }
492
493/*
494 * in6_ifadd -- インタフェースにアドレスを追加する。
495 */
496
497static ER
498in6_ifadd (T_ND6_PREFIX *pr, T_IN6_IFADDR *ia, int_t router_index)
499{
500 T_IFNET *ifp = IF_GET_IFNET();
501 T_IN6_ADDR mask, addr;
502 T_IN6_IFADDR *lla;
503 int_t ix;
504
505 lla = &ifp->in6_ifaddrs[IPV6_IFADDR_IX_LINKLOCAL];
506
507 /*
508 * リンクローカルアドレスが未登録であれば何もしない。
509 */
510 if ((lla->flags & IN6_IFF_DEFINED) == 0)
511 return E_OBJ;
512
513 /*
514 * ルータから通知されたプレフィックス長が、
515 * リンクローカルアドレスのプレフィックス長と
516 * 異なっていればエラー
517 */
518 if (lla->prefix_len != pr->prefix_len)
519 return E_PAR;
520
521 /* プレフィックスマスクを生成する。*/
522 in6_plen2pmask(&mask, pr->prefix_len);
523
524 /* アドレスを生成する。*/
525 for (ix = 0; ix < 4; ix ++)
526 addr.s6_addr32[ix] = (pr->prefix.s6_addr32[ix] & mask.s6_addr32[ix])
527 | ( lla->addr.s6_addr32[ix] & ~mask.s6_addr32[ix]);
528
529 /* フラグを初期化する。*/
530 ia->flags = 0;
531
532 return in6_update_ifa(ifp, ia, &addr,
533 pr->prefix_len, pr->vltime, pr->pltime,
534 router_index, pr - nd6_prefix, IN6_IFF_AUTOCONF);
535 }
536
537/*
538 * nd6_prefix_lookup -- プレフィックスを探索する。
539 */
540
541static T_ND6_PREFIX *
542nd6_prefix_lookup (const T_IN6_ADDR *prefix, uint_t plen)
543{
544 T_ND6_PREFIX *pr;
545 int_t ix;
546
547 for (ix = NUM_ND6_PREFIX_ENTRY; ix -- > 0; ) {
548 pr = &nd6_prefix[ix];
549 if ((pr->flags & ND6_PREFIX_STATE_BUSY) &&
550 pr->prefix_len == plen && IN6_ARE_ADDR_EQUAL(&pr->prefix, prefix))
551 return pr;
552 }
553
554 return NULL;
555 }
556
557/*
558 * prelist_remove -- プレフィックスリストからプレフィックスを削除する。
559 *
560 * 注意: この関数を呼び出すときは、SEM_ND6_DEFRTRLIST で、
561 * ロックしてから呼び出すこと。
562 */
563
564static void
565prelist_remove (T_ND6_PREFIX *pr)
566{
567 ER error = E_OK;
568 uint_t mask;
569 int_t rix;
570
571 /* 有効時間切れにする。*/
572 pr->vltime = 0;
573 pr->pltime = 0;
574
575 if ((pr->flags & ND6_PREFIX_STATE_ONLINK) != 0 &&
576 (error = nd6_prefix_offlink(pr)) != E_OK) {
577 syslog(LOG_ERROR, "[ND6 RTR] prefix remove failed: %s", itron_strerror(error));
578 return;
579 }
580
581 /* プレフィックスエントリとディフォルトルータ・エントリのリンクを解除する。*/
582 pr->routermap = 0;
583 mask = make_mask(pr - nd6_prefix);
584 for (rix = def_router_count; rix --; )
585 nd6_def_router[rix].plistmap &= ~mask;
586
587 /* プレフィックスを無効にする。*/
588 pr->flags &= ~ND6_PREFIX_STATE_BUSY;
589
590 pfxlist_onlink_check();
591 }
592
593/*
594 * nd6_prefix_onlink -- プレフィックスをオンリンクに設定し、アドレスを使用可能にする。
595 *
596 * 注意: この関数を呼び出すときは、SEM_ND6_DEFRTRLIST で、
597 * ロックしてから呼び出すこと。
598 */
599
600ER
601nd6_prefix_onlink (T_ND6_PREFIX *pr)
602{
603 T_IFNET *ifp = IF_GET_IFNET();
604 T_IN6_IFADDR *lla, *ia = NULL;
605 int_t ix;
606
607 /* 既にオンリンク状æ…
608‹ã«ãªã£ã¦ã„る場合はエラー。*/
609 if ((pr->flags & ND6_PREFIX_STATE_ONLINK) != 0)
610 return E_OBJ;
611
612 /* リンクローカルアドレスが未登録であれば何もしない。*/
613 lla = &ifp->in6_ifaddrs[IPV6_IFADDR_IX_LINKLOCAL];
614 if ((lla->flags & IN6_IFF_DEFINED) == 0)
615 return E_OK;
616
617 /*
618 * 指定されたプレフィックスが割り当てられているインタフェースの
619 * アドレス情
620報を探す。
621 */
622 for (ix = NUM_IN6_IFADDR_ENTRY; ix --; ) {
623 ia = &ifp->in6_ifaddrs[ix];
624 if (ia->prefix_index == (pr - nd6_prefix))
625 break;
626 }
627
628 if (ix >= 0) {
629
630 /* アドレス情
631報を使用可能にする。*/
632 ia->flags &= ~IN6_IFF_DETACHED;
633
634 /* プレフィックスをオンリンクに設定する。*/
635 pr->flags |= ND6_PREFIX_STATE_ONLINK;
636 }
637
638 return E_OK;
639 }
640
641/*
642 * nd6_prefix_offlink -- プレフィックスをオフリンクに設定し、アドレスを使用不可にする。
643 *
644 * 注意: この関数を呼び出すときは、SEM_ND6_DEFRTRLIST で、
645 * ロックしてから呼び出すこと。
646 */
647
648ER
649nd6_prefix_offlink (T_ND6_PREFIX *pr)
650{
651 T_IFNET *ifp = IF_GET_IFNET();
652 T_IN6_IFADDR *ia = NULL;
653 int_t ix;
654
655 /* 既にオフリンク状æ…
656‹ã«ãªã£ã¦ã„る場合はエラー。*/
657 if ((pr->flags & ND6_PREFIX_STATE_ONLINK) == 0)
658 return E_OBJ;
659
660 /*
661 * 指定されたプレフィックスが割り当てられているインタフェースの
662 * アドレス情
663報を探す。
664 */
665 for (ix = NUM_IN6_IFADDR_ENTRY; ix --; ) {
666 ia = &ifp->in6_ifaddrs[ix];
667 if (ia->prefix_index == (pr - nd6_prefix))
668 break;
669 }
670
671 if (ix >= 0) {
672
673 /* アドレス情
674報を使用不可にする。*/
675 ia->flags |= IN6_IFF_DETACHED;
676
677 /* プレフィックスをオフリンクに設定する。*/
678 pr->flags &= ~ND6_PREFIX_STATE_ONLINK;
679 }
680
681 return E_OK;
682 }
683
684/*
685 * in6_init_prefix_ltimes -- プレフィックスの有効時間を設定する。
686 */
687
688static ER
689in6_init_prefix_ltimes (T_ND6_PREFIX *pr)
690{
691 SYSTIM now;
692
693 /* 推奨有効時間が有効時間より長いときはエラー */
694 if (pr->pltime > pr->vltime)
695 return E_PAR;
696
697 syscall(get_tim(&now));
698 now /= SYSTIM_HZ;
699
700 if (pr->pltime == ND6_INFINITE_LIFETIME)
701 pr->preferred = 0;
702 else
703 pr->preferred = pr->pltime + now;
704
705 if (pr->vltime == ND6_INFINITE_LIFETIME)
706 pr->expire = 0;
707 else
708 pr->expire = pr->vltime + now;
709
710 return E_OK;
711 }
712
713/*
714 * nd6_prelist_add -- プレフィックスリストにプレフィックスを追加する。
715 *
716 * 注意: この関数を呼び出すときは、SEM_ND6_DEFRTRLIST で、
717 * ロックしてから呼び出すこと。
718 */
719
720static T_ND6_PREFIX *
721nd6_prelist_add (T_ND_OPT_PREFIX_INFO *pi, int_t rtr_index)
722{
723 T_ND6_PREFIX *pr = NULL;
724 int_t ix;
725
726 /* プレフィックスリストから空きのプレフィックスエントリを探索する。*/
727 for (ix = NUM_ND6_PREFIX_ENTRY; ix --; ) {
728 pr = &nd6_prefix[ix];
729 if ((pr->flags & ND6_PREFIX_STATE_BUSY) == 0)
730 break;
731 }
732
733 /* プレフィックスリストに空きがなければエラー */
734 if (ix < 0)
735 return NULL;
736
737 pr->flags |= ND6_PREFIX_STATE_BUSY;
738
739 /* プレフィックスを追加する。*/
740 pr->prefix = pi->prefix;
741 pr->prefix_len = pi->prefix_len;
742
743 /* フラグを設定する。*/
744 if ((pi->flags & ND_OPT_PI_FLAG_ONLINK) != 0)
745 pr->flags |= ND6_PREFIX_FLAG_ONLINK;
746 if ((pi->flags & ND_OPT_PI_FLAG_AUTO) != 0)
747 pr->flags |= ND6_PREFIX_FLAG_AUTO;
748
749 /* プレフィックスの有効時間を設定する。*/
750 pr->vltime = ntohl(pi->valid);
751 pr->pltime = ntohl(pi->preferred);
752 in6_init_prefix_ltimes(pr);
753
754 if ((pr->flags & ND6_PREFIX_FLAG_ONLINK) != 0) {
755 if (nd6_prefix_onlink(pr) != E_OK)
756 return NULL;
757 }
758
759 /* ルータマップを初期化する。*/
760 pr->routermap = 0;
761
762 /* ルータを追加する。*/
763 pfxrtr_add(pr - nd6_prefix, rtr_index);
764
765 return pr;
766 }
767
768/*
769 * prelist_update -- プレフィックス・リストを更新する。
770 */
771
772static void
773prelist_update (T_ND_OPT_PREFIX_INFO *pi, uint_t router_index)
774{
775 T_IFNET *ifp = IF_GET_IFNET();
776 T_ND6_PREFIX *pr;
777 T_IN6_IFADDR *ia = NULL;
778 int_t ix, ifidlen;
779
780 syscall(wai_sem(SEM_ND6_DEFRTRLIST));
781 if ((pr = nd6_prefix_lookup(&pi->prefix, pi->prefix_len)) != NULL) {
782 /*
783 * 登録済みの場合は、プレフィックスリストを更新する。
784 */
785
786 /*
787 * フラグの更新の注意:
788 * on-link ビットと autonomous ビットは
789 * 1 から 0 に変更してはならない。
790 */
791
792 if ((pi->flags & ND_OPT_PI_FLAG_ONLINK) != 0)
793 pr->flags |= ND6_PREFIX_FLAG_ONLINK;
794 if ((pi->flags & ND_OPT_PI_FLAG_AUTO) != 0)
795 pr->flags |= ND6_PREFIX_FLAG_AUTO;
796
797 if ((pi->flags & ND_OPT_PI_FLAG_ONLINK) != 0) {
798 /*
799 * 通知されたプレフィックスがオンリンクの時は、
800 * 有効時間を更新する。
801 */
802 pr->vltime = ntohl(pi->valid);
803 pr->pltime = ntohl(pi->preferred);
804 in6_init_prefix_ltimes(pr);
805 }
806
807 if ((pi->flags & ND_OPT_PI_FLAG_ONLINK ) != 0 &&
808 (pr->flags & ND6_PREFIX_STATE_ONLINK) == 0) {
809 /*
810 * オフリンクのプレフィックスがオンリンクになった時の処理を実行する。
811 */
812 if (nd6_prefix_onlink(pr) != E_OK) {
813 syscall(sig_sem(SEM_ND6_DEFRTRLIST));
814 syslog(LOG_ERROR, "[ND6 RTR] prefix update failed.");
815 return;
816 }
817 }
818
819 if (router_index != IN6_RTR_IX_UNREACH && pfxrtr_lookup(pr, router_index) == IN6_RTR_IX_UNREACH)
820 pfxrtr_add(pr - nd6_prefix, router_index);
821 }
822 else { /* 未登録の場合 */
823
824 /* 有効時間 0 のプレフィックスは追加しない。*/
825 if (pi->valid == 0) {
826 syscall(sig_sem(SEM_ND6_DEFRTRLIST));
827 return;
828 }
829
830 /* オフリンクでアドレス自動設定に使用しなければ追加しない。*/
831 if ((pi->flags & (ND_OPT_PI_FLAG_ONLINK | ND_OPT_PI_FLAG_AUTO)) !=
832 (ND_OPT_PI_FLAG_ONLINK | ND_OPT_PI_FLAG_AUTO)) {
833 syscall(sig_sem(SEM_ND6_DEFRTRLIST));
834 return;
835 }
836
837 /* プレフィックスを追加する。*/
838 if ((pr = nd6_prelist_add(pi, router_index)) == NULL) {
839 syslog(LOG_ERROR, "[ND6 RTR] prefix add failed.");
840 syscall(sig_sem(SEM_ND6_DEFRTRLIST));
841 return;
842 }
843
844#if 1 /* プレフィックスが未登録の場合だけ表示する。*/
845 syslog(LOG_NOTICE, "[ND6 RTR] add prefix: flags[MOH]: %02x, addr: %s\n"
846 " from: %s.",
847 nd6_def_router[router_index].flags,
848 ipv62str(NULL, &pi->prefix),
849 ipv62str(NULL, &nd6_def_router[router_index].addr));
850#endif
851 if ((pr->flags & ND6_PREFIX_FLAG_ONLINK) == 0) {
852 /*
853 * オフリンク・プレフィックスの場合は、有効時間を 0 に設定する。
854 * あとで有効期限切れとなり、リストから削除される。
855 */
856 pr->vltime = 0;
857 pr->pltime = 0;
858 in6_init_prefix_ltimes(pr);
859 }
860 }
861
862 /*
863 * ステートレス・アドレス自動設定を行う。
864 */
865 if ((pr->flags & ND6_PREFIX_FLAG_AUTO) == 0) {
866 syscall(sig_sem(SEM_ND6_DEFRTRLIST));
867 return;
868 }
869
870 /*
871 * 通知されたプレフィックスが割り当てられているインタフェースの
872 * アドレス情
873報を探す。
874 */
875 for (ix = NUM_IN6_IFADDR_ENTRY; ix --; ) {
876 ia = &ifp->in6_ifaddrs[ix];
877 if ((ia->flags & IN6_IFF_DEFINED) != 0 &&
878 ia->prefix_len == pr->prefix_len &&
879 in6_are_prefix_equal(&ia->addr, &pr->prefix, pr->prefix_len))
880 break;
881 }
882
883 if (ix >= 0) { /* 登録済みのとき */
884 if ((ia->flags & IN6_IFF_AUTOCONF) == 0) {
885 /*
886 * ステートレス・アドレス自動設定により
887 * 設定されていなければ更新しない。
888 */
889 ;
890 }
891 else if (ia->flags & IN6_IFF_TENTATIVE) {
892 /*
893 * 重複検出中なら更新しない。
894 */
895 ;
896 }
897 else {
898 T_IN6_ADDR mask, addr;
899 T_IN6_IFADDR *lla;
900 uint32_t vltime;
901 SYSTIM now;
902 int_t ix;
903
904 /* 有効時間を設定する。*/
905 syscall(get_tim(&now));
906
907 if (ia->lifetime.vltime == ND6_INFINITE_LIFETIME)
908 vltime = ND6_INFINITE_LIFETIME;
909 else if (IFA6_IS_INVALID(ia, now))
910 vltime = 0;
911 else
912 vltime = ia->lifetime.expire - now / SYSTIM_HZ;
913
914 if (pr->vltime > (2 * 60 * 60) || pr->vltime > vltime) {
915 /*
916 * lifetime.expire、pi->valid (有効時間) と
917 * pi->preferred (推奨有効時間) の単位は [s]。
918 * 通知された有効時間が 2 時間以上か、現在の残り時間より
919 * 長ければ、新しい有効時間には、通知された有効時間を設定する。
920 */
921 vltime = pr->vltime;
922 }
923 else if (vltime <= (2 * 60 * 60))
924 ;
925 else {
926 /*
927 * IPsec は未実装
928のため、2 時間を設定する。
929 */
930 vltime = 2 * 60 * 60;
931 }
932
933 lla = &ifp->in6_ifaddrs[IPV6_IFADDR_IX_LINKLOCAL];
934
935 /* プレフィックスマスクを生成する。*/
936 in6_plen2pmask(&mask, pr->prefix_len);
937
938 /* アドレスを生成する。*/
939 for (ix = 0; ix < 4; ix ++)
940 addr.s6_addr32[ix] = (pr->prefix.s6_addr32[ix] & mask.s6_addr32[ix])
941 | ( lla->addr.s6_addr32[ix] & ~mask.s6_addr32[ix]);
942
943 in6_update_ifa(ifp, ia, &addr, pr->prefix_len, vltime,
944 pr->pltime, router_index, pr - nd6_prefix,
945 IN6_IFF_AUTOCONF | IN6_IFF_NODAD);
946 }
947 }
948
949 else { /* 未登録のとき */
950
951 /*
952 * プレフィックス長をチェックする。
953 * もし、プレフィックス長とインタフェース ID の合計が
954 * 128 ビットに一致しない時は、プレフィックス情
955報を無視する。
956 */
957 if ((ifidlen = in6_if2idlen(ifp)) < 0)
958 syslog(LOG_ERROR, "[ND6 RTR] IFID undefined.");
959 else if (ifidlen + pr->prefix_len != 128)
960 syslog(LOG_NOTICE, "[ND6 RTR] invalid prefix len: %d.", pr->prefix_len);
961 else {
962
963 for (ix = NUM_IN6_IFADDR_ENTRY; ix --; ) {
964 ia = &ifp->in6_ifaddrs[ix];
965 if ((ia->flags & IN6_IFF_DEFINED) == 0) {
966 in6_ifadd(pr, ia, router_index);
967 pfxlist_onlink_check();
968 break;
969 }
970 }
971
972 if (ix < 0)
973 syslog(LOG_ERROR, "[ND6 RTR] prefix update failed.");
974 }
975 }
976 syscall(sig_sem(SEM_ND6_DEFRTRLIST));
977 }
978
979/*
980 * nd6_prelist_timer -- プレフィックス・リストの管理タイマー
981 */
982
983void
984nd6_prelist_timer (void)
985{
986 T_ND6_PREFIX *pr;
987 SYSTIM now;
988 int_t ix;
989
990 syscall(get_tim(&now));
991 now /= SYSTIM_HZ; /* 有効時間の単位は [s] */
992
993 syscall(wai_sem(SEM_ND6_DEFRTRLIST));
994 for (ix = NUM_ND6_PREFIX_ENTRY; ix -- > 0; ) {
995 pr = &nd6_prefix[ix];
996 if ((pr->flags & ND6_PREFIX_STATE_BUSY) != 0 && (int32_t)(pr->expire - now) <= 0)
997 /* pr->expire <= now */
998 prelist_remove(pr);
999 }
1000 syscall(sig_sem(SEM_ND6_DEFRTRLIST));
1001 }
1002
1003/*
1004 * nd6_rs_output -- ルータ要請を出力する。
1005 */
1006
1007static void
1008nd6_rs_output (void)
1009{
1010 T_ROUTER_SOLICIT_HDR *rsh;
1011 T_NET_BUF *output;
1012 T_IN6_IFADDR *ifa;
1013 const T_IN6_ADDR *saddr;
1014 uint16_t len;
1015
1016 NET_COUNT_ICMP6(net_count_nd6[NC_ND6_RS_OUT_PACKETS], 1);
1017
1018 /*
1019 * 送信å…
1020ƒã‚¢ãƒ‰ãƒ¬ã‚¹ã«ã¯ã€ãƒªãƒ³ã‚¯ãƒ­ãƒ¼ã‚«ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹ã‚’設定するが、
1021 * まだ設定されいなければ、無指定を設定する。
1022 */
1023 if ((ifa = in6ifa_ifpwithix(IF_GET_IFNET(), IPV6_IFADDR_IX_LINKLOCAL)) != NULL && !IFA6_IS_NOTREADY(ifa))
1024 saddr = &ifa->addr;
1025 else
1026 saddr = &in6_addr_unspecified;
1027
1028 len = (ROUTER_SOLICIT_HDR_SIZE + 7) >> 3 << 3;
1029
1030 /* ネットワークバッファを獲得し、IPv6 ヘッダを設定する。*/
1031 if (in6_get_datagram(&output, len, 0, &in6_addr_linklocal_allrouters,
1032 saddr, IPPROTO_ICMPV6,
1033 IPV6_MAXHLIM, NBA_SEARCH_ASCENT, TMO_ND6_RS_OUTPUT) != E_OK)
1034 return;
1035
1036 /* ルータ要請ヘッダを設定する。*/
1037 rsh = GET_ROUTER_SOLICIT_HDR(output, IF_IP6_ROUTER_SOLICIT_HDR_OFFSET);
1038 rsh->hdr.type = ND_ROUTER_SOLICIT;
1039 rsh->hdr.code = 0;
1040 rsh->nd_rs_reserved = 0;
1041
1042 /* チェックサムを計算する。*/
1043 rsh->hdr.sum = 0;
1044 rsh->hdr.sum = in6_cksum(output, IPPROTO_ICMPV6, (uint8_t*)rsh - output->buf, len);
1045
1046 /* 送信する。*/
1047 NET_COUNT_ICMP6(net_count_nd6[NC_ICMP6_OUT_OCTETS],
1048 output->len - GET_IF_IP6_HDR_SIZE(output));
1049 NET_COUNT_ICMP6(net_count_nd6[NC_ICMP6_OUT_PACKETS], 1);
1050 NET_COUNT_MIB(icmp6_ifstat.ipv6IfIcmpOutMsgs, 1);
1051 NET_COUNT_MIB(icmp6_ifstat.ipv6IfIcmpOutRouterSolicits, 1);
1052 ip6_output(output, IPV6_OUT_SET_HOP_LIMIT(IPV6_OUT_FLG_HOP_LIMIT, IPV6_MAXHLIM), TMO_ND6_RS_OUTPUT);
1053 }
1054
1055/*
1056 * nd6_defrtrlist_lookup -- ディフォルトルータ・リストを探索する。
1057 */
1058
1059T_DEF_ROUTER *
1060nd6_defrtrlist_lookup (const T_IN6_ADDR *src)
1061{
1062 T_DEF_ROUTER *dr = NULL;
1063 int_t ix;
1064
1065 for (ix = def_router_count; ix -- > 0; ) {
1066 dr = &nd6_def_router[ix];
1067 if (IN6_ARE_ADDR_EQUAL(&dr->addr, src)) {
1068 return dr;
1069 }
1070 }
1071 return NULL;
1072 }
1073
1074/*
1075 * nd6_router_lookup -- ルータのアドレスを返す。
1076 *
1077 */
1078
1079const T_IN6_ADDR *
1080nd6_router_lookup (void)
1081{
1082 if (def_router_count > 0)
1083 return &nd6_def_router[0].addr;
1084 else
1085 return NULL;
1086 }
1087
1088/*
1089 * nd6_defrtrlist_del -- ディフォルトルータ・リストからルータを削除する。
1090 *
1091 * 注意: この関数を呼び出すときは、SEM_ND6_DEFRTRLIST で、
1092 * ロックしてから呼び出すこと。
1093 */
1094
1095void
1096nd6_defrtrlist_del (T_DEF_ROUTER *dr)
1097{
1098 T_IFNET *ifp = IF_GET_IFNET();
1099 T_IN6_IFADDR *ia;
1100 T_ND6_PREFIX *pr;
1101 uint_t mask;
1102 int_t ix, rix, pix, rtrix = dr - nd6_def_router;
1103
1104 if ((ia = in6ifa_ifpwithrtrix(ifp, rtrix)) != NULL) {
1105 /*
1106 * ネットワークインタフェースのプレフィックスを通知した
1107 * ルータを到達不能にする。
1108 */
1109 ia->router_index = IN6_RTR_IX_UNREACH;
1110 }
1111
1112 /* プレフィックスリストからルータを削除する。*/
1113 mask = make_mask(rtrix);
1114 for (pix = NUM_ND6_PREFIX_ENTRY; pix --; )
1115 nd6_prefix[pix].routermap &= ~mask;
1116
1117 /* 削除したルータ以降を前に詰める。*/
1118 for (rix = rtrix + 1; rix < def_router_count; rix ++)
1119 nd6_def_router[rix - 1] = nd6_def_router[rix];
1120
1121 /* プレフィックスリストのルータも更新する。*/
1122 if (dr != nd6_def_router) {
1123
1124 /* マスクを生成する。*/
1125 mask = 1;
1126 for (ix = rtrix - 1; ix -- > 0; )
1127 mask = (mask << 1) | 1;
1128
1129 for (pix = NUM_ND6_PREFIX_ENTRY; pix --; ) {
1130 pr = &nd6_prefix[pix];
1131 pr->routermap = (pr->routermap & mask) | (((pr->routermap & ~mask) >> 1) & ~mask);
1132 }
1133 }
1134 def_router_count --;
1135
1136 /* プレフィックスのオンリンク状æ…
1137‹ã‚’確認する。*/
1138 pfxlist_onlink_check();
1139
1140 /*
1141 * 削除するルータが優å…
1142ˆãƒ‡ã‚£ãƒ•ã‚©ãƒ«ãƒˆãƒ«ãƒ¼ã‚¿ã®å ´åˆã¯ã€
1143 * 優å…
1144ˆãƒ‡ã‚£ãƒ•ã‚©ãƒ«ãƒˆãƒ«ãƒ¼ã‚¿ã‚’選択しなおす。
1145 */
1146 if (rtrix == 0)
1147 defrouter_select();
1148 }
1149
1150/*
1151 * nd6_defrtrlist_timer -- ディフォルトルータ・リストの管理タイマー
1152 */
1153
1154void
1155nd6_defrtrlist_timer (void)
1156{
1157 T_DEF_ROUTER *dr;
1158 SYSTIM now;
1159 int_t ix;
1160
1161 syscall(get_tim(&now));
1162
1163 syscall(wai_sem(SEM_ND6_DEFRTRLIST));
1164 for (ix = def_router_count; ix -- > 0; ) {
1165 dr = &nd6_def_router[ix];
1166 if ((int32_t)(dr->expire - now) <= 0) {
1167 /* dr->expire <= now */
1168 nd6_defrtrlist_del(dr);
1169 }
1170 }
1171 syscall(sig_sem(SEM_ND6_DEFRTRLIST));
1172 }
1173
1174/*
1175 * nd6_get_drl -- ディフォルトルータ・リストを獲得する。
1176 */
1177
1178const T_DEF_ROUTER *
1179nd6_get_drl (uint_t *count)
1180{
1181 *count = def_router_count;
1182 return nd6_def_router;
1183 }
1184
1185/*
1186 * nd6_get_prl -- プレフィックス・リストを獲得する。
1187 */
1188
1189const T_ND6_PREFIX *
1190nd6_get_prl (void)
1191{
1192 return nd6_prefix;
1193 }
1194
1195#endif /* of #if NUM_ND6_DEF_RTR_ENTRY > 0 */
1196
1197/*
1198 * nd6_ra_input -- ルータ通知のå…
1199¥åŠ›å‡¦ç†ã€‚
1200 */
1201
1202void
1203nd6_ra_input (T_NET_BUF *input, uint_t off)
1204{
1205#if NUM_ND6_DEF_RTR_ENTRY > 0
1206
1207 T_IFNET *ifp = IF_GET_IFNET();
1208 T_IP6_HDR *ip6h;
1209 T_ROUTER_ADVERT_HDR *rah;
1210 T_ND_OPT_HDR *opth;
1211 SYSTIM now;
1212 int_t rix;
1213 uint_t lladdr_len = 0;
1214 uint32_t advrea;
1215 uint8_t *lladdr = NULL;
1216 uint8_t nd_opt_off[ND_OPT_OFF_ARRAY_SIZE];
1217
1218 NET_COUNT_ICMP6(net_count_nd6[NC_ND6_RA_IN_PACKETS], 1);
1219
1220 ip6h = GET_IP6_HDR(input);
1221
1222 /*
1223 * ヘッダのチェック、以下の場合は破棄する。
1224 * ・ホップリミットが IPV6_MAXHLIM (255) 以外
1225 * ・ヘッダ長が短い
1226 * ・始点アドレスが、リンクローカルではない (RFC2461)
1227 */
1228 if (ip6h->hlim != IPV6_MAXHLIM ||
1229 input->len - off < ROUTER_ADVERT_HDR_SIZE ||
1230 !IN6_IS_ADDR_LINKLOCAL(&ip6h->src))
1231 goto err_ret;
1232
1233 rah = GET_ROUTER_ADVERT_HDR(input, off);
1234
1235 /* 近隣探索オプションのオフセットを記録する。*/
1236 if (nd6_options(nd_opt_off, input->buf + (off + ROUTER_ADVERT_HDR_SIZE),
1237 input->len - (off + ROUTER_ADVERT_HDR_SIZE)) != E_OK)
1238 goto err_ret;
1239 /*
1240 * 到達可能状æ…
1241‹ã®æœ‰åŠ¹æ™‚間の更新
1242
1243 */
1244 if (rah->reachable) {
1245 advrea = ntohl(rah->reachable) * SYSTIM_HZ / 1000; /* rah->reachable の単位は ms */
1246 if (advrea <= ND6_MAX_REACHABLE_TIME &&
1247 advrea != nd6_base_reachable_time) {
1248 syscall(get_tim(&now));
1249 nd6_recalc_reachtm_interval
1250 = now + ND6_RECALC_REACHTM_INTERVAL;
1251 nd6_base_reachable_time = advrea;
1252 nd6_reachable_time
1253 = ND6_CALC_REACH_TIME(nd6_base_reachable_time);
1254 }
1255 }
1256
1257 /* 近隣探索の送信間隔の更新 */
1258 if (rah->retransmit) {
1259 nd6_retrans_time = ntohl(rah->retransmit) * SYSTIM_HZ / 1000;
1260 /* rah->retransmit の単位は ms */
1261 }
1262
1263 /* ホップリミットの規定値の更新 */
1264 if (rah->nd_ra_current_hoplimit) {
1265 ip6_defhlim = rah->nd_ra_current_hoplimit;
1266 }
1267
1268 /* ディフォルトルータリストの更新 */
1269 rix = defrtrlist_update(&ip6h->src,
1270 ntohs(rah->nd_ra_router_lifetime),
1271 rah->nd_ra_flags); /* rah->nd_ra_router_lifetime の単位は秒 */
1272
1273 /* プレフィックスリストの更新 */
1274 if (nd_opt_off[ND_OPT_OFF_ARRAY_IX(ND_OPT_PREFIX_INFO_COUNT)]) {
1275 T_ND_OPT_PREFIX_INFO *pi;
1276 uint_t pi_off, pi_count;
1277
1278 pi_count = nd_opt_off[ND_OPT_OFF_ARRAY_IX(ND_OPT_PREFIX_INFO_COUNT)];
1279 pi_off = off + ROUTER_ADVERT_HDR_SIZE
1280 + nd_opt_off[ND_OPT_OFF_ARRAY_IX(ND_OPT_PREFIX_INFORMATION)] - 8;
1281 /* 注意: オプションオフセットé…
1282åˆ—には、オフセット + 8 が設定されている。*/
1283 while (pi_count -- > 0) {
1284 pi = (T_ND_OPT_PREFIX_INFO*)(input->buf + pi_off);
1285 if (pi->type != ND_OPT_PREFIX_INFORMATION)
1286 /* オプションタイプがプレフィックス情
1287報でなければ何もしない。*/
1288 ;
1289 else if (pi->len != 4)
1290 /* プレフィックス情
1291報の長さが 32 (8×4) でなければ不正 */
1292 syslog(LOG_NOTICE, "[ND6 RTR] prefix opt len: %d.", pi->len);
1293 else if (pi->prefix_len > 128)
1294 /* プレフィックス長は 128 ビット以下 */
1295 syslog(LOG_NOTICE, "[ND6 RTR] prefix len: %d.", pi->prefix_len);
1296 else if (IN6_IS_ADDR_MULTICAST(&pi->prefix) ||
1297 IN6_IS_ADDR_LINKLOCAL(&pi->prefix))
1298 /* マルチキャストとリンクローカルは不正 */
1299 syslog(LOG_NOTICE, "[ND6 RTR] invalid addr: %s from %s.",
1300 ipv62str(NULL, &pi->prefix), ipv62str(NULL, &ip6h->src));
1301#if 0 /* FreeBSD 6.3 で削除されている。*/
1302 else if (IN6_IS_ADDR_AGGREGATE_UNICAST(&pi->prefix) &&
1303 (pi->prefix_len != 64) )
1304 /* 集約可能ユニキャストで、プレフィックス長が 64 ビット以外は不正 */
1305 syslog(LOG_NOTICE, "[ND6 RTR] invalid prefix len for global: %d.", pi->prefix_len);
1306#endif
1307 else if (ntohl(pi->preferred) > ntohl(pi->valid))
1308 /* 推奨有効時間が有効時間より長ければ不正 */
1309 syslog(LOG_NOTICE, "[ND6 RTR] preferred(%d) > valid time(%d).", ntohl(pi->preferred), ntohl(pi->valid));
1310 else {
1311#if 0 /* プレフィックスが未登録の場合だけ表示する。*/
1312 syslog(LOG_NOTICE, "[ND6 RTR] update prefix: flags[MOH]: %02x, addr: %s\n"
1313 " from: %s.",
1314 rah->nd_ra_flags, ipv62str(NULL, &pi->prefix), ipv62str(NULL, &ip6h->src));
1315#endif
1316 if (rix >= 0) {
1317 /*
1318 * defrtrlist_update の戻り値は、ルータのインデックス。
1319 * ただし、値が -1 なら、プレフィックス・リストは更新しない。
1320 */
1321 prelist_update(pi, rix); /* プレフィックス・リストを更新する。*/
1322 }
1323 }
1324 pi_off += pi->len << 3; /* オプション長の単位は 8 バイト */
1325 }
1326 }
1327
1328 /* MTU の更新 */
1329 if (nd_opt_off[ND_OPT_OFF_ARRAY_IX(ND_OPT_MTU)]) {
1330 T_ND_OPT_MTU_HDR *optmtuh;
1331 uint32_t mtu;
1332
1333 optmtuh = (T_ND_OPT_MTU_HDR *)((uint8_t *)(input->buf + off + ROUTER_ADVERT_HDR_SIZE) +
1334 nd_opt_off[ND_OPT_OFF_ARRAY_IX(ND_OPT_MTU)] - 8);
1335
1336 /*
1337 * 値のチェック
1338 *
1339 * オプション長: 1
1340 * 予約: 0
1341 */
1342 if (optmtuh->len != 1 || optmtuh->reserved != 0)
1343 goto err_ret;
1344
1345 /* MTU が IPv6 MMTU(1280 オクテット)以下なら無視する。*/
1346 mtu = ntohl(optmtuh->mtu);
1347 if (mtu >= IPV6_MMTU) {
1348 if (mtu <= (linkmtu > IF_MTU ? linkmtu : IF_MTU))
1349 linkmtu = mtu;
1350 }
1351 }
1352
1353 /*
1354 * ルータの始点リンクアドレスを近隣キャッシュに登録する。
1355 */
1356 if (nd_opt_off[ND_OPT_OFF_ARRAY_IX(ND_OPT_SOURCE_LINKADDR)]) {
1357 opth = (T_ND_OPT_HDR *)((uint8_t *)(input->buf + off + ROUTER_ADVERT_HDR_SIZE) +
1358 nd_opt_off[ND_OPT_OFF_ARRAY_IX(ND_OPT_SOURCE_LINKADDR)] - 8);
1359 /* 注意: オプションオフセットé…
1360åˆ—には、オフセット + 8 が設定されている。*/
1361 lladdr = (uint8_t *)(opth + 1);
1362 lladdr_len = (opth->len << 3);
1363 }
1364
1365 /*
1366 * ネットワークインタフェースのアドレス長が一致しなければエラー
1367 */
1368 if (lladdr && lladdr_len != ((sizeof(T_IF_ADDR) + sizeof(T_ND_OPT_HDR) + 7) & ~7))
1369 goto err_ret;
1370
1371 /* 近隣キャッシュに登録する。*/
1372 nd6_cache_lladdr(ifp, &ip6h->src, (T_IF_ADDR *)lladdr, ND_ROUTER_ADVERT, 0);
1373
1374 /*
1375 * ルータの始点リンクアドレスを近隣キャッシュに登録したので、
1376 * オンリンク状æ…
1377‹ãŒå¤‰åŒ–する可能性があるため、それをチェックする。
1378 */
1379 pfxlist_onlink_check();
1380
1381 syscall(rel_net_buf(input));
1382 return;
1383
1384err_ret:
1385 NET_COUNT_ICMP6(net_count_nd6[NC_ICMP6_IN_ERR_PACKETS], 1);
1386 syscall(rel_net_buf(input));
1387
1388#else /* of #if NUM_ND6_DEF_RTR_ENTRY > 0 */
1389
1390 /*
1391 * ルータ通知を受信しない場合は、破棄して終了する。
1392 */
1393 NET_COUNT_ICMP6(net_count_nd6[NC_ND6_RA_IN_PACKETS], 1);
1394 syscall(rel_net_buf(input));
1395
1396#endif /* of #if NUM_ND6_DEF_RTR_ENTRY > 0 */
1397 }
1398
1399#if NUM_ND6_RTR_SOL_RETRY > 0
1400
1401/*
1402 * nd6_rtrsol_ctl -- ルータ要請出力の制御
1403 */
1404
1405void
1406nd6_rtrsol_ctl (void)
1407{
1408 T_IN6_IFADDR *ifa;
1409 int_t try;
1410
1411 /* リンクローカルアドレスのアドレス情
1412報を得る。*/
1413 if ((ifa = in6ifa_ifpwithix(IF_GET_IFNET(), IPV6_IFADDR_IX_LINKLOCAL)) == NULL)
1414 return;
1415
1416 /* リンクローカルアドレスの重複検出終了を待
1417つ。*/
1418 do {
1419 /* リンクローカルアドレスの重複検出終了待
1420ち時間を設定する。*/
1421 syscall(dly_tsk(net_rand() % TMO_ND6_RTR_SOL_DELAY));
1422
1423 /* 待
1424っている間に重複が検出されたら終了する。*/
1425 if (ifa->flags & IN6_IFF_DUPLICATED)
1426 return;
1427
1428 } while (!((ifa->flags & IN6_IFF_DEFINED) && (ifa->flags & IN6_IFF_TENTATIVE) == 0));
1429
1430 for (try = 0; try < NUM_ND6_RTR_SOL_RETRY; try ++) {
1431
1432 /* ディフォルトルータ・リストにエントリがあれば終了 */
1433 if (def_router_count > 0)
1434 return;
1435
1436 /* ルータ要請を出力する。*/
1437 nd6_rs_output();
1438
1439 /* 出力の 2 回目以降の遅
1440延時間を設定する。*/
1441 syscall(dly_tsk(TMO_ND6_RTR_SOL_INTERVAL));
1442 }
1443 }
1444
1445#endif /* of #if NUM_ND6_RTR_SOL_RETRY > 0 */
1446
1447/*
1448 * nd6_onlink_prefix_lookup -- プレフィックスを探索する。
1449 */
1450
1451T_ND6_PREFIX *
1452nd6_onlink_prefix_lookup (const T_IN6_ADDR *dst)
1453{
1454 SYSTIM now;
1455 T_ND6_PREFIX *pr;
1456 int_t ix;
1457
1458 syscall(get_tim(&now));
1459 now /= SYSTIM_HZ;
1460
1461 /* 推奨有効時間内
1462のプレフィックスを探索する。*/
1463 for (ix = NUM_ND6_PREFIX_ENTRY; ix -- > 0; ) {
1464 pr = &nd6_prefix[ix];
1465 if ((pr->flags & ND6_PREFIX_STATE_BUSY) &&
1466 (pr->flags & ND6_PREFIX_FLAG_ONLINK) &&
1467 in6_are_prefix_equal(dst, &pr->prefix, pr->prefix_len) &&
1468 (int32_t)(pr->preferred - now) > 0) {
1469 /* pr->preferred > now */
1470 return pr;
1471 }
1472 }
1473
1474 /* 有効時間内
1475のプレフィックスを探索する。*/
1476 for (ix = NUM_ND6_PREFIX_ENTRY; ix -- > 0; ) {
1477 pr = &nd6_prefix[ix];
1478 if ((pr->flags & ND6_PREFIX_STATE_BUSY) &&
1479 (pr->flags & ND6_PREFIX_FLAG_ONLINK) &&
1480 in6_are_prefix_equal(dst, &pr->prefix, pr->prefix_len) &&
1481 (int32_t)(pr->expire - now) > 0) {
1482 /* pr->expire > now */
1483 return pr;
1484 }
1485 }
1486
1487 return NULL;
1488 }
1489
1490#endif /* of #ifdef _IP6_CFG */
Note: See TracBrowser for help on using the repository browser.