Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/lib/librumphijack Support fork() and dup2().



details:   https://anonhg.NetBSD.org/src/rev/db259752ffca
branches:  trunk
changeset: 760586:db259752ffca
user:      pooka <pooka%NetBSD.org@localhost>
date:      Sat Jan 08 14:19:27 2011 +0000

description:
Support fork() and dup2().

This is sufficient to make an unmodified httpd(8) be able to serve
pages via a rump networking stack.

diffstat:

 lib/librumphijack/hijack.c |  284 +++++++++++++++++++++++++++++---------------
 1 files changed, 189 insertions(+), 95 deletions(-)

diffs (truncated from 584 to 300 lines):

diff -r 1987ae68b5e2 -r db259752ffca lib/librumphijack/hijack.c
--- a/lib/librumphijack/hijack.c        Sat Jan 08 14:01:04 2011 +0000
+++ b/lib/librumphijack/hijack.c        Sat Jan 08 14:19:27 2011 +0000
@@ -1,4 +1,4 @@
-/*      $NetBSD: hijack.c,v 1.1 2011/01/07 19:52:43 pooka Exp $        */
+/*      $NetBSD: hijack.c,v 1.2 2011/01/08 14:19:27 pooka Exp $        */
 
 /*-
  * Copyright (c) 2011 Antti Kantee.  All Rights Reserved.
@@ -26,7 +26,7 @@
  */
 
 #include <sys/cdefs.h>
-__RCSID("$NetBSD: hijack.c,v 1.1 2011/01/07 19:52:43 pooka Exp $");
+__RCSID("$NetBSD: hijack.c,v 1.2 2011/01/08 14:19:27 pooka Exp $");
 
 #include <sys/param.h>
 #include <sys/types.h>
@@ -50,9 +50,6 @@
 #include <stdlib.h>
 #include <unistd.h>
 
-/* XXX: need runtime selection.  low for now due to FD_SETSIZE */
-#define HIJACK_FDOFF 128
-
 enum { RUMPCALL_SOCKET, RUMPCALL_ACCEPT, RUMPCALL_BIND, RUMPCALL_CONNECT,
        RUMPCALL_GETPEERNAME, RUMPCALL_GETSOCKNAME, RUMPCALL_LISTEN,
        RUMPCALL_RECVFROM, RUMPCALL_RECVMSG,
@@ -104,13 +101,13 @@
 static int     (*host_select)(int, fd_set *, fd_set *, fd_set *,
                               struct timeval *);
 static int     (*host_poll)(struct pollfd *, nfds_t, int);
+static pid_t   (*host_fork)(void);
+static int     (*host_dup2)(int, int);
 #if 0
 static int     (*host_pollts)(struct pollfd *, nfds_t,
                               const struct timespec *, const sigset_t *);
 #endif
 
-#define assertfd(_fd_) assert((_fd_) >= HIJACK_FDOFF)
-
 static void *rumpcalls[RUMPCALL__NUM];
 
 /*
@@ -150,6 +147,8 @@
        host_close = dlsym(RTLD_NEXT, "close");
        host_select = dlsym(RTLD_NEXT, "select");
        host_poll = dlsym(RTLD_NEXT, "poll");
+       host_fork = dlsym(RTLD_NEXT, "fork");
+       host_dup2 = dlsym(RTLD_NEXT, "dup2");
 
        for (i = 0; i < RUMPCALL__NUM; i++) {
                char sysname[128];
@@ -166,7 +165,6 @@
                err(1, "rumpclient init");
 }
 
-#define ADJ(fd) (fd - HIJACK_FDOFF)
 //#define DEBUGJACK
 #ifdef DEBUGJACK
 #define DPRINTF(x) printf x
@@ -174,6 +172,45 @@
 #define DPRINTF(x)
 #endif
 
+static unsigned dup2mask;
+#define ISDUP2D(fd) (((fd+1) & dup2mask) == ((fd)+1))
+
+/* XXX: need runtime selection.  low for now due to FD_SETSIZE */
+#define HIJACK_FDOFF 128
+#define HIJACK_SELECT 128 /* XXX */
+#define HIJACK_ASSERT 128 /* XXX */
+static int
+fd_rump2host(int fd)
+{
+
+       if (fd == -1)
+               return fd;
+
+       if (!ISDUP2D(fd))
+               fd += HIJACK_FDOFF;
+
+       return fd;
+}
+
+static int
+fd_host2rump(int fd)
+{
+
+       if (!ISDUP2D(fd))
+               fd -= HIJACK_FDOFF;
+       return fd;
+}
+
+static bool
+fd_isrump(int fd)
+{
+
+       return ISDUP2D(fd) || fd >= HIJACK_FDOFF;
+}
+
+#define assertfd(_fd_) assert(ISDUP2D(_fd_) || (_fd_) >= HIJACK_ASSERT)
+#undef HIJACK_FDOFF
+
 /*
  * Following wrappers always call the rump kernel.
  */
@@ -185,12 +222,12 @@
        int (*rc_socket)(int, int, int);
        int fd;
 
-       DPRINTF(("socket\n"));
        rc_socket = rumpcalls[RUMPCALL_SOCKET];
        fd = rc_socket(domain, type, protocol);
-       if (fd != -1)
-               fd += HIJACK_FDOFF;
-       return fd;
+
+       DPRINTF(("socket <- %d\n", fd_rump2host(fd)));
+
+       return fd_rump2host(fd);
 }
 
 int
@@ -199,13 +236,13 @@
        int (*rc_accept)(int, struct sockaddr *, socklen_t *);
        int fd;
 
-       DPRINTF(("accept %d\n", s));
+       DPRINTF(("accept -> %d", s));
        assertfd(s);
        rc_accept = rumpcalls[RUMPCALL_ACCEPT];
-       fd = rc_accept(ADJ(s), addr, addrlen);
-       if (fd != -1)
-               fd += HIJACK_FDOFF;
-       return fd;
+       fd = rc_accept(fd_host2rump(s), addr, addrlen);
+       DPRINTF((" <- %d\n", fd_rump2host(fd)));
+
+       return fd_rump2host(fd);
 }
 
 int
@@ -213,10 +250,11 @@
 {
        int (*rc_bind)(int, const struct sockaddr *, socklen_t);
 
-       DPRINTF(("bind\n"));
+       DPRINTF(("bind -> %d\n", s));
        assertfd(s);
        rc_bind = rumpcalls[RUMPCALL_BIND];
-       return rc_bind(ADJ(s), name, namelen);
+
+       return rc_bind(fd_host2rump(s), name, namelen);
 }
 
 int
@@ -224,10 +262,11 @@
 {
        int (*rc_connect)(int, const struct sockaddr *, socklen_t);
 
-       DPRINTF(("connect %d\n", s));
+       DPRINTF(("connect -> %d\n", s));
        assertfd(s);
        rc_connect = rumpcalls[RUMPCALL_CONNECT];
-       return rc_connect(ADJ(s), name, namelen);
+
+       return rc_connect(fd_host2rump(s), name, namelen);
 }
 
 int
@@ -235,10 +274,10 @@
 {
        int (*rc_getpeername)(int, struct sockaddr *, socklen_t *);
 
-       DPRINTF(("getpeername\n"));
+       DPRINTF(("getpeername -> %d\n", s));
        assertfd(s);
        rc_getpeername = rumpcalls[RUMPCALL_GETPEERNAME];
-       return rc_getpeername(ADJ(s), name, namelen);
+       return rc_getpeername(fd_host2rump(s), name, namelen);
 }
 
 int
@@ -246,10 +285,10 @@
 {
        int (*rc_getsockname)(int, struct sockaddr *, socklen_t *);
 
-       DPRINTF(("getsockname\n"));
+       DPRINTF(("getsockname -> %d\n", s));
        assertfd(s);
        rc_getsockname = rumpcalls[RUMPCALL_GETSOCKNAME];
-       return rc_getsockname(ADJ(s), name, namelen);
+       return rc_getsockname(fd_host2rump(s), name, namelen);
 }
 
 int
@@ -257,10 +296,10 @@
 {
        int (*rc_listen)(int, int);
 
-       DPRINTF(("listen\n"));
+       DPRINTF(("listen -> %d\n", s));
        assertfd(s);
        rc_listen = rumpcalls[RUMPCALL_LISTEN];
-       return rc_listen(ADJ(s), backlog);
+       return rc_listen(fd_host2rump(s), backlog);
 }
 
 ssize_t
@@ -280,7 +319,7 @@
        DPRINTF(("recvfrom\n"));
        assertfd(s);
        rc_recvfrom = rumpcalls[RUMPCALL_RECVFROM];
-       return rc_recvfrom(ADJ(s), buf, len, flags, from, fromlen);
+       return rc_recvfrom(fd_host2rump(s), buf, len, flags, from, fromlen);
 }
 
 ssize_t
@@ -291,7 +330,7 @@
        DPRINTF(("recvmsg\n"));
        assertfd(s);
        rc_recvmsg = rumpcalls[RUMPCALL_RECVMSG];
-       return rc_recvmsg(ADJ(s), msg, flags);
+       return rc_recvmsg(fd_host2rump(s), msg, flags);
 }
 
 ssize_t
@@ -314,7 +353,7 @@
        DPRINTF(("sendto\n"));
        assertfd(s);
        rc_sendto = rumpcalls[RUMPCALL_SENDTO];
-       return rc_sendto(ADJ(s), buf, len, flags, to, tolen);
+       return rc_sendto(fd_host2rump(s), buf, len, flags, to, tolen);
 }
 
 ssize_t
@@ -325,7 +364,7 @@
        DPRINTF(("sendmsg\n"));
        assertfd(s);
        rc_sendmsg = rumpcalls[RUMPCALL_SENDTO];
-       return rc_sendmsg(ADJ(s), msg, flags);
+       return rc_sendmsg(fd_host2rump(s), msg, flags);
 }
 
 int
@@ -336,7 +375,7 @@
        DPRINTF(("getsockopt\n"));
        assertfd(s);
        rc_getsockopt = rumpcalls[RUMPCALL_GETSOCKOPT];
-       return rc_getsockopt(ADJ(s), level, optname, optval, optlen);
+       return rc_getsockopt(fd_host2rump(s), level, optname, optval, optlen);
 }
 
 int
@@ -347,7 +386,7 @@
        DPRINTF(("setsockopt\n"));
        assertfd(s);
        rc_setsockopt = rumpcalls[RUMPCALL_SETSOCKOPT];
-       return rc_setsockopt(ADJ(s), level, optname, optval, optlen);
+       return rc_setsockopt(fd_host2rump(s), level, optname, optval, optlen);
 }
 
 int
@@ -358,7 +397,69 @@
        DPRINTF(("shutdown\n"));
        assertfd(s);
        rc_shutdown = rumpcalls[RUMPCALL_SHUTDOWN];
-       return rc_shutdown(ADJ(s), how);
+       return rc_shutdown(fd_host2rump(s), how);
+}
+
+/*
+ * dup2 is special.  we allow dup2 of a rump kernel fd to 0-2 since
+ * many programs do that.  dup2 of a rump kernel fd to another value
+ * not >= fdoff is an error.
+ *
+ * Note: cannot rump2host newd, because it is often hardcoded.
+ *
+ * XXX: should disable debug prints after stdout/stderr are dup2'd
+ */
+int
+dup2(int oldd, int newd)
+{
+       int rv;
+
+       DPRINTF(("dup2 -> %d (o) -> %d (n)\n", oldd, newd));
+
+       if (fd_isrump(oldd)) {
+               if (!(newd >= 0 && newd <= 2))
+                       return EBADF;
+               oldd = fd_host2rump(oldd);
+               rv = rump_sys_dup2(oldd, newd);
+               if (rv != -1)
+                       dup2mask |= newd+1;
+               return rv;
+       } else {
+               return host_dup2(oldd, newd);
+       }
+}



Home | Main Index | Thread Index | Old Index