仙石浩明の日記

2006年3月30日

glibc 2.3 での IPv6

一年以上前に tech ML で取り上げたネタなのですが、現在よく使われている Linux ディストリビューションでも glibc 2.3.2 あたりが使われることもある ようなので紹介します。


KLab のイントラのサーバには、IPv6 なアドレスも割り当ててあります。 例えば、

% host kamiya.v6.klab.org
kamiya.v6.klab.org has IPv6 address 2001:c90:c1c:100e:2e0:81ff:feab:cdef

% host 2001:c90:c1c:100e:2e0:81ff:feab:cdef
f.e.d.c.b.a.e.f.f.f.1.8.0.e.2.0.e.0.0.1.c.1.c.0.0.9.c.0.1.0.0.2.ip6.arpa domain name pointer kamiya.v6.klab.org.

のような感じ。kamiya というホスト名は KLab が六本木ヒルズへ移転してくる 前は、神谷町にオフィスがあったことにちなんでいます。イントラのサーバ群に は地名がつけられているマシンが多く、もちろん roppongi というホスト名の マシンもあります。

で、当時は Linux サーバの多くは glibc 2.2 を使っていたのですが、一部の マシンは glibc 2.3 にバージョンアップしていました。ところが、glibc 2.3 な マシンから ping6 を打ってみると異様に遅い...

% time ping6 -c 3 kamiya.v6.klab.org
PING kamiya.v6.klab.org(kamiya.v6.klab.org) 56 data bytes
64 bytes from kamiya.v6.klab.org: icmp_seq=1 ttl=64 time=1.10 ms
64 bytes from kamiya.v6.klab.org: icmp_seq=2 ttl=64 time=0.563 ms
64 bytes from kamiya.v6.klab.org: icmp_seq=3 ttl=64 time=0.363 ms

--- kamiya.v6.klab.org ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 20022ms
rtt min/avg/max/mdev = 0.338/0.475/0.569/0.102 ms
0.006u 0.004s 0:40.04 0.0%      0+0k 0+0io 0pf+0w

3 発 ping を打つだけなのに 40 秒もかかっています。-n オプションを 指定して、逆引きを抑制すると、

% time ping6 -nc 3 kamiya.v6.klab.org
PING kamiya.v6.klab.org(2001:c90:c1c:100e:2e0:81ff:feab:cdef) 56 data bytes
64 bytes from 2001:c90:c1c:100e:2e0:81ff:feab:cdef: icmp_seq=1 ttl=64 time=0.981 ms
64 bytes from 2001:c90:c1c:100e:2e0:81ff:feab:cdef: icmp_seq=2 ttl=64 time=0.354 ms
64 bytes from 2001:c90:c1c:100e:2e0:81ff:feab:cdef: icmp_seq=3 ttl=64 time=0.273 ms

--- kamiya.v6.klab.org ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2002ms
rtt min/avg/max/mdev = 0.273/0.536/0.981/0.316 ms
0.003u 0.004s 0:02.02 0.0%      0+0k 0+0io 0pf+0w

などとフツーに 2 秒程度で終わるので、DNS の逆引きに問題があることが 分かります。一回の逆引きに 10 秒ほどかかっているようです。 てっきりネームサーバの設定の問題かと思ったのですが、host コマンドや dnsqr コマンドを使う限り、このような遅れは生じません。ping6 をはじめ、 glibc の getnameinfo(3) を使う場合だけ遅延が発生します。

後で気づいたのですが、この問題が起きるのは glibc 2.3 だけで glibc 2.2 では起きません (つまり kamiya とかでは正常に ping6 できる)。また、 当然ながら glibc 2.3 でも IP の逆引きは正常で、問題なのは IPv6 の逆引き だけです。

# 後述するように問題があるのは glibc 2.3.3 までで 2.3.4 は問題ありません こーいうときは tcpdump が基本だよね、つーことでパケットダンプしてみると、 getnameinfo(3) の場合は、

\[x20010c900c1c100e02e081fffeabcdef/128].ip6.arpa.

というクエリがまず飛び、10 秒ほどたってタイムアウトした後に

f.e.d.c.b.a.e.f.f.f.1.8.0.e.2.0.e.0.0.1.c.1.c.0.0.9.c.0.1.0.0.2.ip6.arpa.

というクエリが飛ぶことが分かりました。前者は見慣れない形式だったのですが、 「Binary Label」ないし「Bit-String」などと呼ばれる形式のようです (ちなみ に後者は nibble 形式)。「Binary Label」は、ドメイン名の一形式として RFC1035 で規定され、DNS での使い方が RFC2673 で決められたにもかかわらず、 ネームサーバでサポートされなかったために、RFC3363 で IPv6 の逆引きの方法 としては、使うのを断念されてしまった不幸な形式のようです。

とはいえ、「DNS で、どーして上位バイトが先にくるんだ~ 実装のこと何も 考えてないな~」と脊髄反射的に拒否したくなる、頭悪い (brain damaged) 形式なので、断念されて幸い、ということもできますね。

2002年8月に RFC3363 で正式に断念された形式なら、そのまま人々の記憶から 忘れ去られて欲しかったのですが、何を血迷ったか、glibc 2.3 は IPv6 の 逆引きで、まず「Bit-String」クエリを試し、タイムアウトしたら「nibble」 クエリを送信するという実装になっています (glibc の resolv は BIND 由来 だから?)。

少なくとも 2004年8月3日に公開された glibc 2.3.3 では Bit-String が デフォルトのままですね。一刻も早く Bit-String が使われなくなることを 願ってやみません。

願ってるだけではアレ (^^;) なので、ソースを見てみると、 glibc-2.3.3/resolv/nss_dns/dns-host.c (2003年10月26日) では

case AF_INET6:
  /* XXX Maybe we need an option to select whether to use the nibble
     or the bitfield form.  The RFC requires the bitfield form so
     we use it.  */

って書いてありますね (Maybe って書くくらいならオプション指定できるように しろよ...)。これが glibc-2.3.4/resolv/nss_dns/dns-host.c (2004年10月25日) だと

case AF_INET6:
  /* Only lookup with the byte string format if the user wants it.  */
  if (__builtin_expect (_res.options & RES_USEBSTRING, 0))
    {
      qp = stpcpy (qbuf, "\\[x");
      ...

に修正されています! つまりデフォルトでは nibble 形式に変更されたんです ね。めでたしめでたし。さっさと glibc 2.3.4 (2005年1月26日) に上げよっと。

...と書いてる間に自宅マシンで 2.3.4 を make して install してみました。 無事、getnameinfo(3) が遅延なく IPv6 の逆引きができるようになりました。 メール書いているうちに自己完結してしまったわけですが、まあ何かの参考に なるかも知れないし、IPv6 に興味を持ってくれる人が増えるといいな、 ということで tech に投げておきます。

#12237                                                          仙石 浩明
https://www.gcd.org/sengoku/             Hiroaki Sengoku <sengoku@gcd.org>

No Comments »

No comments yet.

RSS feed for comments on this post.

Leave a comment