前回 (iij4u の IPv6 接続(4))
で、IPv6接続に行き詰って放置していたのだが、新たな情報をコメントにいただいたので、
やってみた。結果からいうと、接続できました。ちゃんと RA からとった prefix の
グローバルアドレスが自動で ppp0 に付くようになりました。感謝。
以下、調べたことと、やったことをメモとして書いておく。
結局のところ NetBSD 限定の内容っぽいので記事のタイトルに NetBSD を追記した。
もちろん、ここに書いた情報の信頼度は?なので、参照する人は一次情報で確認すること。
というか、確認してください。
RA (Router Advertisement) からネットワークアドレス取得とかそういうのは、IPv6 では近隣探索 というものの範疇に入るようで、ND (Neighbor Discopvery) とか NDP (Neighbor Discopvery Protocol) とか略されることもある。
近隣探索のデバッグメッセージの出力は sysctl -w net.inet6.icmp6.nd6_debug=1 で有効にすることができる。有効にした状態で iij4u に pppd で ipv6 接続を試みると、syslog に下のようなメッセージが出力される。
in6_ifadd: wrong prefixlen for ppp0 (prefix=64 ifid=0)
これは in6_ifadd で出力しているもので、in6_ifadd は src/sys/netinet6/nd6_rtr.c 内のルーチンである。RA から取得した prefix 長が 64 であるが、リンクローカルアドレスの interface ID の長さが 0 (prefix 長が128) であるため、エラーとなっている(prefix と ifid の合計が128であることが期待されている)。
in6_ifadd は RA からアドレスを生成してインターフェースに割り当てている。アドレス生成のポリシーは同ルーチン内のコメントにあるが、RAの prefix を取り出して、リンクローカルアドレスの interface ID とつなげて作成するというポリシーは、妥当に思える。
要は PPP 接続で付けられるリンクローカルアドレスの prefix 長が 128 であるのが、
カーネル側で RA を処理する際の前提 (たいていは 64) と食い違っているのが
問題だということだ。
PPP のリンクローカルアドレスの prefix 長を決めているのは pppd(8) で、
具体的には src/usr.sbin/pppd/pppd/sys-bsd.c の中。128 bit に決め打ちである。
どうしてそうなったか、ソースの履歴を調べてみると、次のようになっていた。
src/usr.sbin/pppd/pppd/sys-bsd.c の変遷
Rev.1.32 prefix mask: 128bit (correct?)
Rev.1.33 prefix mask: 64bit
Rev.1.36 prefix mask: 128bit
Sat Jul 21 02:28:06 2001 UTC (8 years, 3 months ago) by itojun
follow kame p2p interface management rule. use /128 when we specify
both src and dst addr on p2p interface. sync with kame
最初自信無げに 128bit であったのが、一度 64bit に修正されて、
その後 128bit に戻されている。
戻ったときのコメントから察すると 2001 年当時の KAME の実装にあわせたっぽい。
関連しそうな RFC を見てみると、次のようになっていた。64bit が妥当な気がするな。
参考
- RFC 3627 Use of /127 Prefix Length Between Routers Considered Harmful
- /127 アドレス有害論。P2P でも /64 を使用するべし。
- RFC 4291 IP Version 6 Addressing Architecture
- そもそも prefix は 64 を超えないように書かれている。
- RFC 5072 IP Version 6 over PPP
- Link-Local の prefix は 10 (fe80::/10) + 54 (padding) = 64
ということで、いただいた情報を基に
prefix を /64 とするようにpppd を作り直してみた。
ifconfig ppp0 の結果
ppp0: flags=8051<UP,POINTOPOINT,RUNNING,MULTICAST> mtu 1400 inet6 fe80:::216:e6ff:fe4c:e70c%ppp0 -> prefixlen 64 scopeid 0x6 inet6 xxxx:xxxx:xxxx:xxxx::216:e6ff:fe4c:e70c -> prefixlen 64
グローバルアドレスは prefixlen 64 で正しく付いているようだ。
リンクローカルアドレスも prefilen 64 になり、P2P の対向のアドレスがなくなった。
hanon$ ping6 -c 1 www.wide.ad.jp PING6(56=40+8+8 bytes) xxxx:xxxx:xxxx:xxxx:216:e6ff:fe4c:e70c --> 2001:200:0:1::5 16 bytes from 2001:200:0:1::5, icmp_seq=0 hlim=57 time=17.162 ms --- www.wide.ad.jp ping6 statistics --- 1 packets transmitted, 1 packets received, 0.0% packet loss round-trip min/avg/max/std-dev = 17.162/17.162/17.162/nan ms
通信には問題ないようだ。
(5) の存在に気付いていませんでした…。
既にお気付きかもしれませんが、例のパッチは若干の修正を加えて、current に commit されています(Rev. 1.61)。NetBSD 6.0 が出るときには(いつ?)取り込まれそうです。
http://cvsweb.netbsd.org/bsdweb.cgi/src/usr.sbin/pppd/pppd/sys-bsd.c