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);