Index: ext/socket/socket.c =================================================================== --- ext/socket/socket.c (revision 20285) +++ ext/socket/socket.c (working copy) @@ -1414,75 +1414,42 @@ }; static VALUE -make_hostent_internal(struct hostent_arg *arg) +make_hostent(struct hostent *h) { - VALUE host = arg->host; - struct addrinfo* addr = arg->addr; - VALUE (*ipaddr)(struct sockaddr*, size_t) = arg->ipaddr; + VALUE ary, aliases, addresses; + char **a; - struct addrinfo *ai; - struct hostent *h; - VALUE ary, names; - char **pch; - const char* hostp; - char hbuf[NI_MAXHOST]; - ary = rb_ary_new(); - if (addr->ai_canonname) { - hostp = addr->ai_canonname; + rb_ary_push(ary, rb_str_new2(h->h_name)); + + if (h->h_aliases) { + aliases = rb_ary_new(); + for (a = h->h_aliases; *a; ++a) { + rb_ary_push(aliases, rb_str_new2(*a)); + } } else { - hostp = host_str(host, hbuf, sizeof(hbuf)); + aliases = rb_ary_new2(0); } - rb_ary_push(ary, rb_str_new2(hostp)); + rb_ary_push(ary, aliases); - if (addr->ai_canonname && (h = gethostbyname(addr->ai_canonname))) { - names = rb_ary_new(); - if (h->h_aliases != NULL) { - for (pch = h->h_aliases; *pch; pch++) { - rb_ary_push(names, rb_str_new2(*pch)); - } - } + rb_ary_push(ary, INT2NUM(h->h_addrtype)); + + if (h->h_addr_list) { + addresses = rb_ary_new(); + for (a = h->h_addr_list; *a; ++a) { + rb_ary_push(addresses, rb_str_new(*a, h->h_length)); + } } else { - names = rb_ary_new2(0); + addresses = rb_ary_new2(0); } - rb_ary_push(ary, names); - rb_ary_push(ary, INT2NUM(addr->ai_family)); - for (ai = addr; ai; ai = ai->ai_next) { - rb_ary_push(ary, (*ipaddr)(ai->ai_addr, ai->ai_addrlen)); - } + rb_ary_push(ary, addresses); return ary; } static VALUE -make_hostent(VALUE host, struct addrinfo *addr, VALUE (*ipaddr)(struct sockaddr *, size_t)) -{ - struct hostent_arg arg; - - arg.host = host; - arg.addr = addr; - arg.ipaddr = ipaddr; - return rb_ensure(make_hostent_internal, (VALUE)&arg, - RUBY_METHOD_FUNC(freeaddrinfo), (VALUE)addr); -} - -static VALUE -tcp_sockaddr(struct sockaddr *addr, size_t len) -{ - return make_ipaddr(addr); -} - -static VALUE -tcp_s_gethostbyname(VALUE obj, VALUE host) -{ - rb_secure(3); - return make_hostent(host, sock_addrinfo(host, Qnil, SOCK_STREAM, AI_CANONNAME), - tcp_sockaddr); -} - -static VALUE tcp_svr_init(int argc, VALUE *argv, VALUE sock) { VALUE arg1, arg2; @@ -3136,34 +3103,78 @@ return base; } +/* + * call-seq: Socket.inet_aton(host_addr) => in_addr + * + * Converts an IP address in dotted-quad notation into a + * struct in_addr packed as a Ruby string. + * + * === Parameters + * +host_addr+ - The IP address to convert. + * + * === Examples + * require 'socket' + * p Socket.gethostbyaddr(Socket.inet_aton("127.0.0.1")) + */ static VALUE -sock_sockaddr(struct sockaddr *addr, size_t len) +sock_s_inet_aton(VALUE obj, VALUE host_addr) { - char *ptr; + const char *cp; + struct in_addr addr; - switch (addr->sa_family) { - case AF_INET: - ptr = (char*)&((struct sockaddr_in*)addr)->sin_addr.s_addr; - len = sizeof(((struct sockaddr_in*)addr)->sin_addr.s_addr); - break; -#ifdef INET6 - case AF_INET6: - ptr = (char*)&((struct sockaddr_in6*)addr)->sin6_addr.s6_addr; - len = sizeof(((struct sockaddr_in6*)addr)->sin6_addr.s6_addr); - break; -#endif - default: - rb_raise(rb_eSocket, "unknown socket family:%d", addr->sa_family); - break; + cp = StringValueCStr(host_addr); + if (!inet_aton(cp, &addr)) { + rb_raise(rb_eSocket, "invalid host address"); } - return rb_str_new(ptr, len); + return rb_str_new((char *)&addr, sizeof(addr)); } +/* + * call-seq: Socket.inet_ntoa(in_addr) => host_addr + * + * Converts a struct in_addr packed as a Ruby string into an IP + * address in dotted-quad notation. + * + * === Parameters + * +in_addr+ - The packed struct in_addr to convert. + * + * === Examples + * require 'socket' + * hostent = Socket.gethostbyname('localhost') + * hostent[3].each { |in_addr| p Socket.inet_ntoa(in_addr) } + */ static VALUE +sock_s_inet_ntoa(VALUE obj, VALUE addrstr) +{ + struct in_addr *addr; + + addr = (struct in_addr *)StringValuePtr(addrstr); + if (RSTRING_LEN(addrstr) != sizeof(struct in_addr)) { + rb_raise(rb_eSocket, "invalid address"); + } + return rb_str_new2(inet_ntoa(*addr)); +} + +static VALUE sock_s_gethostbyname(VALUE obj, VALUE host) { + struct hostent *h; + char *hostp; + rb_secure(3); - return make_hostent(host, sock_addrinfo(host, Qnil, SOCK_STREAM, AI_CANONNAME), sock_sockaddr); + + hostp = StringValueCStr(host); + h = gethostbyname(hostp); + if (h == NULL) { +#ifdef HAVE_HSTRERROR + extern int h_errno; + rb_raise(rb_eSocket, "%s", (char*)hstrerror(h_errno)); +#else + rb_raise(rb_eSocket, "host not found"); +#endif + } + + return make_hostent(h); } static VALUE @@ -3171,49 +3182,26 @@ { VALUE addr, type; struct hostent *h; - struct sockaddr *sa; - char **pch; - VALUE ary, names; int t = AF_INET; + rb_scan_args(argc, argv, "11", &addr, &type); - sa = (struct sockaddr*)StringValuePtr(addr); + StringValue(addr); if (!NIL_P(type)) { t = NUM2INT(type); } -#ifdef INET6 - else if (RSTRING_LEN(addr) == 16) { - t = AF_INET6; - } -#endif + h = gethostbyaddr(RSTRING_PTR(addr), RSTRING_LEN(addr), t); if (h == NULL) { #ifdef HAVE_HSTRERROR - extern int h_errno; - rb_raise(rb_eSocket, "%s", (char*)hstrerror(h_errno)); + extern int h_errno; + rb_raise(rb_eSocket, "%s", (char*)hstrerror(h_errno)); #else - rb_raise(rb_eSocket, "host not found"); + rb_raise(rb_eSocket, "host not found"); #endif } - ary = rb_ary_new(); - rb_ary_push(ary, rb_str_new2(h->h_name)); - names = rb_ary_new(); - rb_ary_push(ary, names); - if (h->h_aliases != NULL) { - for (pch = h->h_aliases; *pch; pch++) { - rb_ary_push(names, rb_str_new2(*pch)); - } - } - rb_ary_push(ary, INT2NUM(h->h_addrtype)); -#ifdef h_addr - for (pch = h->h_addr_list; *pch; pch++) { - rb_ary_push(ary, rb_str_new(*pch, h->h_length)); - } -#else - rb_ary_push(ary, rb_str_new(h->h_addr, h->h_length)); -#endif - return ary; + return make_hostent(h); } static VALUE @@ -3632,7 +3620,6 @@ rb_define_singleton_method(rb_cIPSocket, "getaddress", ip_s_getaddress, 1); rb_cTCPSocket = rb_define_class("TCPSocket", rb_cIPSocket); - rb_define_singleton_method(rb_cTCPSocket, "gethostbyname", tcp_s_gethostbyname, 1); rb_define_method(rb_cTCPSocket, "initialize", tcp_init, -1); #ifdef SOCKS @@ -3694,6 +3681,8 @@ rb_define_singleton_method(rb_cSocket, "socketpair", sock_s_socketpair, 3); rb_define_singleton_method(rb_cSocket, "pair", sock_s_socketpair, 3); rb_define_singleton_method(rb_cSocket, "gethostname", sock_gethostname, 0); + rb_define_singleton_method(rb_cSocket, "inet_aton", sock_s_inet_aton, 1); + rb_define_singleton_method(rb_cSocket, "inet_ntoa", sock_s_inet_ntoa, 1); rb_define_singleton_method(rb_cSocket, "gethostbyname", sock_s_gethostbyname, 1); rb_define_singleton_method(rb_cSocket, "gethostbyaddr", sock_s_gethostbyaddr, -1); rb_define_singleton_method(rb_cSocket, "getservbyname", sock_s_getservbyname, -1);