Reentrant version of gethostbyname (XCC)
authorBarret Rhoden <brho@cs.berkeley.edu>
Fri, 5 Jun 2015 19:11:06 +0000 (15:11 -0400)
committerBarret Rhoden <brho@cs.berkeley.edu>
Fri, 12 Jun 2015 16:03:18 +0000 (12:03 -0400)
Ports the plan 9 version of gethostbyname to gethostbyname2_r, and implements
the others with it.  Hard to know if this actually works, since we don't use CS
much.  So it may be just as buggy as it was before, but now is reentrant, and
possibly with new bugs (I had several during this commit).

Also, the old version didn't close the fd in all error cases, so at least
that's fixed now.

Rebuild glibc.

tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/gethstbyad_r.c
tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/gethstbynm.c
tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/gethstbynm2.c
tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/gethstbynm2_r.c
tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/gethstbynm_r.c

index 2509e6b..d2b4a58 100644 (file)
@@ -1,10 +1,47 @@
+/* 
+ * This file is part of the UCB release of Plan 9. It is subject to the license
+ * terms in the LICENSE file found in the top-level directory of this
+ * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
+ * part of the UCB release of Plan 9, including this file, may be copied,
+ * modified, propagated, or distributed except according to the terms contained
+ * in the LICENSE file.
+ */
+/* posix */
+#include <sys/types.h>
+#include <unistd.h>
+
+/* bsd extensions */
+#include <sys/uio.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
 #include <netdb.h>
+#include <errno.h>
+#include <arpa/inet.h>
+
+#include "plan9_sockets.h"
 
+/* similar to gethostbyaddr, just calling the reentrant _r method, and using
+ * inet_ntop instead of the non-reentrant inet_ntoa. */
 int __gethostbyaddr_r(const void *addr, socklen_t len, int type,
                       struct hostent *ret, char *buf, size_t buflen,
                       struct hostent **result, int *h_errnop)
 {
-       return 0;
+       unsigned long y;
+       struct in_addr x;
+       __const unsigned char *p = addr;
+       char name[INET6_ADDRSTRLEN];
+
+       if (type != AF_INET || len != 4) {
+               h_errno = NO_RECOVERY;
+               return -EAFNOSUPPORT;
+       }
+
+       y = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
+       x.s_addr = htonl(y);
+
+       if (!inet_ntop(AF_INET, (void*)&x, name, INET6_ADDRSTRLEN))
+               return -errno;
+
+       return gethostbyname_r(name, ret, buf, buflen, result, h_errnop);
 }
 weak_alias(__gethostbyaddr_r, gethostbyaddr_r);
-stub_warning(gethostbyaddr_r);
index d68da51..69358c9 100644 (file)
@@ -1,135 +1,8 @@
-/* 
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
-
-/* posix */
-#include <sys/types.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <fcntl.h>
-#include <string.h>
-#include <errno.h>
-
-/* bsd extensions */
-#include <sys/uio.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
 #include <netdb.h>
-#include <arpa/inet.h>
-
-#include "plan9_sockets.h"
 
-enum {
-       Nname = 6,
-};
-
-/*
- *  for inet addresses only
- */
 struct hostent *gethostbyname(const char *name)
 {
-       int i, t, fd, m;
-       char *p, *bp;
-       int nn, na;
-       unsigned long x;
-       static struct hostent h;
-       static char buf[1024];
-       static char *nptr[Nname + 1];
-       static char *aptr[Nname + 1];
-       static char addr[Nname][4];
-
-       h.h_name = 0;
-       t = _sock_ipattr(name);
-
-       /* connect to server */
-       fd = open("/net/cs", O_RDWR);
-       if (fd < 0) {
-               h_errno = NO_RECOVERY;
-               return 0;
-       }
-
-       /* construct the query, always expect an ip# back */
-       switch (t) {
-               case Tsys:
-                       snprintf(buf, sizeof buf, "!sys=%s ip=*", name);
-                       break;
-               case Tdom:
-                       snprintf(buf, sizeof buf, "!dom=%s ip=*", name);
-                       break;
-               case Tip:
-                       snprintf(buf, sizeof buf, "!ip=%s", name);
-                       break;
-       }
-
-       /* query the server */
-       if (write(fd, buf, strlen(buf)) < 0) {
-               h_errno = TRY_AGAIN;
-               return 0;
-       }
-       lseek(fd, 0, 0);
-       for (i = 0; i < sizeof(buf) - 1; i += m) {
-               m = read(fd, buf + i, sizeof(buf) - 1 - i);
-               if (m <= 0)
-                       break;
-               buf[i + m++] = ' ';
-       }
-       close(fd);
-       buf[i] = 0;
-
-       /* parse the reply */
-       nn = na = 0;
-       for (bp = buf;;) {
-               p = strchr(bp, '=');
-               if (p == 0)
-                       break;
-               *p++ = 0;
-               if (strcmp(bp, "dom") == 0) {
-                       if (h.h_name == 0)
-                               h.h_name = p;
-                       if (nn < Nname)
-                               nptr[nn++] = p;
-               } else if (strcmp(bp, "sys") == 0) {
-                       if (nn < Nname)
-                               nptr[nn++] = p;
-               } else if (strcmp(bp, "ip") == 0) {
-                       x = inet_addr(p);
-                       x = ntohl(x);
-                       if (na < Nname) {
-                               addr[na][0] = x >> 24;
-                               addr[na][1] = x >> 16;
-                               addr[na][2] = x >> 8;
-                               addr[na][3] = x;
-                               aptr[na] = addr[na];
-                               na++;
-                       }
-               }
-               while (*p && *p != ' ')
-                       p++;
-               if (*p)
-                       *p++ = 0;
-               bp = p;
-       }
-       if (nn + na == 0) {
-               h_errno = HOST_NOT_FOUND;
-               return 0;
-       }
-
-       nptr[nn] = 0;
-       aptr[na] = 0;
-       h.h_aliases = nptr;
-       h.h_addr_list = aptr;
-       h.h_length = 4;
-       h.h_addrtype = AF_INET;
-       if (h.h_name == 0)
-               h.h_name = nptr[0];
-       if (h.h_name == 0)
-               h.h_name = aptr[0];
-
-       return &h;
+       /* not sure if we are supposed to restrict to AF_INET for normal
+        * gethostbyname or not. */
+       return gethostbyname2(name, AF_INET);
 }
index cea6890..a97bdde 100644 (file)
@@ -1,7 +1,21 @@
 #include <netdb.h>
+#include <errno.h>
+#include <assert.h>
 
 struct hostent *gethostbyname2(const char *name, int af)
 {
-       return 0;
+       static struct hostent h;
+       static char buf[1024];
+       int herrno_p, ret_r;
+       struct hostent *ret;
+
+       ret_r = gethostbyname2_r(name, af, &h, buf, sizeof(buf), &ret, &herrno_p);
+       if (ret_r) {
+               /* _r method returns -ERROR on error.  not sure who wants it. */
+               __set_errno(-ret_r);
+               h_errno = herrno_p;
+               return 0;
+       }
+       assert(ret == &h);
+       return &h;
 }
-stub_warning(gethostbyname2);
index 9ab0c83..8d38178 100644 (file)
+/* 
+ * This file is part of the UCB release of Plan 9. It is subject to the license
+ * terms in the LICENSE file found in the top-level directory of this
+ * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
+ * part of the UCB release of Plan 9, including this file, may be copied,
+ * modified, propagated, or distributed except according to the terms contained
+ * in the LICENSE file.
+ */
+
+/* posix */
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <string.h>
+#include <errno.h>
+
+/* bsd extensions */
+#include <sys/uio.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
 #include <netdb.h>
+#include <arpa/inet.h>
+
+#include "plan9_sockets.h"
+
+enum {
+       Nname = 6,
+};
 
 int __gethostbyname2_r(const char *name, int af, struct hostent *ret,
                        char *buf, size_t buflen,
                        struct hostent **result, int *h_errnop)
 {
+       int i, t, fd, m;
+       char *p, *bp;
+       int nn, na;
+       unsigned long x;
+       size_t csmsg_len = 0;
+       /* These three used to be:
+               static char *nptr[Nname + 1];
+               static char *aptr[Nname + 1];
+               static char addr[Nname][4];
+        * we need to use space in buf for them */
+       char **nptr, **aptr, **addr;
+       size_t nptr_sz, aptr_sz, addr_sz;
+       nptr_sz = sizeof(char *) * (Nname + 1);
+       aptr_sz = sizeof(char *) * (Nname + 1);
+       addr_sz = sizeof(char) * Nname * 4;
+
+       if (nptr_sz + aptr_sz + addr_sz >= buflen) {
+               *result = 0;
+               return -ERANGE;
+       }
+       nptr = buf; buf += nptr_sz; buflen -= nptr_sz;
+       aptr = buf; buf += aptr_sz; buflen -= aptr_sz;
+       addr = buf; buf += addr_sz; buflen -= addr_sz;
+
+       /* for inet addresses only */
+       if (af != AF_INET) {
+               *result = 0;
+               return -EAFNOSUPPORT;
+       }
+
+       ret->h_name = 0;
+       t = _sock_ipattr(name);
+
+       /* connect to server */
+       fd = open("/net/cs", O_RDWR);
+       if (fd < 0) {
+               *h_errnop = NO_RECOVERY;
+               *result = 0;
+               return -errno;
+       }
+
+       /* construct the query, always expect an ip# back */
+       switch (t) {
+               case Tsys:
+                       csmsg_len = snprintf(buf, buflen, "!sys=%s ip=*", name);
+                       break;
+               case Tdom:
+                       csmsg_len = snprintf(buf, buflen, "!dom=%s ip=*", name);
+                       break;
+               case Tip:
+                       csmsg_len = snprintf(buf, buflen, "!ip=%s", name);
+                       break;
+               default:
+                       /* we can't get here, but want to be safe for changes to
+                        * _sock_ipattr() */
+                       close(fd);
+                       *result = 0;
+                       return -EINVAL;
+       }
+       /* we don't update buflen, since we're just going to reuse the space after
+        * our nptr/aptr/addr/etc. */
+       if (csmsg_len >= buflen) {
+               close(fd);
+               *result = 0;
+               return -ERANGE;
+       }
+       /* query the server */
+       if (write(fd, buf, csmsg_len) < 0) {
+               *h_errnop = TRY_AGAIN;
+               close(fd);
+               *result = 0;
+               return -1;
+       }
+       lseek(fd, 0, 0);
+       for (i = 0; i < buflen - 1; i += m) {
+               m = read(fd, buf + i, buflen - 1 - i);
+               if (m <= 0)
+                       break;
+               buf[i + m++] = ' ';
+       }
+       close(fd);
+       buf[i] = 0;
+
+       /* parse the reply */
+       nn = na = 0;
+       for (bp = buf;;) {
+               p = strchr(bp, '=');
+               if (p == 0)
+                       break;
+               *p++ = 0;
+               if (strcmp(bp, "dom") == 0) {
+                       if (ret->h_name == 0)
+                               ret->h_name = p;
+                       if (nn < Nname)
+                               nptr[nn++] = p;
+               } else if (strcmp(bp, "sys") == 0) {
+                       if (nn < Nname)
+                               nptr[nn++] = p;
+               } else if (strcmp(bp, "ip") == 0) {
+                       x = inet_addr(p);
+                       x = ntohl(x);
+                       if (na < Nname) {
+                               addr[na][0] = x >> 24;
+                               addr[na][1] = x >> 16;
+                               addr[na][2] = x >> 8;
+                               addr[na][3] = x;
+                               aptr[na] = addr[na];
+                               na++;
+                       }
+               }
+               while (*p && *p != ' ')
+                       p++;
+               if (*p)
+                       *p++ = 0;
+               bp = p;
+       }
+       if (nn + na == 0) {
+               *h_errnop = HOST_NOT_FOUND;
+               *result = 0;
+               return -1;
+       }
+
+       nptr[nn] = 0;
+       aptr[na] = 0;
+       ret->h_aliases = nptr;
+       ret->h_addr_list = aptr;
+       ret->h_length = 4;
+       ret->h_addrtype = AF_INET;
+       if (ret->h_name == 0)
+               ret->h_name = nptr[0];
+       if (ret->h_name == 0)
+               ret->h_name = aptr[0];
+
+       *result = ret;
        return 0;
 }
 weak_alias(__gethostbyname2_r, gethostbyname2_r);
-stub_warning(gethostbyname2_r);
index 001e6c0..5cf2885 100644 (file)
@@ -3,7 +3,7 @@
 int __gethostbyname_r(const char *name, struct hostent *ret, char *buf,
                       size_t buflen, struct hostent **result, int *h_errnop)
 {
-       return 0;
+       return __gethostbyname2_r(name, AF_INET, ret, buf, buflen, result,
+                                 h_errnop);
 }
 weak_alias(__gethostbyname_r, gethostbyname_r);
-stub_warning(gethostbyname_r);