[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.22

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

CVSweb <webmaster@jp.NetBSD.org>