source: EcnlProtoTool/trunk/asp3_dcre/tinet/netinet6/nd6_rtr.c@ 270

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

mruby版ECNLプロトタイピング・ツールを追加

  • 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.0 KB
Line 
1/*
2 * TINET (TCP/IP Protocol Stack)
3 *
4 * Copyright (C) 2001-2009 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 270 2017-02-09 04:03:47Z 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_var.h>
108#include <net/net_buf.h>
109#include <net/net_timer.h>
110#include <net/net_count.h>
111
112#include <netinet/in.h>
113#include <netinet/in_var.h>
114#include <netinet6/in6.h>
115#include <netinet6/in6_var.h>
116#include <netinet6/nd6.h>
117#include <netinet6/in6_ifattach.h>
118#include <netinet/ip6.h>
119#include <netinet/icmp6.h>
120#include <netinet6/ip6_var.h>
121
122#include <net/if6_var.h>
123
124/*
125 * 外部関数の定義
126 */
127
128extern const char *itron_strerror (ER ercd);
129
130#ifdef SUPPORT_INET6
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->in_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->in_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->in_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 fdr->addr = *src;
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->in_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->in_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->in_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->in_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 ER error;
726
727 /* プレフィックスリストから空きのプレフィックスエントリを探索する。*/
728 for (ix = NUM_ND6_PREFIX_ENTRY; ix --; ) {
729 pr = &nd6_prefix[ix];
730 if ((pr->flags & ND6_PREFIX_STATE_BUSY) == 0)
731 break;
732 }
733
734 /* プレフィックスリストに空きがなければエラー */
735 if (ix < 0)
736 return NULL;
737
738 pr->flags |= ND6_PREFIX_STATE_BUSY;
739
740 /* プレフィックスを追加する。*/
741 pr->prefix = pi->prefix;
742 pr->prefix_len = pi->prefix_len;
743
744 /* フラグを設定する。*/
745 if ((pi->flags & ND_OPT_PI_FLAG_ONLINK) != 0)
746 pr->flags |= ND6_PREFIX_FLAG_ONLINK;
747 if ((pi->flags & ND_OPT_PI_FLAG_AUTO) != 0)
748 pr->flags |= ND6_PREFIX_FLAG_AUTO;
749
750 /* プレフィックスの有効時間を設定する。*/
751 pr->vltime = ntohl(pi->valid);
752 pr->pltime = ntohl(pi->preferred);
753 in6_init_prefix_ltimes(pr);
754
755 if ((pr->flags & ND6_PREFIX_FLAG_ONLINK) != 0) {
756 if ((error = nd6_prefix_onlink(pr)) != E_OK)
757 return NULL;
758 }
759
760 /* ルータマップを初期化する。*/
761 pr->routermap = 0;
762
763 /* ルータを追加する。*/
764 pfxrtr_add(pr - nd6_prefix, rtr_index);
765
766 return pr;
767 }
768
769/*
770 * prelist_update -- プレフィックス・リストを更新する。
771 */
772
773static void
774prelist_update (T_ND_OPT_PREFIX_INFO *pi, uint_t router_index)
775{
776 T_IFNET *ifp = IF_GET_IFNET();
777 T_ND6_PREFIX *pr;
778 T_IN6_IFADDR *ia = NULL;
779 int_t ix, ifidlen;
780
781 syscall(wai_sem(SEM_ND6_DEFRTRLIST));
782 if ((pr = nd6_prefix_lookup(&pi->prefix, pi->prefix_len)) != NULL) {
783 /*
784 * 登録済みの場合は、プレフィックスリストを更新する。
785 */
786
787 /*
788 * フラグの更新の注意:
789 * on-link ビットと autonomous ビットは
790 * 1 から 0 に変更してはならない。
791 */
792
793 if ((pi->flags & ND_OPT_PI_FLAG_ONLINK) != 0)
794 pr->flags |= ND6_PREFIX_FLAG_ONLINK;
795 if ((pi->flags & ND_OPT_PI_FLAG_AUTO) != 0)
796 pr->flags |= ND6_PREFIX_FLAG_AUTO;
797
798 if ((pi->flags & ND_OPT_PI_FLAG_ONLINK) != 0) {
799 /*
800 * 通知されたプレフィックスがオンリンクの時は、
801 * 有効時間を更新する。
802 */
803 pr->vltime = ntohl(pi->valid);
804 pr->pltime = ntohl(pi->preferred);
805 in6_init_prefix_ltimes(pr);
806 }
807
808 if ((pi->flags & ND_OPT_PI_FLAG_ONLINK ) != 0 &&
809 (pr->flags & ND6_PREFIX_STATE_ONLINK) == 0) {
810 /*
811 * オフリンクのプレフィックスがオンリンクになった時の処理を実行する。
812 */
813 if (nd6_prefix_onlink(pr) != E_OK) {
814 syscall(sig_sem(SEM_ND6_DEFRTRLIST));
815 syslog(LOG_ERROR, "[ND6 RTR] prefix update failed.");
816 return;
817 }
818 }
819
820 if (router_index != IN6_RTR_IX_UNREACH && pfxrtr_lookup(pr, router_index) == IN6_RTR_IX_UNREACH)
821 pfxrtr_add(pr - nd6_prefix, router_index);
822 }
823 else { /* 未登録の場合 */
824
825 /* 有効時間 0 のプレフィックスは追加しない。*/
826 if (pi->valid == 0) {
827 syscall(sig_sem(SEM_ND6_DEFRTRLIST));
828 return;
829 }
830
831 /* オフリンクでアドレス自動設定に使用しなければ追加しない。*/
832 if ((pi->flags & (ND_OPT_PI_FLAG_ONLINK | ND_OPT_PI_FLAG_AUTO)) !=
833 (ND_OPT_PI_FLAG_ONLINK | ND_OPT_PI_FLAG_AUTO)) {
834 syscall(sig_sem(SEM_ND6_DEFRTRLIST));
835 return;
836 }
837
838 /* プレフィックスを追加する。*/
839 if ((pr = nd6_prelist_add(pi, router_index)) == NULL) {
840 syslog(LOG_ERROR, "[ND6 RTR] prefix add failed.");
841 syscall(sig_sem(SEM_ND6_DEFRTRLIST));
842 return;
843 }
844
845 if ((pr->flags & ND6_PREFIX_FLAG_ONLINK) == 0) {
846 /*
847 * オフリンク・プレフィックスの場合は、有効時間を 0 に設定する。
848 * あとで有効期限切れとなり、リストから削除される。
849 */
850 pr->vltime = 0;
851 pr->pltime = 0;
852 in6_init_prefix_ltimes(pr);
853 }
854 }
855
856 /*
857 * ステートレス・アドレス自動設定を行う。
858 */
859 if ((pr->flags & ND6_PREFIX_FLAG_AUTO) == 0) {
860 syscall(sig_sem(SEM_ND6_DEFRTRLIST));
861 return;
862 }
863
864 /*
865 * 通知されたプレフィックスが割り当てられているインタフェースの
866 * アドレス情
867報を探す。
868 */
869 for (ix = NUM_IN6_IFADDR_ENTRY; ix --; ) {
870 ia = &ifp->in_ifaddrs[ix];
871 if ((ia->flags & IN6_IFF_DEFINED) != 0 &&
872 ia->prefix_len == pr->prefix_len &&
873 in6_are_prefix_equal(&ia->addr, &pr->prefix, pr->prefix_len))
874 break;
875 }
876
877 if (ix >= 0) { /* 登録済みのとき */
878 if ((ia->flags & IN6_IFF_AUTOCONF) == 0) {
879 /*
880 * ステートレス・アドレス自動設定により
881 * 設定されていなければ更新しない。
882 */
883 ;
884 }
885 else if (ia->flags & IN6_IFF_TENTATIVE) {
886 /*
887 * 重複検出中なら更新しない。
888 */
889 ;
890 }
891 else {
892 T_IN6_ADDR mask, addr;
893 T_IN6_IFADDR *lla;
894 uint32_t vltime;
895 SYSTIM now;
896 int_t ix;
897
898 /* 有効時間を設定する。*/
899 syscall(get_tim(&now));
900
901 if (ia->lifetime.vltime == ND6_INFINITE_LIFETIME)
902 vltime = ND6_INFINITE_LIFETIME;
903 else if (IFA6_IS_INVALID(ia, now))
904 vltime = 0;
905 else
906 vltime = ia->lifetime.expire - now / SYSTIM_HZ;
907
908 if (pr->vltime > (2 * 60 * 60) || pr->vltime > vltime) {
909 /*
910 * lifetime.expire、pi->valid (有効時間) と
911 * pi->preferred (推奨有効時間) の単位は [s]。
912 * 通知された有効時間が 2 時間以上か、現在の残り時間より
913 * 長ければ、新しい有効時間には、通知された有効時間を設定する。
914 */
915 vltime = pr->vltime;
916 }
917 else if (vltime <= (2 * 60 * 60))
918 ;
919 else {
920 /*
921 * IPsec は未実装
922のため、2 時間を設定する。
923 */
924 vltime = 2 * 60 * 60;
925 }
926
927 lla = &ifp->in_ifaddrs[IPV6_IFADDR_IX_LINKLOCAL];
928
929 /* プレフィックスマスクを生成する。*/
930 in6_plen2pmask(&mask, pr->prefix_len);
931
932 /* アドレスを生成する。*/
933 for (ix = 0; ix < 4; ix ++)
934 addr.s6_addr32[ix] = (pr->prefix.s6_addr32[ix] & mask.s6_addr32[ix])
935 | ( lla->addr.s6_addr32[ix] & ~mask.s6_addr32[ix]);
936
937 in6_update_ifa(ifp, ia, &addr, pr->prefix_len, vltime,
938 pr->pltime, router_index, pr - nd6_prefix,
939 IN6_IFF_AUTOCONF | IN6_IFF_NODAD);
940 }
941 }
942
943 else { /* 未登録のとき */
944
945 /*
946 * プレフィックス長をチェックする。
947 * もし、プレフィックス長とインタフェース ID の合計が
948 * 128 ビットに一致しない時は、プレフィックス情
949報を無視する。
950 */
951 if ((ifidlen = in6_if2idlen(ifp)) < 0)
952 syslog(LOG_ERROR, "[ND6 RTR] IFID undefined.");
953 else if (ifidlen + pr->prefix_len != 128)
954 syslog(LOG_NOTICE, "[ND6 RTR] invalid prefix len: %d.", pr->prefix_len);
955 else {
956
957 for (ix = NUM_IN6_IFADDR_ENTRY; ix --; ) {
958 ia = &ifp->in_ifaddrs[ix];
959 if ((ia->flags & IN6_IFF_DEFINED) == 0) {
960 in6_ifadd(pr, ia, router_index);
961 pfxlist_onlink_check();
962 break;
963 }
964 }
965
966 if (ix < 0)
967 syslog(LOG_ERROR, "[ND6 RTR] prefix update failed.");
968 }
969 }
970 syscall(sig_sem(SEM_ND6_DEFRTRLIST));
971 }
972
973/*
974 * nd6_prelist_timer -- プレフィックス・リストの管理タイマー
975 */
976
977void
978nd6_prelist_timer (void)
979{
980 T_ND6_PREFIX *pr;
981 SYSTIM now;
982 int_t ix;
983
984 syscall(get_tim(&now));
985 now /= SYSTIM_HZ; /* 有効時間の単位は [s] */
986
987 syscall(wai_sem(SEM_ND6_DEFRTRLIST));
988 for (ix = NUM_ND6_PREFIX_ENTRY; ix -- > 0; ) {
989 pr = &nd6_prefix[ix];
990 if ((pr->flags & ND6_PREFIX_STATE_BUSY) != 0 && (int32_t)(pr->expire - now) <= 0)
991 /* pr->expire <= now */
992 prelist_remove(pr);
993 }
994 syscall(sig_sem(SEM_ND6_DEFRTRLIST));
995 }
996
997/*
998 * nd6_rs_output -- ルータ要請を出力する。
999 */
1000
1001static void
1002nd6_rs_output (void)
1003{
1004 T_ROUTER_SOLICIT_HDR *rsh;
1005 T_NET_BUF *output;
1006 T_IN6_IFADDR *ifa;
1007 T_IN6_ADDR *saddr;
1008 uint16_t len;
1009
1010 NET_COUNT_ICMP6(net_count_nd6[NC_ND6_RS_OUT_PACKETS], 1);
1011
1012 /*
1013 * 送信å…
1014ƒã‚¢ãƒ‰ãƒ¬ã‚¹ã«ã¯ã€ãƒªãƒ³ã‚¯ãƒ­ãƒ¼ã‚«ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹ã‚’設定するが、
1015 * まだ設定されいなければ、無指定を設定する。
1016 */
1017 if ((ifa = in6ifa_ifpwithix(IF_GET_IFNET(), IPV6_IFADDR_IX_LINKLOCAL)) != NULL && !IFA6_IS_NOTREADY(ifa))
1018 saddr = &ifa->addr;
1019 else
1020 saddr = &in6_addr_unspecified;
1021
1022 len = (ROUTER_SOLICIT_HDR_SIZE + 7) >> 3 << 3;
1023
1024 /* ネットワークバッファを獲得し、IPv6 ヘッダを設定する。*/
1025 if (in6_get_datagram(&output, len, 0, &in6_addr_linklocal_allrouters,
1026 saddr, IPPROTO_ICMPV6,
1027 IPV6_MAXHLIM, NBA_SEARCH_ASCENT, TMO_ND6_RS_OUTPUT) != E_OK)
1028 return;
1029
1030 /* ルータ要請ヘッダを設定する。*/
1031 rsh = GET_ROUTER_SOLICIT_HDR(output, IF_IP6_ROUTER_SOLICIT_HDR_OFFSET);
1032 rsh->hdr.type = ND_ROUTER_SOLICIT;
1033 rsh->hdr.code = 0;
1034 rsh->nd_rs_reserved = 0;
1035
1036 /* チェックサムを計算する。*/
1037 rsh->hdr.sum = 0;
1038 rsh->hdr.sum = in6_cksum(output, IPPROTO_ICMPV6, (uint8_t*)rsh - output->buf, len);
1039
1040 /* 送信する。*/
1041 NET_COUNT_ICMP6(net_count_nd6[NC_ICMP6_OUT_OCTETS],
1042 output->len - GET_IF_IP6_HDR_SIZE(output));
1043 NET_COUNT_ICMP6(net_count_nd6[NC_ICMP6_OUT_PACKETS], 1);
1044 NET_COUNT_MIB(icmp6_ifstat.ipv6IfIcmpOutMsgs, 1);
1045 NET_COUNT_MIB(icmp6_ifstat.ipv6IfIcmpOutRouterSolicits, 1);
1046 ip6_output(output, IPV6_OUT_SET_HOP_LIMIT(IPV6_OUT_FLG_HOP_LIMIT, IPV6_MAXHLIM), TMO_ND6_RS_OUTPUT);
1047 }
1048
1049/*
1050 * nd6_defrtrlist_lookup -- ディフォルトルータ・リストを探索する。
1051 */
1052
1053T_DEF_ROUTER *
1054nd6_defrtrlist_lookup (T_IN6_ADDR *src)
1055{
1056 T_DEF_ROUTER *dr = NULL;
1057 int_t ix;
1058
1059 for (ix = def_router_count; ix -- > 0; ) {
1060 dr = &nd6_def_router[ix];
1061 if (IN6_ARE_ADDR_EQUAL(&dr->addr, src)) {
1062 return dr;
1063 }
1064 }
1065 return NULL;
1066 }
1067
1068/*
1069 * nd6_router_lookup -- ルータのアドレスを返す。
1070 *
1071 */
1072
1073T_IN6_ADDR *
1074nd6_router_lookup (void)
1075{
1076 if (def_router_count > 0)
1077 return &nd6_def_router[0].addr;
1078 else
1079 return NULL;
1080 }
1081
1082/*
1083 * nd6_defrtrlist_del -- ディフォルトルータ・リストからルータを削除する。
1084 *
1085 * 注意: この関数を呼び出すときは、SEM_ND6_DEFRTRLIST で、
1086 * ロックしてから呼び出すこと。
1087 */
1088
1089void
1090nd6_defrtrlist_del (T_DEF_ROUTER *dr)
1091{
1092 T_IFNET *ifp = IF_GET_IFNET();
1093 T_IN6_IFADDR *ia;
1094 T_ND6_PREFIX *pr;
1095 uint_t mask;
1096 int_t ix, rix, pix, rtrix = dr - nd6_def_router;
1097
1098 if ((ia = in6ifa_ifpwithrtrix(ifp, rtrix)) != NULL) {
1099 /*
1100 * ネットワークインタフェースのプレフィックスを通知した
1101 * ルータを到達不能にする。
1102 */
1103 ia->router_index = IN6_RTR_IX_UNREACH;
1104 }
1105
1106 /* プレフィックスリストからルータを削除する。*/
1107 mask = make_mask(rtrix);
1108 for (pix = NUM_ND6_PREFIX_ENTRY; pix --; )
1109 nd6_prefix[pix].routermap &= ~mask;
1110
1111 /* 削除したルータ以降を前に詰める。*/
1112 for (rix = rtrix + 1; rix < def_router_count; rix ++)
1113 nd6_def_router[rix - 1] = nd6_def_router[rix];
1114
1115 /* プレフィックスリストのルータも更新する。*/
1116 if (dr != nd6_def_router) {
1117
1118 /* マスクを生成する。*/
1119 mask = 1;
1120 for (ix = rtrix - 1; ix -- > 0; )
1121 mask = (mask << 1) | 1;
1122
1123 for (pix = NUM_ND6_PREFIX_ENTRY; pix --; ) {
1124 pr = &nd6_prefix[pix];
1125 pr->routermap = (pr->routermap & mask) | (((pr->routermap & ~mask) >> 1) & ~mask);
1126 }
1127 }
1128 def_router_count --;
1129
1130 /* プレフィックスのオンリンク状æ…
1131‹ã‚’確認する。*/
1132 pfxlist_onlink_check();
1133
1134 /*
1135 * 削除するルータが優å…
1136ˆãƒ‡ã‚£ãƒ•ã‚©ãƒ«ãƒˆãƒ«ãƒ¼ã‚¿ã®å ´åˆã¯ã€
1137 * 優å…
1138ˆãƒ‡ã‚£ãƒ•ã‚©ãƒ«ãƒˆãƒ«ãƒ¼ã‚¿ã‚’選択しなおす。
1139 */
1140 if (rtrix == 0)
1141 defrouter_select();
1142 }
1143
1144/*
1145 * nd6_defrtrlist_timer -- ディフォルトルータ・リストの管理タイマー
1146 */
1147
1148void
1149nd6_defrtrlist_timer (void)
1150{
1151 T_DEF_ROUTER *dr;
1152 SYSTIM now;
1153 int_t ix;
1154
1155 syscall(get_tim(&now));
1156
1157 syscall(wai_sem(SEM_ND6_DEFRTRLIST));
1158 for (ix = def_router_count; ix -- > 0; ) {
1159 dr = &nd6_def_router[ix];
1160 if ((int32_t)(dr->expire - now) <= 0) {
1161 /* dr->expire <= now */
1162 nd6_defrtrlist_del(dr);
1163 }
1164 }
1165 syscall(sig_sem(SEM_ND6_DEFRTRLIST));
1166 }
1167
1168/*
1169 * nd6_get_drl -- ディフォルトルータ・リストを獲得する。
1170 */
1171
1172const T_DEF_ROUTER *
1173nd6_get_drl (uint_t *count)
1174{
1175 *count = def_router_count;
1176 return nd6_def_router;
1177 }
1178
1179/*
1180 * nd6_get_prl -- プレフィックス・リストを獲得する。
1181 */
1182
1183const T_ND6_PREFIX *
1184nd6_get_prl (void)
1185{
1186 return nd6_prefix;
1187 }
1188
1189#endif /* of #if NUM_ND6_DEF_RTR_ENTRY > 0 */
1190
1191/*
1192 * nd6_ra_input -- ルータ通知のå…
1193¥åŠ›å‡¦ç†ã€‚
1194 */
1195
1196void
1197nd6_ra_input (T_NET_BUF *input, uint_t off)
1198{
1199#if NUM_ND6_DEF_RTR_ENTRY > 0
1200
1201 T_IFNET *ifp = IF_GET_IFNET();
1202 T_IP6_HDR *ip6h;
1203 T_ROUTER_ADVERT_HDR *rah;
1204 T_ND_OPT_HDR *opth;
1205 SYSTIM now;
1206 int_t rix;
1207 uint_t lladdr_len = 0;
1208 uint32_t advrea;
1209 uint8_t *lladdr = NULL;
1210 uint8_t nd_opt_off[ND_OPT_OFF_ARRAY_SIZE];
1211
1212 NET_COUNT_ICMP6(net_count_nd6[NC_ND6_RA_IN_PACKETS], 1);
1213
1214 ip6h = GET_IP6_HDR(input);
1215
1216 /*
1217 * ヘッダのチェック、以下の場合は破棄する。
1218 * ・ホップリミットが IPV6_MAXHLIM (255) 以外
1219 * ・ヘッダ長が短い
1220 * ・始点アドレスが、リンクローカルではない (RFC2461)
1221 */
1222 if (ip6h->hlim != IPV6_MAXHLIM ||
1223 input->len - off < ROUTER_ADVERT_HDR_SIZE ||
1224 !IN6_IS_ADDR_LINKLOCAL(&ip6h->src))
1225 goto err_ret;
1226
1227 rah = GET_ROUTER_ADVERT_HDR(input, off);
1228
1229 /* 近隣探索オプションのオフセットを記録する。*/
1230 if (nd6_options(nd_opt_off, input->buf + (off + ROUTER_ADVERT_HDR_SIZE),
1231 input->len - (off + ROUTER_ADVERT_HDR_SIZE)) != E_OK)
1232 goto err_ret;
1233 /*
1234 * 到達可能状æ…
1235‹ã®æœ‰åŠ¹æ™‚間の更新
1236
1237 */
1238 if (rah->reachable) {
1239 advrea = ntohl(rah->reachable) * SYSTIM_HZ / 1000; /* rah->reachable の単位は ms */
1240 if (advrea <= ND6_MAX_REACHABLE_TIME &&
1241 advrea != nd6_base_reachable_time) {
1242 syscall(get_tim(&now));
1243 nd6_recalc_reachtm_interval
1244 = now + ND6_RECALC_REACHTM_INTERVAL;
1245 nd6_base_reachable_time = advrea;
1246 nd6_reachable_time
1247 = ND6_CALC_REACH_TIME(nd6_base_reachable_time);
1248 }
1249 }
1250
1251 /* 近隣探索の送信間隔の更新 */
1252 if (rah->retransmit) {
1253 nd6_retrans_time = ntohl(rah->retransmit) * SYSTIM_HZ / 1000;
1254 /* rah->retransmit の単位は ms */
1255 }
1256
1257 /* ホップリミットの規定値の更新 */
1258 if (rah->nd_ra_current_hoplimit) {
1259 ip6_defhlim = rah->nd_ra_current_hoplimit;
1260 }
1261
1262 /* ディフォルトルータリストの更新 */
1263 rix = defrtrlist_update(&ip6h->src,
1264 ntohs(rah->nd_ra_router_lifetime),
1265 rah->nd_ra_flags); /* rah->nd_ra_router_lifetime の単位は秒 */
1266
1267 /* プレフィックスリストの更新 */
1268 if (nd_opt_off[ND_OPT_OFF_ARRAY_IX(ND_OPT_PREFIX_INFO_COUNT)]) {
1269 T_ND_OPT_PREFIX_INFO *pi;
1270 uint_t pi_off, pi_count;
1271
1272 pi_count = nd_opt_off[ND_OPT_OFF_ARRAY_IX(ND_OPT_PREFIX_INFO_COUNT)];
1273 pi_off = off + ROUTER_ADVERT_HDR_SIZE
1274 + nd_opt_off[ND_OPT_OFF_ARRAY_IX(ND_OPT_PREFIX_INFORMATION)] - 8;
1275 /* 注意: オプションオフセットé…
1276åˆ—には、オフセット + 8 が設定されている。*/
1277 while (pi_count -- > 0) {
1278 pi = (T_ND_OPT_PREFIX_INFO*)(input->buf + pi_off);
1279 if (pi->type != ND_OPT_PREFIX_INFORMATION)
1280 /* オプションタイプがプレフィックス情
1281報でなければ何もしない。*/
1282 ;
1283 else if (pi->len != 4)
1284 /* プレフィックス情
1285報の長さが 32 (8×4) でなければ不正 */
1286 syslog(LOG_NOTICE, "[ND6 RTR] prefix opt len: %d.", pi->len);
1287 else if (pi->prefix_len > 128)
1288 /* プレフィックス長は 128 ビット以下 */
1289 syslog(LOG_NOTICE, "[ND6 RTR] prefix len: %d.", pi->prefix_len);
1290 else if (IN6_IS_ADDR_MULTICAST(&pi->prefix) ||
1291 IN6_IS_ADDR_LINKLOCAL(&pi->prefix))
1292 /* マルチキャストとリンクローカルは不正 */
1293 syslog(LOG_NOTICE, "[ND6 RTR] invalid addr: %s from %s.",
1294 ipv62str(NULL, &pi->prefix), ipv62str(NULL, &ip6h->src));
1295#if 0 /* FreeBSD 6.3 で削除されている。*/
1296 else if (IN6_IS_ADDR_AGGREGATE_UNICAST(&pi->prefix) &&
1297 (pi->prefix_len != 64) )
1298 /* 集約可能ユニキャストで、プレフィックス長が 64 ビット以外は不正 */
1299 syslog(LOG_NOTICE, "[ND6 RTR] invalid prefix len for global: %d.", pi->prefix_len);
1300#endif
1301 else if (ntohl(pi->preferred) > ntohl(pi->valid))
1302 /* 推奨有効時間が有効時間より長ければ不正 */
1303 syslog(LOG_NOTICE, "[ND6 RTR] preferred(%d) > valid time(%d).", ntohl(pi->preferred), ntohl(pi->valid));
1304 else {
1305 syslog(LOG_NOTICE, "[ND6 RTR] update prefix: %s from %s.",
1306 ipv62str(NULL, &pi->prefix), ipv62str(NULL, &ip6h->src));
1307 if (rix >= 0) {
1308 /*
1309 * defrtrlist_update の戻り値は、ルータのインデックス。
1310 * ただし、値が -1 なら、プレフィックス・リストは更新しない。
1311 */
1312 prelist_update(pi, rix); /* プレフィックス・リストを更新する。*/
1313 }
1314 }
1315 pi_off += pi->len << 3; /* オプション長の単位は 8 バイト */
1316 }
1317 }
1318
1319 /* MTU の更新 */
1320 if (nd_opt_off[ND_OPT_OFF_ARRAY_IX(ND_OPT_MTU)]) {
1321 T_ND_OPT_MTU_HDR *optmtuh;
1322 uint32_t mtu;
1323
1324 optmtuh = (T_ND_OPT_MTU_HDR *)((uint8_t *)(input->buf + off + ROUTER_ADVERT_HDR_SIZE) +
1325 nd_opt_off[ND_OPT_OFF_ARRAY_IX(ND_OPT_MTU)] - 8);
1326
1327 /*
1328 * 値のチェック
1329 *
1330 * オプション長: 1
1331 * 予約: 0
1332 */
1333 if (optmtuh->len != 1 || optmtuh->reserved != 0)
1334 goto err_ret;
1335
1336 /* MTU が IPv6 MMTU(1280 オクテット)以下なら無視する。*/
1337 mtu = ntohl(optmtuh->mtu);
1338 if (mtu >= IPV6_MMTU) {
1339 if (mtu <= (linkmtu > IF_MTU ? linkmtu : IF_MTU))
1340 linkmtu = mtu;
1341 }
1342 }
1343
1344 /*
1345 * ルータの始点リンクアドレスを近隣キャッシュに登録する。
1346 */
1347 if (nd_opt_off[ND_OPT_OFF_ARRAY_IX(ND_OPT_SOURCE_LINKADDR)]) {
1348 opth = (T_ND_OPT_HDR *)((uint8_t *)(input->buf + off + ROUTER_ADVERT_HDR_SIZE) +
1349 nd_opt_off[ND_OPT_OFF_ARRAY_IX(ND_OPT_SOURCE_LINKADDR)] - 8);
1350 /* 注意: オプションオフセットé…
1351åˆ—には、オフセット + 8 が設定されている。*/
1352 lladdr = (uint8_t *)(opth + 1);
1353 lladdr_len = (opth->len << 3);
1354 }
1355
1356 /*
1357 * ネットワークインタフェースのアドレス長が一致しなければエラー
1358 */
1359 if (lladdr && lladdr_len != ((sizeof(T_IF_ADDR) + sizeof(T_ND_OPT_HDR) + 7) & ~7))
1360 goto err_ret;
1361
1362 /* 近隣キャッシュに登録する。*/
1363 nd6_cache_lladdr(ifp, &ip6h->src, (T_IF_ADDR *)lladdr, ND_ROUTER_ADVERT, 0);
1364
1365 /*
1366 * ルータの始点リンクアドレスを近隣キャッシュに登録したので、
1367 * オンリンク状æ…
1368‹ãŒå¤‰åŒ–する可能性があるため、それをチェックする。
1369 */
1370 pfxlist_onlink_check();
1371
1372 syscall(rel_net_buf(input));
1373 return;
1374
1375err_ret:
1376 NET_COUNT_ICMP6(net_count_nd6[NC_ICMP6_IN_ERR_PACKETS], 1);
1377 syscall(rel_net_buf(input));
1378
1379#else /* of #if NUM_ND6_DEF_RTR_ENTRY > 0 */
1380
1381 /*
1382 * ルータ通知を受信しない場合は、破棄して終了する。
1383 */
1384 NET_COUNT_ICMP6(net_count_nd6[NC_ND6_RA_IN_PACKETS], 1);
1385 syscall(rel_net_buf(input));
1386
1387#endif /* of #if NUM_ND6_DEF_RTR_ENTRY > 0 */
1388 }
1389
1390#if NUM_ND6_RTR_SOL_RETRY > 0
1391
1392/*
1393 * nd6_rtrsol_ctl -- ルータ要請出力の制御
1394 */
1395
1396void
1397nd6_rtrsol_ctl (void)
1398{
1399 T_IN6_IFADDR *ifa;
1400 int_t try;
1401
1402 /* リンクローカルアドレスのアドレス情
1403報を得る。*/
1404 if ((ifa = in6ifa_ifpwithix(IF_GET_IFNET(), IPV6_IFADDR_IX_LINKLOCAL)) == NULL)
1405 return;
1406
1407 /* リンクローカルアドレスの重複検出終了を待
1408つ。*/
1409 do {
1410 /* リンクローカルアドレスの重複検出終了待
1411ち時間を設定する。*/
1412 syscall(dly_tsk(net_rand() % TMO_ND6_RTR_SOL_DELAY));
1413
1414 /* 待
1415っている間に重複が検出されたら終了する。*/
1416 if (ifa->flags & IN6_IFF_DUPLICATED)
1417 return;
1418
1419 } while (!((ifa->flags & IN6_IFF_DEFINED) && (ifa->flags & IN6_IFF_TENTATIVE) == 0));
1420
1421 for (try = 0; try < NUM_ND6_RTR_SOL_RETRY; try ++) {
1422
1423 /* ディフォルトルータ・リストにエントリがあれば終了 */
1424 if (def_router_count > 0)
1425 return;
1426
1427 /* ルータ要請を出力する。*/
1428 nd6_rs_output();
1429
1430 /* 出力の 2 回目以降の遅
1431延時間を設定する。*/
1432 syscall(dly_tsk(TMO_ND6_RTR_SOL_INTERVAL));
1433 }
1434 }
1435
1436#endif /* of #if NUM_ND6_RTR_SOL_RETRY > 0 */
1437
1438/*
1439 * nd6_onlink_prefix_lookup -- プレフィックスを探索する。
1440 */
1441
1442T_ND6_PREFIX *
1443nd6_onlink_prefix_lookup (T_IN6_ADDR *dst)
1444{
1445 SYSTIM now;
1446 T_ND6_PREFIX *pr;
1447 int_t ix;
1448
1449 syscall(get_tim(&now));
1450 now /= SYSTIM_HZ;
1451
1452 /* 推奨有効時間内
1453のプレフィックスを探索する。*/
1454 for (ix = NUM_ND6_PREFIX_ENTRY; ix -- > 0; ) {
1455 pr = &nd6_prefix[ix];
1456 if ((pr->flags & ND6_PREFIX_STATE_BUSY) &&
1457 (pr->flags & ND6_PREFIX_FLAG_ONLINK) &&
1458 in6_are_prefix_equal(dst, &pr->prefix, pr->prefix_len) &&
1459 (int32_t)(pr->preferred - now) > 0) {
1460 /* pr->preferred > now */
1461 return pr;
1462 }
1463 }
1464
1465 /* 有効時間内
1466のプレフィックスを探索する。*/
1467 for (ix = NUM_ND6_PREFIX_ENTRY; ix -- > 0; ) {
1468 pr = &nd6_prefix[ix];
1469 if ((pr->flags & ND6_PREFIX_STATE_BUSY) &&
1470 (pr->flags & ND6_PREFIX_FLAG_ONLINK) &&
1471 in6_are_prefix_equal(dst, &pr->prefix, pr->prefix_len) &&
1472 (int32_t)(pr->expire - now) > 0) {
1473 /* pr->expire > now */
1474 return pr;
1475 }
1476 }
1477
1478 return NULL;
1479 }
1480
1481#endif /* of #ifdef SUPPORT_INET6 */
Note: See TracBrowser for help on using the repository browser.