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

Annotation of src/lib/librumpclient/rumpclient.c, Revision 1.25

1.25    ! pooka       1: /*      $NetBSD: rumpclient.c,v 1.24 2011/02/06 15:43:20 pooka Exp $   */
1.1       pooka       2:
                      3: /*
1.11      pooka       4:  * Copyright (c) 2010, 2011 Antti Kantee.  All Rights Reserved.
1.1       pooka       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:
                     28: /*
                     29:  * Client side routines for rump syscall proxy.
                     30:  */
                     31:
                     32: #include <sys/cdefs.h>
                     33: __RCSID("$NetBSD");
                     34:
1.5       pooka      35: #include <sys/param.h>
1.15      pooka      36: #include <sys/event.h>
1.1       pooka      37: #include <sys/mman.h>
                     38: #include <sys/socket.h>
                     39:
                     40: #include <arpa/inet.h>
                     41: #include <netinet/in.h>
                     42: #include <netinet/tcp.h>
                     43:
                     44: #include <assert.h>
1.13      pooka      45: #include <dlfcn.h>
1.1       pooka      46: #include <errno.h>
                     47: #include <fcntl.h>
1.13      pooka      48: #include <link.h>
1.1       pooka      49: #include <poll.h>
                     50: #include <pthread.h>
1.11      pooka      51: #include <signal.h>
1.1       pooka      52: #include <stdarg.h>
1.18      pooka      53: #include <stdbool.h>
1.1       pooka      54: #include <stdio.h>
                     55: #include <stdlib.h>
                     56: #include <string.h>
                     57: #include <unistd.h>
                     58:
                     59: #include <rump/rumpclient.h>
                     60:
1.13      pooka      61: #define HOSTOPS
                     62: int    (*host_socket)(int, int, int);
                     63: int    (*host_close)(int);
                     64: int    (*host_connect)(int, const struct sockaddr *, socklen_t);
1.15      pooka      65: int    (*host_fcntl)(int, int, ...);
1.13      pooka      66: int    (*host_poll)(struct pollfd *, nfds_t, int);
                     67: ssize_t        (*host_read)(int, void *, size_t);
                     68: ssize_t (*host_sendto)(int, const void *, size_t, int,
                     69:                       const struct sockaddr *, socklen_t);
                     70: int    (*host_setsockopt)(int, int, int, const void *, socklen_t);
                     71:
1.17      pooka      72: int    (*host_kqueue)(void);
                     73: int    (*host_kevent)(int, const struct kevent *, size_t,
                     74:                       struct kevent *, size_t, const struct timespec *);
                     75:
1.1       pooka      76: #include "sp_common.c"
                     77:
1.11      pooka      78: static struct spclient clispc = {
                     79:        .spc_fd = -1,
                     80: };
1.1       pooka      81:
1.18      pooka      82: static int kq = -1;
1.15      pooka      83: static sigset_t fullset;
1.12      pooka      84:
1.20      pooka      85: static int doconnect(bool);
1.18      pooka      86: static int handshake_req(struct spclient *, uint32_t *, int, bool);
                     87:
1.20      pooka      88: time_t retrytimo = RUMPCLIENT_RETRYCONN_ONCE;
1.18      pooka      89:
                     90: static int
                     91: send_with_recon(struct spclient *spc, const void *data, size_t dlen)
                     92: {
1.20      pooka      93:        struct timeval starttime, curtime;
                     94:        time_t prevreconmsg;
                     95:        unsigned reconretries;
1.18      pooka      96:        int rv;
                     97:
1.20      pooka      98:        for (prevreconmsg = 0, reconretries = 0;;) {
1.18      pooka      99:                rv = dosend(spc, data, dlen);
                    100:                if (__predict_false(rv == ENOTCONN || rv == EBADF)) {
1.20      pooka     101:                        /* no persistent connections */
                    102:                        if (retrytimo == 0)
                    103:                                break;
1.24      pooka     104:                        if (retrytimo == RUMPCLIENT_RETRYCONN_DIE)
                    105:                                exit(1);
1.20      pooka     106:
                    107:                        if (!prevreconmsg) {
                    108:                                prevreconmsg = time(NULL);
                    109:                                gettimeofday(&starttime, NULL);
                    110:                        }
                    111:                        if (reconretries == 1) {
                    112:                                if (retrytimo == RUMPCLIENT_RETRYCONN_ONCE) {
                    113:                                        rv = ENOTCONN;
                    114:                                        break;
                    115:                                }
                    116:                                fprintf(stderr, "rump_sp: connection to "
                    117:                                    "kernel lost, trying to reconnect ...\n");
                    118:                        } else if (time(NULL) - prevreconmsg > 120) {
                    119:                                fprintf(stderr, "rump_sp: still trying to "
                    120:                                    "reconnect ...\n");
                    121:                                prevreconmsg = time(NULL);
                    122:                        }
                    123:
                    124:                        /* check that we aren't over the limit */
                    125:                        if (retrytimo > 0) {
                    126:                                struct timeval tmp;
                    127:
                    128:                                gettimeofday(&curtime, NULL);
                    129:                                timersub(&curtime, &starttime, &tmp);
                    130:                                if (tmp.tv_sec >= retrytimo) {
                    131:                                        fprintf(stderr, "rump_sp: reconnect "
                    132:                                            "failed, %lld second timeout\n",
                    133:                                            (long long)retrytimo);
                    134:                                        return ENOTCONN;
                    135:                                }
                    136:                        }
                    137:
                    138:                        /* adhoc backoff timer */
                    139:                        if (reconretries < 10) {
                    140:                                usleep(100000 * reconretries);
                    141:                        } else {
                    142:                                sleep(MIN(10, reconretries-9));
                    143:                        }
                    144:                        reconretries++;
                    145:
                    146:                        if ((rv = doconnect(false)) != 0)
1.18      pooka     147:                                continue;
                    148:                        if ((rv = handshake_req(&clispc, NULL, 0, true)) != 0)
                    149:                                continue;
1.20      pooka     150:
                    151:                        /*
                    152:                         * ok, reconnect succesful.  we need to return to
                    153:                         * the upper layer to get the entire PDU resent.
                    154:                         */
                    155:                        if (reconretries != 1)
                    156:                                fprintf(stderr, "rump_sp: reconnected!\n");
                    157:                        rv = EAGAIN;
                    158:                        break;
                    159:                } else {
                    160:                        _DIAGASSERT(errno != EAGAIN);
1.18      pooka     161:                        break;
                    162:                }
1.20      pooka     163:        }
1.18      pooka     164:
                    165:        return rv;
                    166: }
                    167:
1.12      pooka     168: static int
1.18      pooka     169: cliwaitresp(struct spclient *spc, struct respwait *rw, sigset_t *mask,
                    170:        bool keeplock)
1.12      pooka     171: {
1.18      pooka     172:        uint64_t mygen;
                    173:        bool imalive = true;
1.12      pooka     174:
1.15      pooka     175:        pthread_mutex_lock(&spc->spc_mtx);
1.18      pooka     176:        if (!keeplock)
                    177:                sendunlockl(spc);
                    178:        mygen = spc->spc_generation;
1.12      pooka     179:
                    180:        rw->rw_error = 0;
1.18      pooka     181:        while (!rw->rw_done && rw->rw_error == 0) {
                    182:                if (__predict_false(spc->spc_generation != mygen || !imalive))
                    183:                        break;
                    184:
1.12      pooka     185:                /* are we free to receive? */
                    186:                if (spc->spc_istatus == SPCSTATUS_FREE) {
1.15      pooka     187:                        struct kevent kev[8];
                    188:                        int gotresp, dosig, rv, i;
                    189:
1.12      pooka     190:                        spc->spc_istatus = SPCSTATUS_BUSY;
                    191:                        pthread_mutex_unlock(&spc->spc_mtx);
                    192:
1.15      pooka     193:                        dosig = 0;
                    194:                        for (gotresp = 0; !gotresp; ) {
                    195:                                switch (readframe(spc)) {
                    196:                                case 0:
1.17      pooka     197:                                        rv = host_kevent(kq, NULL, 0,
1.15      pooka     198:                                            kev, __arraycount(kev), NULL);
1.18      pooka     199:
                    200:                                        /*
                    201:                                         * XXX: don't know how this can
                    202:                                         * happen (timeout cannot expire
                    203:                                         * since there isn't one), but
                    204:                                         * it does happen
                    205:                                         */
                    206:                                        if (__predict_false(rv == 0))
                    207:                                                continue;
                    208:
1.15      pooka     209:                                        for (i = 0; i < rv; i++) {
                    210:                                                if (kev[i].filter
                    211:                                                    == EVFILT_SIGNAL)
                    212:                                                        dosig++;
                    213:                                        }
                    214:                                        if (dosig)
                    215:                                                goto cleanup;
                    216:
                    217:                                        continue;
                    218:                                case -1:
1.18      pooka     219:                                        imalive = false;
1.15      pooka     220:                                        goto cleanup;
                    221:                                default:
                    222:                                        break;
                    223:                                }
1.12      pooka     224:
1.15      pooka     225:                                switch (spc->spc_hdr.rsp_class) {
1.12      pooka     226:                                case RUMPSP_RESP:
                    227:                                case RUMPSP_ERROR:
                    228:                                        kickwaiter(spc);
1.15      pooka     229:                                        gotresp = spc->spc_hdr.rsp_reqno ==
                    230:                                            rw->rw_reqno;
1.12      pooka     231:                                        break;
                    232:                                case RUMPSP_REQ:
                    233:                                        handlereq(spc);
                    234:                                        break;
                    235:                                default:
                    236:                                        /* panic */
                    237:                                        break;
1.15      pooka     238:                                }
1.12      pooka     239:                        }
                    240:
1.15      pooka     241:  cleanup:
                    242:                        pthread_mutex_lock(&spc->spc_mtx);
                    243:                        if (spc->spc_istatus == SPCSTATUS_WANTED)
                    244:                                kickall(spc);
                    245:                        spc->spc_istatus = SPCSTATUS_FREE;
                    246:
                    247:                        /* take one for the team */
                    248:                        if (dosig) {
                    249:                                pthread_mutex_unlock(&spc->spc_mtx);
                    250:                                pthread_sigmask(SIG_SETMASK, mask, NULL);
                    251:                                pthread_sigmask(SIG_SETMASK, &fullset, NULL);
                    252:                                pthread_mutex_lock(&spc->spc_mtx);
                    253:                        }
1.12      pooka     254:                } else {
                    255:                        spc->spc_istatus = SPCSTATUS_WANTED;
                    256:                        pthread_cond_wait(&rw->rw_cv, &spc->spc_mtx);
                    257:                }
                    258:        }
                    259:        TAILQ_REMOVE(&spc->spc_respwait, rw, rw_entries);
                    260:        pthread_mutex_unlock(&spc->spc_mtx);
                    261:        pthread_cond_destroy(&rw->rw_cv);
                    262:
1.18      pooka     263:        if (spc->spc_generation != mygen || !imalive) {
1.12      pooka     264:                return ENOTCONN;
1.18      pooka     265:        }
1.12      pooka     266:        return rw->rw_error;
                    267: }
                    268:
1.1       pooka     269: static int
1.3       pooka     270: syscall_req(struct spclient *spc, int sysnum,
                    271:        const void *data, size_t dlen, void **resp)
1.1       pooka     272: {
                    273:        struct rsp_hdr rhdr;
1.3       pooka     274:        struct respwait rw;
1.12      pooka     275:        sigset_t omask;
1.3       pooka     276:        int rv;
1.1       pooka     277:
                    278:        rhdr.rsp_len = sizeof(rhdr) + dlen;
1.3       pooka     279:        rhdr.rsp_class = RUMPSP_REQ;
                    280:        rhdr.rsp_type = RUMPSP_SYSCALL;
1.1       pooka     281:        rhdr.rsp_sysnum = sysnum;
                    282:
1.12      pooka     283:        pthread_sigmask(SIG_SETMASK, &fullset, &omask);
1.6       pooka     284:        do {
                    285:                putwait(spc, &rw, &rhdr);
1.18      pooka     286:                if ((rv = send_with_recon(spc, &rhdr, sizeof(rhdr))) != 0) {
                    287:                        unputwait(spc, &rw);
                    288:                        continue;
                    289:                }
                    290:                if ((rv = send_with_recon(spc, data, dlen)) != 0) {
1.6       pooka     291:                        unputwait(spc, &rw);
1.18      pooka     292:                        continue;
1.6       pooka     293:                }
                    294:
1.18      pooka     295:                rv = cliwaitresp(spc, &rw, &omask, false);
1.20      pooka     296:                if (rv == ENOTCONN)
                    297:                        rv = EAGAIN;
                    298:        } while (rv == EAGAIN);
1.12      pooka     299:        pthread_sigmask(SIG_SETMASK, &omask, NULL);
1.3       pooka     300:
                    301:        *resp = rw.rw_data;
                    302:        return rv;
1.1       pooka     303: }
                    304:
                    305: static int
1.18      pooka     306: handshake_req(struct spclient *spc, uint32_t *auth, int cancel, bool haslock)
1.10      pooka     307: {
1.11      pooka     308:        struct handshake_fork rf;
1.10      pooka     309:        struct rsp_hdr rhdr;
                    310:        struct respwait rw;
1.12      pooka     311:        sigset_t omask;
1.21      pooka     312:        size_t bonus;
1.10      pooka     313:        int rv;
                    314:
1.21      pooka     315:        if (auth) {
                    316:                bonus = sizeof(rf);
                    317:        } else {
                    318:                bonus = strlen(getprogname())+1;
                    319:        }
                    320:
1.10      pooka     321:        /* performs server handshake */
1.21      pooka     322:        rhdr.rsp_len = sizeof(rhdr) + bonus;
1.10      pooka     323:        rhdr.rsp_class = RUMPSP_REQ;
                    324:        rhdr.rsp_type = RUMPSP_HANDSHAKE;
1.11      pooka     325:        if (auth)
                    326:                rhdr.rsp_handshake = HANDSHAKE_FORK;
                    327:        else
                    328:                rhdr.rsp_handshake = HANDSHAKE_GUEST;
1.10      pooka     329:
1.12      pooka     330:        pthread_sigmask(SIG_SETMASK, &fullset, &omask);
1.18      pooka     331:        if (haslock)
                    332:                putwait_locked(spc, &rw, &rhdr);
                    333:        else
                    334:                putwait(spc, &rw, &rhdr);
1.10      pooka     335:        rv = dosend(spc, &rhdr, sizeof(rhdr));
1.11      pooka     336:        if (auth) {
                    337:                memcpy(rf.rf_auth, auth, AUTHLEN*sizeof(*auth));
                    338:                rf.rf_cancel = cancel;
1.18      pooka     339:                rv = send_with_recon(spc, &rf, sizeof(rf));
1.21      pooka     340:        } else {
                    341:                rv = dosend(spc, getprogname(), strlen(getprogname())+1);
1.11      pooka     342:        }
1.18      pooka     343:        if (rv || cancel) {
                    344:                if (haslock)
                    345:                        unputwait_locked(spc, &rw);
                    346:                else
                    347:                        unputwait(spc, &rw);
                    348:                if (cancel) {
                    349:                        pthread_sigmask(SIG_SETMASK, &omask, NULL);
                    350:                        return rv;
                    351:                }
                    352:        } else {
                    353:                rv = cliwaitresp(spc, &rw, &omask, haslock);
1.10      pooka     354:        }
1.12      pooka     355:        pthread_sigmask(SIG_SETMASK, &omask, NULL);
1.10      pooka     356:        if (rv)
                    357:                return rv;
                    358:
                    359:        rv = *(int *)rw.rw_data;
                    360:        free(rw.rw_data);
                    361:
                    362:        return rv;
                    363: }
                    364:
                    365: static int
1.11      pooka     366: prefork_req(struct spclient *spc, void **resp)
                    367: {
                    368:        struct rsp_hdr rhdr;
                    369:        struct respwait rw;
1.12      pooka     370:        sigset_t omask;
1.11      pooka     371:        int rv;
                    372:
                    373:        rhdr.rsp_len = sizeof(rhdr);
                    374:        rhdr.rsp_class = RUMPSP_REQ;
                    375:        rhdr.rsp_type = RUMPSP_PREFORK;
                    376:        rhdr.rsp_error = 0;
                    377:
1.12      pooka     378:        pthread_sigmask(SIG_SETMASK, &fullset, &omask);
1.18      pooka     379:        do {
                    380:                putwait(spc, &rw, &rhdr);
                    381:                rv = send_with_recon(spc, &rhdr, sizeof(rhdr));
                    382:                if (rv != 0) {
                    383:                        unputwait(spc, &rw);
                    384:                        continue;
                    385:                }
1.11      pooka     386:
1.18      pooka     387:                rv = cliwaitresp(spc, &rw, &omask, false);
1.20      pooka     388:                if (rv == ENOTCONN)
                    389:                        rv = EAGAIN;
                    390:        } while (rv == EAGAIN);
1.12      pooka     391:        pthread_sigmask(SIG_SETMASK, &omask, NULL);
1.18      pooka     392:
1.11      pooka     393:        *resp = rw.rw_data;
                    394:        return rv;
                    395: }
                    396:
1.18      pooka     397: /*
                    398:  * prevent response code from deadlocking with reconnect code
                    399:  */
1.11      pooka     400: static int
1.18      pooka     401: resp_sendlock(struct spclient *spc)
                    402: {
                    403:        int rv = 0;
                    404:
                    405:        pthread_mutex_lock(&spc->spc_mtx);
                    406:        while (spc->spc_ostatus != SPCSTATUS_FREE) {
                    407:                if (__predict_false(spc->spc_reconnecting)) {
                    408:                        rv = EBUSY;
                    409:                        goto out;
                    410:                }
                    411:                spc->spc_ostatus = SPCSTATUS_WANTED;
                    412:                pthread_cond_wait(&spc->spc_cv, &spc->spc_mtx);
                    413:        }
                    414:        spc->spc_ostatus = SPCSTATUS_BUSY;
                    415:
                    416:  out:
                    417:        pthread_mutex_unlock(&spc->spc_mtx);
                    418:        return rv;
                    419: }
                    420:
                    421: static void
1.5       pooka     422: send_copyin_resp(struct spclient *spc, uint64_t reqno, void *data, size_t dlen,
                    423:        int wantstr)
1.1       pooka     424: {
                    425:        struct rsp_hdr rhdr;
                    426:
1.5       pooka     427:        if (wantstr)
                    428:                dlen = MIN(dlen, strlen(data)+1);
                    429:
1.1       pooka     430:        rhdr.rsp_len = sizeof(rhdr) + dlen;
                    431:        rhdr.rsp_reqno = reqno;
1.3       pooka     432:        rhdr.rsp_class = RUMPSP_RESP;
                    433:        rhdr.rsp_type = RUMPSP_COPYIN;
1.1       pooka     434:        rhdr.rsp_sysnum = 0;
                    435:
1.18      pooka     436:        if (resp_sendlock(spc) != 0)
                    437:                return;
                    438:        (void)dosend(spc, &rhdr, sizeof(rhdr));
                    439:        (void)dosend(spc, data, dlen);
1.3       pooka     440:        sendunlock(spc);
1.1       pooka     441: }
                    442:
1.18      pooka     443: static void
1.1       pooka     444: send_anonmmap_resp(struct spclient *spc, uint64_t reqno, void *addr)
                    445: {
                    446:        struct rsp_hdr rhdr;
                    447:
                    448:        rhdr.rsp_len = sizeof(rhdr) + sizeof(addr);
                    449:        rhdr.rsp_reqno = reqno;
1.3       pooka     450:        rhdr.rsp_class = RUMPSP_RESP;
                    451:        rhdr.rsp_type = RUMPSP_ANONMMAP;
1.1       pooka     452:        rhdr.rsp_sysnum = 0;
                    453:
1.18      pooka     454:        if (resp_sendlock(spc) != 0)
                    455:                return;
                    456:        (void)dosend(spc, &rhdr, sizeof(rhdr));
                    457:        (void)dosend(spc, &addr, sizeof(addr));
1.3       pooka     458:        sendunlock(spc);
1.1       pooka     459: }
                    460:
                    461: int
                    462: rumpclient_syscall(int sysnum, const void *data, size_t dlen,
                    463:        register_t *retval)
                    464: {
                    465:        struct rsp_sysresp *resp;
1.3       pooka     466:        void *rdata;
                    467:        int rv;
                    468:
                    469:        DPRINTF(("rumpsp syscall_req: syscall %d with %p/%zu\n",
                    470:            sysnum, data, dlen));
                    471:
                    472:        rv = syscall_req(&clispc, sysnum, data, dlen, &rdata);
                    473:        if (rv)
                    474:                return rv;
                    475:
                    476:        resp = rdata;
                    477:        DPRINTF(("rumpsp syscall_resp: syscall %d error %d, rv: %d/%d\n",
                    478:            sysnum, rv, resp->rsys_retval[0], resp->rsys_retval[1]));
1.1       pooka     479:
1.3       pooka     480:        memcpy(retval, &resp->rsys_retval, sizeof(resp->rsys_retval));
                    481:        rv = resp->rsys_error;
                    482:        free(rdata);
1.1       pooka     483:
1.3       pooka     484:        return rv;
                    485: }
1.1       pooka     486:
1.3       pooka     487: static void
                    488: handlereq(struct spclient *spc)
                    489: {
                    490:        struct rsp_copydata *copydata;
1.16      pooka     491:        struct rsp_hdr *rhdr = &spc->spc_hdr;
1.3       pooka     492:        void *mapaddr;
                    493:        size_t maplen;
1.5       pooka     494:        int reqtype = spc->spc_hdr.rsp_type;
1.1       pooka     495:
1.5       pooka     496:        switch (reqtype) {
1.3       pooka     497:        case RUMPSP_COPYIN:
1.5       pooka     498:        case RUMPSP_COPYINSTR:
1.3       pooka     499:                /*LINTED*/
                    500:                copydata = (struct rsp_copydata *)spc->spc_buf;
                    501:                DPRINTF(("rump_sp handlereq: copyin request: %p/%zu\n",
                    502:                    copydata->rcp_addr, copydata->rcp_len));
                    503:                send_copyin_resp(spc, spc->spc_hdr.rsp_reqno,
1.5       pooka     504:                    copydata->rcp_addr, copydata->rcp_len,
                    505:                    reqtype == RUMPSP_COPYINSTR);
1.3       pooka     506:                break;
                    507:        case RUMPSP_COPYOUT:
1.5       pooka     508:        case RUMPSP_COPYOUTSTR:
1.3       pooka     509:                /*LINTED*/
                    510:                copydata = (struct rsp_copydata *)spc->spc_buf;
                    511:                DPRINTF(("rump_sp handlereq: copyout request: %p/%zu\n",
                    512:                    copydata->rcp_addr, copydata->rcp_len));
                    513:                /*LINTED*/
                    514:                memcpy(copydata->rcp_addr, copydata->rcp_data,
                    515:                    copydata->rcp_len);
                    516:                break;
                    517:        case RUMPSP_ANONMMAP:
                    518:                /*LINTED*/
                    519:                maplen = *(size_t *)spc->spc_buf;
                    520:                mapaddr = mmap(NULL, maplen, PROT_READ|PROT_WRITE,
                    521:                    MAP_ANON, -1, 0);
                    522:                if (mapaddr == MAP_FAILED)
                    523:                        mapaddr = NULL;
                    524:                DPRINTF(("rump_sp handlereq: anonmmap: %p\n", mapaddr));
                    525:                send_anonmmap_resp(spc, spc->spc_hdr.rsp_reqno, mapaddr);
                    526:                break;
1.16      pooka     527:        case RUMPSP_RAISE:
                    528:                DPRINTF(("rump_sp handlereq: raise sig %d\n", rhdr->rsp_signo));
1.18      pooka     529:                raise((int)rhdr->rsp_signo);
1.16      pooka     530:                /*
                    531:                 * We most likely have signals blocked, but the signal
                    532:                 * will be handled soon enough when we return.
                    533:                 */
                    534:                break;
1.3       pooka     535:        default:
1.12      pooka     536:                printf("PANIC: INVALID TYPE %d\n", reqtype);
1.3       pooka     537:                abort();
                    538:                break;
1.1       pooka     539:        }
                    540:
1.6       pooka     541:        spcfreebuf(spc);
1.1       pooka     542: }
                    543:
1.11      pooka     544: static unsigned ptab_idx;
                    545: static struct sockaddr *serv_sa;
                    546:
                    547: static int
1.20      pooka     548: doconnect(bool noisy)
1.1       pooka     549: {
1.18      pooka     550:        struct respwait rw;
                    551:        struct rsp_hdr rhdr;
1.15      pooka     552:        struct kevent kev[NSIG+1];
1.9       pooka     553:        char banner[MAXBANNER];
1.18      pooka     554:        struct pollfd pfd;
1.15      pooka     555:        int s, error, flags, i;
1.9       pooka     556:        ssize_t n;
1.1       pooka     557:
1.18      pooka     558:        if (kq != -1)
                    559:                host_close(kq);
                    560:        kq = -1;
1.19      pooka     561:        s = -1;
1.18      pooka     562:
                    563:        if (clispc.spc_fd != -1)
                    564:                host_close(clispc.spc_fd);
                    565:        clispc.spc_fd = -1;
                    566:
                    567:        /*
                    568:         * for reconnect, gate everyone out of the receiver code
                    569:         */
                    570:        putwait_locked(&clispc, &rw, &rhdr);
                    571:
                    572:        pthread_mutex_lock(&clispc.spc_mtx);
                    573:        clispc.spc_reconnecting = 1;
                    574:        pthread_cond_broadcast(&clispc.spc_cv);
                    575:        clispc.spc_generation++;
                    576:        while (clispc.spc_istatus != SPCSTATUS_FREE) {
                    577:                clispc.spc_istatus = SPCSTATUS_WANTED;
                    578:                pthread_cond_wait(&rw.rw_cv, &clispc.spc_mtx);
                    579:        }
                    580:        kickall(&clispc);
                    581:
                    582:        /*
                    583:         * we can release it already since we hold the
                    584:         * send lock during reconnect
                    585:         * XXX: assert it
                    586:         */
                    587:        clispc.spc_istatus = SPCSTATUS_FREE;
                    588:        pthread_mutex_unlock(&clispc.spc_mtx);
                    589:        unputwait_locked(&clispc, &rw);
                    590:
                    591:        free(clispc.spc_buf);
                    592:        clispc.spc_off = 0;
                    593:
1.13      pooka     594:        s = host_socket(parsetab[ptab_idx].domain, SOCK_STREAM, 0);
1.11      pooka     595:        if (s == -1)
1.2       pooka     596:                return -1;
1.1       pooka     597:
1.18      pooka     598:        pfd.fd = s;
                    599:        pfd.events = POLLIN;
                    600:        while (host_connect(s, serv_sa, (socklen_t)serv_sa->sa_len) == -1) {
                    601:                if (errno == EINTR)
                    602:                        continue;
1.20      pooka     603:                error = errno;
                    604:                if (noisy)
1.18      pooka     605:                        fprintf(stderr, "rump_sp: client connect failed: %s\n",
                    606:                            strerror(errno));
1.20      pooka     607:                errno = error;
                    608:                return -1;
1.2       pooka     609:        }
1.1       pooka     610:
1.11      pooka     611:        if ((error = parsetab[ptab_idx].connhook(s)) != 0) {
1.2       pooka     612:                error = errno;
1.20      pooka     613:                if (noisy)
                    614:                        fprintf(stderr, "rump_sp: connect hook failed\n");
1.2       pooka     615:                errno = error;
                    616:                return -1;
1.1       pooka     617:        }
1.4       pooka     618:
1.13      pooka     619:        if ((n = host_read(s, banner, sizeof(banner)-1)) < 0) {
1.2       pooka     620:                error = errno;
1.20      pooka     621:                if (noisy)
                    622:                        fprintf(stderr, "rump_sp: failed to read banner\n");
1.2       pooka     623:                errno = error;
                    624:                return -1;
1.1       pooka     625:        }
1.9       pooka     626:
                    627:        if (banner[n-1] != '\n') {
1.20      pooka     628:                if (noisy)
                    629:                        fprintf(stderr, "rump_sp: invalid banner\n");
1.9       pooka     630:                errno = EINVAL;
                    631:                return -1;
                    632:        }
                    633:        banner[n] = '\0';
1.18      pooka     634:        /* parse the banner some day */
1.9       pooka     635:
1.15      pooka     636:        flags = host_fcntl(s, F_GETFL, 0);
                    637:        if (host_fcntl(s, F_SETFL, flags | O_NONBLOCK) == -1) {
1.20      pooka     638:                if (noisy)
                    639:                        fprintf(stderr, "rump_sp: socket fd NONBLOCK: %s\n",
                    640:                            strerror(errno));
1.15      pooka     641:                errno = EINVAL;
                    642:                return -1;
                    643:        }
1.18      pooka     644:        clispc.spc_fd = s;
                    645:        clispc.spc_state = SPCSTATE_RUNNING;
                    646:        clispc.spc_reconnecting = 0;
1.15      pooka     647:
                    648:        /* setup kqueue, we want all signals and the fd */
1.17      pooka     649:        if ((kq = host_kqueue()) == -1) {
1.15      pooka     650:                error = errno;
1.20      pooka     651:                if (noisy)
                    652:                        fprintf(stderr, "rump_sp: cannot setup kqueue");
1.15      pooka     653:                errno = error;
                    654:                return -1;
                    655:        }
                    656:
                    657:        for (i = 0; i < NSIG; i++) {
                    658:                EV_SET(&kev[i], i+1, EVFILT_SIGNAL, EV_ADD|EV_ENABLE, 0, 0, 0);
                    659:        }
1.18      pooka     660:        EV_SET(&kev[NSIG], clispc.spc_fd,
                    661:            EVFILT_READ, EV_ADD|EV_ENABLE, 0, 0, 0);
1.17      pooka     662:        if (host_kevent(kq, kev, NSIG+1, NULL, 0, NULL) == -1) {
1.15      pooka     663:                error = errno;
1.20      pooka     664:                if (noisy)
                    665:                        fprintf(stderr, "rump_sp: kevent() failed");
1.15      pooka     666:                errno = error;
                    667:                return -1;
                    668:        }
                    669:
1.18      pooka     670:        return 0;
                    671: }
                    672:
                    673: static int
                    674: doinit(void)
                    675: {
                    676:
1.11      pooka     677:        TAILQ_INIT(&clispc.spc_respwait);
                    678:        pthread_mutex_init(&clispc.spc_mtx, NULL);
                    679:        pthread_cond_init(&clispc.spc_cv, NULL);
                    680:
                    681:        return 0;
                    682: }
                    683:
1.13      pooka     684: void *(*rumpclient_dlsym)(void *, const char *);
                    685:
1.11      pooka     686: int
                    687: rumpclient_init()
                    688: {
                    689:        char *p;
                    690:        int error;
                    691:
1.25    ! pooka     692:        sigfillset(&fullset);
        !           693:
1.13      pooka     694:        /* dlsym overrided by rumphijack? */
                    695:        if (!rumpclient_dlsym)
                    696:                rumpclient_dlsym = dlsym;
                    697:
                    698:        /*
                    699:         * sag mir, wo die symbol sind.  zogen fort, der krieg beginnt.
                    700:         * wann wird man je verstehen?  wann wird man je verstehen?
                    701:         */
                    702: #define FINDSYM2(_name_,_syscall_)                                     \
                    703:        if ((host_##_name_ = rumpclient_dlsym(RTLD_NEXT,                \
                    704:            #_syscall_)) == NULL)                                       \
                    705:                /* host_##_name_ = _syscall_ */;
                    706: #define FINDSYM(_name_) FINDSYM2(_name_,_name_)
                    707:        FINDSYM2(socket,__socket30);
                    708:        FINDSYM(close);
                    709:        FINDSYM(connect);
1.15      pooka     710:        FINDSYM(fcntl);
1.13      pooka     711:        FINDSYM(poll);
                    712:        FINDSYM(read);
                    713:        FINDSYM(sendto);
                    714:        FINDSYM(setsockopt);
1.17      pooka     715:        FINDSYM(kqueue);
1.22      pooka     716: #if !__NetBSD_Prereq__(5,99,7)
1.17      pooka     717:        FINDSYM(kevent);
1.22      pooka     718: #else
                    719:        FINDSYM2(kevent,_sys___kevent50);
                    720: #endif
1.13      pooka     721: #undef FINDSYM
                    722: #undef FINDSY2
                    723:
1.11      pooka     724:        if ((p = getenv("RUMP_SERVER")) == NULL) {
                    725:                errno = ENOENT;
                    726:                return -1;
                    727:        }
                    728:
                    729:        if ((error = parseurl(p, &serv_sa, &ptab_idx, 0)) != 0) {
                    730:                errno = error;
                    731:                return -1;
                    732:        }
                    733:
1.18      pooka     734:        if (doinit() == -1)
                    735:                return -1;
1.20      pooka     736:        if (doconnect(true) == -1)
1.11      pooka     737:                return -1;
                    738:
1.18      pooka     739:        error = handshake_req(&clispc, NULL, 0, false);
1.11      pooka     740:        if (error) {
                    741:                pthread_mutex_destroy(&clispc.spc_mtx);
                    742:                pthread_cond_destroy(&clispc.spc_cv);
1.18      pooka     743:                if (clispc.spc_fd != -1)
                    744:                        host_close(clispc.spc_fd);
1.10      pooka     745:                errno = error;
                    746:                return -1;
                    747:        }
                    748:
1.11      pooka     749:        return 0;
                    750: }
                    751:
                    752: struct rumpclient_fork {
                    753:        uint32_t fork_auth[AUTHLEN];
                    754: };
                    755:
                    756: struct rumpclient_fork *
                    757: rumpclient_prefork(void)
                    758: {
                    759:        struct rumpclient_fork *rpf;
                    760:        void *resp;
                    761:        int rv;
                    762:
                    763:        rpf = malloc(sizeof(*rpf));
                    764:        if (rpf == NULL)
                    765:                return NULL;
                    766:
                    767:        if ((rv = prefork_req(&clispc, &resp)) != 0) {
                    768:                free(rpf);
                    769:                errno = rv;
                    770:                return NULL;
                    771:        }
                    772:
                    773:        memcpy(rpf->fork_auth, resp, sizeof(rpf->fork_auth));
                    774:        free(resp);
                    775:
                    776:        return rpf;
                    777: }
                    778:
                    779: int
                    780: rumpclient_fork_init(struct rumpclient_fork *rpf)
                    781: {
                    782:        int error;
1.23      pooka     783:        int osock;
1.11      pooka     784:
1.23      pooka     785:        osock = clispc.spc_fd;
1.11      pooka     786:        memset(&clispc, 0, sizeof(clispc));
1.23      pooka     787:        clispc.spc_fd = osock;
                    788:
                    789:        kq = -1; /* kqueue descriptor is not copied over fork() */
1.11      pooka     790:
1.18      pooka     791:        if (doinit() == -1)
                    792:                return -1;
1.20      pooka     793:        if (doconnect(false) == -1)
1.11      pooka     794:                return -1;
1.10      pooka     795:
1.18      pooka     796:        error = handshake_req(&clispc, rpf->fork_auth, 0, false);
1.10      pooka     797:        if (error) {
                    798:                pthread_mutex_destroy(&clispc.spc_mtx);
                    799:                pthread_cond_destroy(&clispc.spc_cv);
1.11      pooka     800:                errno = error;
                    801:                return -1;
1.10      pooka     802:        }
1.11      pooka     803:
                    804:        return 0;
1.1       pooka     805: }
1.20      pooka     806:
                    807: void
                    808: rumpclient_setconnretry(time_t timeout)
                    809: {
                    810:
1.24      pooka     811:        if (timeout < RUMPCLIENT_RETRYCONN_DIE)
1.20      pooka     812:                return; /* gigo */
                    813:
                    814:        retrytimo = timeout;
                    815: }

CVSweb <webmaster@jp.NetBSD.org>