Annotation of qemu/slirp/socket.c, revision 1.1.1.8

1.1       root        1: /*
                      2:  * Copyright (c) 1995 Danny Gasparovski.
1.1.1.3   root        3:  *
                      4:  * Please read the file COPYRIGHT for the
1.1       root        5:  * terms and conditions of the copyright.
                      6:  */
                      7: 
1.1.1.4   root        8: #include "qemu-common.h"
1.1       root        9: #include <slirp.h>
                     10: #include "ip_icmp.h"
1.1.1.2   root       11: #ifdef __sun__
                     12: #include <sys/filio.h>
                     13: #endif
1.1       root       14: 
1.1.1.3   root       15: static void sofcantrcvmore(struct socket *so);
                     16: static void sofcantsendmore(struct socket *so);
                     17: 
1.1       root       18: struct socket *
1.1.1.5   root       19: solookup(struct socket *head, struct in_addr laddr, u_int lport,
                     20:          struct in_addr faddr, u_int fport)
1.1       root       21: {
                     22:        struct socket *so;
1.1.1.3   root       23: 
1.1       root       24:        for (so = head->so_next; so != head; so = so->so_next) {
1.1.1.3   root       25:                if (so->so_lport == lport &&
1.1       root       26:                    so->so_laddr.s_addr == laddr.s_addr &&
                     27:                    so->so_faddr.s_addr == faddr.s_addr &&
                     28:                    so->so_fport == fport)
                     29:                   break;
                     30:        }
1.1.1.3   root       31: 
1.1       root       32:        if (so == head)
                     33:           return (struct socket *)NULL;
                     34:        return so;
1.1.1.3   root       35: 
1.1       root       36: }
                     37: 
                     38: /*
                     39:  * Create a new socket, initialise the fields
                     40:  * It is the responsibility of the caller to
                     41:  * insque() it into the correct linked-list
                     42:  */
                     43: struct socket *
1.1.1.5   root       44: socreate(Slirp *slirp)
1.1       root       45: {
                     46:   struct socket *so;
1.1.1.3   root       47: 
1.1       root       48:   so = (struct socket *)malloc(sizeof(struct socket));
                     49:   if(so) {
                     50:     memset(so, 0, sizeof(struct socket));
                     51:     so->so_state = SS_NOFDREF;
                     52:     so->s = -1;
1.1.1.5   root       53:     so->slirp = slirp;
1.1       root       54:   }
                     55:   return(so);
                     56: }
                     57: 
                     58: /*
                     59:  * remque and free a socket, clobber cache
                     60:  */
                     61: void
1.1.1.5   root       62: sofree(struct socket *so)
1.1       root       63: {
1.1.1.5   root       64:   Slirp *slirp = so->slirp;
                     65: 
1.1       root       66:   if (so->so_emu==EMU_RSH && so->extra) {
                     67:        sofree(so->extra);
                     68:        so->extra=NULL;
                     69:   }
1.1.1.5   root       70:   if (so == slirp->tcp_last_so) {
                     71:       slirp->tcp_last_so = &slirp->tcb;
                     72:   } else if (so == slirp->udp_last_so) {
                     73:       slirp->udp_last_so = &slirp->udb;
1.1.1.8 ! root       74:   } else if (so == slirp->icmp_last_so) {
        !            75:       slirp->icmp_last_so = &slirp->icmp;
1.1.1.5   root       76:   }
1.1       root       77:   m_free(so->so_m);
1.1.1.3   root       78: 
                     79:   if(so->so_next && so->so_prev)
1.1       root       80:     remque(so);  /* crashes if so is not in a queue */
                     81: 
                     82:   free(so);
                     83: }
                     84: 
1.1.1.4   root       85: size_t sopreprbuf(struct socket *so, struct iovec *iov, int *np)
1.1       root       86: {
1.1.1.4   root       87:        int n, lss, total;
1.1       root       88:        struct sbuf *sb = &so->so_snd;
                     89:        int len = sb->sb_datalen - sb->sb_cc;
                     90:        int mss = so->so_tcpcb->t_maxseg;
1.1.1.3   root       91: 
1.1.1.4   root       92:        DEBUG_CALL("sopreprbuf");
1.1       root       93:        DEBUG_ARG("so = %lx", (long )so);
1.1.1.3   root       94: 
1.1.1.4   root       95:        if (len <= 0)
                     96:                return 0;
                     97: 
1.1       root       98:        iov[0].iov_base = sb->sb_wptr;
1.1.1.4   root       99:         iov[1].iov_base = NULL;
                    100:         iov[1].iov_len = 0;
1.1       root      101:        if (sb->sb_wptr < sb->sb_rptr) {
                    102:                iov[0].iov_len = sb->sb_rptr - sb->sb_wptr;
                    103:                /* Should never succeed, but... */
                    104:                if (iov[0].iov_len > len)
                    105:                   iov[0].iov_len = len;
                    106:                if (iov[0].iov_len > mss)
                    107:                   iov[0].iov_len -= iov[0].iov_len%mss;
                    108:                n = 1;
                    109:        } else {
                    110:                iov[0].iov_len = (sb->sb_data + sb->sb_datalen) - sb->sb_wptr;
                    111:                /* Should never succeed, but... */
                    112:                if (iov[0].iov_len > len) iov[0].iov_len = len;
                    113:                len -= iov[0].iov_len;
                    114:                if (len) {
                    115:                        iov[1].iov_base = sb->sb_data;
                    116:                        iov[1].iov_len = sb->sb_rptr - sb->sb_data;
                    117:                        if(iov[1].iov_len > len)
                    118:                           iov[1].iov_len = len;
                    119:                        total = iov[0].iov_len + iov[1].iov_len;
                    120:                        if (total > mss) {
                    121:                                lss = total%mss;
                    122:                                if (iov[1].iov_len > lss) {
                    123:                                        iov[1].iov_len -= lss;
                    124:                                        n = 2;
                    125:                                } else {
                    126:                                        lss -= iov[1].iov_len;
                    127:                                        iov[0].iov_len -= lss;
                    128:                                        n = 1;
                    129:                                }
                    130:                        } else
                    131:                                n = 2;
                    132:                } else {
                    133:                        if (iov[0].iov_len > mss)
                    134:                           iov[0].iov_len -= iov[0].iov_len%mss;
                    135:                        n = 1;
                    136:                }
                    137:        }
1.1.1.4   root      138:        if (np)
                    139:                *np = n;
                    140: 
                    141:        return iov[0].iov_len + (n - 1) * iov[1].iov_len;
                    142: }
                    143: 
                    144: /*
                    145:  * Read from so's socket into sb_snd, updating all relevant sbuf fields
                    146:  * NOTE: This will only be called if it is select()ed for reading, so
                    147:  * a read() of 0 (or less) means it's disconnected
                    148:  */
                    149: int
1.1.1.5   root      150: soread(struct socket *so)
1.1.1.4   root      151: {
                    152:        int n, nn;
                    153:        struct sbuf *sb = &so->so_snd;
                    154:        struct iovec iov[2];
                    155: 
                    156:        DEBUG_CALL("soread");
                    157:        DEBUG_ARG("so = %lx", (long )so);
                    158: 
                    159:        /*
                    160:         * No need to check if there's enough room to read.
                    161:         * soread wouldn't have been called if there weren't
                    162:         */
                    163:        sopreprbuf(so, iov, &n);
1.1.1.3   root      164: 
1.1       root      165: #ifdef HAVE_READV
                    166:        nn = readv(so->s, (struct iovec *)iov, n);
                    167:        DEBUG_MISC((dfd, " ... read nn = %d bytes\n", nn));
                    168: #else
1.1.1.8 ! root      169:        nn = qemu_recv(so->s, iov[0].iov_base, iov[0].iov_len,0);
1.1.1.3   root      170: #endif
1.1       root      171:        if (nn <= 0) {
                    172:                if (nn < 0 && (errno == EINTR || errno == EAGAIN))
                    173:                        return 0;
                    174:                else {
                    175:                        DEBUG_MISC((dfd, " --- soread() disconnected, nn = %d, errno = %d-%s\n", nn, errno,strerror(errno)));
                    176:                        sofcantrcvmore(so);
                    177:                        tcp_sockclosed(sototcpcb(so));
                    178:                        return -1;
                    179:                }
                    180:        }
1.1.1.3   root      181: 
1.1       root      182: #ifndef HAVE_READV
                    183:        /*
                    184:         * If there was no error, try and read the second time round
                    185:         * We read again if n = 2 (ie, there's another part of the buffer)
                    186:         * and we read as much as we could in the first read
                    187:         * We don't test for <= 0 this time, because there legitimately
                    188:         * might not be any more data (since the socket is non-blocking),
                    189:         * a close will be detected on next iteration.
                    190:         * A return of -1 wont (shouldn't) happen, since it didn't happen above
                    191:         */
                    192:        if (n == 2 && nn == iov[0].iov_len) {
                    193:             int ret;
1.1.1.8 ! root      194:             ret = qemu_recv(so->s, iov[1].iov_base, iov[1].iov_len,0);
1.1       root      195:             if (ret > 0)
                    196:                 nn += ret;
                    197:         }
1.1.1.3   root      198: 
1.1       root      199:        DEBUG_MISC((dfd, " ... read nn = %d bytes\n", nn));
                    200: #endif
1.1.1.3   root      201: 
1.1       root      202:        /* Update fields */
                    203:        sb->sb_cc += nn;
                    204:        sb->sb_wptr += nn;
                    205:        if (sb->sb_wptr >= (sb->sb_data + sb->sb_datalen))
                    206:                sb->sb_wptr -= sb->sb_datalen;
                    207:        return nn;
                    208: }
1.1.1.3   root      209: 
1.1.1.4   root      210: int soreadbuf(struct socket *so, const char *buf, int size)
                    211: {
                    212:     int n, nn, copy = size;
                    213:        struct sbuf *sb = &so->so_snd;
                    214:        struct iovec iov[2];
                    215: 
                    216:        DEBUG_CALL("soreadbuf");
                    217:        DEBUG_ARG("so = %lx", (long )so);
                    218: 
                    219:        /*
                    220:         * No need to check if there's enough room to read.
                    221:         * soread wouldn't have been called if there weren't
                    222:         */
                    223:        if (sopreprbuf(so, iov, &n) < size)
                    224:         goto err;
                    225: 
                    226:     nn = MIN(iov[0].iov_len, copy);
                    227:     memcpy(iov[0].iov_base, buf, nn);
                    228: 
                    229:     copy -= nn;
                    230:     buf += nn;
                    231: 
                    232:     if (copy == 0)
                    233:         goto done;
                    234: 
                    235:     memcpy(iov[1].iov_base, buf, copy);
                    236: 
                    237: done:
                    238:     /* Update fields */
                    239:        sb->sb_cc += size;
                    240:        sb->sb_wptr += size;
                    241:        if (sb->sb_wptr >= (sb->sb_data + sb->sb_datalen))
                    242:                sb->sb_wptr -= sb->sb_datalen;
                    243:     return size;
                    244: err:
                    245: 
                    246:     sofcantrcvmore(so);
                    247:     tcp_sockclosed(sototcpcb(so));
                    248:     fprintf(stderr, "soreadbuf buffer to small");
                    249:     return -1;
                    250: }
                    251: 
1.1       root      252: /*
                    253:  * Get urgent data
1.1.1.3   root      254:  *
1.1       root      255:  * When the socket is created, we set it SO_OOBINLINE,
                    256:  * so when OOB data arrives, we soread() it and everything
                    257:  * in the send buffer is sent as urgent data
                    258:  */
                    259: void
1.1.1.5   root      260: sorecvoob(struct socket *so)
1.1       root      261: {
                    262:        struct tcpcb *tp = sototcpcb(so);
                    263: 
                    264:        DEBUG_CALL("sorecvoob");
                    265:        DEBUG_ARG("so = %lx", (long)so);
1.1.1.3   root      266: 
1.1       root      267:        /*
                    268:         * We take a guess at how much urgent data has arrived.
                    269:         * In most situations, when urgent data arrives, the next
                    270:         * read() should get all the urgent data.  This guess will
                    271:         * be wrong however if more data arrives just after the
1.1.1.3   root      272:         * urgent data, or the read() doesn't return all the
1.1       root      273:         * urgent data.
                    274:         */
                    275:        soread(so);
                    276:        tp->snd_up = tp->snd_una + so->so_snd.sb_cc;
                    277:        tp->t_force = 1;
                    278:        tcp_output(tp);
                    279:        tp->t_force = 0;
                    280: }
                    281: 
                    282: /*
                    283:  * Send urgent data
                    284:  * There's a lot duplicated code here, but...
                    285:  */
                    286: int
1.1.1.5   root      287: sosendoob(struct socket *so)
1.1       root      288: {
                    289:        struct sbuf *sb = &so->so_rcv;
                    290:        char buff[2048]; /* XXX Shouldn't be sending more oob data than this */
1.1.1.3   root      291: 
1.1       root      292:        int n, len;
1.1.1.3   root      293: 
1.1       root      294:        DEBUG_CALL("sosendoob");
                    295:        DEBUG_ARG("so = %lx", (long)so);
                    296:        DEBUG_ARG("sb->sb_cc = %d", sb->sb_cc);
1.1.1.3   root      297: 
1.1       root      298:        if (so->so_urgc > 2048)
                    299:           so->so_urgc = 2048; /* XXXX */
1.1.1.3   root      300: 
1.1       root      301:        if (sb->sb_rptr < sb->sb_wptr) {
                    302:                /* We can send it directly */
1.1.1.4   root      303:                n = slirp_send(so, sb->sb_rptr, so->so_urgc, (MSG_OOB)); /* |MSG_DONTWAIT)); */
1.1       root      304:                so->so_urgc -= n;
1.1.1.3   root      305: 
1.1       root      306:                DEBUG_MISC((dfd, " --- sent %d bytes urgent data, %d urgent bytes left\n", n, so->so_urgc));
                    307:        } else {
1.1.1.3   root      308:                /*
1.1       root      309:                 * Since there's no sendv or sendtov like writev,
                    310:                 * we must copy all data to a linear buffer then
                    311:                 * send it all
                    312:                 */
                    313:                len = (sb->sb_data + sb->sb_datalen) - sb->sb_rptr;
                    314:                if (len > so->so_urgc) len = so->so_urgc;
                    315:                memcpy(buff, sb->sb_rptr, len);
                    316:                so->so_urgc -= len;
                    317:                if (so->so_urgc) {
                    318:                        n = sb->sb_wptr - sb->sb_data;
                    319:                        if (n > so->so_urgc) n = so->so_urgc;
                    320:                        memcpy((buff + len), sb->sb_data, n);
                    321:                        so->so_urgc -= n;
                    322:                        len += n;
                    323:                }
1.1.1.4   root      324:                n = slirp_send(so, buff, len, (MSG_OOB)); /* |MSG_DONTWAIT)); */
1.1       root      325: #ifdef DEBUG
                    326:                if (n != len)
                    327:                   DEBUG_ERROR((dfd, "Didn't send all data urgently XXXXX\n"));
1.1.1.3   root      328: #endif
1.1       root      329:                DEBUG_MISC((dfd, " ---2 sent %d bytes urgent data, %d urgent bytes left\n", n, so->so_urgc));
                    330:        }
1.1.1.3   root      331: 
1.1       root      332:        sb->sb_cc -= n;
                    333:        sb->sb_rptr += n;
                    334:        if (sb->sb_rptr >= (sb->sb_data + sb->sb_datalen))
                    335:                sb->sb_rptr -= sb->sb_datalen;
1.1.1.3   root      336: 
1.1       root      337:        return n;
                    338: }
                    339: 
                    340: /*
1.1.1.3   root      341:  * Write data from so_rcv to so's socket,
1.1       root      342:  * updating all sbuf field as necessary
                    343:  */
                    344: int
1.1.1.5   root      345: sowrite(struct socket *so)
1.1       root      346: {
                    347:        int  n,nn;
                    348:        struct sbuf *sb = &so->so_rcv;
                    349:        int len = sb->sb_cc;
                    350:        struct iovec iov[2];
1.1.1.3   root      351: 
1.1       root      352:        DEBUG_CALL("sowrite");
                    353:        DEBUG_ARG("so = %lx", (long)so);
1.1.1.3   root      354: 
1.1       root      355:        if (so->so_urgc) {
                    356:                sosendoob(so);
                    357:                if (sb->sb_cc == 0)
                    358:                        return 0;
                    359:        }
                    360: 
                    361:        /*
                    362:         * No need to check if there's something to write,
                    363:         * sowrite wouldn't have been called otherwise
                    364:         */
1.1.1.3   root      365: 
1.1       root      366:        iov[0].iov_base = sb->sb_rptr;
1.1.1.4   root      367:         iov[1].iov_base = NULL;
                    368:         iov[1].iov_len = 0;
1.1       root      369:        if (sb->sb_rptr < sb->sb_wptr) {
                    370:                iov[0].iov_len = sb->sb_wptr - sb->sb_rptr;
                    371:                /* Should never succeed, but... */
                    372:                if (iov[0].iov_len > len) iov[0].iov_len = len;
                    373:                n = 1;
                    374:        } else {
                    375:                iov[0].iov_len = (sb->sb_data + sb->sb_datalen) - sb->sb_rptr;
                    376:                if (iov[0].iov_len > len) iov[0].iov_len = len;
                    377:                len -= iov[0].iov_len;
                    378:                if (len) {
                    379:                        iov[1].iov_base = sb->sb_data;
                    380:                        iov[1].iov_len = sb->sb_wptr - sb->sb_data;
                    381:                        if (iov[1].iov_len > len) iov[1].iov_len = len;
                    382:                        n = 2;
                    383:                } else
                    384:                        n = 1;
                    385:        }
                    386:        /* Check if there's urgent data to send, and if so, send it */
                    387: 
                    388: #ifdef HAVE_READV
                    389:        nn = writev(so->s, (const struct iovec *)iov, n);
1.1.1.3   root      390: 
1.1       root      391:        DEBUG_MISC((dfd, "  ... wrote nn = %d bytes\n", nn));
                    392: #else
1.1.1.4   root      393:        nn = slirp_send(so, iov[0].iov_base, iov[0].iov_len,0);
1.1       root      394: #endif
                    395:        /* This should never happen, but people tell me it does *shrug* */
                    396:        if (nn < 0 && (errno == EAGAIN || errno == EINTR))
                    397:                return 0;
1.1.1.3   root      398: 
1.1       root      399:        if (nn <= 0) {
                    400:                DEBUG_MISC((dfd, " --- sowrite disconnected, so->so_state = %x, errno = %d\n",
                    401:                        so->so_state, errno));
                    402:                sofcantsendmore(so);
                    403:                tcp_sockclosed(sototcpcb(so));
                    404:                return -1;
                    405:        }
1.1.1.3   root      406: 
1.1       root      407: #ifndef HAVE_READV
                    408:        if (n == 2 && nn == iov[0].iov_len) {
                    409:             int ret;
1.1.1.4   root      410:             ret = slirp_send(so, iov[1].iov_base, iov[1].iov_len,0);
1.1       root      411:             if (ret > 0)
                    412:                 nn += ret;
                    413:         }
                    414:         DEBUG_MISC((dfd, "  ... wrote nn = %d bytes\n", nn));
                    415: #endif
1.1.1.3   root      416: 
1.1       root      417:        /* Update sbuf */
                    418:        sb->sb_cc -= nn;
                    419:        sb->sb_rptr += nn;
                    420:        if (sb->sb_rptr >= (sb->sb_data + sb->sb_datalen))
                    421:                sb->sb_rptr -= sb->sb_datalen;
1.1.1.3   root      422: 
1.1       root      423:        /*
                    424:         * If in DRAIN mode, and there's no more data, set
                    425:         * it CANTSENDMORE
                    426:         */
                    427:        if ((so->so_state & SS_FWDRAIN) && sb->sb_cc == 0)
                    428:                sofcantsendmore(so);
1.1.1.3   root      429: 
1.1       root      430:        return nn;
                    431: }
                    432: 
                    433: /*
                    434:  * recvfrom() a UDP socket
                    435:  */
                    436: void
1.1.1.5   root      437: sorecvfrom(struct socket *so)
1.1       root      438: {
                    439:        struct sockaddr_in addr;
1.1.1.4   root      440:        socklen_t addrlen = sizeof(struct sockaddr_in);
1.1.1.3   root      441: 
1.1       root      442:        DEBUG_CALL("sorecvfrom");
                    443:        DEBUG_ARG("so = %lx", (long)so);
1.1.1.3   root      444: 
1.1       root      445:        if (so->so_type == IPPROTO_ICMP) {   /* This is a "ping" reply */
                    446:          char buff[256];
                    447:          int len;
1.1.1.3   root      448: 
                    449:          len = recvfrom(so->s, buff, 256, 0,
1.1       root      450:                         (struct sockaddr *)&addr, &addrlen);
                    451:          /* XXX Check if reply is "correct"? */
1.1.1.3   root      452: 
1.1       root      453:          if(len == -1 || len == 0) {
                    454:            u_char code=ICMP_UNREACH_PORT;
                    455: 
                    456:            if(errno == EHOSTUNREACH) code=ICMP_UNREACH_HOST;
                    457:            else if(errno == ENETUNREACH) code=ICMP_UNREACH_NET;
1.1.1.3   root      458: 
1.1       root      459:            DEBUG_MISC((dfd," udp icmp rx errno = %d-%s\n",
                    460:                        errno,strerror(errno)));
                    461:            icmp_error(so->so_m, ICMP_UNREACH,code, 0,strerror(errno));
                    462:          } else {
                    463:            icmp_reflect(so->so_m);
1.1.1.5   root      464:             so->so_m = NULL; /* Don't m_free() it again! */
1.1       root      465:          }
                    466:          /* No need for this socket anymore, udp_detach it */
                    467:          udp_detach(so);
                    468:        } else {                                /* A "normal" UDP packet */
                    469:          struct mbuf *m;
1.1.1.5   root      470:           int len;
                    471: #ifdef _WIN32
                    472:           unsigned long n;
                    473: #else
                    474:           int n;
                    475: #endif
1.1       root      476: 
1.1.1.5   root      477:          m = m_get(so->slirp);
                    478:          if (!m) {
                    479:              return;
                    480:          }
1.1.1.3   root      481:          m->m_data += IF_MAXLINKHDR;
                    482: 
                    483:          /*
1.1       root      484:           * XXX Shouldn't FIONREAD packets destined for port 53,
                    485:           * but I don't know the max packet size for DNS lookups
                    486:           */
                    487:          len = M_FREEROOM(m);
                    488:          /* if (so->so_fport != htons(53)) { */
                    489:          ioctlsocket(so->s, FIONREAD, &n);
1.1.1.3   root      490: 
1.1       root      491:          if (n > len) {
                    492:            n = (m->m_data - m->m_dat) + m->m_len + n + 1;
                    493:            m_inc(m, n);
                    494:            len = M_FREEROOM(m);
                    495:          }
                    496:          /* } */
1.1.1.3   root      497: 
1.1       root      498:          m->m_len = recvfrom(so->s, m->m_data, len, 0,
                    499:                              (struct sockaddr *)&addr, &addrlen);
1.1.1.3   root      500:          DEBUG_MISC((dfd, " did recvfrom %d, errno = %d-%s\n",
1.1       root      501:                      m->m_len, errno,strerror(errno)));
                    502:          if(m->m_len<0) {
                    503:            u_char code=ICMP_UNREACH_PORT;
                    504: 
                    505:            if(errno == EHOSTUNREACH) code=ICMP_UNREACH_HOST;
                    506:            else if(errno == ENETUNREACH) code=ICMP_UNREACH_NET;
1.1.1.3   root      507: 
1.1       root      508:            DEBUG_MISC((dfd," rx error, tx icmp ICMP_UNREACH:%i\n", code));
                    509:            icmp_error(so->so_m, ICMP_UNREACH,code, 0,strerror(errno));
                    510:            m_free(m);
                    511:          } else {
                    512:          /*
                    513:           * Hack: domain name lookup will be used the most for UDP,
                    514:           * and since they'll only be used once there's no need
                    515:           * for the 4 minute (or whatever) timeout... So we time them
                    516:           * out much quicker (10 seconds  for now...)
                    517:           */
                    518:            if (so->so_expire) {
                    519:              if (so->so_fport == htons(53))
                    520:                so->so_expire = curtime + SO_EXPIREFAST;
                    521:              else
                    522:                so->so_expire = curtime + SO_EXPIRE;
                    523:            }
                    524: 
1.1.1.3   root      525:            /*
1.1       root      526:             * If this packet was destined for CTL_ADDR,
                    527:             * make it look like that's where it came from, done by udp_output
                    528:             */
                    529:            udp_output(so, m, &addr);
                    530:          } /* rx error */
                    531:        } /* if ping packet */
                    532: }
                    533: 
                    534: /*
                    535:  * sendto() a socket
                    536:  */
                    537: int
1.1.1.5   root      538: sosendto(struct socket *so, struct mbuf *m)
1.1       root      539: {
1.1.1.5   root      540:        Slirp *slirp = so->slirp;
1.1       root      541:        int ret;
                    542:        struct sockaddr_in addr;
                    543: 
                    544:        DEBUG_CALL("sosendto");
                    545:        DEBUG_ARG("so = %lx", (long)so);
                    546:        DEBUG_ARG("m = %lx", (long)m);
1.1.1.3   root      547: 
1.1       root      548:         addr.sin_family = AF_INET;
1.1.1.5   root      549:        if ((so->so_faddr.s_addr & slirp->vnetwork_mask.s_addr) ==
                    550:            slirp->vnetwork_addr.s_addr) {
1.1       root      551:          /* It's an alias */
1.1.1.5   root      552:          if (so->so_faddr.s_addr == slirp->vnameserver_addr.s_addr) {
1.1.1.6   root      553:            if (get_dns_addr(&addr.sin_addr) < 0)
                    554:              addr.sin_addr = loopback_addr;
1.1.1.5   root      555:          } else {
1.1       root      556:            addr.sin_addr = loopback_addr;
                    557:          }
                    558:        } else
                    559:          addr.sin_addr = so->so_faddr;
                    560:        addr.sin_port = so->so_fport;
                    561: 
                    562:        DEBUG_MISC((dfd, " sendto()ing, addr.sin_port=%d, addr.sin_addr.s_addr=%.16s\n", ntohs(addr.sin_port), inet_ntoa(addr.sin_addr)));
1.1.1.3   root      563: 
1.1       root      564:        /* Don't care what port we get */
                    565:        ret = sendto(so->s, m->m_data, m->m_len, 0,
                    566:                     (struct sockaddr *)&addr, sizeof (struct sockaddr));
                    567:        if (ret < 0)
                    568:                return -1;
1.1.1.3   root      569: 
1.1       root      570:        /*
                    571:         * Kill the socket if there's no reply in 4 minutes,
                    572:         * but only if it's an expirable socket
                    573:         */
                    574:        if (so->so_expire)
                    575:                so->so_expire = curtime + SO_EXPIRE;
1.1.1.5   root      576:        so->so_state &= SS_PERSISTENT_MASK;
                    577:        so->so_state |= SS_ISFCONNECTED; /* So that it gets select()ed */
1.1       root      578:        return 0;
                    579: }
                    580: 
                    581: /*
1.1.1.5   root      582:  * Listen for incoming TCP connections
1.1       root      583:  */
                    584: struct socket *
1.1.1.7   root      585: tcp_listen(Slirp *slirp, uint32_t haddr, u_int hport, uint32_t laddr,
1.1.1.5   root      586:            u_int lport, int flags)
1.1       root      587: {
                    588:        struct sockaddr_in addr;
                    589:        struct socket *so;
1.1.1.4   root      590:        int s, opt = 1;
                    591:        socklen_t addrlen = sizeof(addr);
1.1.1.7   root      592:        memset(&addr, 0, addrlen);
1.1       root      593: 
1.1.1.5   root      594:        DEBUG_CALL("tcp_listen");
                    595:        DEBUG_ARG("haddr = %x", haddr);
                    596:        DEBUG_ARG("hport = %d", hport);
1.1       root      597:        DEBUG_ARG("laddr = %x", laddr);
                    598:        DEBUG_ARG("lport = %d", lport);
                    599:        DEBUG_ARG("flags = %x", flags);
1.1.1.3   root      600: 
1.1.1.5   root      601:        so = socreate(slirp);
                    602:        if (!so) {
1.1       root      603:          return NULL;
                    604:        }
1.1.1.3   root      605: 
1.1       root      606:        /* Don't tcp_attach... we don't need so_snd nor so_rcv */
                    607:        if ((so->so_tcpcb = tcp_newtcpcb(so)) == NULL) {
                    608:                free(so);
                    609:                return NULL;
                    610:        }
1.1.1.5   root      611:        insque(so, &slirp->tcb);
1.1.1.3   root      612: 
                    613:        /*
1.1       root      614:         * SS_FACCEPTONCE sockets must time out.
                    615:         */
                    616:        if (flags & SS_FACCEPTONCE)
                    617:           so->so_tcpcb->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT*2;
1.1.1.3   root      618: 
1.1.1.5   root      619:        so->so_state &= SS_PERSISTENT_MASK;
                    620:        so->so_state |= (SS_FACCEPTCONN | flags);
1.1       root      621:        so->so_lport = lport; /* Kept in network format */
                    622:        so->so_laddr.s_addr = laddr; /* Ditto */
1.1.1.3   root      623: 
1.1       root      624:        addr.sin_family = AF_INET;
1.1.1.5   root      625:        addr.sin_addr.s_addr = haddr;
                    626:        addr.sin_port = hport;
1.1.1.3   root      627: 
1.1.1.6   root      628:        if (((s = qemu_socket(AF_INET,SOCK_STREAM,0)) < 0) ||
1.1.1.2   root      629:            (setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(int)) < 0) ||
1.1       root      630:            (bind(s,(struct sockaddr *)&addr, sizeof(addr)) < 0) ||
                    631:            (listen(s,1) < 0)) {
                    632:                int tmperrno = errno; /* Don't clobber the real reason we failed */
1.1.1.3   root      633: 
1.1       root      634:                close(s);
                    635:                sofree(so);
                    636:                /* Restore the real errno */
                    637: #ifdef _WIN32
                    638:                WSASetLastError(tmperrno);
                    639: #else
                    640:                errno = tmperrno;
                    641: #endif
                    642:                return NULL;
                    643:        }
                    644:        setsockopt(s,SOL_SOCKET,SO_OOBINLINE,(char *)&opt,sizeof(int));
1.1.1.3   root      645: 
1.1       root      646:        getsockname(s,(struct sockaddr *)&addr,&addrlen);
                    647:        so->so_fport = addr.sin_port;
                    648:        if (addr.sin_addr.s_addr == 0 || addr.sin_addr.s_addr == loopback_addr.s_addr)
1.1.1.5   root      649:           so->so_faddr = slirp->vhost_addr;
1.1       root      650:        else
                    651:           so->so_faddr = addr.sin_addr;
                    652: 
                    653:        so->s = s;
                    654:        return so;
                    655: }
                    656: 
                    657: /*
                    658:  * Various session state calls
                    659:  * XXX Should be #define's
                    660:  * The socket state stuff needs work, these often get call 2 or 3
                    661:  * times each when only 1 was needed
                    662:  */
                    663: void
1.1.1.5   root      664: soisfconnecting(struct socket *so)
1.1       root      665: {
                    666:        so->so_state &= ~(SS_NOFDREF|SS_ISFCONNECTED|SS_FCANTRCVMORE|
                    667:                          SS_FCANTSENDMORE|SS_FWDRAIN);
                    668:        so->so_state |= SS_ISFCONNECTING; /* Clobber other states */
                    669: }
                    670: 
                    671: void
1.1.1.5   root      672: soisfconnected(struct socket *so)
1.1       root      673: {
                    674:        so->so_state &= ~(SS_ISFCONNECTING|SS_FWDRAIN|SS_NOFDREF);
                    675:        so->so_state |= SS_ISFCONNECTED; /* Clobber other states */
                    676: }
                    677: 
1.1.1.3   root      678: static void
                    679: sofcantrcvmore(struct socket *so)
1.1       root      680: {
                    681:        if ((so->so_state & SS_NOFDREF) == 0) {
                    682:                shutdown(so->s,0);
                    683:                if(global_writefds) {
                    684:                  FD_CLR(so->s,global_writefds);
                    685:                }
                    686:        }
                    687:        so->so_state &= ~(SS_ISFCONNECTING);
1.1.1.5   root      688:        if (so->so_state & SS_FCANTSENDMORE) {
                    689:           so->so_state &= SS_PERSISTENT_MASK;
                    690:           so->so_state |= SS_NOFDREF; /* Don't select it */
                    691:        } else {
1.1       root      692:           so->so_state |= SS_FCANTRCVMORE;
1.1.1.5   root      693:        }
1.1       root      694: }
                    695: 
1.1.1.3   root      696: static void
                    697: sofcantsendmore(struct socket *so)
1.1       root      698: {
                    699:        if ((so->so_state & SS_NOFDREF) == 0) {
                    700:             shutdown(so->s,1);           /* send FIN to fhost */
                    701:             if (global_readfds) {
                    702:                 FD_CLR(so->s,global_readfds);
                    703:             }
                    704:             if (global_xfds) {
                    705:                 FD_CLR(so->s,global_xfds);
                    706:             }
                    707:        }
                    708:        so->so_state &= ~(SS_ISFCONNECTING);
1.1.1.5   root      709:        if (so->so_state & SS_FCANTRCVMORE) {
                    710:           so->so_state &= SS_PERSISTENT_MASK;
                    711:           so->so_state |= SS_NOFDREF; /* as above */
                    712:        } else {
1.1       root      713:           so->so_state |= SS_FCANTSENDMORE;
1.1.1.5   root      714:        }
1.1       root      715: }
                    716: 
                    717: /*
                    718:  * Set write drain mode
                    719:  * Set CANTSENDMORE once all data has been write()n
                    720:  */
                    721: void
1.1.1.5   root      722: sofwdrain(struct socket *so)
1.1       root      723: {
                    724:        if (so->so_rcv.sb_cc)
                    725:                so->so_state |= SS_FWDRAIN;
                    726:        else
                    727:                sofcantsendmore(so);
                    728: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.