Pushes the Plan 9 BSD shims into glibc (XCC)
authorBarret Rhoden <brho@cs.berkeley.edu>
Thu, 4 Jun 2015 19:55:17 +0000 (15:55 -0400)
committerBarret Rhoden <brho@cs.berkeley.edu>
Thu, 4 Jun 2015 20:40:30 +0000 (16:40 -0400)
Glibc had stubs that we were overriding in libbsd.  Those shims ought to be in
glibc, since that's Akaros's way of implementing various socket calls.  This is
also somewhat necessary for some -Werror situations where glibc links with its
versions (which were throwing stub_warnings).

Most functions from libbsd are now in glibc.  nptohl() was removed; no one was
using it.  {get,set}sockopt() were stubs in libbsd that did nothing.  I went
with modified glibc stubs for those.  They won't throw compiler warnings, but
they will fail at runtime.  And with a more appropriate errno.  We can add in
various socket options if they are important.

The bulk of the functions were brought over "as is", with the existing races and
non-reentrancy.  A few of them needed work, since the SOCKADDR_ARG has a
different type within glibc (transparent union).  I did pass the files through
lindent, since they have a fresh git history and needed some formatting.

Rebuild glibc.

24 files changed:
tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/Makefile
tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/accept.c [new file with mode: 0644]
tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/bind.c [new file with mode: 0644]
tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/connect.c [new file with mode: 0644]
tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/gethostname.c
tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/gethstbyad.c
tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/gethstbynm.c
tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/getpeername.c
tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/getprtname.c
tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/getsockname.c [new file with mode: 0644]
tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/getsockopt.c [new file with mode: 0644]
tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/getsrvbynm.c
tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/getsrvbypt.c
tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/listen.c [new file with mode: 0644]
tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/plan9_sockets.c [new file with mode: 0644]
tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/plan9_sockets.h [new file with mode: 0644]
tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/recv.c [new file with mode: 0644]
tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/recvfrom.c [new file with mode: 0644]
tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/send.c [new file with mode: 0644]
tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/sendto.c [new file with mode: 0644]
tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/setsockopt.c [new file with mode: 0644]
tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/shutdown.c [new file with mode: 0644]
tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/socket.c [new file with mode: 0644]
tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/socketpair.c [new file with mode: 0644]

index 74e0b57..b618b63 100644 (file)
@@ -14,7 +14,7 @@ CFLAGS-funlockfile.c = $(libio-mtsafe)
 # else already.  Many posix-ish .c files already are taken care of.  We also
 # need to be careful to only include some of them for specific subdirs.
 ifeq ($(subdir),socket)
-sysdep_routines += sa_len
+sysdep_routines += sa_len plan9_sockets
 endif
 sysdep_headers += sys/syscall.h sys/vcore-tls.h
 
diff --git a/tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/accept.c b/tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/accept.c
new file mode 100644 (file)
index 0000000..2139958
--- /dev/null
@@ -0,0 +1,131 @@
+/* 
+ * 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 <errno.h>
+#include <string.h>
+
+/* bsd extensions */
+#include <sys/uio.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <sys/un.h>
+
+#include "plan9_sockets.h"
+
+/* Await a connection on socket FD.
+   When a connection arrives, open a new socket to communicate with it,
+   set *ADDR (which is *ADDR_LEN bytes long) to the address of the connecting
+   peer and *ADDR_LEN to the address's actual length, and return the
+   new socket's descriptor, or -1 for errors.  */
+int accept(int fd, __SOCKADDR_ARG addr, socklen_t * __restrict alen)
+{
+       int n, nfd, lcfd;
+       Rock *r, *nr;
+       struct sockaddr_in *ip;
+       char name[Ctlsize];
+       char file[8 + Ctlsize + 1];
+       char *p;
+       const char *net = 0;
+       char listen[Ctlsize];
+
+       r = _sock_findrock(fd, 0);
+       if (r == 0) {
+               errno = ENOTSOCK;
+               return -1;
+       }
+
+       switch (r->domain) {
+               case PF_INET:
+                       switch (r->stype) {
+                               case SOCK_DGRAM:
+                                       net = "udp";
+                                       break;
+                               case SOCK_STREAM:
+                                       net = "tcp";
+                                       break;
+                       }
+                       /* at this point, our FD is for the data file.  we need to open the
+                        * listen file.  The line is stored in r->ctl (e.g. /net/tcp/666/ctl) */
+                       strcpy(listen, r->ctl);
+                       p = strrchr(listen, '/');
+                       if (p == 0)
+                               return -1;
+                       strcpy(p + 1, "listen");
+
+                       lcfd = open(listen, O_RDWR);
+                       if (lcfd < 0)
+                               return -1;
+                       /* at this point, we have a new conversation, and lcfd is its ctl fd.
+                        * nfd will be the FD for that conv's data file.  sock_data will trade
+                        * our lcfd for the data file fd.  even if it fails, sock_data will
+                        * close our lcfd for us.  when it succeeds, it'll open the data file
+                        * before closing lcfd, which will keep the converstation alive. */
+                       nfd = _sock_data(lcfd, net, r->domain, r->stype, r->protocol, &nr);
+                       if (nfd < 0)
+                               return -1;
+
+                       /* get remote address */
+                       ip = (struct sockaddr_in *)&nr->raddr;
+                       _sock_ingetaddr(nr, ip, &n, "remote");
+                       if (addr.__sockaddr__) {
+                               memmove(addr.__sockaddr_in__, ip, sizeof(struct sockaddr_in));
+                               *alen = sizeof(struct sockaddr_in);
+                       }
+
+                       return nfd;
+               case PF_UNIX:
+                       if (r->other >= 0) {
+                               errno = EINVAL; // was EGREG
+                               return -1;
+                       }
+
+                       for (;;) {
+                               /* read path to new connection */
+                               n = read(fd, name, sizeof(name) - 1);
+                               if (n < 0)
+                                       return -1;
+                               if (n == 0)
+                                       continue;
+                               name[n] = 0;
+
+                               /* open new connection */
+                               _sock_srvname(file, name);
+                               nfd = open(file, O_RDWR);
+                               if (nfd < 0)
+                                       continue;
+
+                               /* confirm opening on new connection */
+                               if (write(nfd, name, strlen(name)) > 0)
+                                       break;
+
+                               close(nfd);
+                       }
+
+                       nr = _sock_newrock(nfd);
+                       if (nr == 0) {
+                               close(nfd);
+                               return -1;
+                       }
+                       nr->domain = r->domain;
+                       nr->stype = r->stype;
+                       nr->protocol = r->protocol;
+
+                       return nfd;
+               default:
+                       errno = EOPNOTSUPP;
+                       return -1;
+       }
+}
+
+libc_hidden_def(accept)
diff --git a/tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/bind.c b/tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/bind.c
new file mode 100644 (file)
index 0000000..d7a5707
--- /dev/null
@@ -0,0 +1,85 @@
+/* 
+ * 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>
+#include <sys/stat.h>
+#include <signal.h>
+
+/* socket extensions */
+#include <sys/uio.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <sys/un.h>
+
+#include "plan9_sockets.h"
+
+/* Give the socket FD the local address ADDR (which is LEN bytes long).  */
+int __bind(int fd, __CONST_SOCKADDR_ARG addr, socklen_t alen)
+{
+       int n, cfd;
+       socklen_t len;
+       Rock *r;
+       char msg[128];
+       struct sockaddr_in *lip;
+
+       /* assign the address */
+       r = _sock_findrock(fd, 0);
+       if (r == 0) {
+               errno = ENOTSOCK;
+               return -1;
+       }
+       if (alen > sizeof(r->addr)) {
+               errno = ENAMETOOLONG;
+               return -1;
+       }
+       memmove(&r->addr, addr.__sockaddr__, alen);
+
+       /* the rest is IP sepecific */
+       if (r->domain != PF_INET)
+               return 0;
+
+       cfd = open(r->ctl, O_RDWR);
+       if (cfd < 0) {
+               errno = EBADF;
+               return -1;
+       }
+       lip = (struct sockaddr_in *)&r->addr;
+       if (lip->sin_port > 0)
+               snprintf(msg, sizeof msg, "bind %d", ntohs(lip->sin_port));
+       else
+               strcpy(msg, "bind *");
+       n = write(cfd, msg, strlen(msg));
+       if (n < 0) {
+               errno = EOPNOTSUPP;     /* Improve error reporting!!! */
+               close(cfd);
+               return -1;
+       }
+       if (lip->sin_port <= 0)
+               _sock_ingetaddr(r, lip, &len, "local");
+       /* UDP sockets are in headers mode, and need to be announced.  This isn't a
+        * full announce, in that the kernel UDP stack doesn't expect someone to
+        * open the listen file or anything like that. */
+       if ((r->domain == PF_INET) && (r->stype == SOCK_DGRAM)) {
+               n = snprintf(msg, sizeof(msg), "announce *!%d", ntohs(lip->sin_port));
+               n = write(cfd, msg, n);
+               if (n < 0) {
+                       perror("bind-announce failed");
+                       return -1;
+               }
+       }
+       close(cfd);
+       return 0;
+}
+weak_alias(__bind, bind)
diff --git a/tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/connect.c b/tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/connect.c
new file mode 100644 (file)
index 0000000..1fda676
--- /dev/null
@@ -0,0 +1,127 @@
+/* 
+ * 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 <sys/un.h>
+#include <arpa/inet.h>
+
+#include "plan9_sockets.h"
+
+/* Open a connection on socket FD to peer at ADDR (which LEN bytes long).
+   For connectionless socket types, just set the default address to send to
+   and the only address from which to accept transmissions.
+   Return 0 on success, -1 for errors.  */
+int __connect(int fd, __CONST_SOCKADDR_ARG addr, socklen_t alen)
+{
+       Rock *r;
+       int n, cfd, nfd;
+       char msg[8 + 256 + 1], file[8 + 256 + 1];
+       struct sockaddr_in *lip, *rip;
+       struct sockaddr_un *runix;
+       static int vers;
+
+       r = _sock_findrock(fd, 0);
+       if (r == 0) {
+               errno = ENOTSOCK;
+               return -1;
+       }
+       if (alen > sizeof(r->raddr)) {
+               errno = ENAMETOOLONG;
+               return -1;
+       }
+       memmove(&r->raddr, addr.__sockaddr__, alen);
+
+       switch (r->domain) {
+               case PF_INET:
+                       /* UDP sockets are already announced (during bind), so we can't issue
+                        * a connect message.  Either connect or announce, not both.  All sends
+                        * will later do a sendto, based off the contents of r->raddr, so we're
+                        * already done here */
+                       if (r->stype == SOCK_DGRAM)
+                               return 0;
+                       /* set up a tcp or udp connection */
+                       cfd = open(r->ctl, O_RDWR);
+                       if (cfd < 0) {
+                               return -1;
+                       }
+                       /* whatever .. */
+                       rip = (struct sockaddr_in *)addr.__sockaddr_in__;
+                       lip = (struct sockaddr_in *)&r->addr;
+                       if (lip->sin_port)
+                               snprintf(msg, sizeof msg, "connect %s!%d%s %d",
+                                                inet_ntoa(rip->sin_addr), ntohs(rip->sin_port),
+                                                r->reserved ? "!r" : "", ntohs(lip->sin_port));
+                       else
+                               snprintf(msg, sizeof msg, "connect %s!%d%s",
+                                                inet_ntoa(rip->sin_addr), ntohs(rip->sin_port),
+                                                r->reserved ? "!r" : "");
+                       n = write(cfd, msg, strlen(msg));
+                       if (n < 0) {
+                               close(cfd);
+                               return -1;
+                       }
+                       close(cfd);
+                       return 0;
+               case PF_UNIX:
+                       /* null terminate the address */
+                       if (alen == sizeof(r->raddr))
+                               alen--;
+                       *(((char *)&r->raddr) + alen) = 0;
+
+                       if (r->other < 0) {
+                               errno = EINVAL; //EGREG;
+                               return -1;
+                       }
+
+                       /* put far end of our pipe in /srv */
+                       snprintf(msg, sizeof msg, "UD.%d.%d", getpid(), vers++);
+                       if (_sock_srv(msg, r->other) < 0) {
+                               r->other = -1;
+                               return -1;
+                       }
+                       r->other = -1;
+
+                       /* tell server the /srv file to open */
+                       runix = (struct sockaddr_un *)&r->raddr;
+                       _sock_srvname(file, runix->sun_path);
+                       nfd = open(file, O_RDWR);
+                       if (nfd < 0) {
+                               unlink(msg);
+                               return -1;
+                       }
+                       if (write(nfd, msg, strlen(msg)) < 0) {
+                               close(nfd);
+                               unlink(msg);
+                               return -1;
+                       }
+                       close(nfd);
+
+                       /* wait for server to open it and then remove it */
+                       read(fd, file, sizeof(file));
+                       _sock_srvname(file, msg);
+                       unlink(file);
+                       return 0;
+               default:
+                       errno = EAFNOSUPPORT;
+                       return -1;
+       }
+}
+weak_alias(__connect, connect)
+libc_hidden_def(__connect)
index 021aad0..6ef00fe 100644 (file)
@@ -1,34 +1,34 @@
-/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
+/* 
+ * 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.
+ */
 
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, see
-   <http://www.gnu.org/licenses/>.  */
-
-#include <errno.h>
+#include <sys/types.h>
 #include <unistd.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <string.h>
 
-/* Put the name of the current host in no more than LEN bytes of NAME.
-   The result is null-terminated if LEN is large enough for the full
-   name and the terminator.  */
-int
-__gethostname (name, len)
-     char *name;
-     size_t len;
+/* Unlike the glibc version, this ensures that name is null-terminated.*/
+int __gethostname(char *name, size_t namelen)
 {
-  __set_errno (ENOSYS);
-  return -1;
-}
-stub_warning (gethostname)
+       int n, fd;
+       char buf[128];
 
-weak_alias (__gethostname, gethostname)
+       fd = open("/dev/sysname", O_RDONLY);
+       if (fd < 0)
+               return -1;
+       n = read(fd, buf, sizeof(buf) - 1);
+       close(fd);
+       if (n <= 0)
+               return -1;
+       buf[n] = 0;
+       strncpy(name, buf, namelen);
+       name[namelen - 1] = 0;
+       return 0;
+}
+weak_alias(__gethostname, gethostname)
index c79d0e9..8a97105 100644 (file)
@@ -1,7 +1,37 @@
+/* 
+ * 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 <arpa/inet.h>
+
+#include "plan9_sockets.h"
 
 struct hostent *gethostbyaddr(const void *addr, socklen_t len, int type)
 {
-       return 0;
+       unsigned long a, y;
+       struct in_addr x;
+       __const unsigned char *p = addr;
+
+       if (type != AF_INET || len != 4) {
+               h_errno = NO_RECOVERY;
+               return 0;
+       }
+
+       y = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
+       x.s_addr = htonl(y);
+
+       return gethostbyname(inet_ntoa(x));
 }
-stub_warning(gethostbyaddr);
index cbc6710..d68da51 100644 (file)
@@ -1,7 +1,135 @@
+/* 
+ * 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)
 {
-       return 0;
+       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;
 }
-stub_warning(gethostbyname);
index 7b1180b..58c3db4 100644 (file)
@@ -1,34 +1,60 @@
-/* Copyright (C) 1991, 1995, 1996, 1997 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, write to the Free
-   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-   02111-1307 USA.  */
-
+/* 
+ * 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 <sys/un.h>
+
+#include "plan9_sockets.h"
 
 /* Put the address of the peer connected to socket FD into *ADDR
    (which is *LEN bytes long), and its actual length into *LEN.  */
-int
-__getpeername (fd, addr, len)
-     int fd;
-     __SOCKADDR_ARG addr;
-     socklen_t *len;
+int __getpeername(int fd, __SOCKADDR_ARG addr, socklen_t * __restrict alen)
 {
-  __set_errno (ENOSYS);
-  return -1;
+       Rock *r;
+       int i;
+       struct sockaddr_in *rip;
+       struct sockaddr_un *runix;
+
+       r = _sock_findrock(fd, 0);
+       if (r == 0) {
+               errno = ENOTSOCK;
+               return -1;
+       }
+
+       switch (r->domain) {
+               case PF_INET:
+                       rip = (struct sockaddr_in *)&r->raddr;
+                       memmove(addr.__sockaddr_in__, rip, sizeof(struct sockaddr_in));
+                       *alen = sizeof(struct sockaddr_in);
+                       break;
+               case PF_UNIX:
+                       runix = (struct sockaddr_un *)&r->raddr;
+                       i = &runix->sun_path[strlen(runix->sun_path)] - (char *)runix;
+                       memmove(addr.__sockaddr_un__, runix, i);
+                       *alen = i;
+                       break;
+               default:
+                       errno = EAFNOSUPPORT;
+                       return -1;
+       }
+       return 0;
 }
-weak_alias (__getpeername, getpeername)
-stub_warning (getpeername)
+
+weak_alias(__getpeername, getpeername)
index fb7ce76..d0e58e6 100644 (file)
@@ -1,7 +1,94 @@
+/* 
+ * 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 "plan9_sockets.h"
+
+enum {
+       Nname = 6,
+};
+
+static struct protoent r;
+
 struct protoent *getprotobyname(const char *name)
 {
-       return 0;
+       int fd, i, m;
+       char *p, *bp;
+       int nn, na;
+       unsigned long x;
+       static char buf[1024], proto[1024];
+       static char *nptr[Nname + 1];
+
+       /* connect to server */
+       fd = open("/net/cs", O_RDWR);
+       if (fd < 0) {
+               h_errno = NO_RECOVERY;
+               return 0;
+       }
+
+       /* construct the query, always expect a protocol# back */
+       snprintf(buf, sizeof buf, "!protocol=%s ipv4proto=*", name);
+
+       /* 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, "protocol") == 0) {
+                       if (!nn)
+                               r.p_name = p;
+                       if (nn < Nname)
+                               nptr[nn++] = p;
+               } else if (strcmp(bp, "ipv4proto") == 0) {
+                       r.p_proto = atoi(p);
+                       na++;
+               }
+               while (*p && *p != ' ')
+                       p++;
+               if (*p)
+                       *p++ = 0;
+               bp = p;
+       }
+       nptr[nn] = 0;
+       r.p_aliases = nptr;
+       if (nn + na == 0)
+               return 0;
+
+       return &r;
 }
-stub_warning(getprotobyname);
diff --git a/tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/getsockname.c b/tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/getsockname.c
new file mode 100644 (file)
index 0000000..6cf53f2
--- /dev/null
@@ -0,0 +1,58 @@
+/* 
+ * 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 <sys/un.h>
+
+#include "plan9_sockets.h"
+
+/* Put the local address of FD into *ADDR and its length in *LEN.  */
+int __getsockname(int fd, __SOCKADDR_ARG addr, socklen_t * __restrict alen)
+{
+       Rock *r;
+       int i;
+       struct sockaddr_in *lip;
+       struct sockaddr_un *lunix;
+
+       r = _sock_findrock(fd, 0);
+       if (r == 0) {
+               errno = ENOTSOCK;
+               return -1;
+       }
+
+       switch (r->domain) {
+               case PF_INET:
+                       lip = addr.__sockaddr_in__;
+                       _sock_ingetaddr(r, lip, alen, "local");
+                       break;
+               case PF_UNIX:
+                       lunix = (struct sockaddr_un *)&r->addr;
+                       i = &lunix->sun_path[strlen(lunix->sun_path)] - (char *)lunix;
+                       memmove(addr.__sockaddr_un__, lunix, i);
+                       *alen = i;
+                       break;
+               default:
+                       errno = EAFNOSUPPORT;
+                       return -1;
+       }
+       return 0;
+}
+
+weak_alias(__getsockname, getsockname)
diff --git a/tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/getsockopt.c b/tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/getsockopt.c
new file mode 100644 (file)
index 0000000..b60073a
--- /dev/null
@@ -0,0 +1,34 @@
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <sys/socket.h>
+
+/* Put the current value for socket FD's option OPTNAME at protocol level LEVEL
+   into OPTVAL (which is *OPTLEN bytes long), and set *OPTLEN to the value's
+   actual length.  Returns 0 on success, -1 for errors.  */
+int
+getsockopt (fd, level, optname, optval, optlen)
+     int fd;
+     int level;
+     int optname;
+     void *optval;
+     socklen_t *optlen;
+{
+       __set_errno (ENOPROTOOPT);
+       return -1;
+}
index d8bc1b5..41019a2 100644 (file)
@@ -1,7 +1,105 @@
+/* 
+ * 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>
+#include <ctype.h>
+
+/* bsd extensions */
+#include <sys/uio.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
 #include <netdb.h>
 
+#include "plan9_sockets.h"
+
+enum {
+       Nname = 6,
+};
+
+/*
+ *  for inet addresses only
+ */
 struct servent *getservbyname(const char *name, const char *proto)
 {
-       return 0;
+       int i, fd, m, num;
+       char *p;
+       char *bp;
+       int nn, na;
+       static struct servent s;
+       static char buf[1024];
+       static char *nptr[Nname + 1];
+
+       num = 1;
+       for (p = (char *)name; *p; p++)
+               if (!isdigit(*p))
+                       num = 0;
+
+       s.s_name = 0;
+
+       /* connect to server */
+       fd = open("/net/cs", O_RDWR);
+       if (fd < 0) {
+               return 0;
+       }
+
+       /* construct the query, always expect an ip# back */
+       if (num)
+               snprintf(buf, sizeof buf, "!port=%s %s=*", name, proto);
+       else
+               snprintf(buf, sizeof buf, "!%s=%s port=*", proto, name);
+
+       /* query the server */
+       if (write(fd, buf, strlen(buf)) < 0) {
+               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, proto) == 0) {
+                       if (nn < Nname)
+                               nptr[nn++] = p;
+               } else if (strcmp(bp, "port") == 0) {
+                       s.s_port = htons(atoi(p));
+               }
+               while (*p && *p != ' ')
+                       p++;
+               if (*p)
+                       *p++ = 0;
+               bp = p;
+       }
+       if (nn + na == 0)
+               return 0;
+
+       nptr[nn] = 0;
+       s.s_aliases = nptr;
+       if (s.s_name == 0)
+               s.s_name = nptr[0];
+
+       return &s;
 }
-stub_warning(getservbyname);
index 6881f73..df7661d 100644 (file)
@@ -1,7 +1,28 @@
+/* 
+ * 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.
+ */
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdio.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"
 
 struct servent *getservbyport(int port, const char *proto)
 {
-       return 0;
+       char buf[32];
+
+       snprintf(buf, sizeof buf, "%d", port);
+       return getservbyname(buf, proto);
 }
-stub_warning(getservbyport);
diff --git a/tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/listen.c b/tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/listen.c
new file mode 100644 (file)
index 0000000..bad6f43
--- /dev/null
@@ -0,0 +1,90 @@
+/* 
+ * 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>
+#include <sys/stat.h>
+#include <signal.h>
+
+/* socket extensions */
+#include <sys/uio.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <sys/un.h>
+
+#include "plan9_sockets.h"
+
+/* Prepare to accept connections on socket FD.
+   N connection requests will be queued before further requests are refused.
+   Returns 0 on success, -1 for errors.  */
+int __listen(int fd, int backlog)
+{
+       Rock *r;
+       int n, cfd;
+       char msg[128];
+       struct sockaddr_in *lip;
+       struct sockaddr_un *lunix;
+
+       r = _sock_findrock(fd, 0);
+       if (r == 0) {
+               errno = ENOTSOCK;
+               return -1;
+       }
+
+       switch (r->domain) {
+               case PF_INET:
+                       cfd = open(r->ctl, O_RDWR);
+                       if (cfd < 0) {
+                               errno = EBADF;
+                               return -1;
+                       }
+                       lip = (struct sockaddr_in *)&r->addr;
+                       if (lip->sin_port >= 0) {
+                               if (write(cfd, "bind 0", 6) < 0) {
+                                       errno = EINVAL; //EGREG;
+                                       close(cfd);
+                                       return -1;
+                               }
+                               snprintf(msg, sizeof msg, "announce %d", ntohs(lip->sin_port));
+                       } else
+                               strcpy(msg, "announce *");
+                       n = write(cfd, msg, strlen(msg));
+                       if (n < 0) {
+                               errno = EOPNOTSUPP;     /* Improve error reporting!!! */
+                               close(cfd);
+                               return -1;
+                       }
+                       close(cfd);
+
+                       return 0;
+
+               case PF_UNIX:
+                       if (r->other < 0) {
+                               errno = EINVAL; //EGREG;
+                               return -1;
+                       }
+                       lunix = (struct sockaddr_un *)&r->addr;
+                       if (_sock_srv(lunix->sun_path, r->other) < 0) {
+                               r->other = -1;
+                               return -1;
+                       }
+                       r->other = -1;
+                       return 0;
+               default:
+                       errno = EAFNOSUPPORT;
+                       return -1;
+       }
+}
+
+weak_alias(__listen, listen)
diff --git a/tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/plan9_sockets.c b/tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/plan9_sockets.c
new file mode 100644 (file)
index 0000000..77bbfa7
--- /dev/null
@@ -0,0 +1,259 @@
+/* 
+ * 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 <errno.h>
+#include <string.h>
+
+/* bsd extensions */
+#include <sys/uio.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <sys/un.h>
+#include <arpa/inet.h>
+
+#include "plan9_sockets.h"
+
+void
+_sock_ingetaddr(Rock * r, struct sockaddr_in *ip, socklen_t * alen,
+                               const char *a)
+{
+       int n, fd;
+       char *p;
+       char name[Ctlsize];
+
+       /* get remote address */
+       strcpy(name, r->ctl);
+       p = strrchr(name, '/');
+       strcpy(p + 1, a);
+       fd = open(name, O_RDONLY);
+       if (fd >= 0) {
+               n = read(fd, name, sizeof(name) - 1);
+               if (n > 0) {
+                       name[n] = 0;
+                       p = strchr(name, '!');
+                       if (p) {
+                               *p++ = 0;
+                               ip->sin_family = AF_INET;
+                               ip->sin_port = htons(atoi(p));
+                               ip->sin_addr.s_addr = inet_addr(name);
+                               if (alen)
+                                       *alen = sizeof(struct sockaddr_in);
+                       }
+               }
+               close(fd);
+       }
+
+}
+
+/*
+ *  return ndb attribute type of an ip name
+ */
+int _sock_ipattr(const char *name)
+{
+       const char *p;
+       int dot = 0;
+       int alpha = 0;
+
+       for (p = name; *p; p++) {
+               if (isdigit(*p)) ;
+               else if (isalpha(*p) || *p == '-')
+                       alpha = 1;
+               else if (*p == '.')
+                       dot = 1;
+               else
+                       return Tsys;
+       }
+
+       if (alpha) {
+               if (dot)
+                       return Tdom;
+               else
+                       return Tsys;
+       }
+
+       if (dot)
+               return Tip;
+       else
+               return Tsys;
+}
+
+/* we can't avoid overrunning npath because we don't know how big it is. */
+void _sock_srvname(char *npath, char *path)
+{
+       char *p;
+
+       strcpy(npath, "/srv/UD.");
+       p = strrchr(path, '/');
+       if (p == 0)
+               p = path;
+       else
+               p++;
+       strcat(npath, p);
+}
+
+int _sock_srv(char *path, int fd)
+{
+       int sfd;
+       char msg[8 + 256 + 1];
+
+       /* change the path to something in srv */
+       _sock_srvname(msg, path);
+
+       /* remove any previous instance */
+       unlink(msg);
+
+       /* put the fd in /srv and then close it */
+       sfd = creat(msg, 0666);
+       if (sfd < 0) {
+               close(fd);
+               return -1;
+       }
+       snprintf(msg, sizeof msg, "%d", fd);
+       if (write(sfd, msg, strlen(msg)) < 0) {
+               close(sfd);
+               close(fd);
+               return -1;
+       }
+       close(sfd);
+       close(fd);
+       return 0;
+}
+
+#warning "Not threadsafe!"
+Rock *_sock_rock;
+
+Rock *_sock_findrock(int fd, struct stat * dp)
+{
+       Rock *r;
+       struct stat d;
+
+       if (dp == 0)
+               dp = &d;
+       fstat(fd, dp);
+       for (r = _sock_rock; r; r = r->next) {
+               if (r->inode == dp->st_ino && r->dev == dp->st_dev)
+                       break;
+       }
+       return r;
+}
+
+Rock *_sock_newrock(int fd)
+{
+       Rock *r;
+       struct stat d;
+
+       r = _sock_findrock(fd, &d);
+       if (r == 0) {
+               r = malloc(sizeof(Rock));
+               if (r == 0)
+                       return 0;
+               r->dev = d.st_dev;
+               r->inode = d.st_ino;
+               r->other = -1;
+               /* TODO: this is not thread-safe! */
+               r->next = _sock_rock;
+               _sock_rock = r;
+       }
+       memset(&r->raddr, 0, sizeof(r->raddr));
+       memset(&r->addr, 0, sizeof(r->addr));
+       r->reserved = 0;
+       r->dev = d.st_dev;
+       r->inode = d.st_ino;
+       r->other = -1;
+       return r;
+}
+
+/* For a ctlfd and a few other settings, it opens and returns the corresponding
+ * datafd.  This will close cfd for you. */
+int
+_sock_data(int cfd, char *net, int domain, int stype, int protocol, Rock ** rp)
+{
+       int n, fd;
+       Rock *r;
+       char name[Ctlsize];
+
+       /* get the data file name */
+       n = read(cfd, name, sizeof(name) - 1);
+       if (n < 0) {
+               close(cfd);
+               errno = ENOBUFS;
+               return -1;
+       }
+       name[n] = 0;
+       n = strtoul(name, 0, 0);
+       snprintf(name, sizeof name, "/net/%s/%d/data", net, n);
+
+       /* open data file */
+       fd = open(name, O_RDWR);
+       close(cfd);     /* close this no matter what */
+       if (fd < 0) {
+               errno = ENOBUFS;
+               return -1;
+       }
+
+       /* hide stuff under the rock */
+       snprintf(name, sizeof name, "/net/%s/%d/ctl", net, n);
+       r = _sock_newrock(fd);
+       if (r == 0) {
+               errno = ENOBUFS;
+               close(fd);
+               return -1;
+       }
+       if (rp)
+               *rp = r;
+       memset(&r->raddr, 0, sizeof(r->raddr));
+       memset(&r->addr, 0, sizeof(r->addr));
+       r->domain = domain;
+       r->stype = stype;
+       r->protocol = protocol;
+       strcpy(r->ctl, name);
+       return fd;
+}
+
+/* Takes network-byte ordered IPv4 addr and writes it into buf, in the plan 9 IP
+ * addr format */
+void naddr_to_plan9addr(uint32_t sin_addr, uint8_t * buf)
+{
+       uint8_t *sin_bytes = (uint8_t *) & sin_addr;
+       memset(buf, 0, 10);
+       buf += 10;
+       buf[0] = 0xff;
+       buf[1] = 0xff;
+       buf += 2;
+       buf[0] = sin_bytes[0];  /* e.g. 192 */
+       buf[1] = sin_bytes[1];  /* e.g. 168 */
+       buf[2] = sin_bytes[2];  /* e.g.   0 */
+       buf[3] = sin_bytes[3];  /* e.g.   1 */
+}
+
+/* does v4 only */
+uint32_t plan9addr_to_naddr(uint8_t * buf)
+{
+       buf += 12;
+       return (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | (buf[0] << 0);
+}
+
+/* Returns a rock* if the socket exists and is UDP */
+Rock *udp_sock_get_rock(int fd)
+{
+       Rock *r = _sock_findrock(fd, 0);
+       if (!r) {
+               errno = ENOTSOCK;
+               return 0;
+       }
+       if ((r->domain == PF_INET) && (r->stype == SOCK_DGRAM))
+               return r;
+       else
+               return 0;
+}
diff --git a/tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/plan9_sockets.h b/tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/plan9_sockets.h
new file mode 100644 (file)
index 0000000..77e2151
--- /dev/null
@@ -0,0 +1,88 @@
+/* 
+ * 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.
+ */
+#ifndef PLAN9_SOCKETS_H
+#define PLAN9_SOCKETS_H
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <netdb.h>
+
+__BEGIN_DECLS typedef struct Rock Rock;
+
+enum {
+       Ctlsize = 128,
+
+       /* states */
+       Sopen = 0,
+       Sbound,
+       Sconnected,
+
+       /* types of name */
+       Tsys = 0,
+       Tip,
+       Tdom,
+};
+
+/*
+ *  since BSD programs expect to perform both control and data functions
+ *  through a single fd, we need to hide enough info under a rock to
+ *  be able to open the control file when we need it.
+ */
+struct Rock {
+       Rock *next;
+       unsigned long dev;                      /* inode & dev of data file */
+       unsigned long inode;            /* ... */
+       int domain;                                     /* from socket call */
+       int stype;                                      /* ... */
+       int protocol;                           /* ... */
+       struct sockaddr addr;           /* address from bind */
+       int reserved;                           /* use a priveledged port # (< 1024) */
+       struct sockaddr raddr;          /* peer address */
+       char ctl[Ctlsize];                      /* name of control file (if any) */
+       int other;                                      /* fd of the remote end for Unix domain */
+};
+
+extern Rock *_sock_findrock(int, struct stat *);
+extern Rock *_sock_newrock(int);
+extern void _sock_srvname(char *, char *);
+extern int _sock_srv(char *, int);
+extern int _sock_data(int, char *, int, int, int, Rock **);
+extern int _sock_ipattr(const char *);
+extern void _sock_ingetaddr(Rock *, struct sockaddr_in *, socklen_t *,
+                                                       const char *);
+
+extern void _syserrno(void);
+
+/* The plan9 UDP header looks like:
+ *
+ * 52 bytes
+ *             raddr (16 b)
+ *             laddr (16 b)
+ *             IFC addr (ignored if user says it)  (16 b)
+ *             rport (2 b) (network ordering)
+ *             lport (ignored if user says it) (2b)
+ *
+ * The v4 addr format is 10 bytes of 0s, then two 0xff, then 4 bytes of addr. */
+
+#define P9_UDP_HDR_SZ 52
+
+/* Takes network-byte ordered IPv4 addr and writes it into buf, in the plan 9 IP
+ * addr format */
+void naddr_to_plan9addr(uint32_t sin_addr, uint8_t * buf);
+/* does v4 only */
+uint32_t plan9addr_to_naddr(uint8_t * buf);
+/* Returns a rock* if the socket exists and is UDP */
+Rock *udp_sock_get_rock(int fd);
+
+__END_DECLS
+#endif /* PLAN9_SOCKETS_H */
diff --git a/tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/recv.c b/tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/recv.c
new file mode 100644 (file)
index 0000000..7a45726
--- /dev/null
@@ -0,0 +1,30 @@
+/* 
+ * 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 <fcntl.h>
+#include <errno.h>
+
+/* bsd extensions */
+#include <sys/uio.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+
+#include "plan9_sockets.h"
+
+/* Read N bytes into BUF from socket FD.
+   Returns the number read or -1 for errors.  */
+ssize_t __recv(int fd, void *buf, size_t n, int flags)
+{
+       socklen_t dummy;
+       return recvfrom(fd, buf, n, flags, 0, &dummy);
+}
+
+weak_alias(__recv, recv)
diff --git a/tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/recvfrom.c b/tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/recvfrom.c
new file mode 100644 (file)
index 0000000..e96eafb
--- /dev/null
@@ -0,0 +1,75 @@
+/* 
+ * 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 <fcntl.h>
+#include <errno.h>
+#include <stdlib.h>
+
+/* bsd extensions */
+#include <sys/uio.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+#include "plan9_sockets.h"
+
+/* Read N bytes into BUF through socket FD from peer
+   at address FROM (which is FROMLEN bytes long).
+   Returns the number read or -1 for errors.  */
+ssize_t __recvfrom(int fd, void *__restrict buf, size_t n,
+                                  int flags, __SOCKADDR_ARG from,
+                                  socklen_t * __restrict fromlen)
+{
+       Rock *r;
+       if (flags & MSG_OOB) {
+               errno = EOPNOTSUPP;
+               return -1;
+       }
+       if (from.__sockaddr__ && getsockname(fd, from, fromlen) < 0)
+               return -1;
+       /* UDP sockets need to have headers added to the payload for all packets,
+        * since we're supporting blind sendto/recvfrom. */
+       if ((r = udp_sock_get_rock(fd))) {
+               int ret;
+               struct sockaddr_in *remote = from.__sockaddr_in__;
+               char *p, *newbuf = malloc(n + P9_UDP_HDR_SZ);
+               if (!newbuf) {
+                       errno = ENOMEM;
+                       return -1;
+               }
+               ret = read(fd, newbuf, n + P9_UDP_HDR_SZ);
+               /* subtracting before, so that we error out if we got less than the
+                * headers needed */
+               ret -= P9_UDP_HDR_SZ;
+               if (ret < 0) {
+                       free(newbuf);
+                       return -1;
+               }
+               memcpy(buf, newbuf + P9_UDP_HDR_SZ, n);
+               /* Might not have a remote, if we were called via recv().  Could assert
+                * that it's the same remote that we think we connected to, and that we
+                * were already connected. (TODO) */
+               if (remote) {
+                       p = newbuf;
+                       remote->sin_addr.s_addr = plan9addr_to_naddr(p);
+                       p += 16;
+                       p += 16;        /* skip local addr */
+                       p += 16;        /* skip ipifc */
+                       remote->sin_port = (p[0] << 0) | (p[1] << 8);
+                       remote->sin_port = *(uint16_t *) p;
+                       *fromlen = sizeof(struct sockaddr_in);
+               }
+               free(newbuf);
+               return ret;
+       }
+       return read(fd, buf, n);
+}
+
+weak_alias(__recvfrom, recvfrom)
diff --git a/tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/send.c b/tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/send.c
new file mode 100644 (file)
index 0000000..55b05c7
--- /dev/null
@@ -0,0 +1,29 @@
+/* 
+ * 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 <fcntl.h>
+#include <errno.h>
+
+/* bsd extensions */
+#include <sys/uio.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+
+#include "plan9_sockets.h"
+
+/* Send N bytes of BUF to socket FD.  Returns the number sent or -1.  */
+ssize_t __send(int fd, __const void *buf, size_t n, int flags)
+{
+       return sendto(fd, buf, n, flags, 0, 0);
+}
+
+libc_hidden_def(__send)
+weak_alias(__send, send)
diff --git a/tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/sendto.c b/tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/sendto.c
new file mode 100644 (file)
index 0000000..51ad86d
--- /dev/null
@@ -0,0 +1,73 @@
+/* 
+ * 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 <fcntl.h>
+#include <errno.h>
+#include <stdlib.h>
+
+/* bsd extensions */
+#include <sys/uio.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+#include "plan9_sockets.h"
+
+/* Send N bytes of BUF on socket FD to peer at address TO (which is
+   TOLEN bytes long).  Returns the number sent, or -1 for errors.  */
+ssize_t __sendto(int fd, const void *buf, size_t n,
+                                int flags, __CONST_SOCKADDR_ARG to, socklen_t tolen)
+{
+       Rock *r;
+       if (flags & MSG_OOB) {
+               errno = EOPNOTSUPP;
+               return -1;
+       }
+       /* UDP sockets need to have headers added to the payload for all packets,
+        * since we're supporting blind sendto/recvfrom. */
+       if ((r = udp_sock_get_rock(fd))) {
+               int ret;
+               uint32_t remote_addr;
+               uint16_t remote_port;
+               char *p, *newbuf;
+               /* Might not have a to if we were called from send() */
+               if (!to.__sockaddr__) {
+                       /* if they didn't connect yet, then there's no telling what raddr
+                        * will be.  TODO: check a state flag or something? */
+                       to.__sockaddr__ = (struct sockaddr *)(&r->raddr);
+               }
+               remote_addr = (to.__sockaddr_in__)->sin_addr.s_addr;
+               remote_port = (to.__sockaddr_in__)->sin_port;
+               newbuf = malloc(n + P9_UDP_HDR_SZ);
+               if (!newbuf) {
+                       errno = ENOMEM;
+                       return -1;
+               }
+               p = newbuf;
+               naddr_to_plan9addr(remote_addr, p);
+               p += 16;
+               /* we don't need to specify an address.  if we don't specify a valid
+                * local IP addr, the kernel will pick the one closest to dest */
+               p += 16;
+               p += 16;        /* skip ipifc */
+               *(uint16_t *) p = remote_port;
+               p += 2;
+               p += 2; /* skip local port */
+               memcpy(p, buf, n);
+               ret = write(fd, newbuf, n + P9_UDP_HDR_SZ);
+               free(newbuf);
+               if (ret < 0)
+                       return -1;
+               return ret - P9_UDP_HDR_SZ;
+       }
+       return write(fd, buf, n);
+}
+
+weak_alias(__sendto, sendto)
diff --git a/tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/setsockopt.c b/tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/setsockopt.c
new file mode 100644 (file)
index 0000000..e464001
--- /dev/null
@@ -0,0 +1,36 @@
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <sys/socket.h>
+
+/* Set socket FD's option OPTNAME at protocol level LEVEL
+   to *OPTVAL (which is OPTLEN bytes long).
+   Returns 0 on success, -1 for errors.  */
+int
+__setsockopt (fd, level, optname, optval, optlen)
+     int fd;
+     int level;
+     int optname;
+     const __ptr_t optval;
+     socklen_t optlen;
+{
+       __set_errno (ENOPROTOOPT);
+       return -1;
+}
+
+weak_alias (__setsockopt, setsockopt)
diff --git a/tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/shutdown.c b/tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/shutdown.c
new file mode 100644 (file)
index 0000000..d9b1089
--- /dev/null
@@ -0,0 +1,24 @@
+/* 
+ * 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.
+ */
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "plan9_sockets.h"
+
+/* Supposed to shut down all or part of the connection open on socket FD.
+   HOW determines what to shut down:
+     0 = No more receptions;
+     1 = No more transmissions;
+     2 = No more receptions or transmissions.
+   Returns 0 on success, -1 for errors.  */
+int shutdown(int fd, int how)
+{
+       /* plan 9 doesn't do a shutdown.  if you shut it down, it's now closed. */
+       return close(fd);
+}
diff --git a/tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/socket.c b/tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/socket.c
new file mode 100644 (file)
index 0000000..e2acd6f
--- /dev/null
@@ -0,0 +1,83 @@
+/* 
+ * 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 <errno.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+
+/* bsd extensions */
+#include <sys/uio.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+#include "plan9_sockets.h"
+
+/* Create a new socket of type TYPE in domain DOMAIN, using
+   protocol PROTOCOL.  If PROTOCOL is zero, one is chosen automatically.
+   Returns a file descriptor for the new socket, or -1 for errors.  */
+int __socket(int domain, int stype, int protocol)
+{
+       Rock *r;
+       int cfd, fd, n;
+       int pfd[2];
+       char *net;
+       char msg[128];
+
+       switch (domain) {
+               case PF_INET:
+                       /* get a free network directory */
+                       switch (stype) {
+                               case SOCK_DGRAM:
+                                       net = "udp";
+                                       cfd = open("/net/udp/clone", O_RDWR);
+                                       /* All BSD UDP sockets are in 'headers' mode, where each packet has
+                                        * the remote addr:port, local addr:port and other info. */
+                                       if (!(cfd < 0)) {
+                                               n = snprintf(msg, sizeof(msg), "headers");
+                                               n = write(cfd, msg, n);
+                                               if (n < 0) {
+                                                       perror("UDP socket headers failed");
+                                                       return -1;
+                                               }
+                                       }
+                                       break;
+                               case SOCK_STREAM:
+                                       net = "tcp";
+                                       cfd = open("/net/tcp/clone", O_RDWR);
+                                       break;
+                               default:
+                                       errno = EPROTONOSUPPORT;
+                                       return -1;
+                       }
+                       if (cfd < 0) {
+                               return -1;
+                       }
+                       return _sock_data(cfd, net, domain, stype, protocol, 0);
+               case PF_UNIX:
+                       if (pipe(pfd) < 0) {
+                               return -1;
+                       }
+                       r = _sock_newrock(pfd[0]);
+                       r->domain = domain;
+                       r->stype = stype;
+                       r->protocol = protocol;
+                       r->other = pfd[1];
+                       return pfd[0];
+               default:
+                       errno = EPROTONOSUPPORT;
+                       return -1;
+       }
+}
+
+weak_alias(__socket, socket)
diff --git a/tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/socketpair.c b/tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/socketpair.c
new file mode 100644 (file)
index 0000000..644bd2b
--- /dev/null
@@ -0,0 +1,34 @@
+/* 
+ * 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 <errno.h>
+
+/* bsd extensions */
+#include <sys/uio.h>
+#include <sys/socket.h>
+
+#include "plan9_sockets.h"
+
+/* Create two new sockets, of type TYPE in domain DOMAIN and using
+   protocol PROTOCOL, which are connected to each other, and put file
+   descriptors for them in FDS[0] and FDS[1].  If PROTOCOL is zero,
+   one will be chosen automatically.  Returns 0 on success, -1 for errors.  */
+int socketpair(int domain, int type, int protocol, int *sv)
+{
+       switch (domain) {
+               case PF_UNIX:
+                       return pipe(sv);
+               default:
+                       errno = EOPNOTSUPP;
+                       return -1;
+       }
+}