home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / mskermit / msntcp.c < prev    next >
C/C++ Source or Header  |  2020-01-01  |  70KB  |  2,304 lines

  1. /* File MSNTCP.C
  2.  * Main TCP protocol code
  3.  *
  4.  * Copyright (C) 1991, University of Waterloo.
  5.  *    Copyright (C) 1982, 1997, Trustees of Columbia University in the 
  6.  *    City of New York.  The MS-DOS Kermit software may not be, in whole 
  7.  *    or in part, licensed or sold for profit as a software product itself,
  8.  *    nor may it be included in or distributed with commercial products
  9.  *    or otherwise distributed by commercial concerns to their clients 
  10.  *    or customers without written permission of the Office of Kermit 
  11.  *    Development and Distribution, Columbia University.  This copyright 
  12.  *    notice must not be removed, altered, or obscured.
  13.  *
  14.  * Original version created by Erick Engelke of the University of
  15.  *  Waterloo, Waterloo, Ontario, Canada.
  16.  * Adapted and redesigned for MS-DOS Kermit by Joe R. Doupnik, 
  17.  *  Utah State University, jrd@cc.usu.edu, jrd@usu.Bitnet.
  18.  *
  19.  * Last edit
  20.  * 12 Jan 1995 v3.14
  21.  * Class edition: 2 Feb 1996
  22.  *
  23.  */
  24.  
  25. #include "msntcp.h"
  26. #include "msnlib.h"
  27.  
  28. extern    int arp_handler(in_Header *);
  29. extern    int rarp_handler(void *);
  30. extern    int icmp_handler(void *);
  31. extern    void icmp_noport(void *);
  32. extern    void server_hello(tcp_Socket *s);
  33. extern    void eth_release(void);
  34. extern    void icmp_init(void);
  35. extern    int eth_init(void);
  36. extern    word tcp_status;
  37. extern    void krto(word);
  38. extern    void end_bootp(void);
  39. extern    int DHCP_refresh(void);
  40. extern    int request_busy;    /* msnbtp.c, DHCP request() lock */
  41. extern    int odi_busy(void);
  42.  
  43. static    int tcp_handler(void *);
  44. static    int tcp_rst(in_Header *, tcp_Header FAR *);
  45. static    int tcp_read(void *, byte FAR *, int);
  46. static    int tcp_write(void *, byte FAR *, int);
  47. static    int tcp_close(void *);
  48. static    int tcp_processdata(void *, void FAR *, int);
  49. static    int tcp_send(void *);
  50. static    int tcp_retransmitter(void);
  51. static    int tcp_unthread(void *);
  52. static    int udp_handler(void *);
  53. static    int udp_read(void *, byte FAR *, int);
  54. static    int udp_write(void *, byte FAR *, int);
  55. static    int udp_close(udp_Socket *);
  56. static    void lost_ack(tcp_Socket *);
  57. static    void new_rto(tcp_Socket *, int);
  58.  
  59. longword ipbcast = 0xffffffffL;        /* default IP broadcast address */
  60.  
  61. static    initialized = 0;        /* if have started the stack */
  62. static    imposter = 0;            /* ARP for own IP toggle */
  63. extern    byte kdebug;            /* non-zero if debug mode is active */
  64. extern    word ktcpmss;            /* MSS override */
  65.     
  66. /*
  67.  * Local IP address
  68.  */
  69. longword my_ip_addr = 0L;        /* for external references */
  70. longword sin_mask = 0xfffffe00L;    /* IP subnet mask */
  71.  
  72. static int ip_id = 0;            /* IP packet number */
  73. static int next_tcp_port = 1024;    /* auto incremented */
  74. static int next_udp_port = 1024;
  75. static tcp_Socket *tcp_allsocs = NULL;    /* TCP socket linked list head */
  76. static udp_Socket *udp_allsocs = NULL;    /* UDP socket linked list head */
  77.  
  78. #define tcp_FlagFIN     0x0001
  79. #define tcp_FlagSYN     0x0002
  80. #define tcp_FlagRST     0x0004
  81. #define tcp_FlagPUSH    0x0008
  82. #define tcp_FlagACK     0x0010
  83. #define tcp_FlagURG     0x0020
  84. #define tcp_FlagDO      0xF000
  85. #define tcp_GetDataOffset(tp) (ntohs((tp)->flags) >> 12)
  86. /* IP More Fragments header bit, in network order */
  87. #define IP_MF        0x2000
  88.  
  89. /* Timer definitions */
  90. #define tcp_LONGTIMEOUT 13      /* timeout, sec, for opens */
  91. #define tcp_TIMEOUT 13          /* timeout, sec, during a connection */
  92.  
  93. #define TCP_SBUFSIZE 4096     /* max bytes to buffer in a tcp socket */
  94. #define TCP_RBUFSIZE 4096
  95. #define UDP_BUFSIZE ETH_MSS    /* max bytes to buffer in a udp socket */
  96. #define UDP_LENGTH (sizeof(udp_Header))
  97.  
  98. #define CONNECTION_REJECTED 9    /* a returnable status */
  99. #define tcp_NOSEND    0    /* for tcp send_kind, */
  100. #define tcp_SENDNOW    1     /*  controlling tcp_retransmitter() */
  101.  
  102. word    mss = ETH_MSS;        /* Maximum Segment Size */
  103. static word do_window_probe = 0; /* to probe closed windows in tcp_send() */
  104. longword start_time;        /* DEBUGGING, ONLY FOR CLASS */
  105.  
  106. #define in_GetVersion(ip) ((ip)->hdrlen_ver >> 4)
  107. #define in_GetHdrlen(ip)  ((ip)->hdrlen_ver & 0xf)  /* 32 bit word size */
  108. #define in_GetHdrlenBytes(ip)  (in_GetHdrlen(ip) << 2) /* 8 bit byte size */
  109.  
  110. /* Start reassembly section */
  111. static in_Header * reasm(void *);
  112. static int use_reasmbuf;    /* 0 = not doing fragmented IP datagram */
  113.                 /* else is 1 + slot number to clean later*/
  114. #define MAXSLOTS    8    /* number of datagrams in progress */
  115. #define FRAGDATALEN (576-20)    /* size of each datagram */
  116. typedef struct {
  117.     int    next;        /* must be first element */
  118.     int    first;        /* offsets from slot->ipdata[0] */
  119.     int    last;
  120.     } Hole;
  121.  
  122. /* Fragmentation buffer is organized as MAXSLOTS slots, each of which is
  123.    FRAGDATALEN + 20 IP header plus three words of local overhead.
  124. */
  125. struct reasmstruct {
  126.        longword frag_tmo;    /* reassembly timeout, 0 = unused slot */
  127.     int hole_count;            /* count of holes in datagram */
  128.     in_Header iphdr;        /* IP header, 20 bytes */
  129.     byte ipdata[FRAGDATALEN];    /* IP data, 556 bytes */
  130.     } reasmbuf[MAXSLOTS], * slot;
  131. /* End reassembly section */
  132.  
  133. /*    Network order diagrams
  134.  
  135.     IP header
  136.     0                   1                   2                   3   
  137.     0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 
  138.    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  139.    |Version|  IHL  |Type of Service|          Total Length         |
  140.    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  141.    |         Identification        |Flags|      Fragment Offset    |
  142.    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  143.    |  Time to Live |    Protocol   |         Header Checksum       |
  144.    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  145.    |                       Source Address                          |
  146.    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  147.    |                    Destination Address                        |
  148.    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  149.    |                    Options                    |    Padding    |
  150.    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  151.  
  152.        UDP header
  153.                   0      7 8     15 16    23 24    31  
  154.                  +--------+--------+--------+--------+ 
  155.                  |     Source      |   Destination   | 
  156.                  |      Port       |      Port       | 
  157.                  +--------+--------+--------+--------+ 
  158.                  |                 |                 | 
  159.                  |     Length      |    Checksum     | 
  160.                  +--------+--------+--------+--------+ 
  161.                  |                                     
  162.                  |          data octets ...            
  163.                  +---------------- ...                 
  164.  
  165.  
  166.     TCP Header
  167.     0                   1                   2                   3   
  168.     0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 
  169.    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  170.    |          Source Port          |       Destination Port        |
  171.    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  172.    |                        Sequence Number                        |
  173.    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  174.    |                    Acknowledgment Number                      |
  175.    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  176.    |  Data |           |U|A|P|R|S|F|                               |
  177.    | Offset| Reserved  |R|C|S|S|Y|I|            Window             |
  178.    |       |           |G|K|H|T|N|N|                               |
  179.    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  180.    |           Checksum            |         Urgent Pointer        |
  181.    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  182.    |                    Options                    |    Padding    |
  183.    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  184.    |                             data                              |
  185.    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  186. */
  187. /*
  188.  * tcp_init - Initialize the tcp implementation
  189.  *        - may be called more than once without hurting
  190.  */
  191. int
  192. tcp_init(void)
  193. {
  194.     if (initialized != 0) return (1);    /* success, inited already */
  195.                     /* initialize TCP/IP stack */
  196.     icmp_init();            /* clear ICMP material */
  197.     request_busy = 0;        /* clear DHCP request() logic */
  198.     last_nameserver = 0;        /* reset the name server table */
  199.     arp_last_gateway = 0;        /* clear old gateway info */
  200.     tcp_allsocs = NULL;        /* zero socket pointers */
  201.     udp_allsocs = NULL;
  202.     ip_id = (int)(set_timeout(0) & 0xffff);/* packet number, convenient */
  203.     use_reasmbuf = 0;        /* 0 = not using IP reassembly buf */
  204.     memset(reasmbuf, 0, sizeof (reasmbuf));
  205.     imposter = 0;            /* ARP for own IP flag */
  206.     initialized = eth_init();    /* init the hardware, can fail */
  207.                     /* next port numbers to choose */
  208.     next_udp_port = next_tcp_port = 1024 + (int)(set_timeout(0) & 0x1ff);
  209.     eth_free (NULL);        /* clear all pkt rcv bufs */
  210.     return (initialized);        /* success (1) or failure (0) */
  211. }
  212.  
  213. /*
  214.  * Shut down the data link and all services
  215.  */
  216. void
  217. tcp_shutdown(void)
  218. {
  219.     if (initialized)
  220.         {
  221.         while (tcp_abort(tcp_allsocs)) ; /* stop each TCP session */
  222.         end_bootp();            /* release DHCP IP lease */
  223.         }
  224.     initialized = 0;
  225. }
  226.  
  227. int 
  228. udp_open(udp_Socket *s, word lport, longword ina, word port)
  229. {
  230.     if (s == NULL) return (0);
  231.  
  232.     if (imposter == 0 && arp_resolve(my_ip_addr, NULL))/* imposter check */
  233.         {
  234.         outs("\r\n WARNING: our IP address is used by");
  235.         outs(" another station! Quitting.");
  236.         return(0);            /* fail back to user */
  237.         }
  238.     imposter++;                /* say have done the check */
  239.     if (s->rdata) free(s->rdata);        /* free any allocated buffer*/
  240.     memset(s, 0, sizeof(udp_Socket));
  241.     if (lport == 0) lport = ++next_udp_port;  /* get a nonzero port val */
  242.     s->myport = lport;
  243.     /* check for broadcast */
  244.     if (ina == 0xffffffffL || ina == 0L || ina == ipbcast)
  245.         memset(s->hisethaddr, 0xff, sizeof(eth_address));
  246.     else
  247.         if (arp_resolve(ina, &s->hisethaddr[0]) == 0)
  248.             return (0);            /* fail */
  249.     if ((s->rdata = malloc(UDP_BUFSIZE + sizeof(udp_Header))) == NULL)
  250.         return (0);                /* fail */
  251.     s->hisaddr = ina;
  252.     s->hisport = port;
  253.     s->ip_type = UDP_PROTO;
  254.     s->next = udp_allsocs;
  255.     udp_allsocs = s;
  256.     s->sock_mode = UDP_MODE_CHKSUM;        /* turn on checksums */
  257.     s->sisopen = SOCKET_OPEN;
  258.     return (1);                    /* success */
  259. }
  260.  
  261. /*
  262.  * Actively open a TCP connection to a particular destination.
  263.  * return 0 on error
  264.  */
  265. int 
  266. tcp_open(tcp_Socket *s, word lport, longword ina, word port) 
  267. {
  268.     if (s == NULL) return (0);
  269.     if (s->sisopen != SOCKET_CLOSED)
  270.         return (0);
  271.  
  272.     if (imposter == 0 && arp_resolve(my_ip_addr, NULL))/* imposter check */
  273.         {
  274.         outs("\r\n WARNING: our IP address is used by");
  275.         outs(" another station! Quitting.");
  276.         return(0);            /* fail back to user */
  277.         }
  278.     imposter++;                /* say have done the check */
  279.     if (s->rdata) free(s->rdata);        /* free preallocated buf */
  280.     if (s->sdata) free(s->sdata);        /* free preallocated buf */
  281.  
  282.     memset(s, 0, sizeof(tcp_Socket));    /* zero everything */
  283.     s->mss = mss;                /* hardware limit */
  284.     if ((ina ^ my_ip_addr) & sin_mask)    /* if not on this network */
  285.         s->mss = (mss > 536)? 536: mss;    /* non-fragmentable max-40 */
  286.     if (ktcpmss < s->mss)            /* user override */
  287.         s->mss = ktcpmss;        /*  is an upper limit */
  288.     if (lport == 0)
  289.         lport = ++next_tcp_port;  /* get a nonzero port value */
  290.     s->myport = lport;
  291.     if (arp_resolve(ina, &s->hisethaddr[0]) == 0)
  292.         return (0);        /* failed to get host Ethernet addr */
  293.                         /* create data bufs */
  294.     if ((s->rdata = malloc(TCP_RBUFSIZE + sizeof(tcp_Header))) == NULL)
  295.         return (0);            /* fail */
  296.     if ((s->sdata = malloc(TCP_SBUFSIZE)) == NULL)
  297.         {
  298.         free(s->rdata);
  299.         s->rdata = NULL;
  300.         return (0);
  301.         }
  302.     s->next = tcp_allsocs;
  303.     tcp_allsocs = s;
  304.     s->hisaddr = ina;
  305.     s->hisport = port;
  306.     s->seqnum = ntohl(set_timeout(0)) >> 16;
  307.     s->flags = tcp_FlagSYN;
  308.     s->state = tcp_StateSYNSENT;
  309.     s->ip_type = TCP_PROTO;
  310.     s->sisopen = SOCKET_OPEN;
  311.     s->sock_mode = TCP_MODE_NAGLE;        /* Nagle slow start */
  312.     s->rto = 18 * 4;            /* assume four seconds */
  313.     s->cwindow = s->mss;            /* slow start VJ algorithm */
  314.     s->ssthresh = TCP_RBUFSIZE;
  315.     s->timeout = set_timeout(tcp_LONGTIMEOUT); /* seconds */
  316.     start_time = set_ttimeout(0);        /* log time reference */
  317.     return (tcp_send(s));            /* fail if send fails */
  318. }
  319.  
  320. /*
  321.  * Passive open: listen for a connection on a particular port
  322.  */
  323. tcp_listen(tcp_Socket *s, word lport, longword ina, word port, word timeout)
  324. {
  325.     if (s == NULL) return (0);
  326.  
  327.     if (s->rdata) free(s->rdata);        /* free preallocated buf */
  328.     if (s->sdata) free(s->sdata);        /* free preallocated buf */
  329.     memset(s, 0, sizeof(tcp_Socket));    /* zero everything */
  330.     s->ip_type = TCP_PROTO;
  331.     s->mss = mss;                /* hardware limit */
  332.     s->cwindow = s->mss;            /* slow start VJ algorithm */
  333.     s->rto = 18 * 4;            /* assume four seconds */
  334.     s->state = tcp_StateLISTEN;
  335.     if (timeout != 0)
  336.         s->timeout = set_timeout(timeout);    /* seconds */
  337.     s->myport = lport;
  338.     s->hisport = port;
  339.     s->hisaddr = ina;
  340.     s->seqnum = ntohl(set_timeout(0)) >> 16;
  341.     if ((s->rdata = malloc(TCP_RBUFSIZE + sizeof(tcp_Header))) == NULL)
  342.         return (0);            /* fail */
  343.     if ((s->sdata = malloc(TCP_SBUFSIZE)) == NULL)
  344.         {
  345.         free(s->rdata);
  346.         s->rdata = NULL;
  347.         return (0);
  348.         }
  349.     s->next = tcp_allsocs;            /* active socket list */
  350.     tcp_allsocs = s;            /* remember active socket */
  351.     s->ip_type = TCP_PROTO;            /* we speak TCP here */
  352.     s->sisopen = SOCKET_OPEN;        /* socket is open */
  353.     s->sock_mode = TCP_MODE_PASSIVE + TCP_MODE_NAGLE;
  354.     s->send_kind = tcp_NOSEND;        /* say no pending sends */
  355.     timeout = 0;
  356.     return (1);
  357. }
  358.  
  359.  
  360. static int
  361. udp_close(udp_Socket *ds)
  362. {
  363.     register udp_Socket *sp;
  364.  
  365.     sp = udp_allsocs;        /* ptr to first socket */
  366.     if (sp == NULL) return (0);    /* failure */
  367.     ds->sisopen = SOCKET_CLOSED;    /* say socket is closed, do first */
  368.  
  369.     if (sp == ds)
  370.         udp_allsocs = ds->next; /* if we are first, unlink */
  371.     while (sp != NULL)
  372.         {
  373.         if (sp->next == ds)    /* if current points to us */
  374.             {
  375.             sp->next = ds->next; /* point it to our successor */
  376.                break;
  377.             }
  378.         sp = sp->next;        /* look at next socket */
  379.         }
  380.     if (ds->rdata != NULL)
  381.         {
  382.         free(ds->rdata);    /* free received data buffer */
  383.         ds->rdata = NULL;    /* invalidate data buffer address */
  384.         }
  385.         ds->rdatalen = 0;        /* flush pending reads */
  386.     return (1);            /* success */
  387. }
  388.  
  389. /*
  390.  * Send a FIN on a particular port -- only works if it is open
  391.  * Must still allow receives
  392.  * Returns 0 for failure
  393.  */
  394. static int 
  395. tcp_close(tcp_Socket *s)
  396. {
  397.  
  398.     if (s == NULL || s->ip_type != TCP_PROTO)
  399.         return (0);            /* failure */
  400.  
  401.     s->sdatalen = s->sdatahwater; /* cannot send anything now */
  402.     if (s->state & (tcp_StateESTAB | tcp_StateSYNREC | tcp_StateCLOSWT))
  403.         {
  404.         if (kdebug) outs("FIN sent, closing\r\n");
  405.         if (s->state == tcp_StateCLOSWT)
  406.             s->state = tcp_StateLASTACK;
  407.         else
  408.             s->state = tcp_StateFINWT1;
  409.         s->flags = tcp_FlagACK | tcp_FlagFIN;
  410.         s->timeout = set_timeout(tcp_TIMEOUT);    /* added */
  411.         tcp_send(s);
  412.         return (1);            /* success */
  413.         }
  414.     s->state = tcp_StateCLOSED;
  415.     tcp_unthread(s);            /* remove socket from list */
  416.     return (0);
  417. }
  418.  
  419. /*
  420.  * Abort a tcp connection
  421.  * Returns 0 if failure
  422.  */
  423. int 
  424. tcp_abort(tcp_Socket *s)
  425. {
  426.     if (s == NULL) return (0);        /* failure */
  427.  
  428.     if (kdebug != 0) outs("TCP_ABORT\r\n");
  429.     if ((s->state != tcp_StateLISTEN) && (s->state != tcp_StateCLOSED))
  430.         {
  431.         s->flags = tcp_FlagRST | tcp_FlagACK;
  432.         tcp_send(s);
  433.         }
  434.     s->sdatalen = 0;
  435.     s->state = tcp_StateCLOSED;
  436.     tcp_unthread(s);
  437.     return (1);                /* success */
  438. }
  439.  
  440. /*
  441.  * Retransmitter - called periodically to perform tcp retransmissions
  442.  * Returns 0 if failure
  443.  */
  444. static int
  445. tcp_retransmitter(void)
  446. {
  447.     register tcp_Socket *s;
  448.     register int i;
  449.  
  450.     for (s = tcp_allsocs; s != NULL; s = s->next)
  451.         {
  452.                 /* Trigger to send, from tcp_handler() */
  453.         if (s->send_kind == tcp_SENDNOW)
  454.             tcp_send(s); /* if failure it leaves tcp_SENDNOW set*/
  455.                     /* else send_kind changes to tcp_NOSEND */
  456.  
  457.         for (i = 0; i < s->sendqnum; i++)     /* waiting for ACK */
  458.             if (chk_timeout(s->sendq[i].timeout) == TIMED_OUT)
  459.                 {
  460.                 if (kdebug) outs("Timeout\r\n");
  461.                 lost_ack(s);    /* lost ACK actions */
  462.                         tcp_send(s);     /* resend some data */
  463.                 break;        /* exit sendq for-loop */
  464.                     }
  465.  
  466.                   /* if no transmission for idle ticks */
  467.           if (s->idle && (chk_timeout(s->idle) == TIMED_OUT))
  468.             s->cwindow = s->mss;    /* use slow start */
  469.  
  470.             /* IP reassembly buffer timeout checks */
  471.         for (i = 0; i < MAXSLOTS; i++)
  472.             if (reasmbuf[i].frag_tmo &&
  473.                    chk_timeout(reasmbuf[i].frag_tmo) == TIMED_OUT)
  474.                      reasmbuf[i].frag_tmo = 0; /* empty the slot */
  475.  
  476.         if (s->winprobe ||
  477.            (s->keepalive && (chk_timeout(s->keepalive) == TIMED_OUT)))
  478.             {
  479.             do_window_probe++;    /* window probe */
  480.             tcp_send(s);        /* send probe */
  481.             }
  482.  
  483.     /* TCP machine states which can timeout via variable s->timeout */
  484.         if (s->timeout && (chk_timeout(s->timeout) == TIMED_OUT))
  485.             switch (s->state)
  486.             {
  487.             case tcp_StateSYNREC:
  488.             case tcp_StateSYNSENT:
  489.                 tcp_close(s);        /* graceful close */
  490.                 break;
  491.             case tcp_StateTIMEWT:
  492.                 s->state = tcp_StateCLOSED;
  493.                 tcp_unthread(s);    /* purge it */
  494.                 break;
  495.             default:
  496.                 tcp_abort(s);
  497.                 break;
  498.             }        /* end of switch */
  499.         }            /* foot of for loop */
  500.  
  501.     if (DHCP_refresh() == -1)    /* if failed to refresh lease */
  502.         {    /* create no new output from here on, else loops */
  503.         tcp_shutdown();        /* end all traffic */
  504.         return (0);        /* failure */
  505.         }
  506.  
  507.     return (1);            /* success */
  508. }
  509.  
  510. /*
  511.  * Unthread a socket from the socket list, if it's there. Return 0 on failure
  512.  */
  513. static int
  514. tcp_unthread(tcp_Socket *ds)
  515. {
  516.     register tcp_Socket *sp;
  517.  
  518.     if (ds == NULL) return (0);        /* failure */
  519.  
  520.     ds->sisopen = SOCKET_CLOSED;        /* say socket is closed */
  521.  
  522.     if ((sp = tcp_allsocs) == NULL)        /* no socket in the queue */ 
  523.         return (0);
  524.  
  525.     if (sp == ds)
  526.         tcp_allsocs = ds->next; /* if we are first, unlink */
  527.     while (sp != NULL)
  528.         {
  529.         if (sp->next == ds)        /* if current points to us */
  530.             {
  531.             sp->next = ds->next; /* point it to our successor */
  532.                break;
  533.             }
  534.         sp = sp->next;            /* look at next socket */
  535.         }
  536.     return (1);                /* success */
  537. }
  538.  
  539. /*
  540.  * tcp_tick - called periodically by user application
  541.  *        - returns 0 when our socket closes
  542.  *        - called with socket parameter or NULL
  543.  */
  544. tcp_tick(sock_type *s)
  545. {
  546.     in_Header *ip;
  547.     in_Header * temp_ip;
  548.     int packettype;
  549.                     /* read a packet */
  550.     while ((ip = (in_Header *)eth_arrived(&packettype)) != NULL)
  551.     {
  552.     switch (packettype)          /* network big endian form */
  553.     {
  554.     case TYPE_IP:                    /* do IP */
  555.         if ((in_GetVersion(ip) != 4) ||
  556.         (checksum(ip, in_GetHdrlenBytes(ip)) != 0xffff))
  557.             {
  558.             if (kdebug)
  559.                 outs("IP Received BAD Checksum \r\n");
  560.             break;
  561.             }
  562.         if ((my_ip_addr == 0L) || 
  563.             (htonl(ip->destination)    == my_ip_addr))
  564.             {
  565.             if ((temp_ip = reasm(ip)) == NULL)
  566.                 break;    /* reassembly in progress, wait */
  567.  
  568.             if (use_reasmbuf > 0)
  569.                  {    /* reassembly completed, process */
  570.                 eth_free(ip);     /* free lan adapter queue */
  571.                 ip = temp_ip;    /* look at reassembly buf */
  572.                 }
  573.             switch (ip->proto & 0xff)
  574.                 {
  575.                 case TCP_PROTO:
  576.                     tcp_handler(ip);
  577.                     break;
  578.                 case UDP_PROTO:
  579.                     udp_handler(ip);
  580.                     break;
  581.                 case ICMP_PROTO:
  582.                     icmp_handler(ip);
  583.                     break;
  584.                 default:
  585.                     break;
  586.                 }    /* end of switch (ip->proto) */
  587.             }
  588.         break;
  589.  
  590.     case TYPE_ARP:                    /* do ARP */
  591.         arp_handler(ip);
  592.         break;
  593.     case TYPE_RARP:                    /* do RARP */
  594.         rarp_handler(ip);
  595.         break;
  596.     default:                /* unknown type */
  597.         break;
  598.     }                /* end of switch */
  599.  
  600.     if (use_reasmbuf > 0)    /* if processing from reassembly buffer */
  601.         {
  602.         reasmbuf[use_reasmbuf - 1].frag_tmo = 0; /* clear buffer */
  603.         use_reasmbuf = 0;            /* done using it */
  604.         temp_ip = NULL;
  605.         }
  606.     else
  607.         eth_free(ip);        /* free the processed packet */
  608.     }                    /* end of while */
  609.     if (tcp_retransmitter() == 0)
  610.         return (0);        /* check on pending sends */
  611.     return ((s != NULL)? s->tcp.sisopen: 0); /* 0 means closed socket */
  612. }
  613.  
  614. /* IP fragment reassembly process. Enter with packet IP pointer, ip.
  615.    Return that IP pointer if packet is not fragmented.
  616.    Return NULL if do not process packet further (such as building pieces).
  617.    Return new IP pointer for reassembled packet, pointing to a reasmbuf.
  618.    Global variable use_reasmbuf is 0 to not use reassembly results, else
  619.    is 1 + index of reasmbuf to be cleared after use.
  620.    Global variables reasmbuf[..]->frag_tmo hold buffer timeout (Bios ticks);
  621.    clear these to dis-use the buffer.
  622. */
  623. in_Header *
  624. reasm(in_Header *ip)
  625. {
  626.     int ip_hlen, frag, frag_first, frag_last, frag_len;
  627.     Hole * previous;
  628.     register int i;
  629.     register Hole * hole;
  630.  
  631.     use_reasmbuf = 0;    /* assume not finishing IP datagram */
  632.  
  633. /* Fragmented datagrams have either More Frags flag bit set or the 
  634.    fragment offset field non-zero. Unfragmented datagrams have both clear.
  635. */
  636.     if ((frag = ntohs(ip->frag) & 0x3fff) == 0) /* frag flags and offset */
  637.         return (ip);            /* not fragmented */
  638.  
  639. /* See if this fragment has a reassembly buffer assigned. Match on protocol,
  640.    IP identification, source IP, and if not allocated a timeout.
  641. */
  642.     for (i = 0; i < MAXSLOTS; i++)
  643.         {
  644.         slot = &reasmbuf[i];
  645.         use_reasmbuf = i + 1; /* assume finishing IP datagram */
  646.         if ((slot->iphdr.identification == ip->identification) &&
  647.                 (slot->iphdr.source == ip->source) &&
  648.                 (slot->iphdr.proto == ip->proto) &&
  649.                 (slot->frag_tmo != 0))
  650.             goto include;    /* have some pieces already */
  651.         }
  652.  
  653.     for (i = 0; i < MAXSLOTS; i++)    /* find an empty slot for new reasm */
  654.         {
  655.         slot = &reasmbuf[i];
  656.         if (slot->frag_tmo == 0)    /* if slot is unused */
  657.             break;
  658.         }
  659.     if (i >= MAXSLOTS)
  660.         {
  661.         use_reasmbuf = 0;
  662.         return (NULL);        /* insufficient space, discard pkt */
  663.         }
  664.  
  665.     slot->frag_tmo = set_timeout(1 + ip->ttl >> 2); /* timeout from TTL */
  666.     bcopy((byte *)ip, &slot->iphdr, 20);    /* copy basic IP header */
  667.     hole = (Hole *)&slot->ipdata[0]; /* first hole struct goes here */
  668.     previous = (Hole *)&slot->iphdr.checksum;
  669.     previous->next = 0;        /* pointer to first hole struct */
  670.     hole->first = hole->next = 0;
  671.     hole->last = FRAGDATALEN;    /* infinity */
  672.     slot->hole_count = 1;        /* count of holes, just initial one */
  673.  
  674.         /* Move data into the existing reassembly buffer */
  675. include:
  676.     ip_hlen = in_GetHdrlenBytes(ip);    /* IP header length */
  677.     frag_len = ntohs(ip->length) - ip_hlen;    /* bytes of IP data */
  678.     frag_first = (frag & 0x1fff) << 3;    /* offset of first data byte*/
  679.     frag_last = frag_first + frag_len - 1;    /* offset of last data byte */
  680.  
  681.              /* if More Frags bit is clear then have end of
  682.              /* datagram and hence can get datagram length */
  683.     if ((frag & IP_MF) == 0)        /* if More Frags is clear */
  684.         slot->iphdr.length = ntohs(frag_last + ip_hlen + 1);
  685.  
  686.     previous = (Hole *)&slot->iphdr.checksum;     /* first hole */
  687.     hole = (Hole *)&slot->ipdata[previous->next];
  688.  
  689.                 /* find hole where at least one edge fits */
  690.     for ( i = 0; i < slot->hole_count; i++)
  691.         if (frag_first > hole->last || frag_last < hole->first)
  692.             {    /* does not go into this hole, look at next */
  693.             previous = hole;    /* remember backward */
  694.             hole = (Hole *)&slot->ipdata[hole->next]; 
  695.             }
  696.         else
  697.             break;        /* goes in hole, figure where below */
  698.  
  699.     if (i >= slot->hole_count)    /* exhausted search for opening */
  700.         {
  701.         slot->frag_tmo = 0;
  702.         use_reasmbuf = 0;
  703.         return (NULL);        /* Failed, no slot matching offset */
  704.         }
  705.  
  706.     slot->hole_count--;        /* delete current hole pointer */
  707.     previous->next = hole->next;    /* forward link over this hole */  
  708.  
  709.     if (frag_first > hole->first)         /* leaves empty beginning */
  710.         {
  711.             /* recreate forward pointer to this new hole */
  712.         previous->next = hole->first;    /* point to this hole */
  713.         hole->last = frag_first - 1;    /* end of this hole */
  714.         slot->hole_count++;
  715.             /* move view to next hole for trailing edge test */
  716.         if (hole->last < FRAGDATALEN)    /* if so there is another */
  717.             {
  718.             previous = hole;
  719.             hole = (Hole *)&slot->ipdata[hole->next];
  720.             }
  721.         }
  722.  
  723.     if ((frag & IP_MF) &&             /* if More Frags bit is set */
  724.        (frag_last < hole->last))          /* and leaves empty ending */
  725.         {        /* create a new hole for empty portion */
  726.         int old_next, old_last;
  727.  
  728.         old_next = hole->next;        /* old forward pointer */
  729.         old_last = hole->last;
  730.         hole = (Hole *)&slot->ipdata[frag_last + 1]; /* make new hole*/
  731.         hole->next = old_next;        /* copy old pointers */
  732.         hole->last = old_last;
  733.         hole->first = previous->next = frag_last + 1;
  734.         slot->hole_count++;
  735.         }
  736.  
  737.     if ((frag_first + frag_len) > FRAGDATALEN) /* length safety check */
  738.         {
  739.         slot->frag_tmo = 0;        /* delete this buffer */
  740.         use_reasmbuf = 0;
  741.         return (NULL);            /* fail */
  742.         }
  743.  
  744.     bcopy((byte *)ip + ip_hlen, &slot->ipdata[frag_first], frag_len);
  745.  
  746.     if (slot->hole_count)        /* fully reassembled yet? */
  747.         {
  748.         use_reasmbuf = 0;    /* not finished IP datagram */
  749.         return (NULL);        /* not fully reassembled yet */
  750.         }
  751.     slot->iphdr.frag = 0;        /* clear frags information */
  752.     return (&slot->iphdr);         /* use this datagram pointer */
  753. }
  754.  
  755. static int
  756. udp_write(udp_Socket *s, byte FAR *datap, int len)
  757. {
  758.     tcp_PseudoHeader ph;
  759.     struct pkt
  760.         {
  761.         in_Header  in;
  762.         udp_Header udp;
  763.         int       data;
  764.         } register *pkt;
  765.  
  766.     if (s == NULL || datap == NULL)
  767.         return (0);            /* failure */
  768.  
  769.     pkt = (struct pkt *)eth_formatpacket(&s->hisethaddr[0], TYPE_IP);
  770.     pkt->in.length = htons(sizeof(in_Header) + UDP_LENGTH + len);
  771.                         /* UDP header */
  772.     pkt->udp.srcPort = htons(s->myport);
  773.     pkt->udp.dstPort = htons(s->hisport);
  774.     pkt->udp.length = htons(UDP_LENGTH + len);
  775.     bcopyff(datap, &pkt->data, len);
  776.                         /* Internet header */
  777.     pkt->in.hdrlen_ver = 0x45;        /* version 4, hdrlen 5 */
  778.     pkt->in.tos = 0;
  779.     pkt->in.identification = htons(++ip_id);    /* was post inc */
  780.     pkt->in.frag = 0;
  781.     pkt->in.ttl = 60;
  782.     pkt->in.proto = UDP_PROTO;            /* UDP */
  783.     pkt->in.checksum = 0;
  784.     pkt->in.source = htonl(my_ip_addr);
  785.     pkt->in.destination = htonl(s->hisaddr);
  786.     pkt->in.checksum = ~checksum(&pkt->in, sizeof(in_Header));
  787.                     /* compute udp checksum if desired */
  788.     if (s->sock_mode & UDP_MODE_CHKSUM == 0)
  789.         pkt->udp.checksum = 0;
  790.     else
  791.         {
  792.         ph.src = pkt->in.source;        /* big endian now */
  793.         ph.dst = pkt->in.destination;
  794.         ph.mbz = 0;
  795.         ph.protocol = UDP_PROTO;        /* UDP */
  796.         ph.length = pkt->udp.length;        /* big endian now */
  797.         ph.checksum = checksum(&pkt->udp, htons(ph.length));
  798.         pkt->udp.checksum = ~checksum(&ph, sizeof(ph));
  799.         }
  800.     if (eth_send(ntohs(pkt->in.length)) != 0)    /* send pkt */
  801.             return (len);
  802.     if (kdebug) outs("Failed to put packet on wire\r\n");
  803.           return (0);            /* sending failed */
  804. }
  805.  
  806. /*
  807.  * udp_read - read data from buffer, does large buffering.
  808.  * Return 0 on failure.
  809.  */
  810. static int 
  811. udp_read(udp_Socket *s, byte FAR * datap, int maxlen)
  812. {
  813.     register int x;
  814.  
  815.     if (s == NULL || datap == NULL || s->rdata == NULL || maxlen ==0) 
  816.                 return (0);    /* failure */
  817.     if ((x = s->rdatalen) > 0)
  818.         {
  819.         if (x > maxlen) x = maxlen;
  820.         bcopyff(s->rdata, datap, x);
  821.         s->rdatalen -= x;
  822.             }
  823.     return (x);
  824. }
  825.  
  826. udp_cancel(in_Header *ip)
  827. {
  828.     int len;
  829.     register udp_Header *up;
  830.     register udp_Socket *s;
  831.                         /* match to a udp socket */
  832.     len = in_GetHdrlenBytes(ip);
  833.     up = (udp_Header *)((byte *)ip + len);    /* udp frame pointer */
  834.                         /* demux to active sockets */
  835.     for (s = udp_allsocs; s != NULL; s = s->next)
  836.         {
  837.             if (s->hisport != 0 &&
  838.              ntohs(up->dstPort) == s->myport &&
  839.              ntohs(up->srcPort) == s->hisport &&
  840.              ntohl(ip->source) == s->hisaddr)
  841.                  break;
  842.             if (s->hisport != 0 &&        /* ICMP repeat of our pkt */
  843.              ntohs(up->dstPort) == s->hisport &&
  844.              ntohs(up->srcPort) == s->myport &&
  845.              ntohl(ip->source) == my_ip_addr)
  846.             break;        
  847.         }
  848.  
  849.     if (s == NULL)                /* demux to passive sockets */
  850.         for (s = udp_allsocs; s != NULL; s = s->next)
  851.                 if (s->hisport == 0 && 
  852.                 ntohs(up->dstPort) == s->myport)
  853.                     break;
  854.  
  855.     if (s != NULL)
  856.         udp_close(s);
  857.     return (1);                /* success */
  858. }
  859.  
  860. int
  861. tcp_cancel(in_Header *ip)
  862. {
  863.     int len;
  864.     register tcp_Socket *s;
  865.     register tcp_Header *tp;
  866.  
  867.     if (ip == NULL) return (0);        /* failure */
  868.     len = in_GetHdrlenBytes(ip);        /* check work */
  869.  
  870.     tp = (tcp_Header *)((byte *)ip + len);    /* TCP frame pointer */
  871.                         /* demux to active sockets */
  872.     for (s = tcp_allsocs; s != NULL; s = s->next)
  873.         {
  874.             if (s->hisport != 0 &&        /* them to us */
  875.              ntohs(tp->dstPort) == s->myport &&
  876.              ntohs(tp->srcPort) == s->hisport &&
  877.              ntohl(ip->source) == s->hisaddr)
  878.                  break;
  879.             if (s->hisport != 0 &&        /* ICMP repeat of our pkt */
  880.              ntohs(tp->dstPort) == s->hisport &&
  881.              ntohs(tp->srcPort) == s->myport &&
  882.              ntohl(ip->source) == my_ip_addr)
  883.             break;        
  884.         }
  885.  
  886.     if (s == NULL)            /* demux to passive sockets */
  887.         for (s = tcp_allsocs; s != NULL; s = s->next)
  888.                 if (s->hisport == 0 &&
  889.                 ntohs(tp->dstPort) == s->myport)
  890.                     break;
  891.  
  892.     if (s != NULL)
  893.         {
  894.         s->rdatalen = 0;
  895.         s->state = tcp_StateCLOSED;
  896.         tcp_unthread(s);
  897.         }
  898.     return (1);                /* success */
  899. }
  900.  
  901. static int 
  902. tcp_read(tcp_Socket *s, byte FAR *datap, int maxlen)
  903. {
  904.     register int x;
  905.     int obtained = 0;
  906.  
  907.     if (s == NULL || datap == NULL || s->rdata == NULL || maxlen <= 0)
  908.             return (0);        /* failure or read nothing */
  909.     if (s->rdatalen <= 0)            /* if nothing to read */
  910.         return (0);
  911.  
  912.     /* read from rdata, destuff CR NUL, deliver up to maxlen
  913.        bytes to output buffer datap, report # obtained in int
  914.        obtained, remember last read byte for CR NUL state */
  915.     x = destuff(s->rdata, s->rdatalen, datap, maxlen, &obtained,
  916.         &s->last_read);
  917.     if (x <= 0)
  918.         return (obtained);
  919.  
  920.     s->rdatalen -= x;            /* bytes consumed */
  921.     bcopyff(&s->rdata[x], s->rdata, s->rdatalen);  /* copy down */
  922.             /* send a window update if crossing a boundry */
  923.     if (s->rdatalen < (TCP_RBUFSIZE / 2) &&
  924.         (s->rdatalen + x) >= TCP_RBUFSIZE / 2)
  925.             tcp_send(s);        /* send opening update */
  926.     return (obtained);        /* return bytes obtained */
  927. }
  928.  
  929. /*
  930.  * Write data to a connection.
  931.  * Returns number of bytes written, == 0 when connection is not in
  932.  * established state.
  933.  */
  934. static int
  935. tcp_write(tcp_Socket *s, byte FAR *dp, int len)
  936. {
  937.     register int x;
  938.  
  939.     if (s == NULL || dp == NULL || s->sdata == NULL)
  940.         return (0);                /* failure */
  941.     if (s->state != tcp_StateESTAB) 
  942.         return (0);
  943.     x = TCP_SBUFSIZE - s->sdatalen;        /* space remaining in buf */
  944.     if (x > len) x = len;
  945.     if (x < 0)
  946.         x = 0;                /* catch negative errors */
  947.     if (x > 0)
  948.         {
  949.         bcopyff(dp, &s->sdata[s->sdatalen], x); /* append to buf */
  950.         s->sdatalen += x;        /* un-ACK'd data */
  951.                     /* Nagle's algorithm, RFC 896 */
  952.         /* transmit if no previous un-ACK'd data or non-Nagle mode */
  953.         if ((s->sdatalen == x) || 
  954.             ((s->sdatalen - s->sdatahwater) >= (int)s->mss) ||
  955.             ((s->sock_mode & TCP_MODE_NAGLE) != TCP_MODE_NAGLE))
  956.             tcp_send(s);
  957.         }
  958.     return (x);
  959. }
  960.  
  961. /*
  962.  * Handler for incoming UDP packets. If no socket tell the host via ICMP.
  963.  */
  964. static int
  965. udp_handler(in_Header *ip)
  966. {
  967.     register udp_Header FAR * up;
  968.     register udp_Socket *s;
  969.     tcp_PseudoHeader ph;
  970.     byte    FAR * dp;
  971.     word    len;
  972.     int    ip_hlen, frag;
  973.  
  974.     ip_hlen = in_GetHdrlenBytes(ip);
  975.     up = (udp_Header FAR *)((byte *)ip + ip_hlen); /* UDP dgram pointer */
  976.     len = ntohs(up->length);
  977.     frag = ntohs(ip->frag) & 0x3fff;    /* frag flags and offset */
  978.  
  979.                 /* demux to active sockets */
  980.     for (s = udp_allsocs; s != NULL; s = s->next)
  981.         if (s->sisopen == SOCKET_OPEN && s->hisport != 0 && 
  982.             ntohs(up->dstPort) == s->myport &&
  983.             ntohs(up->srcPort) == s->hisport
  984.         /*  && ntohl(ip->source) == s->hisaddr */)
  985.                 break;
  986.  
  987.     if (s == NULL)            /* demux to passive sockets */
  988.         for (s = udp_allsocs; s != NULL; s = s->next)
  989.             if (s->sisopen == SOCKET_OPEN && s->hisaddr == 0 &&
  990.                 ntohs(up->dstPort) == s->myport)
  991.                 {
  992.                 if (arp_resolve(htonl(ip->source),
  993.                     &s->hisethaddr[0]))
  994.                     {
  995.                        s->hisaddr = ntohl(ip->source);
  996.                         s->hisport = ntohs(up->srcPort);
  997.                     }
  998.                 break;
  999.                     }
  1000.  
  1001.     if (s == NULL)        /* demux to broadcast sockets */
  1002.         for (s = udp_allsocs; s != NULL; s = s->next)
  1003.             if (s->sisopen == SOCKET_OPEN && 
  1004.                 s->hisaddr == ipbcast &&
  1005.                 ntohs(up->dstPort) == s->myport)
  1006.                     break;
  1007.  
  1008.     if (s == NULL)
  1009.         {
  1010.         icmp_noport(ip);    /* tell host port is unreachable */
  1011.         if (kdebug) outs(" UDP discarding...\r\n");
  1012.         return (0);            /* say no socket */
  1013.         }
  1014.  
  1015.     if (s->sisopen == SOCKET_CLOSED) return (0);
  1016.  
  1017.     if (up->checksum)            /* if checksum field used */
  1018.         {
  1019.         ph.src = ip->source;        /* already network order */
  1020.         ph.dst = ip->destination;
  1021.         ph.mbz = 0;
  1022.         ph.protocol = UDP_PROTO;
  1023.         ph.length = up->length;
  1024.         ph.checksum = checksum(up, len);
  1025.         if (checksum(&ph, sizeof(tcp_PseudoHeader)) != 0xffff)
  1026.             return (0);        /* failure */
  1027.         }
  1028.  
  1029.                         /* process user data */
  1030.     if ((len -= UDP_LENGTH) > 0)
  1031.         {
  1032.         dp = (byte FAR *)(up);
  1033.         if (len > UDP_BUFSIZE) len = UDP_BUFSIZE;
  1034.         bcopyff(&dp[UDP_LENGTH], s->rdata, len); /* write to buf */
  1035.         s->rdatalen = len;
  1036.         s->hisaddr = ntohl(ip->source); /* sender's IP */
  1037.         }
  1038.     return (1);                /* success */
  1039. }
  1040.  
  1041. /* Handle TCP packets. If no socket send an RST pkt. */
  1042.  
  1043. static 
  1044. tcp_handler(in_Header *ip)
  1045. {
  1046.     tcp_Header FAR * tp;
  1047.     register tcp_Socket *s;
  1048.     tcp_PseudoHeader ph;
  1049.  
  1050.     int ip_hlen, len, diff, data_for_us;    /* signed, please */
  1051.     word flags;
  1052.     long ldiff;                /* must be signed */
  1053.  
  1054.     ip_hlen = in_GetHdrlenBytes(ip);
  1055.     tp = (tcp_Header FAR *)((byte *)ip + ip_hlen); /* tcp frame pointer */
  1056.     len = ntohs(ip->length) - ip_hlen;    /* len of tcp material */
  1057.     flags = ntohs(tp->flags) & 0x003f;    /* tcp flags from pkt */
  1058.         if (ntohs(ip->frag) & 0x3fff)       /* frag flags and offset */
  1059.                 return (0);             /* can't deal with fragments here */
  1060.  
  1061.                 /* demux to active sockets */
  1062.     for (s = tcp_allsocs; s != NULL; s = s->next)
  1063.         if (s->hisport != 0 &&
  1064.             ntohs(tp->dstPort) == s->myport &&
  1065.             ntohs(tp->srcPort) == s->hisport &&
  1066.             ntohl(ip->source) == s->hisaddr)
  1067.             break;
  1068.  
  1069.     if (s == NULL)    /* demux to passive sockets, must be a new session */
  1070.         for (s = tcp_allsocs; s != NULL; s = s->next)
  1071.             if ((s->hisport == 0) &&
  1072.                 (ntohs(tp->dstPort) == s->myport))
  1073.                 break;
  1074.  
  1075.     if (s == NULL)
  1076.         {     /* no matching session exists so we must send a reset */
  1077.         tcp_rst(ip, tp);
  1078.         return (0);        /* 0 to say socket is closed */
  1079.         }
  1080.     if (s->sisopen == SOCKET_CLOSED) return (0);
  1081.  
  1082.     /* pseudo header checking */
  1083.     ph.src = ip->source;            /* still in network order */
  1084.     ph.dst = ip->destination;
  1085.     ph.mbz = 0;
  1086.     ph.protocol = TCP_PROTO;
  1087.     ph.length = htons(len);
  1088.     ph.checksum =  checksum(tp, len);
  1089.     if (checksum(&ph, sizeof(ph)) != 0xffff)
  1090.         {
  1091.         if (kdebug) outs("Bad TCP checksum\r\n");
  1092.         return (1);
  1093.         }
  1094.  
  1095.     if (flags & tcp_FlagRST)    /* reset code */
  1096.         {
  1097.         long limit;
  1098.  
  1099.         if (kdebug != 0)
  1100.             outs("RST received.");
  1101.         outs(" Connection refused by host\r\n");
  1102.         ldiff = ntohl(tp->acknum) - s->seqnum; /* current - prev ack*/
  1103.         if (ldiff < 0)            /* ack out of bounds */
  1104.             {
  1105.             outs("ACK is "); outdec(0xffff & (word)ldiff);
  1106.             outs(" bytes before last sent byte\r\n");
  1107.             return (0);        /* ignore it */
  1108.             }
  1109.  
  1110.         limit = s->sdatahwater;        /* last data byte sent */
  1111.         if (s->flags & (tcp_FlagSYN | tcp_FlagFIN))
  1112.             limit++;        /* count unack'd SYN or FIN */
  1113.     
  1114.         if (ldiff > limit)        /* if ACK out of window */
  1115.             {
  1116.             outs("ACK is "); outdec(0xffff & (word)ldiff);
  1117.             outs(" bytes beyond last sent byte\r\n");
  1118.             return (0);    /* ignore segment */
  1119.             }
  1120.         tcp_status = CONNECTION_REJECTED;
  1121.         s->rdatalen = 0;
  1122.         s->sdatalen = s->sdatahwater;
  1123.         if (s->sock_mode & TCP_MODE_PASSIVE)
  1124.             {
  1125.             s->state = tcp_StateLISTEN;
  1126.             }
  1127.         else
  1128.             {
  1129.             s->state = tcp_StateCLOSED;
  1130.             tcp_unthread(s);    /* unlink from service queue*/
  1131.             }
  1132.         return (0);        /* say session is closed */
  1133.         }
  1134.  
  1135.         /* Update retransmission timeout, Van Jacobson's algorithm */
  1136.     if (flags & tcp_FlagACK)         /* ACK to something */
  1137.         {
  1138.         int i;
  1139.         longword their_ack;
  1140.  
  1141.         their_ack = ntohl(tp->acknum);    /* working copy */
  1142.  
  1143.         for (i = s->sendqnum - 1; i >= 0; i--)
  1144.             if ((s->notimeseq <= their_ack) &&   /* not a resend */
  1145.                 (s->sendq[i].next_seq <= their_ack))  /* in range */
  1146.                 {              /* get new s->rto */
  1147.                 new_rto(s, (int)(set_ttimeout(0) - 
  1148.                         s->sendq[i].time_sent));
  1149.                     /* move down remaining sendq entries*/
  1150.                 bcopyff(&s->sendq[i], &s->sendq[0],
  1151.                         (s->sendqnum - (i + 1)) * 
  1152.                         sizeof (struct sendqstat));
  1153.                 s->sendqnum -= i + 1;    /* adjust free slots*/
  1154.                 break;
  1155.                 }
  1156.         }        /* end of timer update from received ACK */
  1157.  
  1158.  
  1159.     /* Here starts the main TCP state machine */
  1160.     switch (s->state) {
  1161.  
  1162.     case tcp_StateLISTEN:            /* accepting SYNs */
  1163.     /* Passive open. Sit and wait for an arriving SYN, sync to it and */
  1164.     /* respond with an ACK to their SYN plus a SYN of our own. */
  1165.     /* Reset the session if SYN is absent */
  1166.         if (flags & tcp_FlagSYN)
  1167.         {
  1168.         if (kdebug != 0) outs("LISTEN\r\n");
  1169.         if (arp_resolve(ntohl(ip->source), &s->hisethaddr[0]) == 0)
  1170.             return (0);    /* failed to get host MAC address */
  1171.         s->hisport = ntohs(tp->srcPort);
  1172.         s->hisaddr = ntohl(ip->source);
  1173.                     /* if not on this network */
  1174.         if ((s->hisaddr ^ my_ip_addr) & sin_mask)
  1175.             s->mss = (mss > 536)? 536: mss;    /* non-fragmentable */
  1176.         s->flags = tcp_FlagSYN | tcp_FlagACK;
  1177.         s->acknum = ntohl(tp->seqnum) + 1;   /* sync to their SYN */
  1178.         s->send_kind = tcp_SENDNOW;         /* reply immediately */
  1179.         s->state = tcp_StateSYNREC;
  1180.         s->timeout = set_timeout(tcp_TIMEOUT);
  1181.         s->keepalive = set_timeout(100); /* keepalive */
  1182.         }
  1183.     else
  1184.             tcp_rst(ip, tp);        /* send a RST */
  1185.         break;
  1186.  
  1187.     case tcp_StateSYNSENT:            /* we sent a SYN */
  1188.     /* We have sent a SYN from either active or passive opens. */
  1189.     /* Our s->seqnum points at it (no displacement yet). No SYN */
  1190.     /* has been received yet so s->acknum means nothing so far. */
  1191.     /* Get SYN+ACK to our SYN or get just SYN from the remote host. */
  1192.    
  1193.     if (kdebug != 0) outs("SYN_SENT\r\n");
  1194.     if ((flags & tcp_FlagSYN) == 0)        /* they did not send SYN */
  1195.         {
  1196.             tcp_rst(ip, tp);        /* send a RST */
  1197.         break;
  1198.         }
  1199.  
  1200.     if (flags & tcp_FlagACK)        /* if they included an ACK */
  1201.         if (ntohl(tp->acknum) == s->seqnum + 1)
  1202.             {                 /* for our SYN */
  1203.             s->state = tcp_StateESTAB;
  1204.             s->timeout = 0;            /* do not time out */
  1205.             s->seqnum++;            /* count our SYN */
  1206.             s->acknum = ntohl(tp->seqnum) + 1; /* sync to them */
  1207.             s->flags = tcp_FlagACK;        /* ACK their SYN */
  1208.             s->send_kind = tcp_SENDNOW;
  1209.             tcp_processdata(s, tp, len);    /* if sent data */
  1210.             if (kdebug != 0) outs("ESTABLISHED\r\n");
  1211.             break;
  1212.             }
  1213.         else            /* simultaneous open or wrong ACK */
  1214.             {
  1215.             tcp_rst(ip, tp);    /* reset the connection */
  1216.             break;
  1217.             }
  1218.  
  1219.     /* bare SYN arrived, no ACK yet */
  1220.     s->acknum = ntohl(tp->seqnum) + 1;        /* sync to them */
  1221.     s->flags = tcp_FlagSYN  + tcp_FlagACK;        /* ACK their SYN */
  1222.     s->timeout = set_timeout(tcp_TIMEOUT);
  1223.     s->state = tcp_StateSYNREC;
  1224.     s->send_kind = tcp_SENDNOW;    /* reply immediately */
  1225.     break;
  1226.  
  1227.     case tcp_StateSYNREC:
  1228.     /* Received a SYN from active or passive opens, and it has been ACK'd. */
  1229.     /* Our s->acknum points one beyond it. We have sent a SYN but we are */
  1230.     /* awaiting an ACK to it. */
  1231.  
  1232.     if (kdebug != 0) outs("SYN_RECVD\r\n");
  1233.     if ((flags & tcp_FlagACK) &&             /* an ACK */
  1234.         (ntohl(tp->acknum) == (s->seqnum + 1)))    /* to our SYN */
  1235.         {
  1236.         s->flags = tcp_FlagACK;
  1237.         s->seqnum++;            /* move beyond our SYN */
  1238.         tcp_processdata(s, tp, len);    /* gather received data */
  1239.         s->send_kind = tcp_SENDNOW;    /* reply immediately */
  1240.         s->state = tcp_StateESTAB;
  1241.  /*           s->timeout = 0;             /* do not timeout */
  1242.         }
  1243.     break;
  1244.  
  1245.  
  1246.     case tcp_StateESTAB:
  1247.     /* Both sides have exchanged and ACK'd their SYNs. Proceed to exchange */
  1248.     /* data in both directions. An ACK is required on each packet. */
  1249.  
  1250.     if ((flags & tcp_FlagACK) == 0)
  1251.         break;             /* they must ack somthing*/
  1252.  
  1253.                 /* process their ack value in packet */
  1254.     /* ldiff is their ack number minus our oldest sent seq number */
  1255.     /* ldiff < 0 their ack preceeds this window and is an old packet. */
  1256.     /* ldiff == 0 is typically an ACK and might represent their timeout.*/
  1257.     /* ldiff > 0 exceeding the window (our oldest seqnum + sent data */
  1258.     /* s-sdatalen) means pkt is out of order or a window probe (likely)*/
  1259.     /* just ACK to keep their timers happy. */
  1260.     /* However, in all cases grab any useful data for us. */        
  1261.     ldiff = ntohl(tp->acknum) - s->seqnum; /* current ACK - oldest sent */
  1262.     if (ldiff > 0 && ldiff <= s->sdatalen)
  1263.         {             /* their ack is in our window*/
  1264.         s->seqnum += ldiff;    /* update ACK'd file pointer */
  1265.         diff = (int)ldiff;    /* 16 bits, bigger than our window */
  1266.         s->sdatalen -= diff;    /* deduct amount ACK'd data */
  1267.         if ((s->sdatahwater -= diff) < 0) /* less old, sent data */
  1268.             s->sdatahwater = 0;
  1269.                     /* move down residual in send buf */
  1270.          bcopyff(&s->sdata[diff], s->sdata, s->sdatalen);
  1271.  
  1272.         if (s->loss_count >= 3)        /* if fast retransmit */
  1273.             s->cwindow = s->ssthresh; /* shrink congestion wind*/
  1274.         s->loss_count = 0;        /* end of lost packets */
  1275.  
  1276.         if (s->cwindow < s->ssthresh)    /* VJ congestion */
  1277.             s->cwindow += s->mss;    /* fast opening */
  1278.         else                /* additive increase */
  1279.              s->cwindow += s->mss / (s->cwindow / s->mss);
  1280.         if (s->cwindow > TCP_SBUFSIZE)
  1281.             s->cwindow = TCP_SBUFSIZE;
  1282.         }
  1283.  
  1284.     s->flags = tcp_FlagACK;            /* tell them thanks */
  1285.  
  1286.     /* Case of ldiff < 0 means it's an old packet so our last response
  1287.        must have been lost. ACK it to reinform the remote host. */
  1288.  
  1289.     if (ldiff)            /* data of any kind, respond */
  1290.         s->send_kind = tcp_SENDNOW;    /* schedule transmission */
  1291.  
  1292.             /* process incoming data, get s->window */
  1293.     data_for_us = tcp_processdata(s, tp, len);  /* get data for us */
  1294.  
  1295.         /* if we have data to be sent and they have some space */
  1296.     if ((s->sdatalen - s->sdatahwater) && (s->window > 0))
  1297.         s->send_kind = tcp_SENDNOW;    /* schedule transmission */
  1298.  
  1299.     if (s->window)            /* if window is now open */
  1300.         s->winprobe = 0;    /* end window probing, if any */
  1301.  
  1302.     /* They did not ACK more of our sent data, we sent data needing ACK, 
  1303.        no window opening, and they sent us no data. These are congestion
  1304.        loss criteria rather than just a window update. */
  1305.     
  1306.     if ((ldiff == 0) && s->sdatahwater && (s->window <= s->old_window)
  1307.         && (data_for_us == 0))
  1308.         {
  1309.         s->loss_count++;    /* count lost packet */
  1310.         if (s->loss_count == 3)
  1311.             {
  1312.             word temp_hwater;
  1313.  
  1314.             if (kdebug) outs(" Congestion loss\r\n");
  1315.                 /* do Van Jacobson congestion avoidance */
  1316.                 /* don't time below notimedseq seq number */
  1317.             s->notimeseq = s->seqnum + s->sdatahwater;
  1318.             s->sendqnum = 0;      /* flush send-timer queue */
  1319.             s->ssthresh = s->cwindow >> 1; /* drop back */
  1320.             s->cwindow = s->mss;    /* one segment only */
  1321.             temp_hwater = s->sdatahwater;
  1322.             s->sdatahwater = 0;    /* resend oldest segment */
  1323.             tcp_send(s);        /* but only that segment */
  1324.             s->sdatahwater = temp_hwater;
  1325.             s->cwindow = s->ssthresh + 3 * s->mss; /* count ACKs*/
  1326.             }
  1327.         if (s->loss_count > 3)    /* trailing/extra ACKs, count space */
  1328.             s->cwindow += s->mss;
  1329.         }
  1330.  
  1331.     s->old_window = s->window;    /* remember as old remote window */
  1332.  
  1333.  
  1334.     if (flags & tcp_FlagFIN)        /* they said FIN */
  1335.         {
  1336.         if (kdebug != 0) outs("FIN received\r\n");
  1337.         if (s->sdatalen)        /* we have more to send */
  1338.             s->state = tcp_StateCLOSWT;
  1339.         else
  1340.             {        /* we have nothing more to send */
  1341.                      /* say FIN to them too */
  1342.              s->flags |= tcp_FlagFIN;
  1343.             s->state = tcp_StateLASTACK; /* nothing more from us*/
  1344.             }
  1345.         s->acknum++;            /* count their FIN */
  1346.         s->send_kind = tcp_SENDNOW;    /* reply immediately */
  1347.         }
  1348.     break;
  1349.  
  1350.     case tcp_StateCLOSWT:
  1351.         /* Have received and ACK'd their FIN. Our s->acknum points at it. */
  1352.     /* Obtain last minute ACKs of our data, send our FIN with our */
  1353.     /* s->seqnum pointing one byte before our FIN. */
  1354.  
  1355.     if (kdebug != 0) outs("CLOSEWT\r\n");
  1356.     ldiff = ntohl(tp->acknum) - s->seqnum; /* current - prev ack */
  1357.     if (ldiff > 0 && ldiff <= s->sdatalen) /* their ack is in our window*/
  1358.         {
  1359.         s->seqnum += ldiff;    /* update ACK'd file counter */
  1360.         diff = (int)ldiff;    /* 16 bits, more than our window */
  1361.         s->sdatalen -= diff;    /* deduct amount ACK'd */
  1362.         if ((s->sdatahwater -= diff) < 0) /* less old, sent data */
  1363.             s->sdatahwater = 0;
  1364.         bcopyff(&s->sdata[diff], s->sdata, s->sdatalen);
  1365.         }                /* move residual */
  1366.     s->send_kind = tcp_SENDNOW;    /* reply immediately */
  1367.     s->flags = tcp_FlagACK;        /* ACK the reception */
  1368.     if (s->sdatalen <= 0)
  1369.         {
  1370.         s->flags |= tcp_FlagFIN;    /* say no more data */
  1371.         s->state = tcp_StateLASTACK;    /* get their ACK */
  1372.         }
  1373.     break;
  1374.  
  1375.     case tcp_StateFINWT1:
  1376.     /* Have sent our FIN, our s->seqnum points at it. */
  1377.     /* Expect to receive either an ACK for the FIN, or the remote FIN, */
  1378.     /* or a remote FIN and and ACK for our FIN. */
  1379.  
  1380.     if (kdebug != 0) outs("FINWAIT-1\r\n");
  1381.     s->sdatalen = s->sdatahwater; /* we can't send new from here */
  1382.     if (flags & tcp_FlagACK)
  1383.         {
  1384.         ldiff = ntohl(tp->acknum) - s->seqnum; /* current - prev ack*/
  1385.         if (ldiff > 0 && ldiff <= s->sdatalen)
  1386.             {        /* their ack is in our window */
  1387.             s->seqnum += ldiff;    /* update ACK'd file counter */
  1388.             diff = (int)ldiff;    /* 16 bits, more than our window */
  1389.             s->sdatalen -= diff;    /* deduct amount ACK'd */
  1390.             if ((s->sdatahwater -= diff) < 0) /* less old */
  1391.                 s->sdatahwater = 0;
  1392.             bcopyff(&s->sdata[diff], s->sdata, s->sdatalen);
  1393.             }                /* move residual */
  1394.                 /* process our data in the packet */
  1395.         tcp_processdata(s, tp, len);
  1396.         
  1397.                 /* if this ACKs our FIN */
  1398.         if (ntohl(tp->acknum) == s->seqnum + 1)
  1399.             {
  1400.             s->seqnum++;        /* count our FIN */
  1401.             s->state = tcp_StateFINWT2;
  1402.             }
  1403.         }        /* fall through to look at their FIN bit */
  1404.  
  1405.  
  1406.     if (flags & (tcp_FlagFIN || tcp_FlagACK) == 
  1407.                     (tcp_FlagFIN || tcp_FlagACK))
  1408.         {
  1409.         if (kdebug != 0) outs("FIN received\r\n");
  1410.         s->acknum++;        /* ACK their FIN */
  1411.         s->flags = tcp_FlagACK;
  1412.         s->send_kind = tcp_NOSEND;
  1413.  
  1414.         /* if our FIN has been ACK'd then do timed wait */
  1415.         /* else go to CLOSING to await that ACK */
  1416.         if (ntohl(tp->acknum) < s->seqnum)    /* not ACK'd yet */
  1417.             {
  1418.             s->timeout = set_timeout(3);
  1419.             s->state = tcp_StateCLOSING;
  1420.             tcp_send(s);
  1421.             }
  1422.         else
  1423.             {    /* FINs have been ACK'd, we are done */
  1424.             /* state TIMEWT would be next if there were
  1425.                something to drive it, but there isn't */
  1426.             tcp_send(s);
  1427.             s->state = tcp_StateCLOSED;     /* no 2 msl */
  1428.             tcp_unthread(s);
  1429.             }
  1430.         }
  1431.     break;
  1432.  
  1433.     case tcp_StateFINWT2:
  1434.     /* Have sent our FIN and received an ACK to it. We have not */
  1435.     /* yet received a FIN from the remote side so wait for it here. */
  1436.     /* When that FIN arrives send and ACK and do TIMEWT (empty here).*/
  1437.     /* Our s->seqnum points at our FIN, their tp->acknum points to our */
  1438.     /* FIN too, so these two are equal */
  1439.  
  1440.     if (kdebug != 0) outs("FINWAIT-2\r\n");
  1441.     s->sdatalen = s->sdatahwater;    /* cannot send from here */
  1442.     if (flags & tcp_FlagFIN)
  1443.         if ((ntohl(tp->acknum) == s->seqnum) &&
  1444.             (ntohl(tp->seqnum) >= s->acknum))
  1445.             {
  1446.             s->acknum++;        /* ACK their FIN */
  1447.             s->flags = tcp_FlagACK;
  1448.             tcp_send(s);        /* send last ACK */
  1449.             /* state TIMEWT would be next if there were
  1450.                something to drive it, but there isn't */
  1451.             s->state = tcp_StateCLOSED;     /* no 2 msl */
  1452.             tcp_unthread(s);
  1453.             }
  1454.     break;
  1455.  
  1456.     case tcp_StateCLOSING:
  1457.         /* Have sent our FIN, our s->seqnum points at it, but it has */
  1458.     /* not been ACK'd. Thus their tp->acknum < our s->seqnum */
  1459.     /* Have received their FIN, our s->acknum points at it, and */
  1460.     /* we have sent an ACK for their FIN. */
  1461.     /* Get an ACK to our FIN and then go to TIMEWT (empty here). */
  1462.  
  1463.     if (kdebug != 0) outs("CLOSING\r\n");
  1464.         if (flags & tcp_FlagACK)
  1465.         if (ntohl(tp->acknum) == s->seqnum)
  1466.             {
  1467.             /* state TIMEWT would be next if there were
  1468.                something to drive it, but there isn't */
  1469.             s->state = tcp_StateCLOSED;     /* no 2 msl */
  1470.             tcp_unthread(s);
  1471.             }
  1472.     break;
  1473.  
  1474.     case tcp_StateLASTACK:
  1475.     /* Have received and ACK'd their FIN, so our s->acknum points at it. */
  1476.     /* Have sent a FIN to them with our s->seqnum one less than it. */
  1477.     /* Here we get their ACK to our FIN and exit the protocol stack. */
  1478.  
  1479.     if (kdebug != 0) outs("LAST_ACK\r\n");
  1480.     if (flags & tcp_FlagACK)        /* an ACK to our FIN */
  1481.         if (ntohl(tp->acknum) == s->seqnum + 1)
  1482.             {
  1483.             s->state = tcp_StateCLOSED;     /* no 2 msl */
  1484.             tcp_unthread(s);
  1485.             break;
  1486.             }
  1487.     /* Get here if they lost our ACK + FIN pkts. Resend both */
  1488.     if (flags & tcp_FlagFIN)    
  1489.         {
  1490.         s->flags = tcp_FlagACK | tcp_FlagFIN;
  1491.         s->send_kind = tcp_SENDNOW;    /* reply immediately */
  1492.         }
  1493.     break;
  1494.  
  1495.     case tcp_StateTIMEWT:
  1496.     if (kdebug != 0) outs("TIMED_WAIT\r\n");
  1497.     s->state = tcp_StateCLOSED;         /* no 2 msl */
  1498.     tcp_unthread(s);
  1499.     break;
  1500.     }                        /* end switch */
  1501.     return (1);                    /* success */
  1502. }
  1503.  
  1504. /*
  1505.  * Process the data for us in an incoming packet.
  1506.  * Called from all states where incoming data can be received: established,
  1507.  * fin-wait-1, fin-wait-2
  1508.  * len is the length of TCP header + data
  1509.  * Sets s->send_kind if transmission is needed.
  1510.  * Returns int 0 for nothing needs doing, > 0 for data accepted,
  1511.  * and < 0 for data rejected.
  1512.  */
  1513. static int
  1514. tcp_processdata(tcp_Socket *s, tcp_Header FAR *tp, int len)
  1515. {
  1516.     register int diff, x;
  1517.     long ldiff;                    /* signed */
  1518.     word numoptions, opt_temp;
  1519.     byte FAR * dp, FAR * options;
  1520.  
  1521.     if (s == NULL || tp == NULL) return (0);    /* failure */
  1522.  
  1523.     s->window = ntohs(tp->window);
  1524.     if (s->window > 0x7fff)            /* SGI 64KB window nonsense?*/
  1525.         s->window = 0x7fff;        /* yes, cut window to 32KB */
  1526.  
  1527.     ldiff = ntohl(tp->seqnum) - s->acknum;    /* new data, signed long */
  1528.     /* 
  1529.        ldiff is normally zero, meaning their first data byte is what we
  1530.        expect next. A negative value means they sent some old data,
  1531.        a positive value means they are starting beyond/future of what
  1532.        we expect (creating a hole).
  1533.     */
  1534.     if (ntohs(tp->flags) & tcp_FlagSYN)
  1535.         ldiff++;            /* SYN counts as one unit */
  1536.     diff = (int)ldiff;            /* 16 bit version */
  1537.                         /* find the data portion */
  1538.     x = tcp_GetDataOffset(tp) << 2;        /* quadword to byte count */
  1539.     dp = (byte FAR *)tp + x;        /* points to data */
  1540.  
  1541.                         /* process those options */
  1542.     if (numoptions = x - sizeof(tcp_Header))
  1543.         {
  1544.         options = (byte FAR *)tp + sizeof(tcp_Header);
  1545.         while (numoptions-- > 0)
  1546.             switch (*(options++) & 0xff)
  1547.                 {
  1548.                 case 0: numoptions = 0;    /* end of options */
  1549.                 case 1:    break;        /* nop */
  1550.  
  1551.                   /* we are very liberal on MSS stuff */
  1552.                 case 2: if (*options == 4)    /* length */
  1553.                         {
  1554.                 opt_temp = ntohs(* (word FAR *)(&options[1]));
  1555.                         if (opt_temp < s->mss)
  1556.                             s->mss = opt_temp;
  1557.                         }
  1558.                     numoptions -= *options - 1;
  1559.                     options += *options - 1;
  1560.                       break;
  1561.                 default: break;
  1562.                 }    /* end of switch and while */
  1563.         }            /* end of if */
  1564.                         /* done option processing */
  1565.  
  1566.     len -= x;            /* remove the TCP header */
  1567.  
  1568.     if ((len != 0) || (diff != 0))    /* data present or keepalive */
  1569.         s->send_kind = tcp_SENDNOW; /* send an ACK for any data */
  1570.  
  1571.     if (len <= 0)            /* amount of data in this packet */
  1572.         return (len);        /* no new data, 0 = must be an ACK */
  1573.  
  1574.                 /* skip already received bytes */
  1575.                 /* diff = last rcv'd byte - new start*/
  1576.     if (diff > 0)        /* if data starts beyond our last ACK */
  1577.         return (len);    /*  then ignore the data */    
  1578.     dp -= diff;        /* move to new data in packet */
  1579.     len += diff;        /* length of new data in packet */
  1580.                  /* limit receive size to our window */
  1581.     if (s->rdatalen < 0)
  1582.         s->rdatalen = 0; /* sanity check */
  1583.     if (len > (x = TCP_RBUFSIZE - s->rdatalen))
  1584.             len = x;        /* space available only */
  1585.     if (len <= 0)                /* old packet */
  1586.         return (1);            /* say some data for us */
  1587.  
  1588.     bcopyff(dp, &s->rdata[s->rdatalen], len);
  1589.     s->rdatalen += len;
  1590.     s->acknum += len;         /* new ack begins at end of data */
  1591.     return (len);                /* success */
  1592. }
  1593.  
  1594. /* Measure elapsed time, given the observed round trip time (rtt) in tics
  1595.    calculate new s->rto, smoothed average and standard deviation */
  1596. void
  1597. new_rto(tcp_Socket * s, int rtt)
  1598. {
  1599.     register int rtt_error;
  1600.  
  1601. /* s->vj_sa is 8 * (smoothed average round trip time), Bios tics */
  1602. /* s->vj_sd is 8 * (std deviation from smoothed average), Bios tics */
  1603. /* rtt is segment ACK delay, Bios tics */
  1604.     
  1605.     if (rtt < 0)            /* delay time sanity, midnight fails*/
  1606.         return;
  1607.     rtt_error = (rtt << 3) - s->vj_sa;    /* 8 * error from avg */
  1608.     s->vj_sa += (rtt_error >> 3);    /* 8 * smoothed avg delay time */
  1609.     if (rtt_error < 0)        /* want magnitude of the error */
  1610.         rtt_error = - rtt_error;
  1611.     rtt_error -= (s->vj_sd >> 2);
  1612.     s->vj_sd += rtt_error;             /* 8 * smoothed std dev */
  1613.                 /* round trip timeout: avg + 4 std_dev */
  1614.     s->rto = ((s->vj_sa >> 2) + s->vj_sd) >> 1;
  1615.     if (s->rto > 60 * 18)        /* PC clock ticks, 18.2/sec */
  1616.         s->rto = 60 * 18;     /* 60 sec cap */
  1617.     if (s->rto < 2)
  1618.         s->rto = 2;        /* floor of two Bios tics */
  1619.     krto(s->rto);            /* tell Kermit main body */
  1620.     if (kdebug)            /* show round trip time stats */
  1621.         {
  1622.         outs("time="); outdec((int)(0x7fffL &  
  1623.                 (set_ttimeout(0) - start_time)));
  1624.         outs(" rtt="); outdec(rtt);
  1625.         outs(" avg="); outdec(s->vj_sa >> 3);
  1626.         outs(" std_dev="); outdec(s->vj_sd >> 3);
  1627.         outs(" rto="); outdec(s->rto);
  1628.         outs("\r\n");
  1629.         }
  1630. }
  1631.  
  1632. /* TCP ACK has been lost. Reduce congestion window and backoff s->rto. */
  1633. void
  1634. lost_ack(tcp_Socket * s)
  1635. {
  1636.                 /* don't time below notimedseq seq number */
  1637.     s->notimeseq = s->seqnum + s->sdatahwater;
  1638.     s->sendqnum = 0;       /* flush send queue timing information */
  1639.     s->sdatahwater = 0;    /* make all bytes be new to resend all */
  1640.                 /* do Van Jacobson congestion reduction */
  1641.     s->ssthresh = s->cwindow >> 1; /* new congestion threshold */
  1642.     s->cwindow = s->mss;    /* congestion window to one full pkt */
  1643.     s->loss_count = 0;    /* fast retransmit ACK pkt loss counter */
  1644.  
  1645.     if (s->rto == 18 * 60)    /* have reached threshold of pain, quit */
  1646.         {
  1647.         tcp_close(s);
  1648.         if (kdebug) 
  1649.            outs(" Closing session from excessive timeout delay\r\n");
  1650.         return;
  1651.         }
  1652.     if ((s->rto += s->rto) > 18 * 60)    /* double timeout */
  1653.         s->rto = 18 * 60;        /* 1 minute max */
  1654.     krto(s->rto + 5 * 18); /* tell Kermit main body 5 sec minimum */
  1655. }
  1656.  
  1657. /*
  1658.  * Format and send an outgoing segment.
  1659.  * Global word do_window_probe != 0 can initiate a window probe rather than 
  1660.  * a regular data transmission.
  1661.  * Sets idle timeout s->idle after each call.
  1662.  */
  1663. static int
  1664. tcp_send(tcp_Socket *s)
  1665. {
  1666.     tcp_PseudoHeader ph;
  1667.     struct pkt
  1668.         {
  1669.         in_Header in;
  1670.         tcp_Header tcp;
  1671.         word maxsegopt[2];
  1672.         } register *pkt;
  1673.     byte *dp;
  1674.     register int senddatalen, userdata;
  1675.     int sendpktlen, their_window, sendqindex;
  1676.  
  1677.     if (s == NULL) return (0);        /* failure */
  1678.  
  1679.     s->send_kind = tcp_NOSEND;    /* clear flag for tcp_retrasmitter */
  1680.  
  1681.     senddatalen = s->sdatalen - s->sdatahwater;    /* unsent bytes */
  1682.     if (senddatalen < 0)                /* sanity check */
  1683.         senddatalen = 0;
  1684.  
  1685.     if (s->flags & tcp_FlagSYN)        /* no s->window at SYN stage */
  1686.         goto send_packet;
  1687.  
  1688.     /* Closed window probe */
  1689.  
  1690.     if ((s->flags & tcp_FlagFIN) == 0)    /* no window probes on FIN */
  1691.         if (do_window_probe || ((s->window == 0) && senddatalen))
  1692.         {
  1693.         do_window_probe = 0;        /* clear trigger flag */
  1694.         if (s->winprobe)        /* if timing closed window */
  1695.             {
  1696.             if (chk_timeout(s->winprobe) != TIMED_OUT)
  1697.                 return (0);     /* can't send, still waiting*/
  1698.             else
  1699.                 if ((s->probe_wait += s->probe_wait) > 60*18)
  1700.                     s->probe_wait = 60 * 18;
  1701.             }
  1702.         else
  1703.             {
  1704.             s->probe_wait = s->rto << 1; /* initial probe interval */
  1705.             s->winprobe = set_ttimeout(s->probe_wait);
  1706.             return (0);        /* wait for timer to fire */
  1707.             }
  1708.         s->winprobe =  set_ttimeout(s->probe_wait); /* repeat probe */
  1709.         s->notimeseq = s->seqnum + s->sdatahwater; /* no timing */
  1710.         s->sendqnum = 0;           /* flush send queue timing */
  1711.         do_window_probe = 1;        /* say doing probe */
  1712.         their_window = 1;        /* pretend one open byte */
  1713.         senddatalen = 1;        /* for passive keepalive */
  1714.                 /* tell Kermit main body 5 sec minimum */
  1715.         krto(s->probe_wait + 5 * 18);
  1716.         if (kdebug) outs(" Window probe\r\n");
  1717.         goto send_packet;        /* bypass congestion window */
  1718.         }
  1719.  
  1720.     /* Congestion avoidance */
  1721.  
  1722.     /* their announced window minus bytes sent (unACK'd) from here */
  1723.     if ((their_window = s->window - s->sdatahwater) <= 0)
  1724.         if ((s->flags & tcp_FlagFIN) == 0)    /* FIN goes out */
  1725.             return (0);    /* can't send, no remote space */
  1726.  
  1727.     if (senddatalen > their_window)        /* do not exceed their window */
  1728.         senddatalen = their_window;
  1729.     
  1730.     userdata = s->cwindow - (s->cwindow % s->mss);    /* truncate cwindow*/
  1731.     userdata -= s->sdatahwater;        /* minus bytes already sent */
  1732.  
  1733.     /* if new data  > congestion window available, limit sending */
  1734.     if (senddatalen > userdata)
  1735.         if ((senddatalen = userdata) <= 0)
  1736.              {     /* safety in case cwindow shrinks on us */
  1737.             s->idle = set_ttimeout(s->rto); /* inactivity timer */
  1738.             if ((s->flags & tcp_FlagFIN) == 0) /* FIN goes out */
  1739.                 return (0); /* cannot send, congest wind full */
  1740.             }
  1741.  
  1742.     /* Now we know how many bytes can be sent. Prepare a standard
  1743.     IP header and send packets */
  1744.  
  1745. send_packet:
  1746.     sendqindex = s->sendqnum;    /* number of existing queue entries */
  1747.  
  1748.     while (odi_busy()) ;    /* wait for structures to become free */
  1749.  
  1750.     pkt = (struct pkt *)eth_formatpacket(&s->hisethaddr[0], TYPE_IP);
  1751.     pkt->in.hdrlen_ver = 0x45;    /* version 4, hdrlen 5 */
  1752.     pkt->in.tos = 0;        /* type of service, normal */
  1753.     pkt->in.frag = 0;        /* fragment, none, allowed */
  1754.         pkt->in.ttl = 60;        /* seconds */
  1755.     pkt->in.proto = TCP_PROTO;
  1756.            pkt->in.source = htonl(my_ip_addr);
  1757.            pkt->in.destination = htonl(s->hisaddr);
  1758.            ph.src = pkt->in.source;    /* already in network order */
  1759.            ph.dst = pkt->in.destination;
  1760.            ph.mbz = 0;
  1761.            ph.protocol = TCP_PROTO;
  1762.     pkt->tcp.srcPort = htons(s->myport);
  1763.     pkt->tcp.dstPort = htons(s->hisport);
  1764.     pkt->tcp.acknum = htonl(s->acknum);
  1765.     pkt->tcp.window = htons(TCP_RBUFSIZE - s->rdatalen);
  1766.     pkt->tcp.urgentPointer = 0;  /* not used in this program */
  1767.  
  1768.     while (1 == 1)
  1769.         {
  1770.         userdata = 0;            /* user data sent in this pkt*/
  1771.         dp = (byte *)pkt->maxsegopt;
  1772.                 
  1773.         if (senddatalen)        /* set PSH bit on data pkts */
  1774.             s->flags |= tcp_FlagPUSH;
  1775.         else
  1776.             s->flags &= ~tcp_FlagPUSH;
  1777.  
  1778.                     /* tcp header material */
  1779.         if (do_window_probe)            /* window probing */
  1780.             {
  1781.                 pkt->tcp.seqnum = htonl(s->seqnum - 1); /* old data */
  1782.             s->flags &= ~tcp_FlagPUSH;        /* no PUSH */
  1783.             }
  1784.         else
  1785.                 pkt->tcp.seqnum = htonl(s->seqnum + s->sdatahwater);
  1786.  
  1787.             pkt->tcp.checksum = 0;
  1788.                pkt->tcp.flags = htons(s->flags | 0x5000); /* 5 quadbytes */
  1789.                 sendpktlen = sizeof(tcp_Header) + sizeof(in_Header);
  1790.  
  1791.                 /* do options if this is our first packet */
  1792.             if (s->flags & tcp_FlagSYN)
  1793.             {                /* 5 + 1 quadbytes */
  1794.             pkt->tcp.flags = htons(s->flags | (0x5000 + 0x1000));
  1795.             pkt->maxsegopt[0] = 0x0402;
  1796.             pkt->maxsegopt[1] = htons(s->mss);
  1797.             sendpktlen += 4;
  1798.             dp += 4;        /* pointer to data bytes */
  1799.             }
  1800.         else
  1801.             {            /*  not a SYN packet */
  1802.             if (senddatalen > 0)    /* handle packets with data */
  1803.                 {        /* limit pkt to mss */
  1804.                     if (senddatalen > (int)s->mss)
  1805.                         userdata = (int)s->mss;
  1806.                 else
  1807.                         userdata = senddatalen;
  1808.                 if (do_window_probe == 0)
  1809.                     bcopyff(&s->sdata[s->sdatahwater],
  1810.                      dp, userdata);
  1811.                         sendpktlen += userdata; /* len of this pkt */
  1812.                 }
  1813.                 }
  1814.  
  1815.                     /* Internet Packet header */
  1816.             pkt->in.identification = htons(++ip_id); /* pre-inc req'd */
  1817.             pkt->in.checksum = 0;
  1818.             pkt->in.length = htons(sendpktlen);
  1819.             pkt->in.checksum = ~checksum(&pkt->in, sizeof(in_Header));
  1820.  
  1821.             /* compute TCP checksum, ph is pseudo header pointer */
  1822.             ph.length = htons(sendpktlen - sizeof(in_Header));
  1823.             ph.checksum = checksum(&pkt->tcp, 
  1824.                 sendpktlen - sizeof(in_Header));
  1825.             pkt->tcp.checksum = ~checksum(&ph, sizeof(ph));
  1826.  
  1827.     /* Send the packet before recording timeout information so the
  1828.        time of slow transmissions (serial) don't confuse s->rto from
  1829.        variable length packets. Failure to transmit will leave
  1830.        s->send_kind at tcp_SENDNOW, and hence cause retransmission. */
  1831.  
  1832.         if (eth_send(htons(pkt->in.length)) == 0) /* send packet */
  1833.             {                /* here if failed */
  1834.             if (kdebug) outs(" Failed to put packet on wire\r\n");
  1835.             s->send_kind = tcp_SENDNOW;    /* just to be sure */
  1836.             do_window_probe = 0;
  1837.               return (0);            /* sending failed */
  1838.             }
  1839.  
  1840.         if (do_window_probe)
  1841.             {
  1842.             do_window_probe = 0;     /* finished construction */
  1843.             break;            /* no per-packet timing */
  1844.             }
  1845.         s->sdatahwater += userdata;    /* move have-sent-once marker */
  1846.                         /* must be before timing */
  1847. /* Remember each TCP segments's ending sequence number and time of 
  1848.    transmission in sendq so that round trip time can be measured per 
  1849.    TCP segment, and so that we can timeout waiting for an ACK to sent data.
  1850.    If there are more outstanding segments than sendq entries reuse the last
  1851.    sendq slot for the most recent segment. No sendq entry created if no data.
  1852. */
  1853.         if (userdata || (s->flags & (tcp_FlagSYN | tcp_FlagFIN)))
  1854.             {
  1855.                         /* when sent, for rtt */
  1856.             s->sendq[sendqindex].time_sent = set_ttimeout(0);
  1857.                         /* when segment times out */
  1858.             s->sendq[sendqindex].timeout = set_ttimeout(s->rto);
  1859.                         /* seq number of next dgram */
  1860.             s->sendq[sendqindex].next_seq = s->seqnum + 
  1861.                             s->sdatahwater;
  1862.             if (s->flags & tcp_FlagFIN)  /* cover FIN bit too */
  1863.                 s->sendq[sendqindex].next_seq++;
  1864.             sendqindex++;
  1865.             if (sendqindex < NSENDQ - 1)    /* next slot open? */
  1866.                 s->sendqnum = sendqindex;    /* yes */
  1867.             else
  1868.                 sendqindex--;        /* no, reuse last */
  1869.             }
  1870.  
  1871.         senddatalen -= userdata;    /* qty user data yet to send */
  1872.         if (senddatalen <= 0)        /* if have sent all data */
  1873.             break;
  1874.     while (odi_busy()) ;    /* wait for data structures to become free */
  1875.     }                    /* do next IP packet */
  1876.     s->idle = set_ttimeout(s->rto);        /* inactivity timer */
  1877.     if (s->keepalive)        /* passive open keepalive timer */
  1878.         s->keepalive = set_timeout(100);     /* keepalive */
  1879.     return (1);                /* success */
  1880. }
  1881.  
  1882. /*
  1883.  * Format and send a reset tcp packet
  1884.  */
  1885. int
  1886. tcp_rst(in_Header *his_ip, tcp_Header FAR * oldtcpp)
  1887. {
  1888.     tcp_PseudoHeader ph;
  1889.     struct pkt
  1890.         {
  1891.             in_Header in;
  1892.             tcp_Header tcp;
  1893.         word maxsegopt[2];
  1894.         } register *pkt;
  1895.     eth_address eth_addr;                /* six byte array */
  1896.     register int sendtotlen;            /* length of packet */
  1897.  
  1898.     if (his_ip == NULL || oldtcpp == NULL) return (0);    /* failure */
  1899.  
  1900.                     /* see RFC 793 page 65 for details */
  1901.     oldtcpp->flags = ntohs(oldtcpp->flags);        /* net to local */
  1902.  
  1903.     if (oldtcpp->flags & tcp_FlagRST)        /* if a RST to us */
  1904.         return (0);  
  1905.     if ((oldtcpp->flags & tcp_FlagACK) == 0)
  1906.             oldtcpp->flags = tcp_FlagACK;
  1907.     else
  1908.             oldtcpp->flags = 0;
  1909.     /* get MAC addr */
  1910.      if (arp_resolve(htonl(his_ip->source), ð_addr[0]) == 0)
  1911.         return (0);                /* failed */
  1912.     pkt = (struct pkt *)eth_formatpacket(ð_addr[0], TYPE_IP);
  1913.     sendtotlen = sizeof(tcp_Header) + sizeof(in_Header);
  1914.     pkt->in.length = htons(sendtotlen);
  1915.                     /* TCP header */
  1916.     pkt->tcp.srcPort = oldtcpp->dstPort;
  1917.     pkt->tcp.dstPort = oldtcpp->srcPort;
  1918.     pkt->tcp.seqnum = oldtcpp->acknum;
  1919.     pkt->tcp.acknum = htonl(ntohl(oldtcpp->seqnum) + 1);
  1920.     pkt->tcp.window = 0;
  1921.     pkt->tcp.flags = htons(tcp_FlagRST | oldtcpp->flags | 0x5000);
  1922.     pkt->tcp.checksum = 0;
  1923.     pkt->tcp.urgentPointer = 0;
  1924.                     /* Internet header */
  1925.     pkt->in.hdrlen_ver = 0x45;        /* version 4, hdrlen 5 */
  1926.     pkt->in.tos = 0;
  1927.     pkt->in.identification = htons(++ip_id); /* use pre-inc here */
  1928.     pkt->in.frag = 0;
  1929.     pkt->in.ttl = 60;            /* time to live */
  1930.     pkt->in.proto = TCP_PROTO;
  1931.     pkt->in.checksum = 0;
  1932.     pkt->in.source = his_ip->destination;
  1933.     pkt->in.destination = his_ip->source;
  1934.     pkt->in.checksum = ~checksum(&pkt->in, sizeof(in_Header));
  1935.                         /* compute TCP checksum */
  1936.     ph.src = pkt->in.source;        /* already big endian */
  1937.     ph.dst = pkt->in.destination;
  1938.     ph.mbz = 0;                /* must be zero */
  1939.     ph.protocol = TCP_PROTO;
  1940.     ph.length = htons(sendtotlen - sizeof(in_Header));
  1941.     ph.checksum = checksum(&pkt->tcp, sendtotlen - sizeof(in_Header));
  1942.     pkt->tcp.checksum = ~checksum(&ph, sizeof(ph));
  1943.     return (eth_send(htons(pkt->in.length)));
  1944. }
  1945.  
  1946. /* Handle ICMP Redirects. ICMP processor yields new gateway IP number
  1947.    in "gateway" and pointer to offending IP header which we have sent.
  1948.    Find socket with destination IP address matching the gateway
  1949.    sending us the Redirect message, replace the socket's destination
  1950.    Ethernet address with that of the new gateway (use arp_resolve).
  1951.    For TCP resend the packet, for UDP give up all hope.
  1952. */
  1953. void
  1954. do_redirect(longword gateway, in_Header *ip)
  1955. {
  1956.     register udp_Socket *s_udp;
  1957.     register tcp_Socket *s_tcp;
  1958.     tcp_Header *tp;
  1959.     int len;
  1960.     longword host;
  1961.  
  1962.     len = in_GetHdrlenBytes(ip);
  1963.     tp = (tcp_Header *)((byte *)ip + len);    /* tcp frame pointer */
  1964.     host = ntohl(ip->destination);        /* destination IP */
  1965.  
  1966.     switch(ip->proto)
  1967.         {
  1968.         case TCP_PROTO:        /* active TCP sockets */
  1969.         for (s_tcp = tcp_allsocs; s_tcp != NULL; s_tcp = s_tcp->next)
  1970.             if ((host == s_tcp->hisaddr) &&    /* if same dest IP */
  1971.                 (ntohs(tp->srcPort) == s_tcp->myport))
  1972.                                 /* & port */
  1973.                 {
  1974.                 arp_resolve(gateway, &s_tcp->hisethaddr[0]);
  1975.                 tcp_send(s_tcp);    /* resend the packet */
  1976.                 }
  1977.             break;
  1978.         case UDP_PROTO:            /* active UDP sockets */
  1979.         for (s_udp = udp_allsocs; s_udp != NULL; s_udp = s_udp->next)
  1980.             if ((host == s_udp->hisaddr) &&
  1981.                 (ntohs(tp->srcPort) == s_udp->myport))
  1982.                 arp_resolve(gateway, &s_udp->hisethaddr[0]);
  1983.             break;
  1984.         }
  1985. }
  1986.  
  1987. /* Handle ICMP Source Quench. Increase timeouts as if lost packet.
  1988. */
  1989. void
  1990. do_quench(in_Header *ip)
  1991. {
  1992.     register tcp_Socket *s_tcp;
  1993.     register tcp_Header *tp;
  1994.     int len;
  1995.     longword host;
  1996.  
  1997.     len = in_GetHdrlenBytes(ip);
  1998.     tp = (tcp_Header *)((byte *)ip + len);    /* tcp frame pointer */
  1999.     host = ntohl(ip->destination);        /* destination IP */
  2000.  
  2001.     if (ip->proto != TCP_PROTO)
  2002.         return;
  2003.  
  2004.     for (s_tcp = tcp_allsocs; s_tcp != NULL; s_tcp = s_tcp->next)
  2005.         if ((host == s_tcp->hisaddr) &&        /* if same dest IP */
  2006.             (ntohs(tp->srcPort) == s_tcp->myport))    /* & port */
  2007.             {
  2008.             s_tcp->rto++;        /* one Bios clock tick */
  2009.             s_tcp->ssthresh = 0;    /* return to slow start */
  2010.             s_tcp->cwindow = s_tcp->mss;
  2011.             break;
  2012.             }
  2013. }
  2014.  
  2015. /**********************************************************************
  2016.  * socket functions
  2017.  **********************************************************************/
  2018.  
  2019. /* socket based procedures */
  2020.  
  2021. /*
  2022.  * sock_setmode - set mode bit to true or false
  2023.  */
  2024. int
  2025. sock_setmode(tcp_Socket *s, word mode, word value)
  2026. {
  2027.     if (s == NULL)
  2028.         return (0);
  2029.     if (value == TRUE)
  2030.         s->sock_mode |= mode;
  2031.     else
  2032.         s->sock_mode &= ~mode;
  2033.     return (1);        /* success */
  2034. }
  2035.  
  2036. /*
  2037.  * sock_read - read a socket with maximum n bytes
  2038.  *         - returns count also when connection gets closed
  2039.  */
  2040. int
  2041. sock_read(sock_type *s, byte FAR *dp, int len)
  2042. {
  2043.     register int templen, count;
  2044.     count = 0;
  2045.  
  2046.     if (s == NULL || dp == NULL) return (0);        /* failure */
  2047.     do        {
  2048.         switch (s->tcp.ip_type)
  2049.             {
  2050.             case UDP_PROTO:
  2051.                 templen = udp_read((udp_Socket *)s, dp, len);
  2052.                 break;
  2053.             case TCP_PROTO:
  2054.                 templen = tcp_read((tcp_Socket *)s, dp, len);
  2055.                 if (templen == 0 && 
  2056.                     s->tcp.sisopen == SOCKET_CLOSED)
  2057.                         return (count); /*quit early*/
  2058.                 break;
  2059.             default: return (0);
  2060.             }
  2061.         count += templen;
  2062.         len -= templen;
  2063.             }
  2064.     while (len > 0);
  2065.        return (count);
  2066. }
  2067.  
  2068. /*
  2069.  * sock_fastread - read a socket with maximum n bytes
  2070.  *         - does not busywait until buffer is full
  2071.  */
  2072. int
  2073. sock_fastread(sock_type *s, byte FAR *dp, int len)
  2074. {
  2075.     if (s == NULL)  return (0);        /* failure */
  2076.     switch(s->tcp.ip_type)
  2077.         {
  2078.         case UDP_PROTO:
  2079.             return (udp_read((udp_Socket *)s, dp, len));
  2080.         case TCP_PROTO:
  2081.             return (tcp_read((tcp_Socket *)s, dp, len));
  2082.         default: return (0);
  2083.         }
  2084. }
  2085.  
  2086.  
  2087. /*
  2088.  * sock_write - writes data and returns length written
  2089.  */
  2090. sock_write(sock_type *s, byte FAR *dp, int len)
  2091. {
  2092.     if (s == NULL || dp == NULL) return (0);    /* failure */
  2093.  
  2094.     switch (s->tcp.ip_type)
  2095.         {
  2096.         case UDP_PROTO:
  2097.             return (udp_write((udp_Socket *)s, dp, len));
  2098.         case TCP_PROTO:
  2099.             return (tcp_write((tcp_Socket *)s, dp, len));
  2100.         default: return (0);
  2101.         }
  2102. }
  2103.  
  2104. /*
  2105.  * sock_dataready - returns number of bytes waiting to be read
  2106.  */
  2107. word 
  2108. sock_dataready(sock_type *s)
  2109. {
  2110.     if (s == NULL) 
  2111.         return (0);
  2112.         return (s->tcp.rdatalen);
  2113. }
  2114.  
  2115. int
  2116. sock_established(sock_type *s)
  2117. {
  2118.     if (s == NULL) return (0);            /* failure */
  2119.     switch (s->tcp.ip_type)
  2120.         {
  2121.         case UDP_PROTO:
  2122.             return (1);
  2123.         case TCP_PROTO:
  2124.             return (s->tcp.state == tcp_StateESTAB);
  2125.         default:
  2126.             return (0);
  2127.         }
  2128. }
  2129.  
  2130. int
  2131. sock_close(sock_type *s)
  2132. {
  2133.     register int status;
  2134.  
  2135.     if (s == NULL) return (0);            /* failure */
  2136.     tcp_tick(s);            /* process any last packets */
  2137.     switch (s->tcp.ip_type)
  2138.         {
  2139.         case UDP_PROTO:
  2140.             status = udp_close((udp_Socket *)s);
  2141.             break;
  2142.         case TCP_PROTO:
  2143.             status = tcp_close((tcp_Socket *)s);
  2144.             while ((tcp_Socket *)s->tcp.sisopen != SOCKET_CLOSED)
  2145.                 tcp_tick(s);    /* do protocol close */
  2146.             break;
  2147.         default:
  2148.             return (0);
  2149.         }
  2150.     return (status);                    /* success */
  2151. }
  2152.  
  2153. void 
  2154. sock_abort(sock_type *s)
  2155. {
  2156.     if (s == NULL) return;            /* do nothing */
  2157.     switch (s->tcp.ip_type)
  2158.         {
  2159.         case TCP_PROTO:
  2160.             tcp_abort((tcp_Socket *)s);
  2161.             break;
  2162.         case UDP_PROTO:
  2163.             udp_close((udp_Socket *)s);
  2164.             break;
  2165.         }
  2166. }
  2167.  
  2168. /*
  2169.  * ip_delay0 called by macro sock_wait_established()
  2170.  * ip_delay1 called by macro sock_wait_input()
  2171.  * ip_delay2 called by macro sock_wait_closed();
  2172.  *
  2173.  */
  2174.  
  2175. ip_delay0(sock_type *s, int timeoutseconds, procref fn, int *statusptr)
  2176. {
  2177.     register int status;
  2178.     longword timeout;
  2179.  
  2180.     if (s == NULL)
  2181.         {
  2182.         status = -1;        /* failure */
  2183.             if (statusptr != NULL) *statusptr = status;
  2184.         return (status);
  2185.         }
  2186.     timeout = set_timeout(timeoutseconds);
  2187.     do
  2188.         {
  2189.         if (s->tcp.ip_type == TCP_PROTO)
  2190.             if (s->tcp.state == tcp_StateESTAB)
  2191.                 {
  2192.                 status = 0;
  2193.                 break;
  2194.                 }
  2195.         if (tcp_tick(s) == SOCKET_CLOSED)
  2196.             {
  2197.             status = -1;    /* get an early reset */
  2198.             break;
  2199.             }
  2200.  
  2201.         if (chk_timeout(timeout) == TIMED_OUT)
  2202.             {
  2203.             sock_close(s);
  2204.             status = -1;
  2205.             break;
  2206.             }
  2207.         if (fn != NULL) 
  2208.             if (status = fn(s, NULL, 0)) break;
  2209.         if (s->tcp.ip_type == UDP_PROTO)
  2210.             {
  2211.             status = 0;
  2212.             break;
  2213.             }
  2214.         if (chkcon())            /* check console for ^C */
  2215.             {
  2216.             status = -1;        /* a failure */
  2217.             while (chkcon()) ;    /* soak up ^C's */
  2218.             break;
  2219.             }
  2220.         } while (1 == 1);
  2221.     if (statusptr != NULL) *statusptr = status;
  2222.     return (status);
  2223. }
  2224.  
  2225. int
  2226. ip_delay1(sock_type *s, int timeoutseconds, procref fn, int *statusptr)
  2227. {
  2228.     register int status;
  2229.     longword timeout;
  2230.  
  2231.     if (s == NULL)
  2232.         {
  2233.         status = -1;        /* failure */
  2234.             if (statusptr != NULL) *statusptr = status;
  2235.         return (status);
  2236.         }
  2237.  
  2238.     timeout = set_timeout(timeoutseconds);
  2239.  
  2240.     do
  2241.         {
  2242.         if (sock_dataready(s))
  2243.             {
  2244.             status = 0;
  2245.             break;
  2246.             }
  2247.  
  2248.         if (tcp_tick(s) == SOCKET_CLOSED)
  2249.             {
  2250.             status = 1;
  2251.             break;
  2252.             }
  2253.         if (chk_timeout(timeout) == TIMED_OUT)
  2254.             {
  2255.             sock_close(s);
  2256.             status = -1;
  2257.             break;
  2258.             }
  2259.         if (fn != NULL)
  2260.             if (status = fn(s, NULL, 0)) break;
  2261.         } while (1 == 1);
  2262.  
  2263.     if (statusptr != NULL) *statusptr = status;
  2264.     return (status);
  2265. }
  2266.  
  2267. int
  2268. ip_delay2(sock_type *s, int timeoutseconds, procref fn, int *statusptr)
  2269. {
  2270.     register int status;
  2271.     longword timeout;
  2272.  
  2273.     if (s == NULL)
  2274.         {
  2275.         status = 0;        /* failure */
  2276.             if (statusptr != NULL) *statusptr = status;
  2277.         return (status);
  2278.         }
  2279.  
  2280.     timeout = set_timeout(timeoutseconds);
  2281.  
  2282.     if (s->tcp.ip_type != TCP_PROTO) return (1);
  2283.  
  2284.     do
  2285.         {
  2286.         if (tcp_tick(s) == SOCKET_CLOSED)     /*  no socket */
  2287.             {
  2288.             status = 1;
  2289.             break;
  2290.             }
  2291.         if (chk_timeout(timeout) == TIMED_OUT)
  2292.             {
  2293.             sock_abort(s);
  2294.             status = 0;
  2295.             break;
  2296.             }
  2297.         if (fn != NULL)
  2298.             if (status = fn(s, NULL, 0)) break;
  2299.         } while (1 == 1);
  2300.  
  2301.     if (statusptr != NULL) *statusptr = status;
  2302.     return (status);
  2303. }
  2304.