[BACK]Return to hijack.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / lib / librumphijack

Annotation of src/lib/librumphijack/hijack.c, Revision 1.111

1.111   ! pooka       1: /*      $NetBSD: hijack.c,v 1.110 2014/08/12 23:47:09 pooka Exp $      */
1.1       pooka       2:
                      3: /*-
                      4:  * Copyright (c) 2011 Antti Kantee.  All Rights Reserved.
                      5:  *
                      6:  * Redistribution and use in source and binary forms, with or without
                      7:  * modification, are permitted provided that the following conditions
                      8:  * are met:
                      9:  * 1. Redistributions of source code must retain the above copyright
                     10:  *    notice, this list of conditions and the following disclaimer.
                     11:  * 2. Redistributions in binary form must reproduce the above copyright
                     12:  *    notice, this list of conditions and the following disclaimer in the
                     13:  *    documentation and/or other materials provided with the distribution.
                     14:  *
                     15:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
                     16:  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
                     17:  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
                     18:  * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
                     19:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     20:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
                     21:  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     22:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     23:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     24:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     25:  * SUCH DAMAGE.
                     26:  */
                     27:
1.111   ! pooka      28: /*
        !            29:  * XXX: rumphijack sort of works on glibc Linux.  But it's not
        !            30:  * the same quality working as on NetBSD.
        !            31:  * autoconf HAVE_FOO vs. __NetBSD__ / __linux__ could be further
        !            32:  * improved.
        !            33:  */
1.106     pooka      34: #include <rump/rumpuser_port.h>
1.96      pooka      35:
1.101     pooka      36: #if !defined(lint)
1.111   ! pooka      37: __RCSID("$NetBSD: hijack.c,v 1.110 2014/08/12 23:47:09 pooka Exp $");
1.101     pooka      38: #endif
1.1       pooka      39:
                     40: #include <sys/param.h>
                     41: #include <sys/types.h>
                     42: #include <sys/ioctl.h>
1.62      pooka      43: #include <sys/mman.h>
1.48      pooka      44: #include <sys/mount.h>
1.1       pooka      45: #include <sys/socket.h>
1.96      pooka      46: #include <sys/stat.h>
                     47: #include <sys/time.h>
1.102     pooka      48: #include <sys/uio.h>
1.96      pooka      49:
1.111   ! pooka      50: #ifdef __NetBSD__
1.107     justin     51: #include <sys/statvfs.h>
                     52: #endif
                     53:
1.111   ! pooka      54: #ifdef HAVE_KQUEUE
1.96      pooka      55: #include <sys/event.h>
                     56: #endif
                     57:
1.111   ! pooka      58: #ifdef __NetBSD__
1.91      dholland   59: #include <sys/quotactl.h>
1.96      pooka      60: #endif
1.1       pooka      61:
                     62: #include <assert.h>
                     63: #include <dlfcn.h>
                     64: #include <err.h>
                     65: #include <errno.h>
                     66: #include <fcntl.h>
                     67: #include <poll.h>
                     68: #include <pthread.h>
1.3       pooka      69: #include <signal.h>
1.1       pooka      70: #include <stdarg.h>
1.8       pooka      71: #include <stdbool.h>
1.96      pooka      72: #include <stdint.h>
1.1       pooka      73: #include <stdio.h>
                     74: #include <stdlib.h>
1.28      pooka      75: #include <string.h>
1.3       pooka      76: #include <time.h>
1.1       pooka      77: #include <unistd.h>
                     78:
1.96      pooka      79: #include <rump/rumpclient.h>
                     80: #include <rump/rump_syscalls.h>
                     81:
1.64      pooka      82: #include "hijack.h"
                     83:
1.96      pooka      84: /*
                     85:  * XXX: Consider autogenerating this, syscnames[] and syscalls[] with
                     86:  * a DSL where the tool also checks the symbols exported by this library
                     87:  * to make sure all relevant calls are accounted for.
                     88:  */
1.17      pooka      89: enum dualcall {
1.60      pooka      90:        DUALCALL_WRITE, DUALCALL_WRITEV, DUALCALL_PWRITE, DUALCALL_PWRITEV,
1.17      pooka      91:        DUALCALL_IOCTL, DUALCALL_FCNTL,
                     92:        DUALCALL_SOCKET, DUALCALL_ACCEPT, DUALCALL_BIND, DUALCALL_CONNECT,
                     93:        DUALCALL_GETPEERNAME, DUALCALL_GETSOCKNAME, DUALCALL_LISTEN,
                     94:        DUALCALL_RECVFROM, DUALCALL_RECVMSG,
                     95:        DUALCALL_SENDTO, DUALCALL_SENDMSG,
                     96:        DUALCALL_GETSOCKOPT, DUALCALL_SETSOCKOPT,
                     97:        DUALCALL_SHUTDOWN,
1.60      pooka      98:        DUALCALL_READ, DUALCALL_READV, DUALCALL_PREAD, DUALCALL_PREADV,
1.41      pooka      99:        DUALCALL_DUP2,
1.34      pooka     100:        DUALCALL_CLOSE,
1.17      pooka     101:        DUALCALL_POLLTS,
1.97      pooka     102:
                    103: #ifndef __linux__
1.45      pooka     104:        DUALCALL_STAT, DUALCALL_LSTAT, DUALCALL_FSTAT,
1.97      pooka     105: #endif
                    106:
1.45      pooka     107:        DUALCALL_CHMOD, DUALCALL_LCHMOD, DUALCALL_FCHMOD,
                    108:        DUALCALL_CHOWN, DUALCALL_LCHOWN, DUALCALL_FCHOWN,
                    109:        DUALCALL_OPEN,
                    110:        DUALCALL_CHDIR, DUALCALL_FCHDIR,
                    111:        DUALCALL_LSEEK,
                    112:        DUALCALL_UNLINK, DUALCALL_SYMLINK, DUALCALL_READLINK,
1.95      riastrad  113:        DUALCALL_LINK, DUALCALL_RENAME,
1.45      pooka     114:        DUALCALL_MKDIR, DUALCALL_RMDIR,
                    115:        DUALCALL_UTIMES, DUALCALL_LUTIMES, DUALCALL_FUTIMES,
                    116:        DUALCALL_TRUNCATE, DUALCALL_FTRUNCATE,
1.96      pooka     117:        DUALCALL_FSYNC,
1.97      pooka     118:        DUALCALL_ACCESS,
                    119:
                    120: #ifndef __linux__
1.57      pooka     121:        DUALCALL___GETCWD,
1.98      pooka     122:        DUALCALL_GETDENTS,
1.97      pooka     123: #endif
                    124:
                    125: #ifndef __linux__
1.68      pooka     126:        DUALCALL_MKNOD,
1.97      pooka     127: #endif
                    128:
1.111   ! pooka     129: #ifdef __NetBSD__
1.96      pooka     130:        DUALCALL_GETFH, DUALCALL_FHOPEN, DUALCALL_FHSTAT, DUALCALL_FHSTATVFS1,
1.97      pooka     131: #endif
                    132:
1.111   ! pooka     133: #ifdef HAVE_KQUEUE
1.97      pooka     134:        DUALCALL_KEVENT,
                    135: #endif
1.96      pooka     136:
1.111   ! pooka     137: #ifdef __NetBSD__
1.78      pooka     138:        DUALCALL___SYSCTL,
1.96      pooka     139: #endif
                    140:
1.111   ! pooka     141: #ifdef __NetBSD__
1.96      pooka     142:        DUALCALL_NFSSVC,
                    143: #endif
                    144:
1.111   ! pooka     145: #ifdef __NetBSD__
1.96      pooka     146:        DUALCALL_STATVFS1, DUALCALL_FSTATVFS1, DUALCALL_GETVFSSTAT,
                    147: #endif
                    148:
1.111   ! pooka     149: #ifdef __NetBSD__
1.96      pooka     150:        DUALCALL_MOUNT, DUALCALL_UNMOUNT,
                    151: #endif
                    152:
1.111   ! pooka     153: #ifdef HAVE_FSYNC_RANGE
1.96      pooka     154:        DUALCALL_FSYNC_RANGE,
                    155: #endif
                    156:
1.111   ! pooka     157: #ifdef HAVE_CHFLAGS
1.96      pooka     158:        DUALCALL_CHFLAGS, DUALCALL_LCHFLAGS, DUALCALL_FCHFLAGS,
                    159: #endif
                    160:
1.111   ! pooka     161: #ifdef HAVE___QUOTACTL
1.80      bouyer    162:        DUALCALL_QUOTACTL,
1.83      pooka     163: #endif
1.17      pooka     164:        DUALCALL__NUM
1.1       pooka     165: };
                    166:
1.8       pooka     167: #define RSYS_STRING(a) __STRING(a)
                    168: #define RSYS_NAME(a) RSYS_STRING(__CONCAT(RUMP_SYS_RENAME_,a))
                    169:
1.1       pooka     170: /*
1.14      pooka     171:  * Would be nice to get this automatically in sync with libc.
1.97      pooka     172:  * Also, this does not work for compat-using binaries (we should
                    173:  * provide all previous interfaces, not just the current ones)
1.14      pooka     174:  */
1.97      pooka     175: #if defined(__NetBSD__)
                    176:
1.14      pooka     177: #if !__NetBSD_Prereq__(5,99,7)
1.29      pooka     178: #define REALSELECT select
                    179: #define REALPOLLTS pollts
1.34      pooka     180: #define REALKEVENT kevent
1.45      pooka     181: #define REALSTAT __stat30
                    182: #define REALLSTAT __lstat30
                    183: #define REALFSTAT __fstat30
                    184: #define REALUTIMES utimes
                    185: #define REALLUTIMES lutimes
                    186: #define REALFUTIMES futimes
1.68      pooka     187: #define REALMKNOD mknod
1.78      pooka     188: #define REALFHSTAT __fhstat40
1.96      pooka     189: #else /* >= 5.99.7 */
1.29      pooka     190: #define REALSELECT _sys___select50
                    191: #define REALPOLLTS _sys___pollts50
1.34      pooka     192: #define REALKEVENT _sys___kevent50
1.45      pooka     193: #define REALSTAT __stat50
                    194: #define REALLSTAT __lstat50
                    195: #define REALFSTAT __fstat50
                    196: #define REALUTIMES __utimes50
                    197: #define REALLUTIMES __lutimes50
1.69      pooka     198: #define REALFUTIMES __futimes50
1.68      pooka     199: #define REALMKNOD __mknod50
1.78      pooka     200: #define REALFHSTAT __fhstat50
1.96      pooka     201: #endif /* < 5.99.7 */
1.97      pooka     202:
1.31      pooka     203: #define REALREAD _sys_read
1.60      pooka     204: #define REALPREAD _sys_pread
                    205: #define REALPWRITE _sys_pwrite
1.45      pooka     206: #define REALGETDENTS __getdents30
1.48      pooka     207: #define REALMOUNT __mount50
1.78      pooka     208: #define REALGETFH __getfh30
                    209: #define REALFHOPEN __fhopen40
                    210: #define REALFHSTATVFS1 __fhstatvfs140
1.96      pooka     211: #define REALSOCKET __socket30
                    212:
                    213: #define LSEEK_ALIAS _lseek
                    214: #define VFORK __vfork14
                    215:
1.97      pooka     216: int REALSTAT(const char *, struct stat *);
                    217: int REALLSTAT(const char *, struct stat *);
                    218: int REALFSTAT(int, struct stat *);
                    219: int REALMKNOD(const char *, mode_t, dev_t);
1.98      pooka     220: int REALGETDENTS(int, char *, size_t);
1.97      pooka     221:
                    222: int __getcwd(char *, size_t);
                    223:
                    224: #elif defined(__linux__) /* glibc, really */
1.96      pooka     225:
                    226: #define REALREAD read
                    227: #define REALPREAD pread
                    228: #define REALPWRITE pwrite
                    229: #define REALSELECT select
                    230: #define REALPOLLTS ppoll
                    231: #define REALUTIMES utimes
                    232: #define REALLUTIMES lutimes
                    233: #define REALFUTIMES futimes
                    234: #define REALFHSTAT fhstat
                    235: #define REALSOCKET socket
                    236:
1.97      pooka     237: #else /* !NetBSD && !linux */
                    238:
                    239: #error platform not supported
                    240:
                    241: #endif /* platform */
1.14      pooka     242:
1.29      pooka     243: int REALSELECT(int, fd_set *, fd_set *, fd_set *, struct timeval *);
                    244: int REALPOLLTS(struct pollfd *, nfds_t,
1.20      pooka     245:               const struct timespec *, const sigset_t *);
1.34      pooka     246: int REALKEVENT(int, const struct kevent *, size_t, struct kevent *, size_t,
                    247:               const struct timespec *);
1.31      pooka     248: ssize_t REALREAD(int, void *, size_t);
1.60      pooka     249: ssize_t REALPREAD(int, void *, size_t, off_t);
                    250: ssize_t REALPWRITE(int, const void *, size_t, off_t);
1.45      pooka     251: int REALUTIMES(const char *, const struct timeval [2]);
                    252: int REALLUTIMES(const char *, const struct timeval [2]);
                    253: int REALFUTIMES(int, const struct timeval [2]);
1.48      pooka     254: int REALMOUNT(const char *, const char *, int, void *, size_t);
1.78      pooka     255: int REALGETFH(const char *, void *, size_t *);
                    256: int REALFHOPEN(const void *, size_t, int);
                    257: int REALFHSTAT(const void *, size_t, struct stat *);
                    258: int REALFHSTATVFS1(const void *, size_t, struct statvfs *, int);
1.96      pooka     259: int REALSOCKET(int, int, int);
                    260:
1.17      pooka     261: #define S(a) __STRING(a)
                    262: struct sysnames {
                    263:        enum dualcall scm_callnum;
                    264:        const char *scm_hostname;
                    265:        const char *scm_rumpname;
1.83      pooka     266: } syscnames[] = {
1.96      pooka     267:        { DUALCALL_SOCKET,      S(REALSOCKET),  RSYS_NAME(SOCKET)       },
1.17      pooka     268:        { DUALCALL_ACCEPT,      "accept",       RSYS_NAME(ACCEPT)       },
                    269:        { DUALCALL_BIND,        "bind",         RSYS_NAME(BIND)         },
                    270:        { DUALCALL_CONNECT,     "connect",      RSYS_NAME(CONNECT)      },
                    271:        { DUALCALL_GETPEERNAME, "getpeername",  RSYS_NAME(GETPEERNAME)  },
                    272:        { DUALCALL_GETSOCKNAME, "getsockname",  RSYS_NAME(GETSOCKNAME)  },
                    273:        { DUALCALL_LISTEN,      "listen",       RSYS_NAME(LISTEN)       },
                    274:        { DUALCALL_RECVFROM,    "recvfrom",     RSYS_NAME(RECVFROM)     },
                    275:        { DUALCALL_RECVMSG,     "recvmsg",      RSYS_NAME(RECVMSG)      },
                    276:        { DUALCALL_SENDTO,      "sendto",       RSYS_NAME(SENDTO)       },
                    277:        { DUALCALL_SENDMSG,     "sendmsg",      RSYS_NAME(SENDMSG)      },
                    278:        { DUALCALL_GETSOCKOPT,  "getsockopt",   RSYS_NAME(GETSOCKOPT)   },
                    279:        { DUALCALL_SETSOCKOPT,  "setsockopt",   RSYS_NAME(SETSOCKOPT)   },
                    280:        { DUALCALL_SHUTDOWN,    "shutdown",     RSYS_NAME(SHUTDOWN)     },
1.31      pooka     281:        { DUALCALL_READ,        S(REALREAD),    RSYS_NAME(READ)         },
1.17      pooka     282:        { DUALCALL_READV,       "readv",        RSYS_NAME(READV)        },
1.60      pooka     283:        { DUALCALL_PREAD,       S(REALPREAD),   RSYS_NAME(PREAD)        },
                    284:        { DUALCALL_PREADV,      "preadv",       RSYS_NAME(PREADV)       },
1.17      pooka     285:        { DUALCALL_WRITE,       "write",        RSYS_NAME(WRITE)        },
                    286:        { DUALCALL_WRITEV,      "writev",       RSYS_NAME(WRITEV)       },
1.60      pooka     287:        { DUALCALL_PWRITE,      S(REALPWRITE),  RSYS_NAME(PWRITE)       },
                    288:        { DUALCALL_PWRITEV,     "pwritev",      RSYS_NAME(PWRITEV)      },
1.17      pooka     289:        { DUALCALL_IOCTL,       "ioctl",        RSYS_NAME(IOCTL)        },
                    290:        { DUALCALL_FCNTL,       "fcntl",        RSYS_NAME(FCNTL)        },
                    291:        { DUALCALL_DUP2,        "dup2",         RSYS_NAME(DUP2)         },
                    292:        { DUALCALL_CLOSE,       "close",        RSYS_NAME(CLOSE)        },
1.29      pooka     293:        { DUALCALL_POLLTS,      S(REALPOLLTS),  RSYS_NAME(POLLTS)       },
1.97      pooka     294: #ifndef __linux__
1.45      pooka     295:        { DUALCALL_STAT,        S(REALSTAT),    RSYS_NAME(STAT)         },
                    296:        { DUALCALL_LSTAT,       S(REALLSTAT),   RSYS_NAME(LSTAT)        },
                    297:        { DUALCALL_FSTAT,       S(REALFSTAT),   RSYS_NAME(FSTAT)        },
1.97      pooka     298: #endif
1.45      pooka     299:        { DUALCALL_CHOWN,       "chown",        RSYS_NAME(CHOWN)        },
                    300:        { DUALCALL_LCHOWN,      "lchown",       RSYS_NAME(LCHOWN)       },
                    301:        { DUALCALL_FCHOWN,      "fchown",       RSYS_NAME(FCHOWN)       },
                    302:        { DUALCALL_CHMOD,       "chmod",        RSYS_NAME(CHMOD)        },
                    303:        { DUALCALL_LCHMOD,      "lchmod",       RSYS_NAME(LCHMOD)       },
                    304:        { DUALCALL_FCHMOD,      "fchmod",       RSYS_NAME(FCHMOD)       },
                    305:        { DUALCALL_UTIMES,      S(REALUTIMES),  RSYS_NAME(UTIMES)       },
                    306:        { DUALCALL_LUTIMES,     S(REALLUTIMES), RSYS_NAME(LUTIMES)      },
                    307:        { DUALCALL_FUTIMES,     S(REALFUTIMES), RSYS_NAME(FUTIMES)      },
                    308:        { DUALCALL_OPEN,        "open",         RSYS_NAME(OPEN)         },
                    309:        { DUALCALL_CHDIR,       "chdir",        RSYS_NAME(CHDIR)        },
                    310:        { DUALCALL_FCHDIR,      "fchdir",       RSYS_NAME(FCHDIR)       },
1.61      pooka     311:        { DUALCALL_LSEEK,       "lseek",        RSYS_NAME(LSEEK)        },
1.45      pooka     312:        { DUALCALL_UNLINK,      "unlink",       RSYS_NAME(UNLINK)       },
                    313:        { DUALCALL_SYMLINK,     "symlink",      RSYS_NAME(SYMLINK)      },
                    314:        { DUALCALL_READLINK,    "readlink",     RSYS_NAME(READLINK)     },
1.95      riastrad  315:        { DUALCALL_LINK,        "link",         RSYS_NAME(LINK)         },
1.45      pooka     316:        { DUALCALL_RENAME,      "rename",       RSYS_NAME(RENAME)       },
                    317:        { DUALCALL_MKDIR,       "mkdir",        RSYS_NAME(MKDIR)        },
                    318:        { DUALCALL_RMDIR,       "rmdir",        RSYS_NAME(RMDIR)        },
                    319:        { DUALCALL_TRUNCATE,    "truncate",     RSYS_NAME(TRUNCATE)     },
                    320:        { DUALCALL_FTRUNCATE,   "ftruncate",    RSYS_NAME(FTRUNCATE)    },
                    321:        { DUALCALL_FSYNC,       "fsync",        RSYS_NAME(FSYNC)        },
1.97      pooka     322:        { DUALCALL_ACCESS,      "access",       RSYS_NAME(ACCESS)       },
                    323:
                    324: #ifndef __linux__
1.57      pooka     325:        { DUALCALL___GETCWD,    "__getcwd",     RSYS_NAME(__GETCWD)     },
1.98      pooka     326:        { DUALCALL_GETDENTS,    S(REALGETDENTS),RSYS_NAME(GETDENTS)     },
1.97      pooka     327: #endif
                    328:
                    329: #ifndef __linux__
1.68      pooka     330:        { DUALCALL_MKNOD,       S(REALMKNOD),   RSYS_NAME(MKNOD)        },
1.97      pooka     331: #endif
                    332:
1.111   ! pooka     333: #ifdef __NetBSD__
1.79      bouyer    334:        { DUALCALL_GETFH,       S(REALGETFH),   RSYS_NAME(GETFH)        },
1.97      pooka     335:        { DUALCALL_FHOPEN,      S(REALFHOPEN),  RSYS_NAME(FHOPEN)       },
                    336:        { DUALCALL_FHSTAT,      S(REALFHSTAT),  RSYS_NAME(FHSTAT)       },
1.79      bouyer    337:        { DUALCALL_FHSTATVFS1,  S(REALFHSTATVFS1),RSYS_NAME(FHSTATVFS1) },
1.97      pooka     338: #endif
                    339:
1.111   ! pooka     340: #ifdef HAVE_KQUEUE
1.97      pooka     341:        { DUALCALL_KEVENT,      S(REALKEVENT),  RSYS_NAME(KEVENT)       },
                    342: #endif
1.96      pooka     343:
1.111   ! pooka     344: #ifdef __NetBSD__
1.96      pooka     345:        { DUALCALL___SYSCTL,    "__sysctl",     RSYS_NAME(__SYSCTL)     },
                    346: #endif
                    347:
1.111   ! pooka     348: #ifdef __NetBSD__
1.96      pooka     349:        { DUALCALL_NFSSVC,      "nfssvc",       RSYS_NAME(NFSSVC)       },
                    350: #endif
                    351:
1.111   ! pooka     352: #ifdef __NetBSD__
1.96      pooka     353:        { DUALCALL_STATVFS1,    "statvfs1",     RSYS_NAME(STATVFS1)     },
                    354:        { DUALCALL_FSTATVFS1,   "fstatvfs1",    RSYS_NAME(FSTATVFS1)    },
                    355:        { DUALCALL_GETVFSSTAT,  "getvfsstat",   RSYS_NAME(GETVFSSTAT)   },
                    356: #endif
                    357:
1.111   ! pooka     358: #ifdef __NetBSD__
1.96      pooka     359:        { DUALCALL_MOUNT,       S(REALMOUNT),   RSYS_NAME(MOUNT)        },
                    360:        { DUALCALL_UNMOUNT,     "unmount",      RSYS_NAME(UNMOUNT)      },
                    361: #endif
                    362:
1.111   ! pooka     363: #ifdef HAVE_FSYNC_RANGE
1.96      pooka     364:        { DUALCALL_FSYNC_RANGE, "fsync_range",  RSYS_NAME(FSYNC_RANGE)  },
                    365: #endif
                    366:
1.111   ! pooka     367: #ifdef HAVE_CHFLAGS
1.96      pooka     368:        { DUALCALL_CHFLAGS,     "chflags",      RSYS_NAME(CHFLAGS)      },
                    369:        { DUALCALL_LCHFLAGS,    "lchflags",     RSYS_NAME(LCHFLAGS)     },
                    370:        { DUALCALL_FCHFLAGS,    "fchflags",     RSYS_NAME(FCHFLAGS)     },
1.111   ! pooka     371: #endif /* HAVE_CHFLAGS */
1.96      pooka     372:
1.111   ! pooka     373: #ifdef HAVE___QUOTACTL
1.91      dholland  374:        { DUALCALL_QUOTACTL,    "__quotactl",   RSYS_NAME(__QUOTACTL)   },
1.111   ! pooka     375: #endif /* HAVE___QUOTACTL */
1.96      pooka     376:
1.17      pooka     377: };
                    378: #undef S
                    379:
                    380: struct bothsys {
                    381:        void *bs_host;
                    382:        void *bs_rump;
                    383: } syscalls[DUALCALL__NUM];
                    384: #define GETSYSCALL(which, name) syscalls[DUALCALL_##name].bs_##which
                    385:
1.71      pooka     386: static pid_t   (*host_fork)(void);
                    387: static int     (*host_daemon)(int, int);
                    388: static void *  (*host_mmap)(void *, size_t, int, int, int, off_t);
                    389:
1.75      pooka     390: /*
                    391:  * This tracks if our process is in a subdirectory of /rump.
                    392:  * It's preserved over exec.
                    393:  */
                    394: static bool pwdinrump;
                    395:
                    396: enum pathtype { PATH_HOST, PATH_RUMP, PATH_RUMPBLANKET };
                    397:
                    398: static bool            fd_isrump(int);
                    399: static enum pathtype   path_isrump(const char *);
1.71      pooka     400:
1.85      pooka     401: /* default FD_SETSIZE is 256 ==> default fdoff is 128 */
                    402: static int hijack_fdoff = FD_SETSIZE/2;
                    403:
1.71      pooka     404: /*
                    405:  * Maintain a mapping table for the usual dup2 suspects.
1.74      pooka     406:  * Could use atomic ops to operate on dup2vec, but an application
                    407:  * racing there is not well-defined, so don't bother.
1.71      pooka     408:  */
                    409: /* note: you cannot change this without editing the env-passing code */
                    410: #define DUP2HIGH 2
                    411: static uint32_t dup2vec[DUP2HIGH+1];
                    412: #define DUP2BIT (1<<31)
                    413: #define DUP2ALIAS (1<<30)
                    414: #define DUP2FDMASK ((1<<30)-1)
                    415:
                    416: static bool
                    417: isdup2d(int fd)
                    418: {
                    419:
                    420:        return fd <= DUP2HIGH && fd >= 0 && dup2vec[fd] & DUP2BIT;
                    421: }
                    422:
                    423: static int
                    424: mapdup2(int hostfd)
                    425: {
                    426:
                    427:        _DIAGASSERT(isdup2d(hostfd));
                    428:        return dup2vec[hostfd] & DUP2FDMASK;
                    429: }
                    430:
                    431: static int
                    432: unmapdup2(int rumpfd)
                    433: {
                    434:        int i;
                    435:
                    436:        for (i = 0; i <= DUP2HIGH; i++) {
1.72      pooka     437:                if (dup2vec[i] & DUP2BIT &&
                    438:                    (dup2vec[i] & DUP2FDMASK) == (unsigned)rumpfd)
1.71      pooka     439:                        return i;
                    440:        }
                    441:        return -1;
                    442: }
                    443:
                    444: static void
                    445: setdup2(int hostfd, int rumpfd)
                    446: {
                    447:
                    448:        if (hostfd > DUP2HIGH) {
                    449:                _DIAGASSERT(0);
                    450:                return;
                    451:        }
                    452:
                    453:        dup2vec[hostfd] = DUP2BIT | DUP2ALIAS | rumpfd;
                    454: }
                    455:
                    456: static void
                    457: clrdup2(int hostfd)
                    458: {
                    459:
                    460:        if (hostfd > DUP2HIGH) {
                    461:                _DIAGASSERT(0);
                    462:                return;
                    463:        }
                    464:
                    465:        dup2vec[hostfd] = 0;
                    466: }
                    467:
                    468: static bool
                    469: killdup2alias(int rumpfd)
                    470: {
                    471:        int hostfd;
                    472:
                    473:        if ((hostfd = unmapdup2(rumpfd)) == -1)
                    474:                return false;
                    475:
                    476:        if (dup2vec[hostfd] & DUP2ALIAS) {
                    477:                dup2vec[hostfd] &= ~DUP2ALIAS;
                    478:                return true;
                    479:        }
                    480:        return false;
                    481: }
1.17      pooka     482:
                    483: //#define DEBUGJACK
                    484: #ifdef DEBUGJACK
                    485: #define DPRINTF(x) mydprintf x
                    486: static void
                    487: mydprintf(const char *fmt, ...)
                    488: {
                    489:        va_list ap;
                    490:
1.71      pooka     491:        if (isdup2d(STDERR_FILENO))
1.17      pooka     492:                return;
                    493:
                    494:        va_start(ap, fmt);
                    495:        vfprintf(stderr, fmt, ap);
                    496:        va_end(ap);
                    497: }
                    498:
1.71      pooka     499: static const char *
                    500: whichfd(int fd)
                    501: {
                    502:
                    503:        if (fd == -1)
                    504:                return "-1";
                    505:        else if (fd_isrump(fd))
                    506:                return "rump";
                    507:        else
                    508:                return "host";
                    509: }
                    510:
                    511: static const char *
                    512: whichpath(const char *path)
                    513: {
                    514:
                    515:        if (path_isrump(path))
                    516:                return "rump";
                    517:        else
                    518:                return "host";
                    519: }
                    520:
1.17      pooka     521: #else
                    522: #define DPRINTF(x)
1.14      pooka     523: #endif
                    524:
1.17      pooka     525: #define FDCALL(type, name, rcname, args, proto, vars)                  \
                    526: type name args                                                         \
                    527: {                                                                      \
                    528:        type (*fun) proto;                                              \
                    529:                                                                        \
1.71      pooka     530:        DPRINTF(("%s -> %d (%s)\n", __STRING(name), fd, whichfd(fd)));  \
1.17      pooka     531:        if (fd_isrump(fd)) {                                            \
                    532:                fun = syscalls[rcname].bs_rump;                         \
                    533:                fd = fd_host2rump(fd);                                  \
                    534:        } else {                                                        \
                    535:                fun = syscalls[rcname].bs_host;                         \
                    536:        }                                                               \
                    537:                                                                        \
                    538:        return fun vars;                                                \
                    539: }
                    540:
1.45      pooka     541: #define PATHCALL(type, name, rcname, args, proto, vars)                        \
                    542: type name args                                                         \
                    543: {                                                                      \
                    544:        type (*fun) proto;                                              \
1.75      pooka     545:        enum pathtype pt;                                               \
1.45      pooka     546:                                                                        \
1.71      pooka     547:        DPRINTF(("%s -> %s (%s)\n", __STRING(name), path,               \
                    548:            whichpath(path)));                                          \
1.75      pooka     549:        if ((pt = path_isrump(path)) != PATH_HOST) {                    \
1.45      pooka     550:                fun = syscalls[rcname].bs_rump;                         \
1.75      pooka     551:                if (pt == PATH_RUMP)                                    \
                    552:                        path = path_host2rump(path);                    \
1.45      pooka     553:        } else {                                                        \
                    554:                fun = syscalls[rcname].bs_host;                         \
                    555:        }                                                               \
                    556:                                                                        \
                    557:        return fun vars;                                                \
                    558: }
                    559:
1.78      pooka     560: #define VFSCALL(bit, type, name, rcname, args, proto, vars)            \
                    561: type name args                                                         \
                    562: {                                                                      \
                    563:        type (*fun) proto;                                              \
                    564:                                                                        \
                    565:        DPRINTF(("%s (0x%x, 0x%x)\n", __STRING(name), bit, vfsbits));   \
                    566:        if (vfsbits & bit) {                                            \
                    567:                fun = syscalls[rcname].bs_rump;                         \
                    568:        } else {                                                        \
                    569:                fun = syscalls[rcname].bs_host;                         \
                    570:        }                                                               \
                    571:                                                                        \
                    572:        return fun vars;                                                \
                    573: }
                    574:
1.14      pooka     575: /*
1.49      pooka     576:  * These variables are set from the RUMPHIJACK string and control
                    577:  * which operations can product rump kernel file descriptors.
                    578:  * This should be easily extendable for future needs.
                    579:  */
                    580: #define RUMPHIJACK_DEFAULT "path=/rump,socket=all:nolocal"
                    581: static bool rumpsockets[PF_MAX];
                    582: static const char *rumpprefix;
                    583: static size_t rumpprefixlen;
                    584:
                    585: static struct {
                    586:        int pf;
                    587:        const char *name;
                    588: } socketmap[] = {
1.51      pooka     589:        { PF_LOCAL, "local" },
1.49      pooka     590:        { PF_INET, "inet" },
1.96      pooka     591: #ifdef PF_LINK
1.49      pooka     592:        { PF_LINK, "link" },
1.96      pooka     593: #endif
1.55      pooka     594: #ifdef PF_OROUTE
1.56      pooka     595:        { PF_OROUTE, "oroute" },
                    596: #endif
1.49      pooka     597:        { PF_ROUTE, "route" },
                    598:        { PF_INET6, "inet6" },
1.55      pooka     599: #ifdef PF_MPLS
                    600:        { PF_MPLS, "mpls" },
                    601: #endif
1.49      pooka     602:        { -1, NULL }
                    603: };
                    604:
                    605: static void
                    606: sockparser(char *buf)
                    607: {
1.96      pooka     608:        char *p, *l = NULL;
1.49      pooka     609:        bool value;
                    610:        int i;
                    611:
                    612:        /* if "all" is present, it must be specified first */
                    613:        if (strncmp(buf, "all", strlen("all")) == 0) {
1.50      pooka     614:                for (i = 0; i < (int)__arraycount(rumpsockets); i++) {
1.49      pooka     615:                        rumpsockets[i] = true;
                    616:                }
                    617:                buf += strlen("all");
                    618:                if (*buf == ':')
                    619:                        buf++;
                    620:        }
                    621:
                    622:        for (p = strtok_r(buf, ":", &l); p; p = strtok_r(NULL, ":", &l)) {
                    623:                value = true;
                    624:                if (strncmp(p, "no", strlen("no")) == 0) {
                    625:                        value = false;
                    626:                        p += strlen("no");
                    627:                }
1.45      pooka     628:
1.49      pooka     629:                for (i = 0; socketmap[i].name; i++) {
                    630:                        if (strcmp(p, socketmap[i].name) == 0) {
                    631:                                rumpsockets[socketmap[i].pf] = value;
                    632:                                break;
                    633:                        }
                    634:                }
                    635:                if (socketmap[i].name == NULL) {
1.78      pooka     636:                        errx(1, "invalid socket specifier %s", p);
1.49      pooka     637:                }
                    638:        }
                    639: }
                    640:
                    641: static void
                    642: pathparser(char *buf)
                    643: {
                    644:
1.57      pooka     645:        /* sanity-check */
1.49      pooka     646:        if (*buf != '/')
                    647:                errx(1, "hijack path specifier must begin with ``/''");
1.57      pooka     648:        rumpprefixlen = strlen(buf);
                    649:        if (rumpprefixlen < 2)
                    650:                errx(1, "invalid hijack prefix: %s", buf);
                    651:        if (buf[rumpprefixlen-1] == '/' && strspn(buf, "/") != rumpprefixlen)
                    652:                errx(1, "hijack prefix may end in slash only if pure "
                    653:                    "slash, gave %s", buf);
1.49      pooka     654:
                    655:        if ((rumpprefix = strdup(buf)) == NULL)
                    656:                err(1, "strdup");
                    657:        rumpprefixlen = strlen(rumpprefix);
                    658: }
                    659:
1.75      pooka     660: static struct blanket {
                    661:        const char *pfx;
                    662:        size_t len;
                    663: } *blanket;
                    664: static int nblanket;
                    665:
                    666: static void
                    667: blanketparser(char *buf)
                    668: {
1.96      pooka     669:        char *p, *l = NULL;
1.75      pooka     670:        int i;
                    671:
                    672:        for (nblanket = 0, p = buf; p; p = strchr(p+1, ':'), nblanket++)
                    673:                continue;
                    674:
                    675:        blanket = malloc(nblanket * sizeof(*blanket));
                    676:        if (blanket == NULL)
                    677:                err(1, "alloc blanket %d", nblanket);
                    678:
                    679:        for (p = strtok_r(buf, ":", &l), i = 0; p;
                    680:            p = strtok_r(NULL, ":", &l), i++) {
                    681:                blanket[i].pfx = strdup(p);
                    682:                if (blanket[i].pfx == NULL)
                    683:                        err(1, "strdup blanket");
                    684:                blanket[i].len = strlen(p);
                    685:
                    686:                if (blanket[i].len == 0 || *blanket[i].pfx != '/')
                    687:                        errx(1, "invalid blanket specifier %s", p);
                    688:                if (*(blanket[i].pfx + blanket[i].len-1) == '/')
                    689:                        errx(1, "invalid blanket specifier %s", p);
                    690:        }
                    691: }
                    692:
1.78      pooka     693: #define VFSBIT_NFSSVC          0x01
                    694: #define VFSBIT_GETVFSSTAT      0x02
                    695: #define VFSBIT_FHCALLS         0x04
                    696: static unsigned vfsbits;
                    697:
                    698: static struct {
                    699:        int bit;
                    700:        const char *name;
                    701: } vfscalls[] = {
                    702:        { VFSBIT_NFSSVC, "nfssvc" },
                    703:        { VFSBIT_GETVFSSTAT, "getvfsstat" },
                    704:        { VFSBIT_FHCALLS, "fhcalls" },
                    705:        { -1, NULL }
                    706: };
                    707:
                    708: static void
                    709: vfsparser(char *buf)
                    710: {
1.96      pooka     711:        char *p, *l = NULL;
1.78      pooka     712:        bool turnon;
                    713:        unsigned int fullmask;
                    714:        int i;
                    715:
                    716:        /* build the full mask and sanity-check while we're at it */
                    717:        fullmask = 0;
                    718:        for (i = 0; vfscalls[i].name != NULL; i++) {
                    719:                if (fullmask & vfscalls[i].bit)
                    720:                        errx(1, "problem exists between vi and chair");
                    721:                fullmask |= vfscalls[i].bit;
                    722:        }
                    723:
                    724:
                    725:        /* if "all" is present, it must be specified first */
                    726:        if (strncmp(buf, "all", strlen("all")) == 0) {
                    727:                vfsbits = fullmask;
                    728:                buf += strlen("all");
                    729:                if (*buf == ':')
                    730:                        buf++;
                    731:        }
                    732:
                    733:        for (p = strtok_r(buf, ":", &l); p; p = strtok_r(NULL, ":", &l)) {
                    734:                turnon = true;
                    735:                if (strncmp(p, "no", strlen("no")) == 0) {
                    736:                        turnon = false;
                    737:                        p += strlen("no");
                    738:                }
                    739:
                    740:                for (i = 0; vfscalls[i].name; i++) {
                    741:                        if (strcmp(p, vfscalls[i].name) == 0) {
                    742:                                if (turnon)
                    743:                                        vfsbits |= vfscalls[i].bit;
                    744:                                else
                    745:                                        vfsbits &= ~vfscalls[i].bit;
                    746:                                break;
                    747:                        }
                    748:                }
                    749:                if (vfscalls[i].name == NULL) {
                    750:                        errx(1, "invalid vfscall specifier %s", p);
                    751:                }
                    752:        }
                    753: }
                    754:
                    755: static bool rumpsysctl = false;
                    756:
                    757: static void
                    758: sysctlparser(char *buf)
                    759: {
                    760:
                    761:        if (buf == NULL) {
                    762:                rumpsysctl = true;
                    763:                return;
                    764:        }
                    765:
                    766:        if (strcasecmp(buf, "y") == 0 || strcasecmp(buf, "yes") == 0 ||
                    767:            strcasecmp(buf, "yep") == 0 || strcasecmp(buf, "tottakai") == 0) {
                    768:                rumpsysctl = true;
                    769:                return;
                    770:        }
                    771:        if (strcasecmp(buf, "n") == 0 || strcasecmp(buf, "no") == 0) {
                    772:                rumpsysctl = false;
                    773:                return;
                    774:        }
                    775:
                    776:        errx(1, "sysctl value should be y(es)/n(o), gave: %s", buf);
                    777: }
                    778:
1.85      pooka     779: static void
                    780: fdoffparser(char *buf)
                    781: {
                    782:        unsigned long fdoff;
                    783:        char *ep;
                    784:
                    785:        if (*buf == '-') {
                    786:                errx(1, "fdoff must not be negative");
                    787:        }
                    788:        fdoff = strtoul(buf, &ep, 10);
                    789:        if (*ep != '\0')
                    790:                errx(1, "invalid fdoff specifier \"%s\"", buf);
                    791:        if (fdoff >= INT_MAX/2 || fdoff < 3)
                    792:                errx(1, "fdoff out of range");
                    793:        hijack_fdoff = fdoff;
                    794: }
                    795:
1.49      pooka     796: static struct {
                    797:        void (*parsefn)(char *);
                    798:        const char *name;
1.78      pooka     799:        bool needvalues;
1.49      pooka     800: } hijackparse[] = {
1.78      pooka     801:        { sockparser, "socket", true },
                    802:        { pathparser, "path", true },
                    803:        { blanketparser, "blanket", true },
                    804:        { vfsparser, "vfs", true },
                    805:        { sysctlparser, "sysctl", false },
1.86      pooka     806:        { fdoffparser, "fdoff", true },
1.78      pooka     807:        { NULL, NULL, false },
1.49      pooka     808: };
                    809:
                    810: static void
                    811: parsehijack(char *hijack)
                    812: {
                    813:        char *p, *p2, *l;
                    814:        const char *hijackcopy;
1.78      pooka     815:        bool nop2;
1.49      pooka     816:        int i;
                    817:
                    818:        if ((hijackcopy = strdup(hijack)) == NULL)
                    819:                err(1, "strdup");
                    820:
                    821:        /* disable everything explicitly */
                    822:        for (i = 0; i < PF_MAX; i++)
                    823:                rumpsockets[i] = false;
                    824:
                    825:        for (p = strtok_r(hijack, ",", &l); p; p = strtok_r(NULL, ",", &l)) {
1.78      pooka     826:                nop2 = false;
1.49      pooka     827:                p2 = strchr(p, '=');
1.78      pooka     828:                if (!p2) {
                    829:                        nop2 = true;
                    830:                        p2 = p + strlen(p);
                    831:                }
1.49      pooka     832:
                    833:                for (i = 0; hijackparse[i].parsefn; i++) {
                    834:                        if (strncmp(hijackparse[i].name, p,
                    835:                            (size_t)(p2-p)) == 0) {
1.78      pooka     836:                                if (nop2 && hijackparse[i].needvalues)
                    837:                                        errx(1, "invalid hijack specifier: %s",
                    838:                                            hijackcopy);
                    839:                                hijackparse[i].parsefn(nop2 ? NULL : p2+1);
1.49      pooka     840:                                break;
                    841:                        }
                    842:                }
1.81      pooka     843:
                    844:                if (hijackparse[i].parsefn == NULL)
                    845:                        errx(1, "invalid hijack specifier name in %s", p);
1.49      pooka     846:        }
                    847:
                    848: }
1.7       pooka     849:
1.1       pooka     850: static void __attribute__((constructor))
                    851: rcinit(void)
                    852: {
1.49      pooka     853:        char buf[1024];
1.19      pooka     854:        unsigned i, j;
1.1       pooka     855:
1.17      pooka     856:        host_fork = dlsym(RTLD_NEXT, "fork");
1.25      pooka     857:        host_daemon = dlsym(RTLD_NEXT, "daemon");
1.62      pooka     858:        host_mmap = dlsym(RTLD_NEXT, "mmap");
1.17      pooka     859:
                    860:        /*
                    861:         * In theory cannot print anything during lookups because
                    862:         * we might not have the call vector set up.  so, the errx()
                    863:         * is a bit of a strech, but it might work.
                    864:         */
1.1       pooka     865:
1.17      pooka     866:        for (i = 0; i < DUALCALL__NUM; i++) {
                    867:                /* build runtime O(1) access */
1.83      pooka     868:                for (j = 0; j < __arraycount(syscnames); j++) {
                    869:                        if (syscnames[j].scm_callnum == i)
                    870:                                break;
                    871:                }
1.81      pooka     872:
1.83      pooka     873:                if (j == __arraycount(syscnames))
                    874:                        errx(1, "rumphijack error: syscall pos %d missing", i);
1.17      pooka     875:
1.23      pooka     876:                syscalls[i].bs_host = dlsym(RTLD_NEXT,
1.83      pooka     877:                    syscnames[j].scm_hostname);
                    878:                if (syscalls[i].bs_host == NULL)
                    879:                        errx(1, "hostcall %s not found!",
                    880:                            syscnames[j].scm_hostname);
1.17      pooka     881:
1.23      pooka     882:                syscalls[i].bs_rump = dlsym(RTLD_NEXT,
1.83      pooka     883:                    syscnames[j].scm_rumpname);
1.17      pooka     884:                if (syscalls[i].bs_rump == NULL)
1.70      pooka     885:                        errx(1, "rumpcall %s not found!",
1.83      pooka     886:                            syscnames[j].scm_rumpname);
1.1       pooka     887:        }
                    888:
1.22      pooka     889:        if (rumpclient_init() == -1)
1.1       pooka     890:                err(1, "rumpclient init");
1.28      pooka     891:
1.49      pooka     892:        /* check which syscalls we're supposed to hijack */
                    893:        if (getenv_r("RUMPHIJACK", buf, sizeof(buf)) == -1) {
                    894:                strcpy(buf, RUMPHIJACK_DEFAULT);
                    895:        }
                    896:        parsehijack(buf);
                    897:
1.28      pooka     898:        /* set client persistence level */
1.44      pooka     899:        if (getenv_r("RUMPHIJACK_RETRYCONNECT", buf, sizeof(buf)) != -1) {
1.28      pooka     900:                if (strcmp(buf, "die") == 0)
                    901:                        rumpclient_setconnretry(RUMPCLIENT_RETRYCONN_DIE);
                    902:                else if (strcmp(buf, "inftime") == 0)
                    903:                        rumpclient_setconnretry(RUMPCLIENT_RETRYCONN_INFTIME);
                    904:                else if (strcmp(buf, "once") == 0)
                    905:                        rumpclient_setconnretry(RUMPCLIENT_RETRYCONN_ONCE);
                    906:                else {
                    907:                        time_t timeout;
1.44      pooka     908:                        char *ep;
1.28      pooka     909:
1.44      pooka     910:                        timeout = (time_t)strtoll(buf, &ep, 10);
                    911:                        if (timeout <= 0 || ep != buf + strlen(buf))
                    912:                                errx(1, "RUMPHIJACK_RETRYCONNECT must be "
                    913:                                    "keyword or integer, got: %s", buf);
1.28      pooka     914:
                    915:                        rumpclient_setconnretry(timeout);
                    916:                }
                    917:        }
1.39      pooka     918:
1.71      pooka     919:        if (getenv_r("RUMPHIJACK__DUP2INFO", buf, sizeof(buf)) == 0) {
                    920:                if (sscanf(buf, "%u,%u,%u",
                    921:                    &dup2vec[0], &dup2vec[1], &dup2vec[2]) != 3) {
                    922:                        warnx("invalid dup2mask: %s", buf);
                    923:                        memset(dup2vec, 0, sizeof(dup2vec));
                    924:                }
                    925:                unsetenv("RUMPHIJACK__DUP2INFO");
1.45      pooka     926:        }
                    927:        if (getenv_r("RUMPHIJACK__PWDINRUMP", buf, sizeof(buf)) == 0) {
1.49      pooka     928:                pwdinrump = true;
1.45      pooka     929:                unsetenv("RUMPHIJACK__PWDINRUMP");
1.39      pooka     930:        }
1.1       pooka     931: }
                    932:
1.2       pooka     933: static int
                    934: fd_rump2host(int fd)
                    935: {
                    936:
                    937:        if (fd == -1)
                    938:                return fd;
1.85      pooka     939:        return fd + hijack_fdoff;
1.71      pooka     940: }
1.2       pooka     941:
1.71      pooka     942: static int
                    943: fd_rump2host_withdup(int fd)
                    944: {
                    945:        int hfd;
1.2       pooka     946:
1.71      pooka     947:        _DIAGASSERT(fd != -1);
                    948:        hfd = unmapdup2(fd);
                    949:        if (hfd != -1) {
                    950:                _DIAGASSERT(hfd <= DUP2HIGH);
                    951:                return hfd;
                    952:        }
                    953:        return fd_rump2host(fd);
1.2       pooka     954: }
                    955:
                    956: static int
                    957: fd_host2rump(int fd)
                    958: {
                    959:
1.71      pooka     960:        if (!isdup2d(fd))
1.85      pooka     961:                return fd - hijack_fdoff;
1.71      pooka     962:        else
                    963:                return mapdup2(fd);
1.2       pooka     964: }
                    965:
                    966: static bool
                    967: fd_isrump(int fd)
                    968: {
                    969:
1.85      pooka     970:        return isdup2d(fd) || fd >= hijack_fdoff;
1.2       pooka     971: }
                    972:
1.85      pooka     973: #define assertfd(_fd_) assert(ISDUP2D(_fd_) || (_fd_) >= hijack_fdoff)
1.40      pooka     974:
1.75      pooka     975: static enum pathtype
1.45      pooka     976: path_isrump(const char *path)
                    977: {
1.76      pooka     978:        size_t plen;
1.75      pooka     979:        int i;
1.45      pooka     980:
1.75      pooka     981:        if (rumpprefix == NULL && nblanket == 0)
                    982:                return PATH_HOST;
1.49      pooka     983:
1.45      pooka     984:        if (*path == '/') {
1.76      pooka     985:                plen = strlen(path);
                    986:                if (rumpprefix && plen >= rumpprefixlen) {
                    987:                        if (strncmp(path, rumpprefix, rumpprefixlen) == 0
                    988:                            && (plen == rumpprefixlen
                    989:                              || *(path + rumpprefixlen) == '/')) {
1.75      pooka     990:                                return PATH_RUMP;
                    991:                        }
                    992:                }
                    993:                for (i = 0; i < nblanket; i++) {
                    994:                        if (strncmp(path, blanket[i].pfx, blanket[i].len) == 0)
                    995:                                return PATH_RUMPBLANKET;
                    996:                }
                    997:
                    998:                return PATH_HOST;
1.45      pooka     999:        } else {
1.75      pooka    1000:                return pwdinrump ? PATH_RUMP : PATH_HOST;
1.45      pooka    1001:        }
                   1002: }
                   1003:
                   1004: static const char *rootpath = "/";
                   1005: static const char *
                   1006: path_host2rump(const char *path)
                   1007: {
                   1008:        const char *rv;
                   1009:
                   1010:        if (*path == '/') {
1.49      pooka    1011:                rv = path + rumpprefixlen;
1.45      pooka    1012:                if (*rv == '\0')
                   1013:                        rv = rootpath;
                   1014:        } else {
                   1015:                rv = path;
                   1016:        }
                   1017:
                   1018:        return rv;
                   1019: }
                   1020:
1.40      pooka    1021: static int
                   1022: dodup(int oldd, int minfd)
                   1023: {
                   1024:        int (*op_fcntl)(int, int, ...);
                   1025:        int newd;
                   1026:        int isrump;
                   1027:
                   1028:        DPRINTF(("dup -> %d (minfd %d)\n", oldd, minfd));
                   1029:        if (fd_isrump(oldd)) {
                   1030:                op_fcntl = GETSYSCALL(rump, FCNTL);
                   1031:                oldd = fd_host2rump(oldd);
1.85      pooka    1032:                if (minfd >= hijack_fdoff)
                   1033:                        minfd -= hijack_fdoff;
1.40      pooka    1034:                isrump = 1;
                   1035:        } else {
                   1036:                op_fcntl = GETSYSCALL(host, FCNTL);
                   1037:                isrump = 0;
                   1038:        }
                   1039:
                   1040:        newd = op_fcntl(oldd, F_DUPFD, minfd);
                   1041:
                   1042:        if (isrump)
                   1043:                newd = fd_rump2host(newd);
                   1044:        DPRINTF(("dup <- %d\n", newd));
                   1045:
                   1046:        return newd;
                   1047: }
1.2       pooka    1048:
1.47      pooka    1049: /*
1.85      pooka    1050:  * Check that host fd value does not exceed fdoffset and if necessary
                   1051:  * dup the file descriptor so that it doesn't collide with the dup2mask.
1.47      pooka    1052:  */
                   1053: static int
1.85      pooka    1054: fd_host2host(int fd)
1.47      pooka    1055: {
                   1056:        int (*op_fcntl)(int, int, ...) = GETSYSCALL(host, FCNTL);
                   1057:        int (*op_close)(int) = GETSYSCALL(host, CLOSE);
                   1058:        int ofd, i;
                   1059:
1.85      pooka    1060:        if (fd >= hijack_fdoff) {
                   1061:                op_close(fd);
                   1062:                errno = ENFILE;
                   1063:                return -1;
                   1064:        }
                   1065:
1.71      pooka    1066:        for (i = 1; isdup2d(fd); i++) {
1.47      pooka    1067:                ofd = fd;
                   1068:                fd = op_fcntl(ofd, F_DUPFD, i);
                   1069:                op_close(ofd);
                   1070:        }
                   1071:
                   1072:        return fd;
                   1073: }
                   1074:
1.45      pooka    1075: int
                   1076: open(const char *path, int flags, ...)
                   1077: {
                   1078:        int (*op_open)(const char *, int, ...);
                   1079:        bool isrump;
                   1080:        va_list ap;
1.75      pooka    1081:        enum pathtype pt;
1.45      pooka    1082:        int fd;
                   1083:
1.71      pooka    1084:        DPRINTF(("open -> %s (%s)\n", path, whichpath(path)));
                   1085:
1.75      pooka    1086:        if ((pt = path_isrump(path)) != PATH_HOST) {
                   1087:                if (pt == PATH_RUMP)
                   1088:                        path = path_host2rump(path);
1.45      pooka    1089:                op_open = GETSYSCALL(rump, OPEN);
                   1090:                isrump = true;
                   1091:        } else {
                   1092:                op_open = GETSYSCALL(host, OPEN);
                   1093:                isrump = false;
                   1094:        }
                   1095:
                   1096:        va_start(ap, flags);
                   1097:        fd = op_open(path, flags, va_arg(ap, mode_t));
                   1098:        va_end(ap);
                   1099:
                   1100:        if (isrump)
                   1101:                fd = fd_rump2host(fd);
1.47      pooka    1102:        else
1.85      pooka    1103:                fd = fd_host2host(fd);
1.71      pooka    1104:
                   1105:        DPRINTF(("open <- %d (%s)\n", fd, whichfd(fd)));
1.45      pooka    1106:        return fd;
                   1107: }
                   1108:
                   1109: int
                   1110: chdir(const char *path)
                   1111: {
                   1112:        int (*op_chdir)(const char *);
1.75      pooka    1113:        enum pathtype pt;
1.45      pooka    1114:        int rv;
                   1115:
1.75      pooka    1116:        if ((pt = path_isrump(path)) != PATH_HOST) {
1.45      pooka    1117:                op_chdir = GETSYSCALL(rump, CHDIR);
1.75      pooka    1118:                if (pt == PATH_RUMP)
                   1119:                        path = path_host2rump(path);
1.45      pooka    1120:        } else {
                   1121:                op_chdir = GETSYSCALL(host, CHDIR);
                   1122:        }
                   1123:
                   1124:        rv = op_chdir(path);
1.75      pooka    1125:        if (rv == 0)
                   1126:                pwdinrump = pt != PATH_HOST;
1.45      pooka    1127:
                   1128:        return rv;
                   1129: }
                   1130:
                   1131: int
                   1132: fchdir(int fd)
                   1133: {
                   1134:        int (*op_fchdir)(int);
                   1135:        bool isrump;
                   1136:        int rv;
                   1137:
                   1138:        if (fd_isrump(fd)) {
                   1139:                op_fchdir = GETSYSCALL(rump, FCHDIR);
                   1140:                isrump = true;
                   1141:                fd = fd_host2rump(fd);
                   1142:        } else {
                   1143:                op_fchdir = GETSYSCALL(host, FCHDIR);
                   1144:                isrump = false;
                   1145:        }
                   1146:
                   1147:        rv = op_fchdir(fd);
                   1148:        if (rv == 0) {
1.75      pooka    1149:                pwdinrump = isrump;
1.45      pooka    1150:        }
                   1151:
                   1152:        return rv;
                   1153: }
                   1154:
1.97      pooka    1155: #ifndef __linux__
1.52      pooka    1156: int
1.57      pooka    1157: __getcwd(char *bufp, size_t len)
                   1158: {
                   1159:        int (*op___getcwd)(char *, size_t);
1.75      pooka    1160:        size_t prefixgap;
                   1161:        bool iamslash;
1.57      pooka    1162:        int rv;
                   1163:
1.75      pooka    1164:        if (pwdinrump && rumpprefix) {
1.57      pooka    1165:                if (rumpprefix[rumpprefixlen-1] == '/')
                   1166:                        iamslash = true;
                   1167:                else
                   1168:                        iamslash = false;
                   1169:
                   1170:                if (iamslash)
                   1171:                        prefixgap = rumpprefixlen - 1; /* ``//+path'' */
                   1172:                else
                   1173:                        prefixgap = rumpprefixlen; /* ``/pfx+/path'' */
                   1174:                if (len <= prefixgap) {
1.66      pooka    1175:                        errno = ERANGE;
                   1176:                        return -1;
1.57      pooka    1177:                }
                   1178:
                   1179:                op___getcwd = GETSYSCALL(rump, __GETCWD);
                   1180:                rv = op___getcwd(bufp + prefixgap, len - prefixgap);
                   1181:                if (rv == -1)
                   1182:                        return rv;
                   1183:
                   1184:                /* augment the "/" part only for a non-root path */
                   1185:                memcpy(bufp, rumpprefix, rumpprefixlen);
                   1186:
                   1187:                /* append / only to non-root cwd */
                   1188:                if (rv != 2)
                   1189:                        bufp[prefixgap] = '/';
                   1190:
                   1191:                /* don't append extra slash in the purely-slash case */
                   1192:                if (rv == 2 && !iamslash)
                   1193:                        bufp[rumpprefixlen] = '\0';
1.75      pooka    1194:        } else if (pwdinrump) {
                   1195:                /* assume blanket.  we can't provide a prefix here */
                   1196:                op___getcwd = GETSYSCALL(rump, __GETCWD);
                   1197:                rv = op___getcwd(bufp, len);
1.57      pooka    1198:        } else {
                   1199:                op___getcwd = GETSYSCALL(host, __GETCWD);
1.75      pooka    1200:                rv = op___getcwd(bufp, len);
1.57      pooka    1201:        }
1.75      pooka    1202:
                   1203:        return rv;
1.57      pooka    1204: }
1.97      pooka    1205: #endif
1.57      pooka    1206:
1.95      riastrad 1207: static int
                   1208: moveish(const char *from, const char *to,
                   1209:     int (*rump_op)(const char *, const char *),
                   1210:     int (*host_op)(const char *, const char *))
1.52      pooka    1211: {
1.95      riastrad 1212:        int (*op)(const char *, const char *);
1.75      pooka    1213:        enum pathtype ptf, ptt;
1.52      pooka    1214:
1.75      pooka    1215:        if ((ptf = path_isrump(from)) != PATH_HOST) {
                   1216:                if ((ptt = path_isrump(to)) == PATH_HOST) {
1.66      pooka    1217:                        errno = EXDEV;
                   1218:                        return -1;
                   1219:                }
1.52      pooka    1220:
1.75      pooka    1221:                if (ptf == PATH_RUMP)
                   1222:                        from = path_host2rump(from);
                   1223:                if (ptt == PATH_RUMP)
                   1224:                        to = path_host2rump(to);
1.95      riastrad 1225:                op = rump_op;
1.52      pooka    1226:        } else {
1.75      pooka    1227:                if (path_isrump(to) != PATH_HOST) {
1.66      pooka    1228:                        errno = EXDEV;
                   1229:                        return -1;
                   1230:                }
1.53      pooka    1231:
1.95      riastrad 1232:                op = host_op;
1.52      pooka    1233:        }
                   1234:
1.95      riastrad 1235:        return op(from, to);
                   1236: }
                   1237:
                   1238: int
                   1239: link(const char *from, const char *to)
                   1240: {
                   1241:        return moveish(from, to,
                   1242:            GETSYSCALL(rump, LINK), GETSYSCALL(host, LINK));
                   1243: }
                   1244:
                   1245: int
                   1246: rename(const char *from, const char *to)
                   1247: {
                   1248:        return moveish(from, to,
                   1249:            GETSYSCALL(rump, RENAME), GETSYSCALL(host, RENAME));
1.52      pooka    1250: }
                   1251:
1.1       pooka    1252: int
1.96      pooka    1253: REALSOCKET(int domain, int type, int protocol)
1.1       pooka    1254: {
1.17      pooka    1255:        int (*op_socket)(int, int, int);
1.1       pooka    1256:        int fd;
1.49      pooka    1257:        bool isrump;
1.7       pooka    1258:
1.49      pooka    1259:        isrump = domain < PF_MAX && rumpsockets[domain];
1.1       pooka    1260:
1.49      pooka    1261:        if (isrump)
                   1262:                op_socket = GETSYSCALL(rump, SOCKET);
                   1263:        else
1.17      pooka    1264:                op_socket = GETSYSCALL(host, SOCKET);
                   1265:        fd = op_socket(domain, type, protocol);
1.2       pooka    1266:
1.49      pooka    1267:        if (isrump)
1.7       pooka    1268:                fd = fd_rump2host(fd);
1.47      pooka    1269:        else
1.85      pooka    1270:                fd = fd_host2host(fd);
1.7       pooka    1271:        DPRINTF(("socket <- %d\n", fd));
1.2       pooka    1272:
1.7       pooka    1273:        return fd;
1.1       pooka    1274: }
                   1275:
                   1276: int
                   1277: accept(int s, struct sockaddr *addr, socklen_t *addrlen)
                   1278: {
1.17      pooka    1279:        int (*op_accept)(int, struct sockaddr *, socklen_t *);
1.1       pooka    1280:        int fd;
1.7       pooka    1281:        bool isrump;
                   1282:
                   1283:        isrump = fd_isrump(s);
1.1       pooka    1284:
1.2       pooka    1285:        DPRINTF(("accept -> %d", s));
1.7       pooka    1286:        if (isrump) {
1.17      pooka    1287:                op_accept = GETSYSCALL(rump, ACCEPT);
1.7       pooka    1288:                s = fd_host2rump(s);
                   1289:        } else {
1.17      pooka    1290:                op_accept = GETSYSCALL(host, ACCEPT);
1.7       pooka    1291:        }
1.17      pooka    1292:        fd = op_accept(s, addr, addrlen);
1.7       pooka    1293:        if (fd != -1 && isrump)
                   1294:                fd = fd_rump2host(fd);
1.47      pooka    1295:        else
1.85      pooka    1296:                fd = fd_host2host(fd);
1.7       pooka    1297:
                   1298:        DPRINTF((" <- %d\n", fd));
1.2       pooka    1299:
1.7       pooka    1300:        return fd;
1.1       pooka    1301: }
                   1302:
1.17      pooka    1303: /*
1.103     pooka    1304:  * ioctl() and fcntl() are varargs calls and need special treatment.
                   1305:  */
                   1306:
                   1307: /*
                   1308:  * Various [Linux] libc's have various signatures for ioctl so we
                   1309:  * need to handle the discrepancies.  On NetBSD, we use the
                   1310:  * one with unsigned long cmd.
1.17      pooka    1311:  */
1.1       pooka    1312: int
1.103     pooka    1313: #ifdef HAVE_IOCTL_CMD_INT
                   1314: ioctl(int fd, int cmd, ...)
                   1315: {
                   1316:        int (*op_ioctl)(int, int cmd, ...);
                   1317: #else
1.17      pooka    1318: ioctl(int fd, unsigned long cmd, ...)
1.1       pooka    1319: {
1.17      pooka    1320:        int (*op_ioctl)(int, unsigned long cmd, ...);
1.103     pooka    1321: #endif
1.17      pooka    1322:        va_list ap;
                   1323:        int rv;
1.1       pooka    1324:
1.17      pooka    1325:        DPRINTF(("ioctl -> %d\n", fd));
                   1326:        if (fd_isrump(fd)) {
                   1327:                fd = fd_host2rump(fd);
                   1328:                op_ioctl = GETSYSCALL(rump, IOCTL);
1.7       pooka    1329:        } else {
1.17      pooka    1330:                op_ioctl = GETSYSCALL(host, IOCTL);
1.7       pooka    1331:        }
1.1       pooka    1332:
1.17      pooka    1333:        va_start(ap, cmd);
                   1334:        rv = op_ioctl(fd, cmd, va_arg(ap, void *));
                   1335:        va_end(ap);
                   1336:        return rv;
1.1       pooka    1337: }
                   1338:
                   1339: int
1.17      pooka    1340: fcntl(int fd, int cmd, ...)
1.1       pooka    1341: {
1.17      pooka    1342:        int (*op_fcntl)(int, int, ...);
                   1343:        va_list ap;
1.96      pooka    1344:        int rv, minfd;
1.40      pooka    1345:
                   1346:        DPRINTF(("fcntl -> %d (cmd %d)\n", fd, cmd));
                   1347:
                   1348:        switch (cmd) {
                   1349:        case F_DUPFD:
                   1350:                va_start(ap, cmd);
                   1351:                minfd = va_arg(ap, int);
                   1352:                va_end(ap);
                   1353:                return dodup(fd, minfd);
                   1354:
1.96      pooka    1355: #ifdef F_CLOSEM
                   1356:        case F_CLOSEM: {
                   1357:                int maxdup2, i;
                   1358:
1.40      pooka    1359:                /*
                   1360:                 * So, if fd < HIJACKOFF, we want to do a host closem.
                   1361:                 */
                   1362:
1.85      pooka    1363:                if (fd < hijack_fdoff) {
1.40      pooka    1364:                        int closemfd = fd;
1.1       pooka    1365:
1.40      pooka    1366:                        if (rumpclient__closenotify(&closemfd,
1.39      pooka    1367:                            RUMPCLIENT_CLOSE_FCLOSEM) == -1)
                   1368:                                return -1;
1.40      pooka    1369:                        op_fcntl = GETSYSCALL(host, FCNTL);
                   1370:                        rv = op_fcntl(closemfd, cmd);
                   1371:                        if (rv)
                   1372:                                return rv;
                   1373:                }
                   1374:
                   1375:                /*
                   1376:                 * Additionally, we want to do a rump closem, but only
1.71      pooka    1377:                 * for the file descriptors not dup2'd.
1.40      pooka    1378:                 */
                   1379:
1.110     pooka    1380:                for (i = 0, maxdup2 = -1; i <= DUP2HIGH; i++) {
1.72      pooka    1381:                        if (dup2vec[i] & DUP2BIT) {
                   1382:                                int val;
                   1383:
                   1384:                                val = dup2vec[i] & DUP2FDMASK;
                   1385:                                maxdup2 = MAX(val, maxdup2);
                   1386:                        }
1.40      pooka    1387:                }
                   1388:
1.85      pooka    1389:                if (fd >= hijack_fdoff)
                   1390:                        fd -= hijack_fdoff;
1.40      pooka    1391:                else
                   1392:                        fd = 0;
1.71      pooka    1393:                fd = MAX(maxdup2+1, fd);
1.40      pooka    1394:
                   1395:                /* hmm, maybe we should close rump fd's not within dup2mask? */
                   1396:                return rump_sys_fcntl(fd, F_CLOSEM);
1.96      pooka    1397:        }
                   1398: #endif /* F_CLOSEM */
1.40      pooka    1399:
1.96      pooka    1400: #ifdef F_MAXFD
1.40      pooka    1401:        case F_MAXFD:
                   1402:                /*
                   1403:                 * For maxfd, if there's a rump kernel fd, return
                   1404:                 * it hostified.  Otherwise, return host's MAXFD
                   1405:                 * return value.
                   1406:                 */
                   1407:                if ((rv = rump_sys_fcntl(fd, F_MAXFD)) != -1) {
                   1408:                        /*
                   1409:                         * This might go a little wrong in case
                   1410:                         * of dup2 to [012], but I'm not sure if
                   1411:                         * there's a justification for tracking
                   1412:                         * that info.  Consider e.g.
                   1413:                         * dup2(rumpfd, 2) followed by rump_sys_open()
                   1414:                         * returning 1.  We should return 1+HIJACKOFF,
                   1415:                         * not 2+HIJACKOFF.  However, if [01] is not
                   1416:                         * open, the correct return value is 2.
                   1417:                         */
                   1418:                        return fd_rump2host(fd);
                   1419:                } else {
                   1420:                        op_fcntl = GETSYSCALL(host, FCNTL);
                   1421:                        return op_fcntl(fd, F_MAXFD);
                   1422:                }
                   1423:                /*NOTREACHED*/
1.96      pooka    1424: #endif /* F_MAXFD */
1.40      pooka    1425:
                   1426:        default:
                   1427:                if (fd_isrump(fd)) {
                   1428:                        fd = fd_host2rump(fd);
                   1429:                        op_fcntl = GETSYSCALL(rump, FCNTL);
                   1430:                } else {
                   1431:                        op_fcntl = GETSYSCALL(host, FCNTL);
                   1432:                }
                   1433:
                   1434:                va_start(ap, cmd);
                   1435:                rv = op_fcntl(fd, cmd, va_arg(ap, void *));
                   1436:                va_end(ap);
                   1437:                return rv;
1.7       pooka    1438:        }
1.40      pooka    1439:        /*NOTREACHED*/
1.1       pooka    1440: }
                   1441:
1.39      pooka    1442: int
                   1443: close(int fd)
                   1444: {
                   1445:        int (*op_close)(int);
                   1446:        int rv;
                   1447:
                   1448:        DPRINTF(("close -> %d\n", fd));
                   1449:        if (fd_isrump(fd)) {
1.71      pooka    1450:                bool undup2 = false;
                   1451:                int ofd;
                   1452:
                   1453:                if (isdup2d(ofd = fd)) {
                   1454:                        undup2 = true;
                   1455:                }
1.39      pooka    1456:
1.47      pooka    1457:                fd = fd_host2rump(fd);
1.71      pooka    1458:                if (!undup2 && killdup2alias(fd)) {
1.47      pooka    1459:                        return 0;
                   1460:                }
                   1461:
1.39      pooka    1462:                op_close = GETSYSCALL(rump, CLOSE);
                   1463:                rv = op_close(fd);
1.71      pooka    1464:                if (rv == 0 && undup2) {
                   1465:                        clrdup2(ofd);
                   1466:                }
1.39      pooka    1467:        } else {
                   1468:                if (rumpclient__closenotify(&fd, RUMPCLIENT_CLOSE_CLOSE) == -1)
                   1469:                        return -1;
                   1470:                op_close = GETSYSCALL(host, CLOSE);
                   1471:                rv = op_close(fd);
                   1472:        }
                   1473:
                   1474:        return rv;
                   1475: }
                   1476:
1.17      pooka    1477: /*
                   1478:  * write cannot issue a standard debug printf due to recursion
                   1479:  */
1.1       pooka    1480: ssize_t
1.17      pooka    1481: write(int fd, const void *buf, size_t blen)
1.1       pooka    1482: {
1.17      pooka    1483:        ssize_t (*op_write)(int, const void *, size_t);
1.1       pooka    1484:
1.17      pooka    1485:        if (fd_isrump(fd)) {
                   1486:                fd = fd_host2rump(fd);
                   1487:                op_write = GETSYSCALL(rump, WRITE);
1.16      pooka    1488:        } else {
1.17      pooka    1489:                op_write = GETSYSCALL(host, WRITE);
1.16      pooka    1490:        }
1.1       pooka    1491:
1.17      pooka    1492:        return op_write(fd, buf, blen);
1.2       pooka    1493: }
                   1494:
                   1495: /*
1.94      yamt     1496:  * file descriptor passing
                   1497:  *
                   1498:  * we intercept sendmsg and recvmsg to convert file descriptors in
                   1499:  * control messages.  an attempt to send a descriptor from a different kernel
                   1500:  * is rejected.  (ENOTSUP)
                   1501:  */
                   1502:
                   1503: static int
                   1504: msg_convert(struct msghdr *msg, int (*func)(int))
                   1505: {
                   1506:        struct cmsghdr *cmsg;
                   1507:
                   1508:        for (cmsg = CMSG_FIRSTHDR(msg); cmsg != NULL;
                   1509:            cmsg = CMSG_NXTHDR(msg, cmsg)) {
                   1510:                if (cmsg->cmsg_level == SOL_SOCKET &&
                   1511:                    cmsg->cmsg_type == SCM_RIGHTS) {
                   1512:                        int *fdp = (void *)CMSG_DATA(cmsg);
                   1513:                        const size_t size =
                   1514:                            cmsg->cmsg_len - __CMSG_ALIGN(sizeof(*cmsg));
1.99      martin   1515:                        const int nfds = (int)(size / sizeof(int));
1.94      yamt     1516:                        const int * const efdp = fdp + nfds;
                   1517:
                   1518:                        while (fdp < efdp) {
                   1519:                                const int newval = func(*fdp);
                   1520:
                   1521:                                if (newval < 0) {
                   1522:                                        return ENOTSUP;
                   1523:                                }
                   1524:                                *fdp = newval;
                   1525:                                fdp++;
                   1526:                        }
                   1527:                }
                   1528:        }
                   1529:        return 0;
                   1530: }
                   1531:
                   1532: ssize_t
                   1533: recvmsg(int fd, struct msghdr *msg, int flags)
                   1534: {
                   1535:        ssize_t (*op_recvmsg)(int, struct msghdr *, int);
                   1536:        ssize_t ret;
                   1537:        const bool isrump = fd_isrump(fd);
                   1538:
                   1539:        if (isrump) {
                   1540:                fd = fd_host2rump(fd);
                   1541:                op_recvmsg = GETSYSCALL(rump, RECVMSG);
                   1542:        } else {
                   1543:                op_recvmsg = GETSYSCALL(host, RECVMSG);
                   1544:        }
                   1545:        ret = op_recvmsg(fd, msg, flags);
                   1546:        if (ret == -1) {
                   1547:                return ret;
                   1548:        }
                   1549:        /*
                   1550:         * convert descriptors in the message.
                   1551:         */
                   1552:        if (isrump) {
                   1553:                msg_convert(msg, fd_rump2host);
                   1554:        } else {
                   1555:                msg_convert(msg, fd_host2host);
                   1556:        }
                   1557:        return ret;
                   1558: }
                   1559:
1.97      pooka    1560: ssize_t
                   1561: recv(int fd, void *buf, size_t len, int flags)
                   1562: {
                   1563:
                   1564:        return recvfrom(fd, buf, len, flags, NULL, NULL);
                   1565: }
                   1566:
                   1567: ssize_t
                   1568: send(int fd, const void *buf, size_t len, int flags)
                   1569: {
                   1570:
                   1571:        return sendto(fd, buf, len, flags, NULL, 0);
                   1572: }
                   1573:
1.94      yamt     1574: static int
                   1575: fd_check_rump(int fd)
                   1576: {
                   1577:
                   1578:        return fd_isrump(fd) ? 0 : -1;
                   1579: }
                   1580:
                   1581: static int
                   1582: fd_check_host(int fd)
                   1583: {
                   1584:
                   1585:        return !fd_isrump(fd) ? 0 : -1;
                   1586: }
                   1587:
                   1588: ssize_t
                   1589: sendmsg(int fd, const struct msghdr *msg, int flags)
                   1590: {
                   1591:        ssize_t (*op_sendmsg)(int, const struct msghdr *, int);
                   1592:        const bool isrump = fd_isrump(fd);
                   1593:        int error;
                   1594:
                   1595:        /*
                   1596:         * reject descriptors from a different kernel.
                   1597:         */
                   1598:        error = msg_convert(__UNCONST(msg),
                   1599:            isrump ? fd_check_rump: fd_check_host);
                   1600:        if (error != 0) {
                   1601:                errno = error;
                   1602:                return -1;
                   1603:        }
                   1604:        /*
                   1605:         * convert descriptors in the message to raw values.
                   1606:         */
                   1607:        if (isrump) {
                   1608:                fd = fd_host2rump(fd);
                   1609:                /*
                   1610:                 * XXX we directly modify the given message assuming:
                   1611:                 * - cmsg is writable (typically on caller's stack)
                   1612:                 * - caller don't care cmsg's contents after calling sendmsg.
                   1613:                 *   (thus no need to restore values)
                   1614:                 *
                   1615:                 * it's safer to copy and modify instead.
                   1616:                 */
                   1617:                msg_convert(__UNCONST(msg), fd_host2rump);
                   1618:                op_sendmsg = GETSYSCALL(rump, SENDMSG);
                   1619:        } else {
                   1620:                op_sendmsg = GETSYSCALL(host, SENDMSG);
                   1621:        }
                   1622:        return op_sendmsg(fd, msg, flags);
                   1623: }
                   1624:
                   1625: /*
1.2       pooka    1626:  * dup2 is special.  we allow dup2 of a rump kernel fd to 0-2 since
                   1627:  * many programs do that.  dup2 of a rump kernel fd to another value
                   1628:  * not >= fdoff is an error.
                   1629:  *
                   1630:  * Note: cannot rump2host newd, because it is often hardcoded.
                   1631:  */
                   1632: int
                   1633: dup2(int oldd, int newd)
                   1634: {
1.17      pooka    1635:        int (*host_dup2)(int, int);
1.2       pooka    1636:        int rv;
                   1637:
                   1638:        DPRINTF(("dup2 -> %d (o) -> %d (n)\n", oldd, newd));
                   1639:
                   1640:        if (fd_isrump(oldd)) {
1.71      pooka    1641:                int (*op_close)(int) = GETSYSCALL(host, CLOSE);
                   1642:
                   1643:                /* only allow fd 0-2 for cross-kernel dup */
                   1644:                if (!(newd >= 0 && newd <= 2 && !fd_isrump(newd))) {
1.66      pooka    1645:                        errno = EBADF;
                   1646:                        return -1;
                   1647:                }
1.71      pooka    1648:
                   1649:                /* regular dup2? */
                   1650:                if (fd_isrump(newd)) {
                   1651:                        newd = fd_host2rump(newd);
                   1652:                        rv = rump_sys_dup2(oldd, newd);
                   1653:                        return fd_rump2host(rv);
                   1654:                }
                   1655:
                   1656:                /*
                   1657:                 * dup2 rump => host?  just establish an
                   1658:                 * entry in the mapping table.
                   1659:                 */
                   1660:                op_close(newd);
                   1661:                setdup2(newd, fd_host2rump(oldd));
                   1662:                rv = 0;
1.2       pooka    1663:        } else {
1.17      pooka    1664:                host_dup2 = syscalls[DUALCALL_DUP2].bs_host;
1.39      pooka    1665:                if (rumpclient__closenotify(&newd, RUMPCLIENT_CLOSE_DUP2) == -1)
                   1666:                        return -1;
1.10      pooka    1667:                rv = host_dup2(oldd, newd);
1.2       pooka    1668:        }
1.10      pooka    1669:
                   1670:        return rv;
1.2       pooka    1671: }
                   1672:
1.34      pooka    1673: int
                   1674: dup(int oldd)
                   1675: {
                   1676:
1.40      pooka    1677:        return dodup(oldd, 0);
1.34      pooka    1678: }
                   1679:
1.2       pooka    1680: pid_t
1.93      abs      1681: fork(void)
1.2       pooka    1682: {
                   1683:        pid_t rv;
                   1684:
                   1685:        DPRINTF(("fork\n"));
                   1686:
1.43      pooka    1687:        rv = rumpclient__dofork(host_fork);
1.2       pooka    1688:
                   1689:        DPRINTF(("fork returns %d\n", rv));
                   1690:        return rv;
1.1       pooka    1691: }
1.96      pooka    1692: #ifdef VFORK
1.43      pooka    1693: /* we do not have the luxury of not requiring a stackframe */
1.96      pooka    1694: __strong_alias(VFORK,fork);
                   1695: #endif
1.1       pooka    1696:
1.25      pooka    1697: int
                   1698: daemon(int nochdir, int noclose)
                   1699: {
                   1700:        struct rumpclient_fork *rf;
                   1701:
                   1702:        if ((rf = rumpclient_prefork()) == NULL)
                   1703:                return -1;
                   1704:
                   1705:        if (host_daemon(nochdir, noclose) == -1)
                   1706:                return -1;
                   1707:
                   1708:        if (rumpclient_fork_init(rf) == -1)
                   1709:                return -1;
                   1710:
                   1711:        return 0;
                   1712: }
                   1713:
1.39      pooka    1714: int
1.42      pooka    1715: execve(const char *path, char *const argv[], char *const envp[])
1.39      pooka    1716: {
                   1717:        char buf[128];
                   1718:        char *dup2str;
1.49      pooka    1719:        const char *pwdinrumpstr;
1.42      pooka    1720:        char **newenv;
                   1721:        size_t nelem;
                   1722:        int rv, sverrno;
1.71      pooka    1723:        int bonus = 2, i = 0;
1.45      pooka    1724:
1.71      pooka    1725:        snprintf(buf, sizeof(buf), "RUMPHIJACK__DUP2INFO=%u,%u,%u",
                   1726:            dup2vec[0], dup2vec[1], dup2vec[2]);
                   1727:        dup2str = strdup(buf);
                   1728:        if (dup2str == NULL) {
                   1729:                errno = ENOMEM;
                   1730:                return -1;
1.45      pooka    1731:        }
1.39      pooka    1732:
1.45      pooka    1733:        if (pwdinrump) {
1.49      pooka    1734:                pwdinrumpstr = "RUMPHIJACK__PWDINRUMP=true";
1.45      pooka    1735:                bonus++;
                   1736:        } else {
                   1737:                pwdinrumpstr = NULL;
                   1738:        }
1.39      pooka    1739:
1.42      pooka    1740:        for (nelem = 0; envp && envp[nelem]; nelem++)
                   1741:                continue;
1.71      pooka    1742:        newenv = malloc(sizeof(*newenv) * (nelem+bonus));
1.42      pooka    1743:        if (newenv == NULL) {
1.39      pooka    1744:                free(dup2str);
1.66      pooka    1745:                errno = ENOMEM;
                   1746:                return -1;
1.39      pooka    1747:        }
1.42      pooka    1748:        memcpy(newenv, envp, nelem*sizeof(*newenv));
1.71      pooka    1749:        newenv[nelem+i] = dup2str;
                   1750:        i++;
                   1751:
1.45      pooka    1752:        if (pwdinrumpstr) {
1.49      pooka    1753:                newenv[nelem+i] = __UNCONST(pwdinrumpstr);
1.45      pooka    1754:                i++;
                   1755:        }
                   1756:        newenv[nelem+i] = NULL;
                   1757:        _DIAGASSERT(i < bonus);
1.42      pooka    1758:
                   1759:        rv = rumpclient_exec(path, argv, newenv);
                   1760:
                   1761:        _DIAGASSERT(rv != 0);
                   1762:        sverrno = errno;
                   1763:        free(newenv);
                   1764:        free(dup2str);
                   1765:        errno = sverrno;
1.39      pooka    1766:        return rv;
                   1767: }
                   1768:
1.1       pooka    1769: /*
1.17      pooka    1770:  * select is done by calling poll.
1.1       pooka    1771:  */
                   1772: int
1.29      pooka    1773: REALSELECT(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
1.4       pooka    1774:        struct timeval *timeout)
1.1       pooka    1775: {
1.4       pooka    1776:        struct pollfd *pfds;
                   1777:        struct timespec ts, *tsp = NULL;
1.19      pooka    1778:        nfds_t realnfds;
                   1779:        int i, j;
1.4       pooka    1780:        int rv, incr;
                   1781:
1.100     pooka    1782:        DPRINTF(("select %d %p %p %p %p\n", nfds,
                   1783:            readfds, writefds, exceptfds, timeout));
1.7       pooka    1784:
1.4       pooka    1785:        /*
                   1786:         * Well, first we must scan the fds to figure out how many
                   1787:         * fds there really are.  This is because up to and including
1.17      pooka    1788:         * nb5 poll() silently refuses nfds > process_maxopen_fds.
1.4       pooka    1789:         * Seems to be fixed in current, thank the maker.
                   1790:         * god damn cluster...bomb.
                   1791:         */
                   1792:
                   1793:        for (i = 0, realnfds = 0; i < nfds; i++) {
                   1794:                if (readfds && FD_ISSET(i, readfds)) {
                   1795:                        realnfds++;
                   1796:                        continue;
                   1797:                }
                   1798:                if (writefds && FD_ISSET(i, writefds)) {
                   1799:                        realnfds++;
                   1800:                        continue;
                   1801:                }
                   1802:                if (exceptfds && FD_ISSET(i, exceptfds)) {
                   1803:                        realnfds++;
                   1804:                        continue;
1.1       pooka    1805:                }
                   1806:        }
                   1807:
1.6       pooka    1808:        if (realnfds) {
1.38      pooka    1809:                pfds = calloc(realnfds, sizeof(*pfds));
1.6       pooka    1810:                if (!pfds)
                   1811:                        return -1;
                   1812:        } else {
                   1813:                pfds = NULL;
                   1814:        }
1.1       pooka    1815:
1.4       pooka    1816:        for (i = 0, j = 0; i < nfds; i++) {
                   1817:                incr = 0;
                   1818:                if (readfds && FD_ISSET(i, readfds)) {
                   1819:                        pfds[j].fd = i;
                   1820:                        pfds[j].events |= POLLIN;
                   1821:                        incr=1;
                   1822:                }
                   1823:                if (writefds && FD_ISSET(i, writefds)) {
                   1824:                        pfds[j].fd = i;
                   1825:                        pfds[j].events |= POLLOUT;
                   1826:                        incr=1;
                   1827:                }
                   1828:                if (exceptfds && FD_ISSET(i, exceptfds)) {
                   1829:                        pfds[j].fd = i;
                   1830:                        pfds[j].events |= POLLHUP|POLLERR;
                   1831:                        incr=1;
1.1       pooka    1832:                }
1.4       pooka    1833:                if (incr)
                   1834:                        j++;
1.1       pooka    1835:        }
1.37      pooka    1836:        assert(j == (int)realnfds);
1.1       pooka    1837:
1.4       pooka    1838:        if (timeout) {
                   1839:                TIMEVAL_TO_TIMESPEC(timeout, &ts);
                   1840:                tsp = &ts;
                   1841:        }
1.29      pooka    1842:        rv = REALPOLLTS(pfds, realnfds, tsp, NULL);
1.36      pooka    1843:        /*
                   1844:         * "If select() returns with an error the descriptor sets
                   1845:         * will be unmodified"
                   1846:         */
                   1847:        if (rv < 0)
1.4       pooka    1848:                goto out;
                   1849:
                   1850:        /*
1.36      pooka    1851:         * zero out results (can't use FD_ZERO for the
                   1852:         * obvious select-me-not reason).  whee.
                   1853:         *
                   1854:         * We do this here since some software ignores the return
                   1855:         * value of select, and hence if the timeout expires, it may
                   1856:         * assume all input descriptors have activity.
1.4       pooka    1857:         */
                   1858:        for (i = 0; i < nfds; i++) {
                   1859:                if (readfds)
                   1860:                        FD_CLR(i, readfds);
                   1861:                if (writefds)
                   1862:                        FD_CLR(i, writefds);
                   1863:                if (exceptfds)
                   1864:                        FD_CLR(i, exceptfds);
1.1       pooka    1865:        }
1.36      pooka    1866:        if (rv == 0)
                   1867:                goto out;
1.1       pooka    1868:
1.36      pooka    1869:        /*
                   1870:         * We have >0 fds with activity.  Harvest the results.
                   1871:         */
1.19      pooka    1872:        for (i = 0; i < (int)realnfds; i++) {
1.4       pooka    1873:                if (readfds) {
                   1874:                        if (pfds[i].revents & POLLIN) {
                   1875:                                FD_SET(pfds[i].fd, readfds);
                   1876:                        }
                   1877:                }
                   1878:                if (writefds) {
                   1879:                        if (pfds[i].revents & POLLOUT) {
                   1880:                                FD_SET(pfds[i].fd, writefds);
                   1881:                        }
                   1882:                }
                   1883:                if (exceptfds) {
                   1884:                        if (pfds[i].revents & (POLLHUP|POLLERR)) {
                   1885:                                FD_SET(pfds[i].fd, exceptfds);
                   1886:                        }
                   1887:                }
1.1       pooka    1888:        }
                   1889:
1.4       pooka    1890:  out:
                   1891:        free(pfds);
1.1       pooka    1892:        return rv;
                   1893: }
                   1894:
                   1895: static void
                   1896: checkpoll(struct pollfd *fds, nfds_t nfds, int *hostcall, int *rumpcall)
                   1897: {
                   1898:        nfds_t i;
                   1899:
                   1900:        for (i = 0; i < nfds; i++) {
1.12      pooka    1901:                if (fds[i].fd == -1)
                   1902:                        continue;
                   1903:
1.2       pooka    1904:                if (fd_isrump(fds[i].fd))
                   1905:                        (*rumpcall)++;
                   1906:                else
1.1       pooka    1907:                        (*hostcall)++;
                   1908:        }
                   1909: }
                   1910:
                   1911: static void
1.2       pooka    1912: adjustpoll(struct pollfd *fds, nfds_t nfds, int (*fdadj)(int))
1.1       pooka    1913: {
                   1914:        nfds_t i;
                   1915:
                   1916:        for (i = 0; i < nfds; i++) {
1.2       pooka    1917:                fds[i].fd = fdadj(fds[i].fd);
1.1       pooka    1918:        }
                   1919: }
                   1920:
                   1921: /*
                   1922:  * poll is easy as long as the call comes in the fds only in one
                   1923:  * kernel.  otherwise its quite tricky...
                   1924:  */
                   1925: struct pollarg {
                   1926:        struct pollfd *pfds;
                   1927:        nfds_t nfds;
1.3       pooka    1928:        const struct timespec *ts;
                   1929:        const sigset_t *sigmask;
1.1       pooka    1930:        int pipefd;
                   1931:        int errnum;
                   1932: };
                   1933:
                   1934: static void *
                   1935: hostpoll(void *arg)
                   1936: {
1.17      pooka    1937:        int (*op_pollts)(struct pollfd *, nfds_t, const struct timespec *,
                   1938:                         const sigset_t *);
1.1       pooka    1939:        struct pollarg *parg = arg;
                   1940:        intptr_t rv;
                   1941:
1.35      pooka    1942:        op_pollts = GETSYSCALL(host, POLLTS);
1.17      pooka    1943:        rv = op_pollts(parg->pfds, parg->nfds, parg->ts, parg->sigmask);
1.1       pooka    1944:        if (rv == -1)
                   1945:                parg->errnum = errno;
                   1946:        rump_sys_write(parg->pipefd, &rv, sizeof(rv));
                   1947:
1.92      martin   1948:        return (void *)rv;
1.1       pooka    1949: }
                   1950:
                   1951: int
1.29      pooka    1952: REALPOLLTS(struct pollfd *fds, nfds_t nfds, const struct timespec *ts,
1.3       pooka    1953:        const sigset_t *sigmask)
1.1       pooka    1954: {
1.3       pooka    1955:        int (*op_pollts)(struct pollfd *, nfds_t, const struct timespec *,
                   1956:                         const sigset_t *);
1.17      pooka    1957:        int (*host_close)(int);
1.1       pooka    1958:        int hostcall = 0, rumpcall = 0;
                   1959:        pthread_t pt;
                   1960:        nfds_t i;
                   1961:        int rv;
                   1962:
1.100     pooka    1963:        DPRINTF(("poll %p %d %p %p\n", fds, (int)nfds, ts, sigmask));
1.1       pooka    1964:        checkpoll(fds, nfds, &hostcall, &rumpcall);
                   1965:
                   1966:        if (hostcall && rumpcall) {
                   1967:                struct pollfd *pfd_host = NULL, *pfd_rump = NULL;
                   1968:                int rpipe[2] = {-1,-1}, hpipe[2] = {-1,-1};
                   1969:                struct pollarg parg;
1.92      martin   1970:                void *trv_val;
1.99      martin   1971:                int sverrno = 0, rv_rump, rv_host, errno_rump, errno_host;
1.1       pooka    1972:
                   1973:                /*
                   1974:                 * ok, this is where it gets tricky.  We must support
                   1975:                 * this since it's a very common operation in certain
                   1976:                 * types of software (telnet, netcat, etc).  We allocate
                   1977:                 * two vectors and run two poll commands in separate
                   1978:                 * threads.  Whichever returns first "wins" and the
                   1979:                 * other kernel's fds won't show activity.
                   1980:                 */
                   1981:                rv = -1;
                   1982:
                   1983:                /* allocate full vector for O(n) joining after call */
                   1984:                pfd_host = malloc(sizeof(*pfd_host)*(nfds+1));
                   1985:                if (!pfd_host)
                   1986:                        goto out;
                   1987:                pfd_rump = malloc(sizeof(*pfd_rump)*(nfds+1));
                   1988:                if (!pfd_rump) {
                   1989:                        goto out;
                   1990:                }
                   1991:
1.59      pooka    1992:                /*
                   1993:                 * then, open two pipes, one for notifications
                   1994:                 * to each kernel.
1.73      pooka    1995:                 *
                   1996:                 * At least the rump pipe should probably be
                   1997:                 * cached, along with the helper threads.  This
                   1998:                 * should give a microbenchmark improvement (haven't
                   1999:                 * experienced a macro-level problem yet, though).
1.59      pooka    2000:                 */
                   2001:                if ((rv = rump_sys_pipe(rpipe)) == -1) {
                   2002:                        sverrno = errno;
                   2003:                }
                   2004:                if (rv == 0 && (rv = pipe(hpipe)) == -1) {
                   2005:                        sverrno = errno;
                   2006:                }
                   2007:
                   2008:                /* split vectors (or signal errors) */
1.1       pooka    2009:                for (i = 0; i < nfds; i++) {
1.59      pooka    2010:                        int fd;
                   2011:
                   2012:                        fds[i].revents = 0;
1.3       pooka    2013:                        if (fds[i].fd == -1) {
                   2014:                                pfd_host[i].fd = -1;
                   2015:                                pfd_rump[i].fd = -1;
                   2016:                        } else if (fd_isrump(fds[i].fd)) {
1.2       pooka    2017:                                pfd_host[i].fd = -1;
1.59      pooka    2018:                                fd = fd_host2rump(fds[i].fd);
                   2019:                                if (fd == rpipe[0] || fd == rpipe[1]) {
                   2020:                                        fds[i].revents = POLLNVAL;
                   2021:                                        if (rv != -1)
                   2022:                                                rv++;
                   2023:                                }
                   2024:                                pfd_rump[i].fd = fd;
1.2       pooka    2025:                                pfd_rump[i].events = fds[i].events;
                   2026:                        } else {
                   2027:                                pfd_rump[i].fd = -1;
1.59      pooka    2028:                                fd = fds[i].fd;
                   2029:                                if (fd == hpipe[0] || fd == hpipe[1]) {
                   2030:                                        fds[i].revents = POLLNVAL;
                   2031:                                        if (rv != -1)
                   2032:                                                rv++;
                   2033:                                }
                   2034:                                pfd_host[i].fd = fd;
1.1       pooka    2035:                                pfd_host[i].events = fds[i].events;
                   2036:                        }
1.39      pooka    2037:                        pfd_rump[i].revents = pfd_host[i].revents = 0;
1.1       pooka    2038:                }
1.59      pooka    2039:                if (rv) {
1.1       pooka    2040:                        goto out;
1.59      pooka    2041:                }
1.1       pooka    2042:
                   2043:                pfd_host[nfds].fd = hpipe[0];
                   2044:                pfd_host[nfds].events = POLLIN;
                   2045:                pfd_rump[nfds].fd = rpipe[0];
                   2046:                pfd_rump[nfds].events = POLLIN;
                   2047:
                   2048:                /*
                   2049:                 * then, create a thread to do host part and meanwhile
                   2050:                 * do rump kernel part right here
                   2051:                 */
                   2052:
                   2053:                parg.pfds = pfd_host;
                   2054:                parg.nfds = nfds+1;
1.3       pooka    2055:                parg.ts = ts;
                   2056:                parg.sigmask = sigmask;
1.1       pooka    2057:                parg.pipefd = rpipe[1];
                   2058:                pthread_create(&pt, NULL, hostpoll, &parg);
                   2059:
1.35      pooka    2060:                op_pollts = GETSYSCALL(rump, POLLTS);
1.99      martin   2061:                rv_rump = op_pollts(pfd_rump, nfds+1, ts, NULL);
                   2062:                errno_rump = errno;
1.1       pooka    2063:                write(hpipe[1], &rv, sizeof(rv));
1.92      martin   2064:                pthread_join(pt, &trv_val);
1.99      martin   2065:                rv_host = (int)(intptr_t)trv_val;
                   2066:                errno_host = parg.errnum;
1.1       pooka    2067:
1.99      martin   2068:                /* strip cross-thread notification from real results */
1.109     gson     2069:                if (rv_host > 0 && pfd_host[nfds].revents & POLLIN) {
1.99      martin   2070:                        rv_host--;
                   2071:                }
1.109     gson     2072:                if (rv_rump > 0 && pfd_rump[nfds].revents & POLLIN) {
1.99      martin   2073:                        rv_rump--;
                   2074:                }
                   2075:
                   2076:                /* then merge the results into what's reported to the caller */
                   2077:                if (rv_rump > 0 || rv_host > 0) {
                   2078:                        /* SUCCESS */
                   2079:
                   2080:                        rv = 0;
                   2081:                        if (rv_rump > 0) {
                   2082:                                for (i = 0; i < nfds; i++) {
                   2083:                                        if (pfd_rump[i].fd != -1)
                   2084:                                                fds[i].revents
                   2085:                                                    = pfd_rump[i].revents;
                   2086:                                }
                   2087:                                rv += rv_rump;
1.1       pooka    2088:                        }
1.99      martin   2089:                        if (rv_host > 0) {
                   2090:                                for (i = 0; i < nfds; i++) {
                   2091:                                        if (pfd_host[i].fd != -1)
                   2092:                                                fds[i].revents
                   2093:                                                    = pfd_host[i].revents;
                   2094:                                }
                   2095:                                rv += rv_host;
                   2096:                        }
                   2097:                        assert(rv > 0);
                   2098:                        sverrno = 0;
                   2099:                } else if (rv_rump == -1 || rv_host == -1) {
                   2100:                        /* ERROR */
                   2101:
                   2102:                        /* just pick one kernel at "random" */
                   2103:                        rv = -1;
                   2104:                        if (rv_host == -1) {
                   2105:                                sverrno = errno_host;
                   2106:                        } else if (rv_rump == -1) {
                   2107:                                sverrno = errno_rump;
1.1       pooka    2108:                        }
                   2109:                } else {
1.99      martin   2110:                        /* TIMEOUT */
                   2111:
1.1       pooka    2112:                        rv = 0;
1.99      martin   2113:                        assert(rv_rump == 0 && rv_host == 0);
1.1       pooka    2114:                }
                   2115:
                   2116:  out:
1.35      pooka    2117:                host_close = GETSYSCALL(host, CLOSE);
1.1       pooka    2118:                if (rpipe[0] != -1)
                   2119:                        rump_sys_close(rpipe[0]);
                   2120:                if (rpipe[1] != -1)
                   2121:                        rump_sys_close(rpipe[1]);
                   2122:                if (hpipe[0] != -1)
1.9       pooka    2123:                        host_close(hpipe[0]);
1.1       pooka    2124:                if (hpipe[1] != -1)
1.9       pooka    2125:                        host_close(hpipe[1]);
1.1       pooka    2126:                free(pfd_host);
                   2127:                free(pfd_rump);
                   2128:                errno = sverrno;
                   2129:        } else {
                   2130:                if (hostcall) {
1.35      pooka    2131:                        op_pollts = GETSYSCALL(host, POLLTS);
1.1       pooka    2132:                } else {
1.35      pooka    2133:                        op_pollts = GETSYSCALL(rump, POLLTS);
1.2       pooka    2134:                        adjustpoll(fds, nfds, fd_host2rump);
1.1       pooka    2135:                }
                   2136:
1.3       pooka    2137:                rv = op_pollts(fds, nfds, ts, sigmask);
1.1       pooka    2138:                if (rumpcall)
1.71      pooka    2139:                        adjustpoll(fds, nfds, fd_rump2host_withdup);
1.1       pooka    2140:        }
                   2141:
                   2142:        return rv;
                   2143: }
                   2144:
                   2145: int
1.24      pooka    2146: poll(struct pollfd *fds, nfds_t nfds, int timeout)
1.1       pooka    2147: {
1.3       pooka    2148:        struct timespec ts;
                   2149:        struct timespec *tsp = NULL;
                   2150:
                   2151:        if (timeout != INFTIM) {
                   2152:                ts.tv_sec = timeout / 1000;
1.11      pooka    2153:                ts.tv_nsec = (timeout % 1000) * 1000*1000;
1.3       pooka    2154:
                   2155:                tsp = &ts;
                   2156:        }
1.1       pooka    2157:
1.29      pooka    2158:        return REALPOLLTS(fds, nfds, tsp, NULL);
1.1       pooka    2159: }
1.10      pooka    2160:
1.111   ! pooka    2161: #ifdef HAVE_KQUEUE
1.10      pooka    2162: int
1.34      pooka    2163: REALKEVENT(int kq, const struct kevent *changelist, size_t nchanges,
                   2164:        struct kevent *eventlist, size_t nevents,
                   2165:        const struct timespec *timeout)
1.10      pooka    2166: {
1.34      pooka    2167:        int (*op_kevent)(int, const struct kevent *, size_t,
                   2168:                struct kevent *, size_t, const struct timespec *);
                   2169:        const struct kevent *ev;
                   2170:        size_t i;
1.10      pooka    2171:
1.34      pooka    2172:        /*
                   2173:         * Check that we don't attempt to kevent rump kernel fd's.
                   2174:         * That needs similar treatment to select/poll, but is slightly
                   2175:         * trickier since we need to manage to different kq descriptors.
                   2176:         * (TODO, in case you're wondering).
                   2177:         */
                   2178:        for (i = 0; i < nchanges; i++) {
                   2179:                ev = &changelist[i];
                   2180:                if (ev->filter == EVFILT_READ || ev->filter == EVFILT_WRITE ||
                   2181:                    ev->filter == EVFILT_VNODE) {
1.66      pooka    2182:                        if (fd_isrump((int)ev->ident)) {
                   2183:                                errno = ENOTSUP;
                   2184:                                return -1;
                   2185:                        }
1.34      pooka    2186:                }
1.27      pooka    2187:        }
1.10      pooka    2188:
1.35      pooka    2189:        op_kevent = GETSYSCALL(host, KEVENT);
1.34      pooka    2190:        return op_kevent(kq, changelist, nchanges, eventlist, nevents, timeout);
1.10      pooka    2191: }
1.111   ! pooka    2192: #endif /* HAVE_KQUEUE */
1.17      pooka    2193:
                   2194: /*
1.62      pooka    2195:  * mmapping from a rump kernel is not supported, so disallow it.
                   2196:  */
                   2197: void *
                   2198: mmap(void *addr, size_t len, int prot, int flags, int fd, off_t offset)
                   2199: {
                   2200:
                   2201:        if (flags & MAP_FILE && fd_isrump(fd)) {
                   2202:                errno = ENOSYS;
                   2203:                return MAP_FAILED;
                   2204:        }
                   2205:        return host_mmap(addr, len, prot, flags, fd, offset);
                   2206: }
                   2207:
1.111   ! pooka    2208: #ifdef __NetBSD__
1.62      pooka    2209: /*
1.78      pooka    2210:  * these go to one or the other on a per-process configuration
                   2211:  */
                   2212: int __sysctl(const int *, unsigned int, void *, size_t *, const void *, size_t);
                   2213: int
                   2214: __sysctl(const int *name, unsigned int namelen, void *old, size_t *oldlenp,
                   2215:        const void *new, size_t newlen)
                   2216: {
                   2217:        int (*op___sysctl)(const int *, unsigned int, void *, size_t *,
                   2218:            const void *, size_t);
                   2219:
                   2220:        if (rumpsysctl) {
                   2221:                op___sysctl = GETSYSCALL(rump, __SYSCTL);
                   2222:        } else {
                   2223:                op___sysctl = GETSYSCALL(host, __SYSCTL);
                   2224:                /* we haven't inited yet */
                   2225:                if (__predict_false(op___sysctl == NULL)) {
1.84      pooka    2226:                        op___sysctl = rumphijack_dlsym(RTLD_NEXT, "__sysctl");
1.78      pooka    2227:                }
                   2228:        }
                   2229:
                   2230:        return op___sysctl(name, namelen, old, oldlenp, new, newlen);
                   2231: }
1.96      pooka    2232: #endif
1.78      pooka    2233:
                   2234: /*
1.17      pooka    2235:  * Rest are std type calls.
                   2236:  */
                   2237:
                   2238: FDCALL(int, bind, DUALCALL_BIND,                                       \
                   2239:        (int fd, const struct sockaddr *name, socklen_t namelen),       \
                   2240:        (int, const struct sockaddr *, socklen_t),                      \
                   2241:        (fd, name, namelen))
                   2242:
                   2243: FDCALL(int, connect, DUALCALL_CONNECT,                                 \
                   2244:        (int fd, const struct sockaddr *name, socklen_t namelen),       \
                   2245:        (int, const struct sockaddr *, socklen_t),                      \
                   2246:        (fd, name, namelen))
                   2247:
                   2248: FDCALL(int, getpeername, DUALCALL_GETPEERNAME,                         \
                   2249:        (int fd, struct sockaddr *name, socklen_t *namelen),            \
                   2250:        (int, struct sockaddr *, socklen_t *),                          \
                   2251:        (fd, name, namelen))
                   2252:
                   2253: FDCALL(int, getsockname, DUALCALL_GETSOCKNAME,                                 \
                   2254:        (int fd, struct sockaddr *name, socklen_t *namelen),            \
                   2255:        (int, struct sockaddr *, socklen_t *),                          \
                   2256:        (fd, name, namelen))
                   2257:
                   2258: FDCALL(int, listen, DUALCALL_LISTEN,                                   \
                   2259:        (int fd, int backlog),                                          \
                   2260:        (int, int),                                                     \
                   2261:        (fd, backlog))
                   2262:
                   2263: FDCALL(ssize_t, recvfrom, DUALCALL_RECVFROM,                           \
                   2264:        (int fd, void *buf, size_t len, int flags,                      \
                   2265:            struct sockaddr *from, socklen_t *fromlen),                 \
                   2266:        (int, void *, size_t, int, struct sockaddr *, socklen_t *),     \
                   2267:        (fd, buf, len, flags, from, fromlen))
                   2268:
                   2269: FDCALL(ssize_t, sendto, DUALCALL_SENDTO,                               \
                   2270:        (int fd, const void *buf, size_t len, int flags,                \
                   2271:            const struct sockaddr *to, socklen_t tolen),                \
                   2272:        (int, const void *, size_t, int,                                \
                   2273:            const struct sockaddr *, socklen_t),                        \
                   2274:        (fd, buf, len, flags, to, tolen))
                   2275:
                   2276: FDCALL(int, getsockopt, DUALCALL_GETSOCKOPT,                           \
                   2277:        (int fd, int level, int optn, void *optval, socklen_t *optlen), \
                   2278:        (int, int, int, void *, socklen_t *),                           \
                   2279:        (fd, level, optn, optval, optlen))
                   2280:
                   2281: FDCALL(int, setsockopt, DUALCALL_SETSOCKOPT,                           \
                   2282:        (int fd, int level, int optn,                                   \
                   2283:            const void *optval, socklen_t optlen),                      \
                   2284:        (int, int, int, const void *, socklen_t),                       \
                   2285:        (fd, level, optn, optval, optlen))
                   2286:
                   2287: FDCALL(int, shutdown, DUALCALL_SHUTDOWN,                               \
                   2288:        (int fd, int how),                                              \
                   2289:        (int, int),                                                     \
                   2290:        (fd, how))
                   2291:
1.31      pooka    2292: FDCALL(ssize_t, REALREAD, DUALCALL_READ,                               \
1.17      pooka    2293:        (int fd, void *buf, size_t buflen),                             \
                   2294:        (int, void *, size_t),                                          \
                   2295:        (fd, buf, buflen))
                   2296:
1.100     pooka    2297: #ifdef __linux__
                   2298: ssize_t __read_chk(int, void *, size_t)
                   2299:     __attribute__((alias("read")));
                   2300: #endif
                   2301:
1.18      pooka    2302: FDCALL(ssize_t, readv, DUALCALL_READV,                                         \
1.17      pooka    2303:        (int fd, const struct iovec *iov, int iovcnt),                  \
                   2304:        (int, const struct iovec *, int),                               \
                   2305:        (fd, iov, iovcnt))
                   2306:
1.60      pooka    2307: FDCALL(ssize_t, REALPREAD, DUALCALL_PREAD,                             \
                   2308:        (int fd, void *buf, size_t nbytes, off_t offset),               \
                   2309:        (int, void *, size_t, off_t),                                   \
                   2310:        (fd, buf, nbytes, offset))
                   2311:
                   2312: FDCALL(ssize_t, preadv, DUALCALL_PREADV,                               \
                   2313:        (int fd, const struct iovec *iov, int iovcnt, off_t offset),    \
                   2314:        (int, const struct iovec *, int, off_t),                        \
                   2315:        (fd, iov, iovcnt, offset))
                   2316:
1.17      pooka    2317: FDCALL(ssize_t, writev, DUALCALL_WRITEV,                               \
                   2318:        (int fd, const struct iovec *iov, int iovcnt),                  \
                   2319:        (int, const struct iovec *, int),                               \
                   2320:        (fd, iov, iovcnt))
1.45      pooka    2321:
1.60      pooka    2322: FDCALL(ssize_t, REALPWRITE, DUALCALL_PWRITE,                           \
                   2323:        (int fd, const void *buf, size_t nbytes, off_t offset),         \
                   2324:        (int, const void *, size_t, off_t),                             \
                   2325:        (fd, buf, nbytes, offset))
                   2326:
                   2327: FDCALL(ssize_t, pwritev, DUALCALL_PWRITEV,                             \
                   2328:        (int fd, const struct iovec *iov, int iovcnt, off_t offset),    \
                   2329:        (int, const struct iovec *, int, off_t),                        \
                   2330:        (fd, iov, iovcnt, offset))
                   2331:
1.97      pooka    2332: #ifndef __linux__
1.45      pooka    2333: FDCALL(int, REALFSTAT, DUALCALL_FSTAT,                                 \
                   2334:        (int fd, struct stat *sb),                                      \
                   2335:        (int, struct stat *),                                           \
                   2336:        (fd, sb))
1.97      pooka    2337: #endif
1.45      pooka    2338:
1.111   ! pooka    2339: #ifdef __NetBSD__
1.45      pooka    2340: FDCALL(int, fstatvfs1, DUALCALL_FSTATVFS1,                             \
                   2341:        (int fd, struct statvfs *buf, int flags),                       \
                   2342:        (int, struct statvfs *, int),                                   \
                   2343:        (fd, buf, flags))
1.96      pooka    2344: #endif
1.45      pooka    2345:
1.61      pooka    2346: FDCALL(off_t, lseek, DUALCALL_LSEEK,                                   \
1.45      pooka    2347:        (int fd, off_t offset, int whence),                             \
                   2348:        (int, off_t, int),                                              \
                   2349:        (fd, offset, whence))
1.96      pooka    2350: #ifdef LSEEK_ALIAS
                   2351: __strong_alias(LSEEK_ALIAS,lseek);
                   2352: #endif
1.45      pooka    2353:
1.98      pooka    2354: #ifndef __linux__
1.45      pooka    2355: FDCALL(int, REALGETDENTS, DUALCALL_GETDENTS,                           \
                   2356:        (int fd, char *buf, size_t nbytes),                             \
                   2357:        (int, char *, size_t),                                          \
                   2358:        (fd, buf, nbytes))
1.98      pooka    2359: #endif
1.45      pooka    2360:
                   2361: FDCALL(int, fchown, DUALCALL_FCHOWN,                                   \
                   2362:        (int fd, uid_t owner, gid_t group),                             \
                   2363:        (int, uid_t, gid_t),                                            \
                   2364:        (fd, owner, group))
                   2365:
                   2366: FDCALL(int, fchmod, DUALCALL_FCHMOD,                                   \
                   2367:        (int fd, mode_t mode),                                          \
                   2368:        (int, mode_t),                                                  \
                   2369:        (fd, mode))
                   2370:
                   2371: FDCALL(int, ftruncate, DUALCALL_FTRUNCATE,                             \
                   2372:        (int fd, off_t length),                                         \
                   2373:        (int, off_t),                                                   \
                   2374:        (fd, length))
                   2375:
                   2376: FDCALL(int, fsync, DUALCALL_FSYNC,                                     \
                   2377:        (int fd),                                                       \
                   2378:        (int),                                                          \
                   2379:        (fd))
                   2380:
1.111   ! pooka    2381: #ifdef HAVE_FSYNC_RANGE
1.45      pooka    2382: FDCALL(int, fsync_range, DUALCALL_FSYNC_RANGE,                         \
                   2383:        (int fd, int how, off_t start, off_t length),                   \
                   2384:        (int, int, off_t, off_t),                                       \
                   2385:        (fd, how, start, length))
1.96      pooka    2386: #endif
1.45      pooka    2387:
                   2388: FDCALL(int, futimes, DUALCALL_FUTIMES,                                 \
                   2389:        (int fd, const struct timeval *tv),                             \
                   2390:        (int, const struct timeval *),                                  \
                   2391:        (fd, tv))
                   2392:
1.111   ! pooka    2393: #ifdef HAVE_CHFLAGS
1.60      pooka    2394: FDCALL(int, fchflags, DUALCALL_FCHFLAGS,                               \
                   2395:        (int fd, u_long flags),                                         \
                   2396:        (int, u_long),                                                  \
                   2397:        (fd, flags))
1.96      pooka    2398: #endif
1.60      pooka    2399:
1.45      pooka    2400: /*
                   2401:  * path-based selectors
                   2402:  */
                   2403:
1.97      pooka    2404: #ifndef __linux__
1.45      pooka    2405: PATHCALL(int, REALSTAT, DUALCALL_STAT,                                 \
                   2406:        (const char *path, struct stat *sb),                            \
                   2407:        (const char *, struct stat *),                                  \
                   2408:        (path, sb))
                   2409:
                   2410: PATHCALL(int, REALLSTAT, DUALCALL_LSTAT,                               \
                   2411:        (const char *path, struct stat *sb),                            \
                   2412:        (const char *, struct stat *),                                  \
                   2413:        (path, sb))
1.97      pooka    2414: #endif
1.45      pooka    2415:
                   2416: PATHCALL(int, chown, DUALCALL_CHOWN,                                   \
                   2417:        (const char *path, uid_t owner, gid_t group),                   \
                   2418:        (const char *, uid_t, gid_t),                                   \
                   2419:        (path, owner, group))
                   2420:
                   2421: PATHCALL(int, lchown, DUALCALL_LCHOWN,                                 \
                   2422:        (const char *path, uid_t owner, gid_t group),                   \
                   2423:        (const char *, uid_t, gid_t),                                   \
                   2424:        (path, owner, group))
                   2425:
                   2426: PATHCALL(int, chmod, DUALCALL_CHMOD,                                   \
                   2427:        (const char *path, mode_t mode),                                \
                   2428:        (const char *, mode_t),                                         \
                   2429:        (path, mode))
                   2430:
                   2431: PATHCALL(int, lchmod, DUALCALL_LCHMOD,                                 \
                   2432:        (const char *path, mode_t mode),                                \
                   2433:        (const char *, mode_t),                                         \
                   2434:        (path, mode))
                   2435:
1.111   ! pooka    2436: #ifdef __NetBSD__
1.45      pooka    2437: PATHCALL(int, statvfs1, DUALCALL_STATVFS1,                             \
                   2438:        (const char *path, struct statvfs *buf, int flags),             \
                   2439:        (const char *, struct statvfs *, int),                          \
                   2440:        (path, buf, flags))
1.96      pooka    2441: #endif
1.45      pooka    2442:
                   2443: PATHCALL(int, unlink, DUALCALL_UNLINK,                                 \
                   2444:        (const char *path),                                             \
                   2445:        (const char *),                                                 \
                   2446:        (path))
                   2447:
                   2448: PATHCALL(int, symlink, DUALCALL_SYMLINK,                               \
1.58      pooka    2449:        (const char *target, const char *path),                         \
1.45      pooka    2450:        (const char *, const char *),                                   \
1.58      pooka    2451:        (target, path))
1.45      pooka    2452:
1.100     pooka    2453: /*
                   2454:  * readlink() can be called from malloc which can be called
                   2455:  * from dlsym() during init
                   2456:  */
                   2457: ssize_t
                   2458: readlink(const char *path, char *buf, size_t bufsiz)
                   2459: {
                   2460:        int (*op_readlink)(const char *, char *, size_t);
                   2461:        enum pathtype pt;
                   2462:
                   2463:        if ((pt = path_isrump(path)) != PATH_HOST) {
                   2464:                op_readlink = GETSYSCALL(rump, READLINK);
                   2465:                if (pt == PATH_RUMP)
                   2466:                        path = path_host2rump(path);
                   2467:        } else {
                   2468:                op_readlink = GETSYSCALL(host, READLINK);
                   2469:        }
                   2470:
                   2471:        if (__predict_false(op_readlink == NULL)) {
                   2472:                errno = ENOENT;
                   2473:                return -1;
                   2474:        }
                   2475:
                   2476:        return op_readlink(path, buf, bufsiz);
                   2477: }
1.45      pooka    2478:
                   2479: PATHCALL(int, mkdir, DUALCALL_MKDIR,                                   \
                   2480:        (const char *path, mode_t mode),                                \
                   2481:        (const char *, mode_t),                                         \
                   2482:        (path, mode))
                   2483:
                   2484: PATHCALL(int, rmdir, DUALCALL_RMDIR,                                   \
                   2485:        (const char *path),                                             \
                   2486:        (const char *),                                                 \
                   2487:        (path))
                   2488:
                   2489: PATHCALL(int, utimes, DUALCALL_UTIMES,                                 \
                   2490:        (const char *path, const struct timeval *tv),                   \
                   2491:        (const char *, const struct timeval *),                         \
                   2492:        (path, tv))
                   2493:
                   2494: PATHCALL(int, lutimes, DUALCALL_LUTIMES,                               \
                   2495:        (const char *path, const struct timeval *tv),                   \
                   2496:        (const char *, const struct timeval *),                         \
                   2497:        (path, tv))
                   2498:
1.111   ! pooka    2499: #ifdef HAVE_CHFLAGS
1.60      pooka    2500: PATHCALL(int, chflags, DUALCALL_CHFLAGS,                               \
                   2501:        (const char *path, u_long flags),                               \
                   2502:        (const char *, u_long),                                         \
                   2503:        (path, flags))
                   2504:
                   2505: PATHCALL(int, lchflags, DUALCALL_LCHFLAGS,                             \
                   2506:        (const char *path, u_long flags),                               \
                   2507:        (const char *, u_long),                                         \
                   2508:        (path, flags))
1.111   ! pooka    2509: #endif /* HAVE_CHFLAGS */
1.60      pooka    2510:
1.45      pooka    2511: PATHCALL(int, truncate, DUALCALL_TRUNCATE,                             \
                   2512:        (const char *path, off_t length),                               \
                   2513:        (const char *, off_t),                                          \
                   2514:        (path, length))
1.48      pooka    2515:
1.65      pooka    2516: PATHCALL(int, access, DUALCALL_ACCESS,                                 \
                   2517:        (const char *path, int mode),                                   \
                   2518:        (const char *, int),                                            \
                   2519:        (path, mode))
                   2520:
1.97      pooka    2521: #ifndef __linux__
1.68      pooka    2522: PATHCALL(int, REALMKNOD, DUALCALL_MKNOD,                               \
                   2523:        (const char *path, mode_t mode, dev_t dev),                     \
                   2524:        (const char *, mode_t, dev_t),                                  \
                   2525:        (path, mode, dev))
1.97      pooka    2526: #endif
1.68      pooka    2527:
1.48      pooka    2528: /*
                   2529:  * Note: with mount the decisive parameter is the mount
                   2530:  * destination directory.  This is because we don't really know
                   2531:  * about the "source" directory in a generic call (and besides,
                   2532:  * it might not even exist, cf. nfs).
                   2533:  */
1.111   ! pooka    2534: #ifdef __NetBSD__
1.48      pooka    2535: PATHCALL(int, REALMOUNT, DUALCALL_MOUNT,                               \
                   2536:        (const char *type, const char *path, int flags,                 \
                   2537:            void *data, size_t dlen),                                   \
                   2538:        (const char *, const char *, int, void *, size_t),              \
                   2539:        (type, path, flags, data, dlen))
                   2540:
                   2541: PATHCALL(int, unmount, DUALCALL_UNMOUNT,                               \
                   2542:        (const char *path, int flags),                                  \
                   2543:        (const char *, int),                                            \
                   2544:        (path, flags))
1.111   ! pooka    2545: #endif /* __NetBSD__ */
1.78      pooka    2546:
1.111   ! pooka    2547: #ifdef HAVE___QUOTACTL
1.91      dholland 2548: PATHCALL(int, __quotactl, DUALCALL_QUOTACTL,                           \
                   2549:        (const char *path, struct quotactl_args *args),                 \
                   2550:        (const char *, struct quotactl_args *),                         \
                   2551:        (path, args))
1.111   ! pooka    2552: #endif /* HAVE___QUOTACTL */
1.80      bouyer   2553:
1.111   ! pooka    2554: #ifdef __NetBSD__
1.82      pooka    2555: PATHCALL(int, REALGETFH, DUALCALL_GETFH,                               \
                   2556:        (const char *path, void *fhp, size_t *fh_size),                 \
                   2557:        (const char *, void *, size_t *),                               \
                   2558:        (path, fhp, fh_size))
1.97      pooka    2559: #endif
1.82      pooka    2560:
1.78      pooka    2561: /*
                   2562:  * These act different on a per-process vfs configuration
                   2563:  */
                   2564:
1.111   ! pooka    2565: #ifdef __NetBSD__
1.78      pooka    2566: VFSCALL(VFSBIT_GETVFSSTAT, int, getvfsstat, DUALCALL_GETVFSSTAT,       \
                   2567:        (struct statvfs *buf, size_t buflen, int flags),                \
                   2568:        (struct statvfs *, size_t, int),                                \
                   2569:        (buf, buflen, flags))
1.96      pooka    2570: #endif
1.78      pooka    2571:
1.111   ! pooka    2572: #ifdef __NetBSD__
1.78      pooka    2573: VFSCALL(VFSBIT_FHCALLS, int, REALFHOPEN, DUALCALL_FHOPEN,              \
                   2574:        (const void *fhp, size_t fh_size, int flags),                   \
                   2575:        (const char *, size_t, int),                                    \
                   2576:        (fhp, fh_size, flags))
                   2577:
                   2578: VFSCALL(VFSBIT_FHCALLS, int, REALFHSTAT, DUALCALL_FHSTAT,              \
                   2579:        (const void *fhp, size_t fh_size, struct stat *sb),             \
                   2580:        (const char *, size_t, struct stat *),                          \
                   2581:        (fhp, fh_size, sb))
                   2582:
                   2583: VFSCALL(VFSBIT_FHCALLS, int, REALFHSTATVFS1, DUALCALL_FHSTATVFS1,      \
                   2584:        (const void *fhp, size_t fh_size, struct statvfs *sb, int flgs),\
                   2585:        (const char *, size_t, struct statvfs *, int),                  \
                   2586:        (fhp, fh_size, sb, flgs))
1.97      pooka    2587: #endif
1.78      pooka    2588:
1.96      pooka    2589:
1.111   ! pooka    2590: #ifdef __NetBSD__
1.96      pooka    2591:
1.78      pooka    2592: /* finally, put nfssvc here.  "keep the namespace clean" */
                   2593: #include <nfs/rpcv2.h>
                   2594: #include <nfs/nfs.h>
                   2595:
                   2596: int
                   2597: nfssvc(int flags, void *argstructp)
                   2598: {
                   2599:        int (*op_nfssvc)(int, void *);
                   2600:
                   2601:        if (vfsbits & VFSBIT_NFSSVC){
                   2602:                struct nfsd_args *nfsdargs;
                   2603:
                   2604:                /* massage the socket descriptor if necessary */
                   2605:                if (flags == NFSSVC_ADDSOCK) {
                   2606:                        nfsdargs = argstructp;
                   2607:                        nfsdargs->sock = fd_host2rump(nfsdargs->sock);
                   2608:                }
                   2609:                op_nfssvc = GETSYSCALL(rump, NFSSVC);
                   2610:        } else
                   2611:                op_nfssvc = GETSYSCALL(host, NFSSVC);
                   2612:
                   2613:        return op_nfssvc(flags, argstructp);
                   2614: }
1.111   ! pooka    2615: #endif /* __NetBSD__ */

CVSweb <webmaster@jp.NetBSD.org>