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

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

unix.superglobalmegacorp.com

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