Annotation of previous_trunk/src/slirp/socket.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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