home *** CD-ROM | disk | FTP | other *** search
/ ftp.wwiv.com / ftp.wwiv.com.zip / ftp.wwiv.com / pub / CEREBRUM / WAT9609.ZIP / SRC / PCTCP.C < prev    next >
C/C++ Source or Header  |  1996-09-24  |  69KB  |  2,297 lines

  1. /* DEBUG flag may be set for my internal playing */
  2.  
  3. /*
  4. #define DEBUG
  5. */
  6.  
  7. /*
  8.  *  PCTCP - the true worker of Waterloo TCP
  9.  *         - contains all opens, closes, major read/write routines and
  10.  *        basic IP handler for incomming packets
  11.  *      - NOTE: much of the TCP/UDP/IP layering is done at the data structure
  12.  *        level, not in separate routines or tasks
  13.  *
  14.  */
  15.  
  16. #include <copyright.h>
  17. #include <time.h>
  18. #include <stdio.h>
  19. #include <stdarg.h>
  20. #include <stdlib.h>
  21. #include <conio.h>
  22. #include <string.h>
  23. #include <mem.h>
  24. #include <dos.h>
  25. #include <values.h>
  26.  
  27. #include "wattcp.h"
  28. #include "elib.h"
  29.  
  30. static void udp_handler(in_Header *ip);
  31. static udp_write(udp_Socket *s, byte *datap, int len, word offset);
  32. static int udp_read(udp_Socket *s, byte *datap, int maxlen);
  33. static void tcp_Retransmitter(void);
  34.  
  35.  
  36. #define TCP_LOCAL 0x4000
  37.  
  38. /* statics */
  39. //static tcp_ProcessData(tcp_Socket *s, tcp_Header *tp, int len);
  40. static void tcp_ProcessData(tcp_Socket *s, tcp_Header *tp, int len, // 94.11.19
  41.                                     tcp_PseudoHeader *ph);
  42.  
  43. static char far *mono = (char far *)0xb0000000L;
  44. static char far *colour = (char far *)0xb8000000L;
  45.  
  46. static initialized = 0;
  47. static void (*system_yield)() = NULL;
  48. extern int multihomes;
  49. extern word _pktipofs;
  50. void (*_dbugxmit)( sock_type *s, in_Header *inp, void *phdr, unsigned line ) = NULL;
  51. void (*_dbugrecv)( sock_type *s, in_Header *inp, void *phdr, unsigned line ) = NULL;
  52. void (*wattcpd)(void) = NULL;
  53.  
  54. char *_hostname = "012345678901234567890123456789012345678901234567890";
  55.  
  56. word _mss = ETH_MSS;
  57.  
  58. char *_wattcp = WATTCP_C;
  59.  
  60. static void tcp_handler(in_Header *ip);
  61. static void udp_handler(in_Header *ip);
  62.  
  63. static void tcp_unthread(tcp_Socket *ds);
  64. static void tcp_abort(tcp_Socket *s);
  65. void tcp_sendsoon(tcp_Socket *s );
  66. static void tcp_send(tcp_Socket *s, int line);
  67. static void tcp_rst( in_Header *his_ip, tcp_Header *oldtcpp);
  68. static udp_close(udp_Socket *ds);
  69.  
  70.  
  71. /*
  72.  * sock_yield - enable user defined yield function
  73.  */
  74. int sock_yield( tcp_Socket *s, void (*fn)( void ) )
  75. {
  76.     if ( s )
  77.     s->usr_yield = fn;
  78.     else
  79.     system_yield = fn;
  80.     return( 0 );
  81. }
  82.  
  83. /*
  84.  * sock_mode - set binary or ascii - affects sock_gets, sock_dataready
  85.  *         - set udp checksums
  86.  */
  87. word sock_mode( sock_type *s, word mode )
  88. {
  89.      return( s->tcp.sock_mode = (s->tcp.sock_mode & 0xfffc) | mode);
  90. }
  91.  
  92. /*
  93.  * ip user level timer stuff
  94.  *   void ip_timer_init( void *s, int delayseconds )
  95.  *   int  ip_timer_expired( void *s )
  96.  *    - 0 if not expired
  97.  */
  98. static unsigned long far *realclock = (unsigned long far *)0x000046cL;
  99. #define MAXTICKS 0x1800b0L
  100.  
  101. void ip_timer_init( sock_type *s , int delayseconds )
  102. {
  103.     if (delayseconds)
  104.     s->tcp.usertimer = set_timeout( delayseconds );
  105.     else
  106.     s->tcp.usertimer = 0;
  107. }
  108.  
  109. int ip_timer_expired( sock_type *s )
  110. {
  111.     if (! s->tcp.usertimer)    /* cannot expire */
  112.     return( 0 );
  113.     return( chk_timeout( s->tcp.usertimer));
  114. }
  115.  
  116. longword MsecClock( void )
  117. {
  118.     return( (*realclock) * 055L);
  119. }
  120.  
  121. static long make_timeout( word timeout )
  122. {
  123.     if ( timeout ) return( set_timeout( timeout ));
  124.     return( 0 );
  125. }
  126.  
  127. #if 0    /* 94.11.27 -- not used? */
  128. /*
  129.  * check_timeout - test agains timeout clock - account for overflow
  130.  */
  131. static int check_timeout( unsigned long timeout )
  132. {
  133.     if (timeout) return( chk_timeout( timeout ));
  134.     return( 0 );
  135. }
  136. #endif
  137.  
  138. /*
  139.  * Local IP address
  140.  */
  141. longword my_ip_addr = 0L;    /* for external references */
  142. longword sin_mask = 0xfffffe00L;
  143. longword sin_gate = 0x0;
  144.  
  145.  
  146. /*
  147.  * IP identification numbers
  148.  */
  149.  
  150. static int ip_id = 0;            /* packet number */
  151. static int next_tcp_port = 1024;    /* auto incremented */
  152. static int next_udp_port = 1024;
  153. static tcp_Socket *tcp_allsocs = NULL;
  154. static udp_Socket *udp_allsocs = NULL;
  155.  
  156. /* Timer definitions */
  157. #define RETRAN_STRAT_TIME  1     /* in ticks - how often do we check retransmitter tables*/
  158. #define tcp_RETRANSMITTIME 3     /* interval at which retransmitter is called */
  159. #define tcp_LONGTIMEOUT 31       /* timeout for opens */
  160. #define tcp_TIMEOUT 13           /* timeout during a connection */
  161.  
  162. word debug_on = 0;
  163.  
  164. /*
  165.  * look for bugs
  166.  */
  167. int tcp_checkfor( sock_type *t )
  168. {
  169.     tcp_Socket *p;
  170.  
  171.     for ( p = tcp_allsocs ; p ; p = p->next )
  172.         if ( p == (tcp_Socket *)t ) return( 1 );
  173.     return( 0 );
  174. }
  175.  
  176. /*
  177.  * Shut down the card and all services
  178.  */
  179. void tcp_shutdown( void )
  180. {
  181.     while (tcp_allsocs)
  182.     tcp_abort( tcp_allsocs );
  183.     _eth_release();
  184.     initialized = 0;
  185. }
  186.  
  187. /*
  188.  * tcp_init - Initialize the tcp implementation
  189.  *        - may be called more than once without hurting
  190.  */
  191. void tcp_init( void )
  192. {
  193.     extern int _arp_last_gateway;
  194.     extern int _last_nameserver;
  195.  
  196.     if (!initialized) {
  197.     /* initialize ethernet interface */
  198.     initialized = 1;
  199.     _eth_init();
  200.  
  201.     /* reset the various tables */
  202.     _arp_last_gateway = 0;    /* reset the gateway table */
  203.     _last_nameserver = 0;    /* reset the nameserver table */
  204.     _last_cookie = 0;    /* eat all remaining crumbs */
  205.     *_hostname = 0;        /* reset the host's name */
  206.  
  207.     _eth_free( 0 );
  208.     next_udp_port = next_tcp_port = 1024 + ((*realclock >> 7 )& 0x1ff);
  209.     }
  210. }
  211.  
  212. /*
  213.  * Checks for bugs when compiling in large model C compiler
  214.  *
  215.  * Borland C uses a 4K stack by default.  In all memory models the
  216.  * stack grows down toward the heap.
  217.  *
  218.  * If you accidentally place tcp_Socket onto the stack (like by making
  219.  * it an automatic variable), then you will have already used up that
  220.  * whole 4K and then some!
  221.  *
  222.  * In large model, this will mess up the data space in a major way
  223.  * because the stack starts at SS:_stklen, or SS:1000, so you will
  224.  * wrap the SP pointer back around to FFFE and start writing over
  225.  * the far heap.  Yuck.
  226.  *
  227.  * In small model it usually doesn't kill your application because
  228.  * you would have to be down to your last 4K of memory and this is
  229.  * not as common.
  230.  *
  231.  * The solutions: declare your sockets as static, or put them on the
  232.  * heap, or bump up your stack size by using the global special variable:
  233.  *
  234.  * unsigned _stklen = 16536;    // set stack to 16 k
  235.  */
  236. static void largecheck( void *s, int size )
  237. {
  238. #ifdef __TURBOC__
  239.     if ( (word)(FP_OFF(s)) > (word)(-size)) {
  240.         outs("ERROR: user stack size error\n");
  241.         exit( 3 );
  242.     }
  243. #endif
  244. }
  245.  
  246. /*
  247.  * findfreeport - return unused local port
  248.  *              - oldport = 0:normal port, 1:special port (513-1023)
  249.  *              - we need not be this picky, but it doesn't hurt
  250.  */
  251. static word findfreeport( word oldport )
  252. {
  253.     word temp;
  254.     tcp_Socket *s;
  255.  
  256.     if (( oldport > 0 ) && (oldport < 0xffff))
  257.         return( oldport );
  258.  
  259.     if ( oldport == 0 ) oldport = 1025;
  260.     else oldport = 513;
  261.  
  262.     for ( temp = oldport ; temp < oldport + 510 ; ++temp ) {
  263.         if (( s = (tcp_Socket*)udp_allsocs) != NULL ) {
  264.             while ( s->next && (s->myport != temp))
  265.                 s = (tcp_Socket*)s->next;
  266.             if ( s->myport == temp ) continue;
  267.         }
  268.         if ( (s = tcp_allsocs ) != NULL ) {
  269.             while ( s->next && (s->myport != temp ))
  270.                 s = s->next;
  271.             if ( s->myport == temp ) continue;
  272.         }
  273.         break;
  274.     }
  275.     return( temp );
  276. }
  277.  
  278. /* socket, localport, destaddress */
  279. int udp_open( udp_Socket *s, word lport, longword ina, word port, dataHandler_t datahandler )
  280. {
  281.     udp_close( s );
  282.     largecheck( s, sizeof( udp_Socket ));
  283.     memset( s, 0, sizeof( udp_Socket ));
  284.     s->rdata = s->rddata;
  285.     s->maxrdatalen = tcp_MaxBufSize;
  286.     s->ip_type = UDP_PROTO;
  287.  
  288.     lport = findfreeport(lport);
  289.  
  290.     s->myport = lport;
  291.     s->myaddr = my_ip_addr;
  292.  
  293.     /* check for broadcast */
  294.     if ( (long)(ina) == -1 || !ina )
  295.     memset( &s->hisethaddr, 0xff, sizeof( eth_address ));
  296.     else if ( ! _arp_resolve(ina, &s->hisethaddr, 0) )
  297.     return( 0 );
  298.  
  299.     s->hisaddr = ina;
  300.     s->hisport = port;
  301.     s->dataHandler = datahandler;
  302.     s->usr_yield = system_yield;
  303.     s->safetysig = SAFETYUDP;
  304.     s->next = udp_allsocs;
  305.     udp_allsocs = s;
  306.     return( 1 );
  307. }
  308.  
  309. /*
  310.  * Actively open a TCP connection to a particular destination.
  311.  *    - 0 on error
  312.  */
  313. int tcp_open( tcp_Socket *s, word lport, longword ina, word port, dataHandler_t datahandler )
  314. {
  315.     largecheck( s, sizeof( tcp_Socket ));   /* stack space warnings */
  316.     tcp_unthread(s);                        /* just in case not totally closed */
  317.  
  318.     memset( s, 0, sizeof( tcp_Socket));
  319.     s->rdata = s->rddata;
  320.     s->maxrdatalen = tcp_MaxBufSize;
  321.     s->ip_type = TCP_PROTO;
  322.     s->mss = _mss;
  323.     s->state = tcp_StateSYNSENT;
  324.     s->timeout = set_timeout( tcp_LONGTIMEOUT );
  325.     s->cwindow = 1;
  326.     s->wwindow = 0;     /* slow start VJ algorithm */
  327.     s->vj_sa = 4;      /* about 250 ms */
  328.     lport = findfreeport( lport );  /* get a nonzero port val */
  329.     s->myaddr = my_ip_addr;
  330.     s->myport = lport;
  331.  
  332.     if ( ina - my_ip_addr <= multihomes ) return( 0 );
  333.     if ( ! _arp_resolve(ina, &s->hisethaddr, 0) )
  334.     return( 0 );
  335.  
  336.     s->hisaddr = ina;
  337.     s->hisport = port;
  338.     s->seqnum = intel( set_timeout( 1 )) & 0xffff0000uL;
  339.     s->datalen = 0;
  340.     s->flags = tcp_FlagSYN;
  341.     s->unhappy = true;
  342.     s->dataHandler = datahandler;
  343.     s->usr_yield = system_yield;
  344.  
  345.     s->safetysig = SAFETYTCP;       /* insert into chain */
  346.     s->next = tcp_allsocs;
  347.     tcp_allsocs = s;
  348.  
  349.     s->rtt_delay = s->rtt_smooth = 18;    /* one second startup */
  350.     tcp_send(s, __LINE__ );
  351.     s->rtt_time = set_timeout( 1 );
  352.     return( 1 );
  353. }
  354.  
  355. /*
  356.  * Passive open: listen for a connection on a particular port
  357.  */
  358. int tcp_listen( tcp_Socket *s, word lport, longword ina, word port, dataHandler_t datahandler, word timeout )
  359. {
  360.     largecheck( s, sizeof( tcp_Socket ));
  361.     tcp_unthread(s);                        /* just in case not totally closed */
  362.     memset( s, 0, sizeof( tcp_Socket));
  363.     s->rdata = s->rddata;
  364.     s->maxrdatalen = tcp_MaxBufSize;
  365.     s->ip_type = TCP_PROTO;
  366.     s->mss = _mss;
  367.     s->cwindow = 1;
  368.     s->wwindow = 0;     /* slow start VJ algorithm */
  369. /*    s->vj_sa = 36;      /* about 250 ms */
  370. /* tcpwinfix -- mdurkin */
  371.     s->vj_sa = 4;      /* about 250 ms */    /* was wrong val 95.05.02 */
  372.  
  373.     s->state = tcp_StateLISTEN;
  374.     if ( !timeout ) s->timeout = 0; /* forever... */
  375.     else s->timeout = set_timeout( timeout );
  376.     lport = findfreeport( lport );  /* get a nonzero port val */
  377.     s->myport = lport;
  378.     s->hisport = port;
  379.     s->hisaddr = ina;
  380.     s->seqnum = intel( (word)(s));
  381.     s->datalen = 0;
  382.     s->flags = 0;
  383.     s->unhappy = false;
  384.     s->dataHandler = datahandler;
  385.     s->usr_yield = system_yield;
  386.  
  387.     s->safetysig = SAFETYTCP;       /* insert into chain */
  388.     s->next = tcp_allsocs;
  389.     tcp_allsocs = s;
  390.  
  391.     return( 1 );
  392. }
  393.  
  394. static udp_close( udp_Socket *ds )
  395. {
  396.     udp_Socket *s, **sp;
  397.  
  398.     sp = &udp_allsocs;
  399.     for (;;) {
  400.         s = *sp;
  401.         if ( s == ds ) {
  402.             *sp = s->next;
  403.             break;
  404.         }
  405.     if ( !s ) break;
  406.     if ( ! s->err_msg ) s->err_msg = "UDP Close called";
  407.     sp = &s->next;
  408.     }
  409.     return( 0 );
  410. }
  411.  
  412. /*
  413.  * Send a FIN on a particular port -- only works if it is open
  414.  *   Must still allow receives
  415.  */
  416. static void tcp_close( tcp_Socket *s )
  417. {
  418.     if ( s->ip_type != TCP_PROTO )
  419.     return;
  420.     if ( s->state == tcp_StateESTAB ||
  421.          s->state == tcp_StateESTCL ||
  422.          s->state == tcp_StateSYNREC ) {
  423.  
  424.        if ( s->datalen ) {     /* must first flush all data */
  425.             s->flags |= tcp_FlagPUSH | tcp_FlagACK;
  426.             if ( s->state < tcp_StateESTCL ) {
  427.                 s->state = tcp_StateESTCL;
  428.         tcp_sendsoon( s );
  429.             }
  430.         } else { /* really closing */
  431.             s->flags = tcp_FlagACK | tcp_FlagFIN;
  432.             if (!s->err_msg)
  433.                 s->err_msg = "Connection closed normally";
  434.             s->state = tcp_StateFINWT1;
  435.             s->timeout = set_timeout( 4 ); /* should be a pretty lengthy time */
  436.             tcp_send( s, __LINE__ );
  437.         }
  438.         s->unhappy = true;
  439.     } else if (s->state == tcp_StateCLOSWT ) {
  440.         /* need to ack the fin and get on with it */
  441.         s->state = tcp_StateLASTACK;
  442.         s->flags |= tcp_FlagFIN;
  443.         tcp_send( s, __LINE__ );
  444.         s->unhappy = true;
  445.     }
  446. }
  447.  
  448. /*
  449.  * Abort a tcp connection
  450.  */
  451. static void tcp_abort( tcp_Socket *s )
  452. {
  453.     if (!s->err_msg) s->err_msg = "TCP_ABORT";
  454.     if ( s->state != tcp_StateLISTEN && s->state != tcp_StateCLOSED ) {
  455.         s->flags = tcp_FlagRST  | tcp_FlagACK ;
  456.         s->unhappy = true;
  457.         tcp_send(s, __LINE__);
  458.     }
  459.     s->unhappy = false;
  460.     s->datalen = 0;
  461.     s->ip_type = 0;
  462.     s->state = tcp_StateCLOSED;
  463. /*    if (s->dataHandler) s->dataHandler(s, 0, -1); */
  464.     tcp_unthread(s);
  465. }
  466.  
  467. void sock_abort( sock_type *s )
  468. {
  469.     if ( s->tcp.ip_type == TCP_PROTO )
  470.     tcp_abort( (tcp_Socket *)s );
  471.     else
  472.         udp_close( (udp_Socket *)s );
  473. }
  474.  
  475. /*
  476.  * tcp_sendsoon - schedule a transmission pretty soon
  477.  *        - this one has an imperfection at midnight, but it
  478.  *          is not significant to the connection performance
  479.  */
  480. void tcp_sendsoon( tcp_Socket *s )
  481. {
  482.     longword temp;
  483.     if (s->ip_type == TCP_PROTO ) {
  484.     temp = set_ttimeout( 1 );
  485.         if ( temp == s->rtt_time && s->rto < 2 && s->recent == 0 ) {
  486.             s->karn_count = 0;
  487.             tcp_send( s, __LINE__ );
  488.             s->recent = 1;
  489.             return;
  490.         }
  491.         if ((s->unhappy || s->datalen > 0 || s->karn_count == 1)
  492.           && (s->rtt_time < temp ))
  493.             return;
  494.  
  495.         s->rtt_time = set_ttimeout( 1 + (s->rto >> 4) );
  496.     s->karn_count = 1;
  497.     }
  498. }
  499.  
  500. /*
  501.  * Retransmitter - called periodically to perform tcp retransmissions
  502.  */
  503. static longword retran_strat = 0L; /* timeout retran strategy */
  504.  
  505. static void tcp_Retransmitter( void )
  506. {
  507.     tcp_Socket *s;
  508.  
  509.     /* only do this once per RETRAN_STRAT_TIME milliseconds */
  510.     if ( !chk_timeout( retran_strat ))
  511.     return;
  512.     retran_strat = set_ttimeout( RETRAN_STRAT_TIME );
  513.  
  514.     for ( s = tcp_allsocs; s; s = s->next ) {
  515.         if ( s->datalen > 0 || s->unhappy || s->karn_count == 1 ) {
  516.         /* retransmission strategy */
  517.         if ( chk_timeout( s->rtt_time)) {
  518.  
  519. #ifdef DEBUG
  520.     if(debug_on >1) printf("regular retran TO set unacked back to 0 from %u\n", s->unacked);
  521. #endif DEBUG
  522.                 /* strategy handles closed windows   J.D. + E.E. */
  523.                if (s->window == 0 && s->karn_count == 2)
  524.                   s->window = 1;
  525.  
  526.                 if ( s->karn_count == 0 ) {
  527.                     /* if really did timeout */
  528.  
  529.  
  530.                     s->karn_count = 2;
  531.  
  532.                     s->unacked = 0;
  533.                     /* use the backed off rto - implied, no code necessary */
  534.                     /* reduce the transmit window */
  535.                     s->cwindow =  ((s->cwindow + 1) * 3) >> 2;
  536.                     if ( s->cwindow == 0 ) s->cwindow = 1;
  537.                     s->wwindow = 0;
  538.                 }
  539.                 if (s->datalen)
  540.                     s->flags |= tcp_FlagPUSH | tcp_FlagACK;
  541.                 tcp_send(s, __LINE__);
  542.         }
  543.     }
  544.         /* handle inactive tcp timeouts */
  545.         if ( sock_inactive && s->inactive_to ) {
  546.             if ( chk_timeout( s->inactive_to)) {
  547.                 /* this baby has timed out */
  548.                 s->err_msg = "Connection timed out - no activity";
  549.                 sock_close( (sock_type *) s );
  550.             }
  551.         }
  552.         if ( s->timeout && chk_timeout( s->timeout)) {
  553.         if ( s->state == tcp_StateTIMEWT ) {
  554.         s->state = tcp_StateCLOSED;
  555.         tcp_unthread(s);
  556.                 break;
  557.             } else if (s->state != tcp_StateESTAB && s->state != tcp_StateESTCL ) {
  558.         s->err_msg = "Timeout, aborting";
  559.         tcp_abort(s);
  560.                 break;
  561.         }
  562.     }
  563.     }
  564.     /* do our various daemons */
  565.     if ( wattcpd ) (*wattcpd)();
  566. }
  567.  
  568.  
  569. /*
  570.  * Unthread a socket from the tcp socket list, if it's there
  571.  */
  572. static void tcp_unthread( tcp_Socket *ds )
  573. {
  574.     tcp_Socket *s, **sp;
  575.  
  576.     if (!ds->rdatalen || (ds->state > tcp_StateESTCL))
  577.         ds->ip_type = 0;                /* fail io */
  578.     ds->state = tcp_StateCLOSED;   /* tcp_tick needs this */
  579.     sp = &tcp_allsocs;
  580.     for (;;) {
  581.     s = *sp;
  582.     if ( s == ds ) {
  583.         *sp = s->next;
  584.             continue;           /* unthread multiple copies if necessary */
  585.     }
  586.     if ( !s ) break;
  587.     sp = &s->next;
  588.     }
  589. }
  590.  
  591. /*
  592.  * tcp_tick - called periodically by user application
  593.  *        - returns 1 when our socket closes
  594.  *        - called with socket parameter or NULL
  595.  */
  596. int tcp_tick( sock_type *s )
  597. {
  598.     in_Header *ip;
  599.     static longword timeout = 0;
  600.     static longword start = 0;
  601.  
  602. /*    int x; */
  603.     int packettype;
  604.  
  605.     /* finish off dead sockets */
  606.     if ( s ) {
  607.         if (( s->tcp.ip_type == TCP_PROTO ) &&
  608.             ( s->tcp.state == tcp_StateCLOSED ) &&
  609.             ( s->tcp.rdatalen == 0 )) {
  610.                 tcp_unthread( & s->tcp );
  611.         s->tcp.ip_type = 0;
  612.         }
  613.     }
  614.  
  615.  
  616.     /* plan our next retransmit */
  617.  
  618.     if ( !timeout )
  619.     timeout = make_timeout( tcp_RETRANSMITTIME );
  620.  
  621.     while ( (ip = (in_Header *)_eth_arrived( (word *) &packettype )) != NULL ) {
  622.     start = *realclock;
  623.  
  624.     switch ( packettype ) {
  625.     case /*0x800*/ 0x008 :
  626.         /* do IP */
  627.         if ( checksum(ip, in_GetHdrlenBytes(ip)) == 0xffff ) {
  628.         switch ( ip->proto ) {
  629.             case TCP_PROTO :
  630.             tcp_handler(ip);
  631.             break;
  632.             case UDP_PROTO :
  633.             udp_handler(ip);
  634.             break;
  635.             case ICMP_PROTO :
  636.             icmp_handler(ip);
  637.             break;
  638.         }
  639.         } else  {
  640.         if (debug_on)
  641.             outs("IP Received BAD Checksum \n\r");
  642.         }
  643.         break;
  644.     case /*0x806*/ 0x608 :
  645.             /* do arp */
  646.         _arp_handler( (arp_Header *)ip );
  647.         break;
  648.     }
  649.     if (ip) _eth_free(ip);
  650.  
  651.     continue;
  652.     }
  653.     /* check for our outstanding packets */
  654.     tcp_Retransmitter();
  655.  
  656.     return( s->udp.ip_type );
  657. }
  658.  
  659. void tcp_set_debug_state( int x )
  660. {
  661.     debug_on = x;
  662. }
  663.  
  664. /* returns 1 if connection is established */
  665. int tcp_established( tcp_Socket *s )
  666. {
  667.     return( s->state >= tcp_StateESTAB );
  668. }
  669.  
  670. /*
  671.  * udp_write() handles fragmented UDP by assuming it'll be called
  672.  *     once for all fragments with no intervening calls.  This is
  673.  *     the case in sock_write().
  674.  * Handles upto a hair-under 32K datagrams.  Could be made to handle
  675.  *     upto a hair-under 64K easily...  wanna Erick?
  676.  * Might be possible to test 'offset' for non/zero fewer times to be
  677.  *     more efficient.  Might also be more efficient to use the old
  678.  *     UDP checksum() call when more_frags is false in the first frag
  679.  *     (i.e., not a fragmented dgram).
  680.  * Uses _mss to decide splits which defaults to 1400.  Could pack
  681.  *     more into an Ethernet packet.
  682.  */
  683. #define IP_MF 0x0020               // more fragments, net byte order
  684.  
  685. static udp_write( udp_Socket *s, byte *datap, int len, word offset )
  686. {
  687.     struct {                    // special pseudo header because need to
  688.         tcp_PseudoHeader ph;    //    compute checksum in two parts (may not
  689.         word checksum2;         //    have all of datagram built at once).
  690.     } ph;
  691.     struct _pkt {
  692.     in_Header  in;
  693.     udp_Header udp;
  694.     int       data;
  695. /*    longword maxsegopt; */
  696.     } *pkt;
  697.     byte *dp;
  698.     in_Header *inp;
  699.     udp_Header *udpp;
  700.  
  701.     word maxlen;
  702.     int more_frags;
  703.     word origlen = len;
  704.  
  705.     pkt = (struct _pkt *)_eth_formatpacket(&s->hisethaddr, /*0x800*/ 8);
  706.  
  707.     if( offset ) {              // this is not the first fragment
  708.         dp = (byte *) &pkt->udp;    // data goes right after IP header
  709.     } else {
  710.         dp = (byte *) &pkt->data;
  711.         udpp = &pkt->udp;
  712.  
  713.         /* udp header */
  714.         udpp->srcPort = intel16( s->myport );
  715.         udpp->dstPort = intel16( s->hisport );
  716.         udpp->checksum = 0;
  717.         udpp->length = intel16( UDP_LENGTH + len );
  718.     }
  719.     inp = &pkt->in;
  720.  
  721.     memset( inp, 0, sizeof( in_Header ));
  722.  
  723.     maxlen = _mss & 0xFFF8;             // make a multiple of 8
  724.     if( !offset ) maxlen -= UDP_LENGTH; // note UDP_LENGTH is 8, so ok
  725.  
  726.     if( len > maxlen ) {
  727.         len = maxlen;
  728.         more_frags = 1;
  729.     } else more_frags = 0;
  730.  
  731.     inp->length = intel16( sizeof(in_Header) +
  732.                                      (offset ? 0 : UDP_LENGTH) + len );
  733.     movmem(datap, dp, len );
  734.  
  735.     /* internet header */
  736.     inp->ver = 4;
  737.     inp->hdrlen = 5;
  738.     inp->tos = 0;
  739. /* inp->vht = 0x4500;*/   /* version 4, hdrlen 5, tos 0 */
  740.  /* if offset non-zero, then is part of a prev datagram so don't incr ID */
  741.     inp->identification = intel16( offset ? ip_id : ++ip_id );   /* was post inc */
  742. //    inp->frag = 0;
  743.     inp->frags = (offset ? intel16((offset + UDP_LENGTH) >> 3) : 0);
  744.     if(more_frags) inp->frags |= IP_MF;
  745.     inp->ttl = 254;
  746.     inp->proto = UDP_PROTO;    /* udp */
  747. /* inp->ttlProtocol = (250<<8) + 6; */
  748.     inp->checksum = 0;
  749.     inp->source = intel( s->myaddr );
  750.     inp->destination = intel( s->hisaddr );
  751.     inp->checksum = ~checksum( inp, sizeof(in_Header));
  752.  
  753.  
  754.     /* compute udp checksum if desired */
  755.     if(!offset) {  // only first of frags has UDP header for entire UDP dgram
  756.         if ( s->sock_mode & UDP_MODE_NOCHK )
  757.         udpp->checksum = 0;
  758.         else {
  759.         ph.ph.src = inp->source;    /* already INTELled */
  760.         ph.ph.dst = inp->destination;
  761.         ph.ph.mbz = 0;
  762.         ph.ph.protocol = UDP_PROTO;    /* udp */
  763.         ph.ph.length = udpp->length;    /* already INTELled */
  764.  
  765.           /* can't use since may not have the whole dgram built at once */
  766. //        ph.checksum = checksum(&pkt->udp, intel16(ph.length));
  767.           /* this way handles it */
  768.             ph.ph.checksum = checksum(&pkt->udp, UDP_LENGTH);
  769.             ph.checksum2 = checksum(datap, origlen);
  770.  
  771.         udpp->checksum =  ~checksum(&ph, sizeof(ph));
  772.         }
  773.     }
  774.     
  775.     if (_dbugxmit) (*_dbugxmit)( (sock_type*)s, inp, udpp, 0 );
  776.     _eth_send( intel16( inp->length ));
  777.  
  778.     return ( len );
  779. }
  780.  
  781. /*
  782.  * udp_read - read data from buffer, does large buffering
  783.  */
  784. static int udp_read( udp_Socket *s, byte *datap, int maxlen )
  785. {
  786.     int x;
  787.  
  788.     if (maxlen < 0) maxlen = MAXINT;
  789.     if (( x = s->rdatalen ) > 0) {
  790.     if ( x > maxlen ) x = maxlen;
  791.     if ( x > 0 ) {
  792.             if (datap) movmem( s->rdata, datap, x );
  793.         if ( s->rdatalen -= x )
  794.                 movmem( s->rdata + x, s->rdata, s->rdatalen);
  795.     }
  796.     }
  797.     return( x );
  798. }
  799.  
  800. void _udp_cancel( in_Header *ip )
  801. {
  802.     int len;
  803.     udp_Header *up;
  804.     udp_Socket *s;
  805.  
  806.     /* match to a udp socket */
  807.     len = in_GetHdrlenBytes(ip);
  808.     up = (udp_Header *)((byte *)ip + len);    /* udp frame pointer */
  809.  
  810.     /* demux to active sockets */
  811.     for ( s = udp_allsocs; s; s = s->next )
  812.         if ( s->hisport != 0 &&
  813.              intel16( up->dstPort ) == s->hisport &&
  814.              intel16( up->srcPort ) == s->myport &&
  815.              intel( ip->destination ) == s->hisaddr ) break;
  816.     if ( !s ) {
  817.     /* demux to passive sockets */
  818.     for ( s = udp_allsocs; s; s = s->next )
  819.         if ( s->hisport == 0 && intel16( up->dstPort ) == s->myport ) break;
  820.     }
  821.     if (s) {
  822.         s->rdatalen = 0;
  823.     s->ip_type = 0;
  824.     }
  825. }
  826.  
  827. void *_tcp_lookup( longword hisip, word hisport, word myport )
  828. {
  829.     tcp_Socket *s;
  830.     for ( s = tcp_allsocs; s; s = s->next ) {
  831.         if ( ( myport == s->myport ) &&         /* always unique under WATTCP */
  832.              ( hisport == s->hisport ) &&
  833.              ( hisip == s->hisaddr ))
  834.                 return( s );
  835.     }
  836.     return( NULL );
  837. }
  838.  
  839. void _tcp_cancel( in_Header *ip, int code, char *msg, longword dummyip )
  840. {
  841.     static int in_icmp_redirect = 0;            // smart@actrix.gen.nz
  842.     int len;
  843.     tcp_Socket *s;
  844.     tcp_Header *tp;
  845.  
  846.     len = in_GetHdrlenBytes(ip);    /* check work */
  847.  
  848.     tp = (tcp_Header *)((byte *)ip + len);    /* tcp frame pointer */
  849.  
  850.     /* demux to active sockets */
  851.     for ( s = tcp_allsocs; s; s = s->next ) {
  852.         if ( intel16( tp->srcPort) == s->myport &&
  853.              intel16( tp->dstPort ) == s->hisport &&
  854.              intel( ip->destination ) == s->hisaddr ) {
  855.                 switch (code) {
  856.                     /* halt it */
  857.                     case  1 : if (( s->stress ++ > s->rigid ) &&
  858.                                   ( s->rigid < 100 )) {
  859.                                   s->err_msg = (msg) ?
  860.                                     msg : "ICMP closed connection";
  861.                                   s->rdatalen = s->datalen = 0;
  862.                                   s->unhappy = false;
  863.                                   tcp_abort( s );
  864.                 /*      if (s->dataHandler) s->dataHandler(s, 0, -1); */
  865.                                   break;
  866.                               }
  867.                               // follow through to next case
  868.  
  869.                     /* slow it down */
  870.                     case  2 : s->cwindow = 1;
  871.                               s->wwindow = 1;
  872.                               s->rto <<= 2;
  873.                               s->vj_sa <<= 2;
  874.                               s->vj_sd <<= 2;
  875.                               break;
  876.                     /* icmp redirect for host */
  877.                     case  5 : /* save his NEW network address */
  878.                         /* Dummy is passed in NW form need to intel! */
  879.                         /* This was a bug fixed QVS - smart@actrix.gen.nz */
  880.                               if (!in_icmp_redirect)
  881.                               {
  882.                                   in_icmp_redirect = 1;
  883.                                   _arp_resolve(intel(dummyip), &s->hisethaddr, 0);
  884.                                   in_icmp_redirect = 0;
  885.                               }
  886.                               break;
  887.                 }
  888.         }
  889.     }
  890. }
  891.  
  892. static int tcp_read( tcp_Socket *s, byte *datap, int maxlen )
  893. {
  894.     int x;
  895.  
  896.     if (maxlen < 0 ) maxlen = MAXINT;
  897.     if (( x = s->rdatalen) > 0) {
  898.     if ( x > maxlen ) x = maxlen;
  899.         if ( x > 0 ) {
  900.             if (datap) movmem( s->rdata, datap, x );
  901.             if (( s->rdatalen -= x ) > 0 ) {
  902.                 movmem( s->rdata + x, s->rdata, s->rdatalen );
  903.                 tcp_sendsoon( s );   /* update the window */
  904.             } else
  905.                 tcp_send( s, __LINE__ );      /* update window el-pronto */
  906.     }
  907.     } else if ( s->state == tcp_StateCLOSWT )
  908.         tcp_close( s );
  909.     return( x );
  910. }
  911.  
  912. /*
  913.  * Write data to a connection.
  914.  * Returns number of bytes written, == 0 when connection is not in
  915.  * established state.
  916.  */
  917. static int tcp_write( tcp_Socket *s, byte *dp, int len )
  918. {
  919.     int x;
  920.  
  921.     if (len < 0 ) len = MAXINT;
  922.     /* no longer uses tcp_MaxData */
  923.     if ( s->state != tcp_StateESTAB ) len = 0;
  924.     if ( len > (x = s->maxrdatalen - s->datalen) ) len = x;
  925.     if ( len > 0 ) {
  926.         movmem( dp, s->data + s->datalen, len );
  927.  
  928.     s->datalen += len;
  929.     s->unhappy = true;    /* redundant because we have outstanding data */
  930.  
  931.         if ( s->sock_mode & TCP_LOCAL )
  932.             s->sock_mode &= ~TCP_LOCAL;
  933.         else {
  934.             if ( s->sock_mode & TCP_MODE_NONAGLE ) {
  935.                 tcp_send( s, __LINE__ );
  936.             } else {
  937.                 /* transmit if first data or reached MTU */
  938.                 /* not true MTU, but better than nothing */
  939.                 if (( s->datalen == len ) || ( s->datalen > (s->mss)/2 ))
  940.                     tcp_send( s, __LINE__ );
  941.                 else
  942.                     tcp_sendsoon( s );
  943.             }
  944.     }
  945.     }
  946.  
  947.     return ( len );
  948. }
  949.  
  950. /*
  951.  * Send pending data
  952.  */
  953. static void tcp_Flush( tcp_Socket *s )
  954. {
  955.     if ( s->datalen > 0 ) {
  956.         s->flags |= tcp_FlagPUSH;
  957.         tcp_send(s, __LINE__);
  958.     }
  959. }
  960.  
  961. /*
  962.  * Handler for incoming packets.
  963.  */
  964. static void udp_handler( in_Header *ip )
  965. {
  966.     udp_Header *up;
  967.     tcp_PseudoHeader ph;
  968.     word len;
  969.     byte *dp;
  970.     longword temp;
  971.     udp_Socket *s;
  972.  
  973.     temp = intel( ip->destination );
  974.  
  975.     // temp = ip number
  976.     //     or 255.255.255.255
  977.     //     or sin_mask.255.255
  978.  
  979.     if ( ((~temp & ~sin_mask) != 0) &&  /* not a broadcast packet*/
  980.         ((( temp - my_ip_addr) > multihomes )   /* not my address */
  981.         && my_ip_addr))                 /* and I know my address */
  982.           return;
  983.  
  984.  
  985.     len = in_GetHdrlenBytes(ip);
  986.     up = (udp_Header *)((byte *)ip + len);    /* udp segment pointer */
  987.     len = intel16( up->length );
  988.  
  989.     /* demux to active sockets */
  990.     for ( s = udp_allsocs; s; s = s->next ) {
  991.         if ( s->safetysig != SAFETYUDP ) {
  992.             if (debug_on) outs("chain error in udp\r\n");
  993.         }
  994.         if ( (s->hisport != 0) &&
  995.              (intel16( up->dstPort ) == s->myport) &&
  996.              (intel16( up->srcPort ) == s->hisport) &&
  997.              ((intel( ip->destination ) & sin_mask)  == (s->myaddr & sin_mask)) &&
  998.              (intel( ip->source ) == s->hisaddr )) break;
  999.     }
  1000.     if (_dbugrecv) (*_dbugrecv)( (sock_type*)s, ip, up, 0);
  1001.     if ( !s ) {
  1002.         /* demux to passive sockets */
  1003.     for ( s = udp_allsocs; s; s = s->next )
  1004.             if ( ((s->hisaddr == 0) || (s->hisaddr == 0xffffffffuL))
  1005.               && intel16( up->dstPort ) == s->myport ) {
  1006.  
  1007.                 // do we record this information ???
  1008.                 if ( s->hisaddr == 0 ) {
  1009.                     s->hisaddr = intel( ip->source );
  1010.                     s->hisport = intel16( up->srcPort );
  1011.                     _arp_resolve(intel(ip->source), &s->hisethaddr, 0);
  1012.                     // take on value of expected destination unless it
  1013.                     // is broadcast
  1014.                     if ( (~ip->destination & ~sin_mask) != 0 )
  1015.                         s->myaddr = intel( ip->destination );
  1016.                 }
  1017.         break;
  1018.         }
  1019.     }
  1020.     if ( !s ) {
  1021.     /* demux to broadcast sockets */
  1022.     for ( s = udp_allsocs; s; s = s->next )
  1023.             if ( (s->hisaddr == 0xffffffffuL) &&
  1024.                  (intel16( up->dstPort ) == s->myport )) break;
  1025.     }
  1026.  
  1027.     if ( !s ) {
  1028.     if (debug_on) outs("discarding...");
  1029.     return;
  1030.     }
  1031.  
  1032.     // these parameters are used for things other than just checksums
  1033.     ph.src = ip->source;    /* already INTELled */
  1034.     ph.dst = ip->destination;
  1035.     ph.mbz = 0;
  1036.     ph.protocol = UDP_PROTO;
  1037.     ph.length = up->length;
  1038.     if ( up->checksum ) {
  1039.     ph.checksum =  checksum(up, len);
  1040.     if (checksum(&ph, sizeof( tcp_PseudoHeader)) != 0xffff)
  1041.         return;
  1042.     }
  1043.  
  1044.     /* process user data */
  1045.     if ( (len -= UDP_LENGTH ) > 0) {
  1046.     dp = (byte *)( up );
  1047.         if (s->dataHandler) s->dataHandler( s, &dp[ UDP_LENGTH ], len , &ph, up);
  1048.     else {
  1049.             if (len > s->maxrdatalen ) len = s->maxrdatalen;
  1050.         movmem( &dp[ UDP_LENGTH ], s->rdata, len );
  1051.         s->rdatalen = len;
  1052.     }
  1053.     }
  1054. }
  1055.  
  1056. static void tcp_handler( in_Header *ip )
  1057. {
  1058.     tcp_Header *tp;
  1059.     tcp_PseudoHeader ph;
  1060.     int len;
  1061. /*    byte *dp;  */
  1062.     int diff;
  1063.     tcp_Socket *s;
  1064.     word flags;
  1065.     long diffticks, ldiff;    /* must be signed */
  1066.     long scheduleto;
  1067.  
  1068.  
  1069.     if ( (longword)(intel( ip->destination ) - my_ip_addr) > multihomes )
  1070.         return;
  1071.  
  1072.     len = in_GetHdrlenBytes(ip);
  1073.     len = intel16( ip->length ) - len;        /* len of tcp data */
  1074.  
  1075.     len = in_GetHdrlenBytes(ip);
  1076.     tp = (tcp_Header *)((byte *)ip + len);    /* tcp frame pointer */
  1077.     len = intel16( ip->length ) - len;        /* len of tcp data */
  1078.     flags = intel16( tp->flags );
  1079.  
  1080.     if (debug_on > 1) {
  1081.             mono[160]++;
  1082.             colour[160]++;
  1083.             mono[162] = colour[162] = (flags & tcp_FlagSYN) ? 'S' : ' ';
  1084.             mono[164] = colour[164] = (flags & tcp_FlagACK) ? 'A' : ' ';
  1085.             mono[166] = colour[166] = (flags & tcp_FlagFIN) ? 'F' : ' ';
  1086.             mono[168] = colour[168] = (flags & tcp_FlagRST) ? 'R' : ' ';
  1087.         }
  1088.  
  1089.     /* demux to active sockets */
  1090.     for ( s = tcp_allsocs; s; s = s->next ) {
  1091.         if ( s->safetysig != SAFETYTCP ) {
  1092.             if (debug_on) outs("chain error in tcp\r\n");
  1093.         }
  1094.     if ( s->hisport != 0 &&
  1095.          intel16( tp->dstPort ) == s->myport &&
  1096.          intel16( tp->srcPort ) == s->hisport &&
  1097.              intel( ip->destination )   == s->myaddr     &&
  1098.          intel( ip->source ) == s->hisaddr ) break;
  1099.     }
  1100.     if ( !s && (flags & tcp_FlagSYN)) {
  1101.     /* demux to passive sockets, must be a new session */
  1102.     for ( s = tcp_allsocs; s; s = s->next )
  1103.             if ((s->hisport == 0) && (intel16( tp->dstPort ) == s->myport )) {
  1104.                 s->myaddr = intel( ip->destination );
  1105.         break;
  1106.             }
  1107.     }
  1108.  
  1109.  
  1110.     if (_dbugrecv) (*_dbugrecv)( (sock_type*)s, ip, tp, 0 );
  1111.     if ( !s ) {
  1112.         if (!(flags & tcp_FlagRST)) tcp_rst( ip, tp );
  1113.     return;
  1114.     }
  1115.  
  1116.     ph.src = ip->source;    /* already INTELled */
  1117.     ph.dst = ip->destination;
  1118.     ph.mbz = 0;
  1119.     ph.protocol = TCP_PROTO;
  1120.     ph.length = intel16( len );
  1121.     ph.checksum =  checksum(tp, len);
  1122.     if ( checksum(&ph, sizeof(ph)) != 0xffff ) {
  1123.      if (debug_on) outs("bad tcp checksum \n\r");
  1124.  
  1125.          /* tester */
  1126.          ph.checksum =  checksum(tp, len);
  1127.          checksum(&ph, sizeof(ph));
  1128.  
  1129.          tcp_sendsoon( s );
  1130.      return;
  1131.     }
  1132.  
  1133. /* reset code */
  1134.     if ( flags & tcp_FlagRST ) {
  1135.     if (debug_on) outs("\7\7\7\7\7\7\7connection reset\n");
  1136.         s->rdatalen = s->datalen = 0;
  1137.         s->err_msg = "Remote reset connection";
  1138.     s->state = tcp_StateCLOSED;
  1139. /*    if (s->dataHandler) s->dataHandler(s, 0, -1); */
  1140.     tcp_unthread(s);
  1141.     return;
  1142.     }
  1143.  
  1144.     if ( sock_inactive )
  1145.         s->inactive_to = set_timeout( sock_inactive );
  1146.  
  1147.  
  1148.     /* update our retransmission stuff */
  1149.     /* new algorithms */
  1150.     if (s->karn_count == 2) {
  1151.         s->karn_count = 0;
  1152. #ifdef DEBUG
  1153.         if (debug_on > 1 ) printf("finally got it safely zapped from %u to ????\n\r",s->unacked);
  1154. #endif /* DEBUG */
  1155.     } else {
  1156.         if ( s->vj_last ) {
  1157.             /* unnecessary to use unhappy || s->datalen ) */
  1158.             if ((diffticks = set_ttimeout( 0 ) - s->vj_last) >= 0 ) {
  1159.                 /* we ignore the overnight case */
  1160.                 diffticks -= (longword)( s->vj_sa >> 3 );
  1161.                 s->vj_sa += (int)diffticks;
  1162.                 if (diffticks < 0)
  1163.                     diffticks = - diffticks;
  1164.                 diffticks -= (s->vj_sd >> 2);
  1165.                 s->vj_sd += (int)diffticks;
  1166.                 if (s->vj_sa > MAXVJSA) s->vj_sa = MAXVJSA;
  1167.                 if (s->vj_sd > MAXVJSD) s->vj_sd = MAXVJSD;
  1168.             }
  1169.             /* only recompute rtt hence rto after success */
  1170.             s->rto = 1 + ((s->vj_sa >> 2) + (s->vj_sd)) >> 1 ;
  1171. #ifdef DEBUG
  1172.             if (debug_on > 1 ) printf("rto  %u  sa  %u  sd  %u   cwindow %u  wwindow %u  unacked %u\n",
  1173.                 s->rto, s->vj_sa, s->vj_sd, s->cwindow, s->wwindow, s->unacked );
  1174. #endif /* DEBUG */
  1175.     }
  1176.         s->karn_count = 0;
  1177.         if ( s->wwindow != 255 ) {
  1178.             if ( s->wwindow++ >= s->cwindow ) {
  1179.                 if ( s->cwindow != 255 )
  1180.                     s->cwindow ++;
  1181.       /* tcpwinfix
  1182.        *    Movement of the next line *seems* to fix the failure of the TCP
  1183.        *    send window to open up (which makes TCP writes very slow, as
  1184.        *    seen with some previous releases of WatFTP), though it's been
  1185.        *    a long time since I made this change (today is 96.09.24) and
  1186.        *    I'm not sure how confident I was even then that it was correct.
  1187.        *    Also I don't have any description of the VJ algorithm and don't
  1188.        *    really understand this code all that well, but some time ago
  1189.        *    this seemed to be the right thing to do and seems to work.
  1190.        *    That said, if I'm wrong, I hope I haven't broken things worse :-)
  1191.        *    There is one other place, also marked 'tcpwinfix' above in this
  1192.        *    file, and those are the only two changes I made for this bug
  1193.        *    which may need undoing if I'm wrong. -- mdurkin
  1194.        */
  1195.                 s->wwindow = 0;  /* mdurkin -- added 95.05.02 */
  1196.             }
  1197. /*            s->wwindow = 0;    /* mdurkin -- removed 95.05.02 */
  1198.         }
  1199.     }
  1200.     /* all new */
  1201.     scheduleto = set_ttimeout( s->rto + 2 );
  1202.     if ( s->rtt_time < scheduleto ) s->rtt_time = scheduleto;
  1203.  
  1204.  
  1205.     switch ( s->state ) {
  1206.  
  1207.     case tcp_StateLISTEN:    /* accepting SYNs */
  1208.             /* save his ethernet address */
  1209.             if ( _pktipofs )
  1210.                 movmem(&((((eth_Header *)ip) - 1)->source), &s->hisethaddr, sizeof(eth_address));
  1211.             if ( flags & tcp_FlagSYN ) {
  1212.  
  1213.                 if ( ip->tos > s->tos )
  1214.                     s->tos = ip->tos;
  1215.                 else if ( ip->tos < s->tos ) {
  1216.                     /* RFC 793 says we should close connection */
  1217.                     /* we best not do that while SunOS ignores TOS */
  1218.                 }
  1219.  
  1220.                 s->acknum = intel( tp->seqnum ) + 1;
  1221.         s->hisport = intel16( tp->srcPort );
  1222.         s->hisaddr = intel( ip->source );
  1223.         s->flags = tcp_FlagSYN | tcp_FlagACK;
  1224.                 s->state = tcp_StateSYNREC;
  1225.         s->unhappy = true;
  1226.                 tcp_send(s, __LINE__);    /* we must respond immediately */
  1227.  
  1228.         s->timeout = set_timeout( tcp_TIMEOUT );
  1229.         } else
  1230.         tcp_rst( ip , tp );  /* send a reset */
  1231.  
  1232.             return;
  1233.  
  1234.     case tcp_StateSYNSENT:  /* added ACK Section */
  1235.         if ( flags & tcp_FlagSYN ) {
  1236.  
  1237.                 if ( ip->tos > s->tos )
  1238.                     s->tos = ip->tos;
  1239.                 else if ( ip->tos < s->tos ) {
  1240.                     /* RFC 793 says we should close connection */
  1241.                     /* we best not do that while SunOS ignores TOS */
  1242.                 }
  1243.  
  1244.                 s->flags = tcp_FlagACK;
  1245.         s->timeout = set_timeout( tcp_TIMEOUT );
  1246.  
  1247.         /* FlagACK means connection established, else SYNREC */
  1248.         if ( flags & tcp_FlagACK) {
  1249.             /* but is it for the correct session ? */
  1250.                 if (tp->acknum == intel(s->seqnum + 1)) {
  1251.                 s->state = tcp_StateESTAB;
  1252.                 s->seqnum++;    /* good increment */
  1253.                 s->acknum = intel( tp->seqnum  ) + 1;   /* 32 bits */
  1254.                 tcp_ProcessData(s, tp, len, &ph);    /* someone may try it */
  1255.                 s->unhappy = true;             /* rely on their attempts */
  1256.                 tcp_send( s, __LINE__ );
  1257.             } else {
  1258.                 /* wrong ack, force a RST and resend SYN soon*/
  1259.                 s->flags = tcp_FlagRST;
  1260.                 s->unhappy = true;
  1261.                 tcp_send( s, __LINE__ );
  1262.                 s->flags = tcp_FlagSYN;
  1263.                 tcp_send( s, __LINE__ );
  1264.             }
  1265.         } else {
  1266.             s->acknum++;
  1267.             s->state = tcp_StateSYNREC;
  1268.                     return;
  1269.         }
  1270.             } else
  1271.                 tcp_rst( ip, tp );
  1272.         break;
  1273.  
  1274.     case tcp_StateSYNREC:    /* recSYNSENT, sentACK, waiting  EST */
  1275.         if ( flags & tcp_FlagSYN ) {
  1276.         s->flags = tcp_FlagSYN | tcp_FlagACK;
  1277.         s->unhappy = true;
  1278.                 tcp_send(s, __LINE__);
  1279.         s->timeout = set_timeout( tcp_TIMEOUT );
  1280.                 return;
  1281.         }
  1282.         if ( (flags & tcp_FlagACK) && (intel( tp->acknum ) == (s->seqnum + 1))) {
  1283.                 if ( (s->window = intel16( tp->window )) > 0x7fff )
  1284.                     s->window = 0x7fff;
  1285.         s->flags = tcp_FlagACK;
  1286.                 s->state = tcp_StateESTAB;
  1287.                 s->seqnum++;
  1288.                 s->timeout = 0;     /* never timeout */
  1289.                 s->unhappy = false;
  1290.                 return;
  1291.         }
  1292.  
  1293.         break;
  1294.     case tcp_StateESTAB:
  1295.         case tcp_StateESTCL:
  1296.         case tcp_StateCLOSWT:
  1297.  
  1298.             /* handle lost SYN */
  1299.             if ((flags & tcp_FlagSYN) && (flags & tcp_FlagACK)) {
  1300.                 tcp_send( s, __LINE__ );
  1301.                 return;
  1302.             }
  1303.  
  1304.         if ( !(flags & tcp_FlagACK)) return;  /* must ack somthing */
  1305.             if ( flags & tcp_FlagSYN ) {
  1306.                 tcp_rst( ip , tp );
  1307.                 return;
  1308.             }
  1309.         s->timeout = 0l;    /* we do not timeout at this point */
  1310.  
  1311.         /* process ack value in packet - but only if it falls
  1312.          * within current window */
  1313.  
  1314.         ldiff = intel( tp->acknum ) - s->seqnum;
  1315.         diff = (int) ldiff;
  1316.  
  1317.             if ( ldiff >= 0 && diff <= s->datalen ) {
  1318.         s->datalen -= diff;
  1319.                 s->unacked -= diff;
  1320.                 if (s->datalen < 0) s->datalen = 0; /* remote proto error */
  1321.                 if ( s->queuelen ) {
  1322.                     s->queue += diff;
  1323.                     s->queuelen -= diff;
  1324.                 } else
  1325.                     movmem(s->data + diff, s->data, s->datalen );
  1326.         s->seqnum += ldiff;
  1327.             } else {
  1328. #ifdef DEBUG
  1329.     if(debug_on >1) printf("tcphandler confused so set unacked back to 0 from %u\n",s->unacked);
  1330. #endif DEBUG
  1331.                 s->unacked = 0;
  1332.             }
  1333.             if (s->unacked < 0) s->unacked = 0;
  1334.  
  1335.         s->flags = tcp_FlagACK;
  1336.         tcp_ProcessData(s, tp, len, &ph);
  1337.  
  1338.             if (( flags & tcp_FlagFIN ) && (s->state != tcp_StateCLOSWT )
  1339.                 && ( s->acknum == intel( tp->seqnum ))) {
  1340.                 s->acknum ++;
  1341.                 if ( ! s->err_msg ) s->err_msg = "Connection closed";
  1342.                 s->state = tcp_StateCLOSWT;
  1343.                 tcp_send( s, __LINE__ );
  1344.                 s->state = tcp_StateLASTACK;
  1345.                 s->flags |= tcp_FlagFIN;
  1346.                 s->unhappy = true;
  1347.             }
  1348.  
  1349.             if ( diff > 0 || len > 0 ) {
  1350.                 /* need to update window, but how urgent ??? */
  1351.                 if ( diff > 0 || (len > (s->mss >> 1))) {
  1352.                     tcp_send( s, __LINE__ );
  1353.                 } else
  1354.                     tcp_sendsoon( s );
  1355.  
  1356.             }
  1357.             if ( s->state == tcp_StateESTCL )
  1358.                 tcp_close( s );
  1359.             return;
  1360.  
  1361.     case tcp_StateFINWT1:
  1362.         /* They have not necessarily read all the data yet, we must
  1363.            still supply it as requested */
  1364.  
  1365.         ldiff = intel( tp->acknum ) - s->seqnum;
  1366.         diff = (int) ldiff;
  1367.         if ( ldiff >= 0 && diff <= s->datalen ) {
  1368.         s->datalen -= diff;
  1369.                 s->unacked -= diff;
  1370.                 if (s->datalen < 0) s->datalen = 0;
  1371.                 if ( s->queuelen ) {
  1372.                     s->queue += diff;
  1373.                     s->queuelen -= diff;
  1374.                 } else
  1375.                     movmem(s->data + diff, s->data, s->datalen );
  1376.         s->seqnum += ldiff;
  1377.                 if (ldiff == 0 || s->unacked < 0) s->unacked = 0;
  1378.  
  1379.         }
  1380.  
  1381.         /* they may still be transmitting data, we must read it */
  1382.  
  1383.         tcp_ProcessData(s, tp, len, &ph);
  1384.  
  1385.         /* check if other tcp has acked all sent data and is ready
  1386.            to change states */
  1387.  
  1388.             if ( (flags & (tcp_FlagFIN|tcp_FlagACK) ) == (tcp_FlagFIN|tcp_FlagACK)) {
  1389.         /* trying to do similtaneous close */
  1390.         if (( intel( tp->acknum ) >= s->seqnum + 1 ) &&
  1391.             ( intel( tp->seqnum) == s->acknum )) {
  1392.             s->seqnum++;
  1393. // we shouldn't be inc'ing the ack
  1394. //                  s->acknum++;
  1395.                     s->flags = tcp_FlagACK;
  1396.                     tcp_send( s, __LINE__ );
  1397.                     s->unhappy = false;
  1398.                     s->timeout = set_timeout( 2 );
  1399.                     s->state = tcp_StateCLOSED;
  1400.         }
  1401.         } else if ( flags & tcp_FlagACK ) {
  1402.         /* other side is legitimately acking our fin */
  1403.         if (( intel( tp->acknum ) == s->seqnum + 1 ) &&
  1404.             ( intel( tp->seqnum ) == s->acknum ) &&
  1405.             (  s->datalen == 0 )) {
  1406.                         s->seqnum++;
  1407. // they are just acking our seq num, not sending more data for us to ack
  1408. //                      s->acknum++;
  1409.                         s->state = tcp_StateFINWT2;
  1410.                         s->timeout = set_timeout( 3 );
  1411.                         s->unhappy = false; /* we don't send anything */
  1412.         }
  1413.         }
  1414.         break;
  1415.  
  1416.     case tcp_StateFINWT2:
  1417.  
  1418.         /* they may still be transmitting data, we must read it */
  1419.         tcp_ProcessData(s, tp, len, &ph);
  1420.  
  1421.             if ((flags & (tcp_FlagACK | tcp_FlagFIN)) ==
  1422.                   (tcp_FlagACK | tcp_FlagFIN)) {
  1423.                 if (( intel( tp->acknum ) == s->seqnum) &&
  1424.             ( intel( tp->seqnum ) == s->acknum )) {
  1425.             s->acknum++;
  1426.             s->flags = tcp_FlagACK;
  1427.                     tcp_send( s, __LINE__ );
  1428.             s->unhappy = false;    /* we don't send anything */
  1429.             s->timeout = set_timeout( 2 );
  1430.                     s->state = tcp_StateCLOSED;
  1431.                     return;
  1432.                 }
  1433.         }
  1434.         break;
  1435.  
  1436.     case tcp_StateCLOSING:
  1437.         if ((flags & (tcp_FlagACK | tcp_FlagFIN)) == tcp_FlagACK ) {
  1438.         if (( tp->acknum == intel(s->seqnum) ) &&
  1439.             ( tp->seqnum == intel(s->acknum))) {
  1440.             s->state = tcp_StateTIMEWT;
  1441.             s->timeout = set_timeout( tcp_TIMEOUT );
  1442.             s->unhappy = false;
  1443.         }
  1444.         }
  1445.         break;
  1446.  
  1447.     case tcp_StateLASTACK:
  1448.         if ( flags & tcp_FlagFIN ) {
  1449.         /* they lost our two packets, back up */
  1450.         s->flags = tcp_FlagACK | tcp_FlagFIN;
  1451.                 tcp_send( s, __LINE__ );
  1452.                 s->unhappy = TRUE;  /* FALSE; */
  1453.                 return;
  1454.         } else {
  1455.         if (( intel( tp->acknum ) == (s->seqnum + 1 )) &&
  1456.             ( intel( tp->seqnum ) == s->acknum )) {
  1457.             s->state = tcp_StateCLOSED;     /* no 2msl necessary */
  1458.             s->unhappy = false;             /* we're done */
  1459.                         return;
  1460.             }
  1461.         }
  1462.         break;
  1463.  
  1464.     case tcp_StateTIMEWT:
  1465.             if ( flags & (tcp_FlagACK | tcp_FlagFIN) == (tcp_FlagACK | tcp_FlagFIN)) {
  1466.                 /* he needs an ack */
  1467.                 s->flags = tcp_FlagACK;
  1468.                 tcp_send( s, __LINE__ );
  1469.                 s->unhappy = false;
  1470.                 s->state = tcp_StateCLOSED;     /* support 2 msl in rst code */
  1471.             }
  1472.             break;
  1473.     }
  1474.     if (s->unhappy) tcp_sendsoon(s);
  1475. }
  1476.  
  1477. /*
  1478.  * Process the data in an incoming packet.
  1479.  * Called from all states where incoming data can be received: established,
  1480.  * fin-wait-1, fin-wait-2
  1481.  */
  1482. static void tcp_ProcessData(tcp_Socket *s, tcp_Header *tp, int len,
  1483.                                                    tcp_PseudoHeader *ph)
  1484. {
  1485.     long ldiff;
  1486.     int diff, x;
  1487.     word flags;
  1488.     byte *dp;
  1489.  
  1490.     word *options, numoptions, opt_temp;
  1491.  
  1492.     if ( s->stress > 0 ) s->stress--;
  1493.  
  1494.     if ( (s->window = intel16( tp->window )) > 0x7fff )
  1495.         s->window = 0x7fff;
  1496.  
  1497.     flags = intel16( tp->flags );
  1498.     ldiff = s->acknum - intel( tp->seqnum );
  1499.  
  1500.     if ( flags & tcp_FlagSYN ) ldiff--;  /* back up to 0 */
  1501.     diff = (int) ldiff;
  1502.  
  1503.     /* find the data portion */
  1504.     x = tcp_GetDataOffset(tp) << 2;    /* quadword to byte format */
  1505.     dp = (byte *)tp + x;
  1506.  
  1507.     /* process those options */
  1508.     if ( (numoptions = x - sizeof( tcp_Header )) != 0 ) {
  1509.     options = (word *)((byte *)(tp) + sizeof( tcp_Header));
  1510.     while ( numoptions-- > 0 ) {
  1511.         switch ( *options++ ) {
  1512.         case  0 : numoptions = 0;    /* end of options */
  1513.               break;
  1514.         case  1 : break;        /* nop */
  1515.  
  1516.               /* we are very liberal on MSS stuff */
  1517.         case  2 : if (*options == 2) {
  1518.                   opt_temp = intel16( *(word*)(&options[1]));
  1519.                   if (opt_temp < s->mss )
  1520.                   s->mss = opt_temp;
  1521.               }
  1522.               numoptions -= 2 + *options;
  1523.               options += *options;
  1524.               break;
  1525.         }
  1526.     }
  1527.     }
  1528.     /* done option processing */
  1529.  
  1530.     len -= x;        /* remove the header length */
  1531.     if ( ldiff >= 0 ) {  /* skip already received bytes */
  1532.     dp += diff;
  1533.     len -= diff;
  1534.  
  1535.     if (s->dataHandler) {
  1536.         s->acknum += s->dataHandler(s, dp, len, ph, tp);  // 94.11.19
  1537. //        s->acknum += s->dataHandler(s, dp, len);
  1538.     } else {
  1539.         /* no handler, just dump to buffer, should be indexed, handles goofs */
  1540.         /* limit receive size to our window */
  1541.         if ( s->rdatalen >= 0 ) {
  1542.                 if ( len > ( x = s->maxrdatalen - s->rdatalen )) {
  1543.             len = x;
  1544.                 }
  1545.         if ( len > 0 ) {
  1546.             s->acknum += len;    /* our new ack begins at end of data */
  1547.                     movmem(dp, s->rdata + s->rdatalen, len );
  1548.             s->rdatalen += len;
  1549. /*
  1550.                     s->karn_count = 3;
  1551. */
  1552.         }
  1553.         }
  1554.         }
  1555.         s->unhappy = (s->datalen) ? true : false;
  1556.         if (ldiff == 0 && s->unacked && chk_timeout( s->rtt_lasttran )) {
  1557. #ifdef DEBUG
  1558.             if(debug_on >1) printf("data process timeout so set unacked back to 0 from %u\n",s->unacked);
  1559. #endif DEBUG
  1560.             s->unacked = 0;
  1561.         }
  1562.     } else {
  1563.         tcp_sendsoon( s );
  1564.     }
  1565.  
  1566.     s->timeout = set_timeout( tcp_TIMEOUT );
  1567.     return;
  1568. }
  1569.  
  1570. /*
  1571.  * Format and send an outgoing segment
  1572.  */
  1573.  
  1574. static void tcp_send( tcp_Socket *s, int line )
  1575. {
  1576.     tcp_PseudoHeader ph;
  1577.     struct _pkt {
  1578.     in_Header in;
  1579.     tcp_Header tcp;
  1580.     word maxsegopt[2];
  1581.     } *pkt;
  1582.     byte *dp;
  1583.     in_Header *inp;
  1584.     tcp_Header *tcpp;
  1585.     int senddatalen, sendtotlen, sendpktlen, startdata, sendtotdata;
  1586.  
  1587.     int ippkt;         /* 1..s->cwindow */
  1588.  
  1589.     s->recent = 0;
  1590.     pkt = (struct _pkt *)_eth_formatpacket(&s->hisethaddr, /*0x800*/ 8);
  1591.     dp = (byte *) &pkt->maxsegopt;  /* dp constant for multi-packet sends */
  1592.     inp = &pkt->in;
  1593.     tcpp = &pkt->tcp;
  1594.  
  1595.  
  1596.     /* this is our total possible send size */
  1597.     if ( s->karn_count != 2 ) {
  1598.         /* BUG FIX : jason dent found this */
  1599. /*      sendtotdata = min( s->datalen - s->unacked, s->window );  */
  1600.         sendtotdata = max (min ( s->datalen, s->window ) - s->unacked, 0);
  1601.         startdata = s->unacked;
  1602.     } else {
  1603.         sendtotdata = (s->datalen >= s->window)? s->window : s->datalen;
  1604.         startdata = 0;
  1605.     }
  1606. /*
  1607.     if (sendtotdata < 0) sendtotdata = 0;
  1608. */
  1609.     sendtotlen = 0;    /* running count of what we've sent */
  1610.  
  1611.     /* step through our packets */
  1612.     for ( ippkt = 1; ippkt <= s->cwindow; ++ippkt ) {
  1613.         /* adjust size for each packet */
  1614.         senddatalen = min( sendtotdata, s->mss );
  1615.  
  1616.     /*
  1617.         sendpktlen = senddatalen + sizeof( tcp_Header ) + sizeof( in_Header );
  1618.         inp->length = intel16( sendpktlen );
  1619.     */
  1620.         /* tcp header */
  1621.         tcpp->srcPort = intel16( s->myport );
  1622.         tcpp->dstPort = intel16( s->hisport );
  1623.         tcpp->seqnum = intel( s->seqnum + startdata ); /* unacked - no longer sendtotlen */
  1624.         tcpp->acknum = intel( s->acknum );
  1625.  
  1626.         tcpp->window = intel16( s->maxrdatalen - s->rdatalen );
  1627.         tcpp->flags = intel16( s->flags | 0x5000 );
  1628.         tcpp->checksum = 0;
  1629.         tcpp->urgentPointer = 0;
  1630.  
  1631.         /* do options if this is our first packet */
  1632.         if ( s->flags & tcp_FlagSYN ) {
  1633.             sendpktlen = sizeof( tcp_Header ) + sizeof( in_Header ) + 4;
  1634.             tcpp->flags = intel16( intel16( tcpp->flags) + 0x1000 );
  1635.             pkt->maxsegopt[0] = 0x0402;
  1636.             pkt->maxsegopt[1] = intel16( s->mss );
  1637.             dp += 4;
  1638.         } else {
  1639.             /* handle packets with data */
  1640.             if (senddatalen > 0) {
  1641.                 sendpktlen = senddatalen + sizeof( tcp_Header ) + sizeof( in_Header );
  1642.  
  1643.                 /* get data from appropriate place */
  1644.                 if (s->queuelen) movmem(s->queue + startdata, dp, senddatalen );
  1645.                 else movmem(s->data + startdata, dp, senddatalen);
  1646. /*                dp[ senddatalen ] = 0; */
  1647.             } else {
  1648.             /* handle no-data, not-first-SYN packets */
  1649.                 sendpktlen = sizeof( tcp_Header ) + sizeof( in_Header );
  1650.             }
  1651.         }
  1652.  
  1653.         /* internet header */
  1654.         memset( inp, 0, sizeof( in_Header ));
  1655.         inp->ver = 4;
  1656.         inp->hdrlen = 5;
  1657.         inp->tos = s->tos;
  1658.         inp->identification = intel16( ++ip_id );   /* was post inc */
  1659. //        inp->frag = 0;
  1660.         inp->ttl = 254;
  1661.         inp->proto = TCP_PROTO;
  1662.         inp->checksum = 0;
  1663.         inp->source = intel( s->myaddr );
  1664.         inp->destination = intel( s->hisaddr );
  1665.         inp->length = intel16( sendpktlen );
  1666.  
  1667.         inp->checksum = ~checksum( inp, sizeof(in_Header));
  1668.  
  1669.         /* compute tcp checksum */
  1670.         ph.src = inp->source;   /* already INTELled */
  1671.         ph.dst = inp->destination;
  1672.         ph.mbz = 0;
  1673.         ph.protocol = 6;
  1674.         ph.length = intel16( sendpktlen - sizeof(in_Header));
  1675. /*
  1676.         ph.checksum = checksum(&pkt->tcp, (sendpktlen - sizeof(in_Header) +1) & 0xfffe);
  1677. */
  1678.         ph.checksum = checksum(&pkt->tcp, sendpktlen - sizeof(in_Header));
  1679.  
  1680.         tcpp->checksum = ~checksum(&ph, sizeof(ph));
  1681.  
  1682.         if (_dbugxmit) (*_dbugxmit)( (sock_type *)s, inp, tcpp, line );
  1683.         if (debug_on > 1) {
  1684.             mono[0]++;
  1685.             colour[0]++;
  1686.             mono[2] = colour[2] = (s->flags & tcp_FlagSYN) ? 'S' : ' ';
  1687.             mono[4] = colour[4] = (s->flags & tcp_FlagACK) ? 'A' : ' ';
  1688.             mono[6] = colour[6] = (s->flags & tcp_FlagFIN) ? 'F' : ' ';
  1689.             mono[8] = colour[8] = (s->flags & tcp_FlagRST) ? 'R' : ' ';
  1690.         }
  1691.         if ( _eth_send( intel16( inp->length ))) { /* encounterred error */
  1692.             tcp_sendsoon( s );
  1693.             return;
  1694.         }
  1695.  
  1696.         /* do next ip pkt */
  1697.         sendtotlen += senddatalen;
  1698.         startdata += senddatalen;
  1699.         sendtotdata -= senddatalen;
  1700.         if (sendtotdata <= 0 ) break;
  1701.     }
  1702.     s->unacked = startdata;
  1703. #ifdef DEBUG
  1704. if (debug_on) printf(" Sent %u/%u bytes in %u/%u packets  with (%u) unacked  SYN %lu  line %u\n",
  1705.         sendtotlen, s->window, (ippkt-1), s->cwindow, s->unacked, s->seqnum, line);
  1706. #endif DEBUG
  1707.     s->vj_last = 0;
  1708.     if ( s->karn_count == 2 ) {
  1709.         if (s->rto) s->rto = (s->rto * 3) / 2;
  1710.         else s->rto = 4;
  1711.     } else {
  1712.         /* vj_last nonzero if we expect an immediate response */
  1713.         if (s->unhappy || s->datalen)
  1714.             s->vj_last = set_ttimeout( 0 );
  1715.     s->karn_count = 0;
  1716.     }
  1717.     s->rtt_time = set_ttimeout( s->rto + 2 );
  1718.     if (sendtotlen > 0 ) s->rtt_lasttran =  s->rtt_time + s->rto;
  1719. }
  1720.  
  1721. /*
  1722.  * Format and send a reset tcp packet
  1723.  */
  1724. static void tcp_rst( in_Header *his_ip, tcp_Header *oldtcpp )
  1725. {
  1726.     tcp_PseudoHeader ph;
  1727.     struct _pkt {
  1728.         in_Header in;
  1729.         tcp_Header tcp;
  1730.     word maxsegopt[2];
  1731.     } *pkt;   /*, *his_pkt; */
  1732.  
  1733.     static longword nextrst = 0L;
  1734.     word oldflags;
  1735.     in_Header *inp;
  1736.     tcp_Header *tcpp;
  1737.     eth_Header *eth;
  1738.     int sendtotlen;    /* length of packet */
  1739.     int temp;
  1740. #ifdef NEVER
  1741.     longword templong;
  1742. #endif
  1743.  
  1744.     /* see RFC 793 page 65 for details */
  1745.  
  1746.     if ( !chk_timeout( nextrst )) return;
  1747.     nextrst = set_ttimeout( 1 );
  1748.  
  1749.     oldflags = intel16( oldtcpp->flags );
  1750.     if (oldflags & tcp_FlagRST ) return;
  1751. #ifdef NEVER
  1752.     if ( (oldflags & (tcp_FlagACK | tcp_FlagFIN)) == (tcp_FlagACK | tcp_FlagFIN) ){
  1753.         templong = oldtcpp->seqnum;
  1754.         oldtcpp->seqnum = oldtcpp->acknum;
  1755.         oldtcpp->acknum = templong;
  1756.         oldflags = tcp_FlagACK;
  1757.     } else if ((oldflags & (tcp_FlagSYN | tcp_FlagACK)) ==  tcp_FlagSYN ) {
  1758.         oldtcpp->acknum = intel( intel( oldtcpp->seqnum ) + 1 );
  1759.         oldtcpp->seqnum = 0;
  1760.         oldflags = tcp_FlagACK | tcp_FlagRST;
  1761.     } else if ( oldflags & tcp_FlagACK ) {
  1762.         oldtcpp->seqnum = oldtcpp->acknum;
  1763.         oldtcpp->acknum = 0;
  1764.     } else {
  1765.         oldtcpp->acknum = intel( intel(oldtcpp->seqnum) + 1);
  1766.         oldtcpp->seqnum = 0;
  1767.     }
  1768.     if ( oldflags & ( tcp_FlagFIN | tcp_FlagSYN ) == 0 )
  1769.         oldflags ^= tcp_FlagACK | tcp_FlagRST;
  1770.  
  1771.     if ( oldflags & tcp_FlagACK ) {
  1772.         oldtcpp->seqnum = oldtcpp->acknum;
  1773.  
  1774. #else
  1775.     /* better strategy - Dean Roth */
  1776.     if ( oldflags & tcp_FlagACK ) {
  1777.         oldtcpp->seqnum = oldtcpp->acknum;
  1778.         oldtcpp->acknum = 0;
  1779.         oldflags = tcp_FlagRST;
  1780.     } else if ((oldflags & (tcp_FlagSYN | tcp_FlagACK)) ==  tcp_FlagSYN ) {
  1781.         oldtcpp->acknum = intel( intel( oldtcpp->seqnum ) + 1 );
  1782.         oldtcpp->seqnum = 0;
  1783.         oldflags = tcp_FlagACK | tcp_FlagRST;
  1784.     } else {
  1785.         temp = intel16( his_ip->length) - in_GetHdrlenBytes( his_ip );
  1786.         oldtcpp->acknum = intel( intel( oldtcpp->seqnum ) + temp );
  1787.         oldtcpp->seqnum = 0;
  1788.         oldflags = tcp_FlagRST;
  1789.     }
  1790. #endif
  1791.  
  1792. /* 94.11.19 -- removed, not used? */
  1793. /*    his_pkt  = (struct _pkt*)( his_ip );  */
  1794.  
  1795.     /* convoluted mechanism - reads his ethernet address or garbage */
  1796.     eth = _eth_hardware( (byte *)his_ip );
  1797.  
  1798.     pkt = (struct _pkt *)_eth_formatpacket( (eth_address *)eth, 8);
  1799.     inp = &pkt->in;
  1800.     tcpp = &pkt->tcp;
  1801.  
  1802.     sendtotlen = sizeof( tcp_Header ) + sizeof( in_Header );
  1803.     memset( inp, 0, sizeof( in_Header ));
  1804.     inp->length = intel16( sendtotlen );
  1805.  
  1806.     /* tcp header */
  1807.     tcpp->srcPort = oldtcpp->dstPort;
  1808.     tcpp->dstPort = oldtcpp->srcPort;
  1809.     tcpp->seqnum = oldtcpp->seqnum;
  1810.     tcpp->acknum = oldtcpp->acknum;
  1811.     tcpp->window = 0;
  1812. /*    tcpp->flags = intel16( oldflags ); */
  1813.     /* BUG FIX : jason dent found this thanks to SCO */
  1814.     tcpp->flags = intel16( (oldflags & 0x0fff ) | 0x5000 );
  1815.     tcpp->checksum = 0;
  1816.     tcpp->urgentPointer = 0;
  1817.  
  1818.     /* internet header */
  1819.     inp->ver = 4;
  1820.     inp->hdrlen = 5;
  1821.     inp->tos = his_ip->tos;
  1822.     inp->identification = intel16( ++ip_id );
  1823. //    inp->frag = 0;
  1824.     inp->ttl = 254;
  1825.     inp->proto = TCP_PROTO;
  1826.     inp->checksum = 0;
  1827.     inp->source = his_ip->destination;
  1828.     inp->destination = his_ip->source;
  1829.  
  1830.     inp->checksum = ~checksum( inp, sizeof(in_Header))/* 0*/;
  1831.  
  1832.     /* compute tcp checksum */
  1833.     ph.src = inp->source;    /* already INTELled */
  1834.     ph.dst = inp->destination;
  1835.     ph.mbz = 0;
  1836.     ph.protocol = 6;
  1837.     ph.length = intel16( sendtotlen - sizeof(in_Header));
  1838.  
  1839.     ph.checksum = checksum(&pkt->tcp, sizeof(tcp_Header));
  1840.     tcpp->checksum =  ~checksum(&ph, sizeof(ph));
  1841.  
  1842.     if (_dbugxmit) (*_dbugxmit)(NULL,inp,tcpp,__LINE__);
  1843.     _eth_send( intel16( inp->length ));
  1844. }
  1845.  
  1846.  
  1847. /**********************************************************************
  1848.  * socket functions
  1849.  **********************************************************************/
  1850.  
  1851. /* socket based stuff */
  1852.  
  1853. /*
  1854.  * sock_read - read a socket with maximum n bytes
  1855.  *         - busywaits until buffer is full but calls s->usr_yield
  1856.  *         - returns count also when connection gets closed
  1857.  */
  1858. int sock_read( sock_type *s, byte *dp, int len )
  1859. {
  1860.     int templen, count;
  1861.     count = 0;
  1862.     do {
  1863.     if ( s->udp.ip_type == UDP_PROTO )
  1864.             templen = udp_read( &(s->udp), dp, len );
  1865.     else
  1866.             templen = tcp_read( &(s->tcp), dp, len);
  1867.         if (s->tcp.usr_yield) (s->tcp.usr_yield)();
  1868.         if (templen < 1 ) {
  1869.             if (!tcp_tick( s )) return( count );
  1870.         } else {
  1871.             count += templen;
  1872.             dp += templen;
  1873.             len -= templen;
  1874.         }
  1875.     } while ( len );
  1876.     return( count );
  1877. }
  1878.  
  1879. /*
  1880.  * sock_fead - read a socket with maximum n bytes
  1881.  *         - does not busywait until buffer is full
  1882.  */
  1883. int sock_fastread( sock_type *s, byte *dp, int len )
  1884. {
  1885.     if ( s->udp.ip_type == UDP_PROTO )
  1886.         len = udp_read( &(s->udp), dp, len );
  1887.     else
  1888.         len = tcp_read( &(s->tcp), dp, len);
  1889.     return( len );
  1890. }
  1891.  
  1892.  
  1893. /*
  1894.  * sock_write - writes data and returns length written
  1895.  *          - does not perform flush
  1896.  *          - repeatedly calls s->usr_yield
  1897.  */
  1898.  
  1899. int sock_write( sock_type *s, byte *dp, int len )
  1900. {
  1901.     int offset, oldlen, oldmode, proto;
  1902.  
  1903.     oldlen = len;
  1904.     offset = 0;
  1905.  
  1906.     proto = (s->udp.ip_type == TCP_PROTO);
  1907.     if ( proto ) oldmode = s->tcp.flags & tcp_FlagPUSH;
  1908.     while ( len  > 0) {
  1909.         if (proto) {
  1910.             s->tcp.flags |= oldmode;
  1911.             offset += tcp_write( &(s->tcp), &dp[ offset ], len);
  1912.         } else
  1913.             offset += udp_write( &(s->udp), &dp[ offset ], len, offset );
  1914.     len = oldlen - offset;
  1915.     if (s->udp.usr_yield)(s->udp.usr_yield)();
  1916.     if (!tcp_tick(s)) return( 0 );
  1917.     }
  1918.     return( oldlen );
  1919. }
  1920.  
  1921.  
  1922. /* NOTE: for UDP, assumes data fits in one datagram, else only the first
  1923.        fragment will be sent!!!!!  Because _mss is used for splits,
  1924.        by default the max data size is 1400 - UDP_LENGTH for a non-fragged
  1925.        datagram.
  1926.  */
  1927. int sock_fastwrite( sock_type *s, byte *dp, int len )
  1928. {
  1929.     return( ( s->udp.ip_type == UDP_PROTO ) ?
  1930.         udp_write( &(s->udp), dp, len, 0 ) :
  1931.         tcp_write( &(s->tcp), dp, len) );
  1932. }
  1933.  
  1934. int sock_setbuf( sock_type *s, byte *dp, int len )
  1935. {
  1936.     if ( len < 0 ) return( 0 );
  1937.     if (len == 0 || dp == NULL ) {
  1938.         s->tcp.rdata = s->tcp.rddata;
  1939.         s->tcp.maxrdatalen = tcp_MaxBufSize;
  1940.     } else {
  1941.         s->tcp.rdata = dp;
  1942.         s->tcp.maxrdatalen = len;
  1943.     }
  1944.     return( s->tcp.maxrdatalen);
  1945. }
  1946.  
  1947. int sock_enqueue( sock_type *s, byte *dp, int len )
  1948. {
  1949.     int written;
  1950.     word offset = 0;
  1951.  
  1952.     if ( len < 0 ) return( 0 );
  1953.     if ( s->udp.ip_type == UDP_PROTO ) {
  1954.         do {
  1955.             written = udp_write( &(s->udp), dp, len, offset );
  1956.             dp += written;
  1957.             offset += written;
  1958.         } while (len -= written > 0);
  1959.     } else {
  1960.         s->tcp.queue = dp;
  1961.         s->tcp.queuelen = len;
  1962.         s->tcp.datalen = len;
  1963.         tcp_send( &(s->tcp), __LINE__ );  /* start sending it */
  1964.     }
  1965.     return( len );
  1966. }
  1967.  
  1968. void sock_noflush( sock_type *s )
  1969. {
  1970.     if ( s->tcp.ip_type == TCP_PROTO ) {
  1971.     s->tcp.flags &= ~tcp_FlagPUSH;
  1972.     s->tcp.sock_mode |= TCP_LOCAL ;
  1973.     }
  1974. }
  1975.  
  1976. void sock_flush( sock_type *s )
  1977. {
  1978.     if ( s->tcp.ip_type == TCP_PROTO ) {
  1979.         s->tcp.sock_mode &= ~TCP_LOCAL;
  1980.     tcp_Flush( &(s->tcp) );
  1981.     }
  1982. }
  1983.  
  1984. /*
  1985.  * sock_flushnext - cause next transmission to have a flush
  1986.  */
  1987. void sock_flushnext( sock_type *s)
  1988. {
  1989.     if (s->tcp.ip_type == TCP_PROTO ) {
  1990.         s->tcp.flags |= tcp_FlagPUSH;
  1991.         s->tcp.sock_mode &= ~TCP_LOCAL;
  1992.     }
  1993. }
  1994.  
  1995. /*
  1996.  * sock_putc - put a character
  1997.  *         - no expansion but flushes on '\n'
  1998.  *         - returns character
  1999.  */
  2000. byte sock_putc( sock_type *s, byte c )
  2001. {
  2002.     if (( c == '\n') || ( c == '\r'))
  2003.     sock_flushnext( s );
  2004.     sock_write( s, &c, 1 );
  2005.     return( c );
  2006. }
  2007.  
  2008. int sock_getc( sock_type *s )
  2009. {
  2010.     char ch;
  2011.     return( sock_read( s, &ch, 1 ) < 1 ? EOF : ch );
  2012. }
  2013.  
  2014. /*
  2015.  * sock_puts - does not append carriage return in binary mode
  2016.  *         - returns length
  2017.  */
  2018. int sock_puts( sock_type *s, byte *dp )
  2019. {
  2020.     int len;   /*, oldmode;*/
  2021.  
  2022.     len = strlen( dp );
  2023.  
  2024.     if (s->tcp.sock_mode & TCP_MODE_ASCII ) {
  2025.         if (s->tcp.ip_type == TCP_PROTO )
  2026.             s->tcp.sock_mode |= TCP_LOCAL;
  2027.         sock_noflush( s );
  2028.         if (len) sock_write( s, dp, len );
  2029.         sock_flushnext( s );
  2030.         sock_write( s, "\r\n", 2 );
  2031.     } else {
  2032.         sock_flushnext( s );
  2033.         sock_write( s, dp, len );
  2034.     }
  2035.     return( len );
  2036. }
  2037.  
  2038. /*
  2039.  * sock_update - update the socket window size to the other guy
  2040.  */
  2041. static void sock_update( tcp_Socket *s )
  2042. {
  2043.     if (s->ip_type == TCP_PROTO) {
  2044.         if ( !s->rdatalen )
  2045.             tcp_send( s, __LINE__ );              /* update the window */
  2046.     else
  2047.         tcp_sendsoon( s );
  2048.     }
  2049. }
  2050.  
  2051. /*
  2052.  * sock_gets - read a string from any socket
  2053.  *         - return length of returned string
  2054.  *           - removes end of line terminator(s)
  2055.  *
  2056.  *           - Quentin Smart fixed some problems
  2057.  */
  2058. int sock_gets( sock_type *s, byte *dp, int n )
  2059. {
  2060.     int len, *np;
  2061.     char *src_p, *temp, *temp2;
  2062.  
  2063.     if ( s->udp.ip_type == UDP_PROTO ) {
  2064.     src_p = s->udp.rdata;
  2065.     np = &s->udp.rdatalen;
  2066.     } else {
  2067.     src_p = s->tcp.rdata;
  2068.     np = &s->tcp.rdatalen;
  2069.     }
  2070.     if ( *np == 0 ) return( 0 );
  2071.  
  2072.     // eat trailing \n or \0 from previous line
  2073.     if ( *src_p == 0 || *src_p == '\n' ) {
  2074.         movmem( src_p + 1, src_p, *np -= 1 );
  2075.         if ( !*np ) return( 0 );
  2076.     }
  2077.  
  2078.     if ( --n > *np ) n = *np;
  2079.  
  2080.     // Q.Smart found and fixed a bug here
  2081.     memcpy( dp, src_p, n );     // copy everything
  2082.     dp[ n ] = 0;                // terminate new string
  2083.     temp = memchr( dp, '\n', n);
  2084.     temp2= memchr( dp, '\r', n);
  2085.  
  2086.     if (temp)  *temp = 0;
  2087.     if (temp2) *temp2= 0;
  2088.  
  2089.     // skip if there were no crs
  2090.     if ( !temp2 ) {
  2091.         *dp = 0;
  2092.         return( 0 );
  2093.     }
  2094.  
  2095. //  not: len = strlen( dp );
  2096.     len = (int)(( temp ? min( FP_OFF(temp), FP_OFF(temp2)) :
  2097.         FP_OFF(temp2)) - FP_OFF(dp));
  2098.  
  2099.     // expect \r\n or \r\0 or \n or \r
  2100.     // so get first of the two
  2101.  
  2102.     if ( temp == NULL ) {       /* handles \r only */
  2103.         temp = temp2;
  2104.         temp2 = NULL;
  2105.     } else if ( FP_OFF( temp ) > FP_OFF( temp2 ))
  2106.         temp = temp2;           // handles trailing \n or \0
  2107.  
  2108.     n = len + 1;                // account for first \r
  2109.  
  2110.     // we check next char if it exists, and skip it if 0, \r, or \n
  2111.     if ((*np > n) && !src_p[n] ) n++;
  2112.     movmem( &src_p[ n ], src_p, *np -= n );
  2113.     if (*np < 0) *np = 0;
  2114.  
  2115.     sock_update( &(s->tcp) );   /* new window */
  2116.     return( len );
  2117. }
  2118.  
  2119.  
  2120. /*
  2121.  * sock_dataready - returns number of bytes waiting to be ready
  2122.  *          - if in ASCII mode, return 0 until a line is present
  2123.  *            or the buffer is full
  2124.  */
  2125. int sock_dataready( sock_type *s )
  2126. {
  2127.     int len;
  2128.     char *p;
  2129.  
  2130.     if (!(len = s->tcp.rdatalen)) return( 0 );
  2131.  
  2132.     if ( s->tcp.sock_mode & TCP_MODE_ASCII ) {
  2133.         p = s->tcp.rdata;
  2134.         if ( *p == '\n' ) {
  2135.             movmem( p + 1, p, s->tcp.rdatalen = --len);
  2136.             if ( ! len ) return( 0 );
  2137.         }
  2138.         /* check for terminating \r */
  2139.         if ( memchr( p, '\r', len))
  2140.             return( len );
  2141.         return( 0 );
  2142.     } else
  2143.         return( len );
  2144. }
  2145.  
  2146. int sock_established( sock_type *s )
  2147. {
  2148.     switch ( s->tcp.ip_type ) {
  2149.     case UDP_PROTO :
  2150.         return( 1 );
  2151.     case TCP_PROTO :
  2152.                 return( s->tcp.state == tcp_StateESTAB ||
  2153.                         s->tcp.state == tcp_StateESTCL ||
  2154.                         s->tcp.state == tcp_StateCLOSWT );
  2155.     default :
  2156.         return( 0 );
  2157.     }
  2158. }
  2159.  
  2160. void sock_close( sock_type *s )
  2161. {
  2162.     switch (s->udp.ip_type) {
  2163.     case UDP_PROTO :
  2164.         udp_close( &(s->udp) );
  2165.         break;
  2166.     case TCP_PROTO :
  2167.         tcp_close( &(s->tcp) );
  2168.         tcp_tick( s );
  2169.         break;
  2170.     }
  2171. }
  2172.  
  2173. void sock_sturdy( sock_type *s, int level )
  2174. {
  2175.     s->tcp.rigid = level;
  2176.     if ( s->tcp.rigid < s->tcp.stress ) sock_abort( s );
  2177. }
  2178.  
  2179. /*
  2180.  * _ip_delay0 called by macro sock_wait_established()
  2181.  * _ip_delay1 called by macro sock_wait_intput()
  2182.  * _ip_delay2 called by macro sock_wait_closed();
  2183.  *
  2184.  */
  2185.  
  2186. int _ip_delay0( sock_type *s, int timeoutseconds, sockfunct_t fn, int *statusptr )
  2187. {
  2188.     int status;
  2189.     ip_timer_init( s , timeoutseconds );
  2190.     do {
  2191.     if ( s->tcp.ip_type == TCP_PROTO ) {
  2192.         if ( tcp_established( &(s->tcp) )) {
  2193.         status = 0;
  2194.         break;
  2195.         }
  2196.     }
  2197.     kbhit();    /* permit ^c */
  2198.     if ( !tcp_tick( s )) {
  2199.              if (!s->tcp.err_msg) s->tcp.err_msg = "Host refused connection";
  2200.          status = -1;    /* get an early reset */
  2201.          break;
  2202.     }
  2203.     if ( ip_timer_expired( s )) {
  2204.             s->tcp.err_msg = "Open timed out";
  2205.             sock_close( s );
  2206.         status = -1;
  2207.         break;
  2208.     }
  2209.     if ( (fn != NULL) && ((status = fn(s)) != 0) ) break;
  2210.     if ( s->tcp.usr_yield ) (*s->tcp.usr_yield)();
  2211.     if ( s->tcp.ip_type == UDP_PROTO ) {
  2212.         status = 0;
  2213.         break;
  2214.     }
  2215.     } while ( 1 );
  2216.     if (statusptr) *statusptr = status;
  2217.     return( status );
  2218. }
  2219.  
  2220. int _ip_delay1( sock_type *s, int timeoutseconds, sockfunct_t fn, int *statusptr)
  2221. {
  2222.     int status;
  2223.     ip_timer_init( s , timeoutseconds );
  2224.  
  2225.     sock_flush( s );    /* new enhancement */
  2226.  
  2227.     do {
  2228.     if ( sock_dataready( s )) {
  2229.         status = 0;
  2230.         break;
  2231.     }
  2232.     kbhit();    /* permit ^c */
  2233.  
  2234.     if ( !tcp_tick( s )) {
  2235.         status = 1;
  2236.         break;
  2237.     }
  2238.     if ( ip_timer_expired( s )) {
  2239.             s->tcp.err_msg = "Connection timed out";
  2240.             sock_close( s );
  2241.         status = -1;
  2242.         break;
  2243.     }
  2244.     if (fn) {
  2245.         if ((status = fn(s)) != 0)
  2246.         break;
  2247.     }
  2248.     if ( s->tcp.usr_yield ) (*s->tcp.usr_yield)();
  2249.     } while ( 1 );
  2250.     if (statusptr) *statusptr = status;
  2251.     return( status );
  2252. }
  2253.  
  2254. int _ip_delay2( sock_type *s, int timeoutseconds, sockfunct_t fn, int *statusptr)
  2255. {
  2256.     int status;
  2257.     ip_timer_init( s , timeoutseconds );
  2258.  
  2259.     if (s->tcp.ip_type != TCP_PROTO ) {
  2260.         if ( statusptr ) * statusptr = 1;
  2261.         return( 1 );
  2262.     }
  2263.  
  2264.     do {
  2265.         /* in this situation we KNOW user not planning to read rdata */
  2266.         s->tcp.rdatalen = 0;
  2267.     kbhit();    /* permit ^c */
  2268.     if ( !tcp_tick( s )) {
  2269.         status = 1;
  2270.         break;
  2271.     }
  2272.     if ( ip_timer_expired( s )) {
  2273.             s->tcp.err_msg = "Connection timed out";
  2274.         sock_abort( s );
  2275.         status = -1;
  2276.         break;
  2277.     }
  2278.     if (fn) {
  2279.         if ((status = fn(s)) != 0)
  2280.         break;
  2281.     }
  2282.     if ( s->tcp.usr_yield ) (*s->tcp.usr_yield)();
  2283.  
  2284.     } while ( 1 );
  2285.     if (statusptr) *statusptr = status;
  2286.     return( status );
  2287. }
  2288.  
  2289. char *rip( char *s )
  2290. {
  2291.     char *temp;
  2292.  
  2293.     if ((temp = strchr( s, '\n')) != NULL) *temp = '\0';
  2294.     if ((temp = strchr( s, '\r')) != NULL) *temp = '\0';
  2295.     return( s );
  2296. }
  2297.