home *** CD-ROM | disk | FTP | other *** search
/ ftp.wwiv.com / ftp.wwiv.com.zip / ftp.wwiv.com / pub / PPPBCKP / SRC15B21.ZIP / WATTSRC.ZIP / SRC / PCTCP.C < prev    next >
C/C++ Source or Header  |  1997-03-08  |  70KB  |  2,224 lines

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