[#29736] [提案] Kernel#p をもっと便利に — "Yusuke ENDOH" <mame@...>

遠藤侑介と申します。

19 messages 2006/11/01

[#29765] merge with YARV — SASADA Koichi <ko1@...>

 ささだです。

16 messages 2006/11/03

[#29767] 1.8 proposal of RUBY_PATCHLEVEL — URABE Shyouhei <root@...>

-----BEGIN PGP SIGNED MESSAGE-----

52 messages 2006/11/04
[#29771] Re: 1.8 proposal of RUBY_PATCHLEVEL — Shugo Maeda <shugo@...> 2006/11/04

前田です。

[#29925] ruby -v — Urabe Shyouhei <shyouhei@...>

卜部です。

28 messages 2006/11/24

[#29964] 1.8, 1.9, svn化, などなどのまとめ — "U.Nakamura" <usa@...>

こんにちは、なかむら(う)です。

15 messages 2006/11/28

[#29970] BUG: Incorrect handling of Ignorecase matching (regex.c of 1.8.5) — "きむらこういち" <hogemuta@...>

木村です。

15 messages 2006/11/28

[ruby-dev:29744] AIXのgetnameinfoについて

From: "Yutaka Kanemoto" <kinpoco@...>
Date: 2006-11-02 11:24:07 UTC
List: ruby-dev #29744
金本ともうします。
お世話になっています。

今rubyをAIXで ./configure && make しますと、
ext/socketのコンパイルのときに、--enable-wide-getaddrinfolを
使ってください。といわれます。

ためしにこのオプションをつかってもgetnameinfoやgetaddrinfoがhave_funcで
みつかるので、wideのgetaddrinfo等が使われないままコンパイルされます。

原因はext/socket/extconf.rbのgetaddrinfoのcheck codeにおいて、
passivedでgetaddrinfoして返ってきた情報のうち、
AF_INET6のもの('::')をgetnameinfoしたときに、0ではなく、
EAI_NONAMEが返ってくるというものでした。

関係ないかもしれませんが、RFC3493の6.2章にこんな記述がありました。
> If the address is the IPv6 unspecified address ("::"), a lookup is
> not performed, and the [EAI_NONAME] error is returned.

おそらくこれはAIXの仕様なのだと思いました。ただ、返事の内容は
わかりきっているので、このqueryが来たときにはsystemのgetnameinfoを
使わないで返事をかえすwrapperでもつくってしのごうと思いましたが、
google codeでちょっと調べたところ、すでにそのようなHackがあるのを
opensshにみつけました。

http://www.google.com/codesearch?q=show:yh4t_0p1IMw:pZKHUfIHZ8g:2kf_Hlq0QNs&sa=\
N&ct=rd&cs_p=http://gentoo.osuosl.org/distfiles/openssh-4.0p1.tar.gz&cs_f=opens\
sh-4.0p1/openbsd-compat/port-aix.c

この一番下のsshaix_getnameinfoという関数です。

これをflagが省略されても返せるようにしたpatchにしてみました。とりあえず
extconf.rbのこの部分のtestをAIXの時だけバイパスするようにしたところ、

patch適用前
$ ~/r18oi/bin/ruby -r socket -e 'p Socket.getnameinfo([nil, 80, "::"]) '
-e:1:in `getnameinfo': getnameinfo: Hostname and service name not provided or f\
ound (SocketError)
        from -e:1
となっていたところが、
patch適用後
$ ~/r18/bin/ruby -r socket -e 'p Socket.getnameinfo([nil, 80, "::"]) '
["::", "80"]

となります。このpatchがないと、たとえば、
> require 'webrick'
> include WEBrick
> s = HTTPServer.new(
>   :Port            => 2000,
>   :DocumentRoot    => Dir::pwd + "/htdocs"
> )
のようなコードで
> /home/kanemoto/r18oi/lib/ruby/1.8/webrick/utils.rb:63:in `getaddrinfo': \
> getnameinfo: Hostname and service name not provided or found (SocketError)
というエラーがおきます。BindAddressを指定しないといけなくなってしまいます。

extconf.rbのtestはバイパスするぐらいしか思いつかなかったのですが、
これでAIXでだいぶ幸せになれます。採用いただけませんでしょうか?

このパッチで、
./configure ; make; make install
ですむようになり、AIX5.2TL9で1.8は、make checkで 0F0E でした。

よろしくおねがいいたします。
-- 
Yutaka KANEMOTO
http://d.hatena.ne.jp/kinpoco/

Attachments (1)

getnameinfo.patch (1.92 KB, text/x-diff)
Index: ext/socket/extconf.rb
===================================================================
RCS file: /src/ruby/ext/socket/extconf.rb,v
retrieving revision 1.36.2.9
diff -U2 -r1.36.2.9 extconf.rb
--- ext/socket/extconf.rb	2 Sep 2006 19:44:42 -0000	1.36.2.9
+++ ext/socket/extconf.rb	2 Nov 2006 09:53:54 -0000
@@ -157,4 +157,8 @@
         goto bad;
 #if defined(_AIX)
+      if (ai->ai_family == AF_INET6 && passive) {
+        inet6++;
+        continue;
+      }
       ai->ai_addr->sa_len = ai->ai_addrlen;
       ai->ai_addr->sa_family = ai->ai_family;
Index: ext/socket/socket.c
===================================================================
RCS file: /src/ruby/ext/socket/socket.c,v
retrieving revision 1.108.2.56
diff -U2 -r1.108.2.56 socket.c
--- ext/socket/socket.c	26 Sep 2006 23:31:35 -0000	1.108.2.56
+++ ext/socket/socket.c	2 Nov 2006 09:53:54 -0000
@@ -199,4 +199,32 @@
 #undef getaddrinfo
 #define getaddrinfo(node,serv,hints,res) ruby_getaddrinfo__aix((node),(serv),(hints),(res))
+static int
+ruby_getnameinfo__aix(sa, salen, host, hostlen, serv, servlen, flags)
+     const struct sockaddr *sa;
+     size_t salen;
+     char *host;
+     size_t hostlen;
+     char *serv;
+     size_t servlen;
+     int flags;
+{
+  struct sockaddr_in6 *sa6;
+  u_int32_t *a6;
+
+  if (sa->sa_family == AF_INET6) {
+    sa6 = (struct sockaddr_in6 *)sa;
+    a6 = sa6->sin6_addr.u6_addr.u6_addr32;
+
+    if (a6[0] == 0 && a6[1] == 0 && a6[2] == 0 && a6[3] == 0) {
+      strncpy(host, "::", hostlen);
+      snprintf(serv, servlen, "%d", sa6->sin6_port);
+      return 0;
+    }
+  }
+  return getnameinfo(sa, salen, host, hostlen, serv, servlen, flags);
+}
+#undef getnameinfo
+#define getnameinfo(sa, salen, host, hostlen, serv, servlen, flags) \
+            ruby_getnameinfo__aix((sa), (salen), (host), (hostlen), (serv), (servlen), (flags))
 #ifndef CMSG_SPACE
 # define CMSG_SPACE(len) (_CMSG_ALIGN(sizeof(struct cmsghdr)) + _CMSG_ALIGN(len))

In This Thread

Prev Next