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

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

unix.superglobalmegacorp.com

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