home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / archives / msk316src.zip / MSNTCP.C < prev    next >
C/C++ Source or Header  |  1999-06-17  |  77KB  |  2,392 lines

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