home *** CD-ROM | disk | FTP | other *** search
/ GEMini Atari / GEMini_Atari_CD-ROM_Walnut_Creek_December_1993.iso / files / telecomm / nhclb120 / tcpin.c < prev    next >
C/C++ Source or Header  |  1993-09-26  |  24KB  |  916 lines

  1. /* Process incoming TCP segments. Page number references are to ARPA RFC-793,
  2.  * the TCP specification.
  3.  */
  4.  
  5. #include "global.h"
  6. #include "timer.h"
  7. #include "mbuf.h"
  8. #include "netuser.h"
  9. #include "internet.h"
  10. #include "tcp.h"
  11. #include "icmp.h"
  12. #include "iface.h"
  13. #include "ip.h"
  14.  
  15. static void update();
  16. static void reset();
  17. struct tcp_stat tcp_stat;
  18. static void proc_syn();
  19. static void add_reseq();
  20. static void get_reseq();
  21. static int trim();
  22. /* This function is called from IP with the IP header in machine byte order,
  23.  * along with a mbuf chain pointing to the TCP header.
  24.  */
  25. void
  26. tcp_input(bp,protocol,source,dest,tos,length,rxbroadcast)
  27. struct mbuf *bp;    /* Data field, if any */
  28. char protocol;        /* Should always be TCP_PTCL */
  29. int32 source;        /* Remote IP address */
  30. int32 dest;        /* Our IP address */
  31. char tos;        /* Type of Service */
  32. int16 length;        /* Length of data field */
  33. char rxbroadcast;    /* Incoming broadcast - discard if true */
  34. {
  35.     void reset(),update();
  36.     void proc_syn(),send_syn(),add_reseq(),get_reseq(),unlink_tcb();
  37.  
  38.     register struct tcb *tcb;    /* TCP Protocol control block */
  39.     struct tcp seg;            /* Local copy of segment header */
  40.     struct connection conn;        /* Local copy of addresses */
  41.     struct pseudo_header ph;    /* Pseudo-header for checksumming */
  42.     int hdrlen;            /* Length of TCP header */
  43.  
  44.     if(bp == NULLBUF)
  45.         return;
  46.  
  47.     if(rxbroadcast){
  48.         /* Any TCP packet arriving as a broadcast is
  49.          * to be completely IGNORED!!
  50.          */
  51.         tcp_stat.bdcsts++;
  52.         free_p(bp);
  53.         return;
  54.     }
  55.     ph.source = source;
  56.     ph.dest = dest;
  57.     ph.protocol = protocol;
  58.     ph.length = length;
  59.     if(cksum(&ph,bp,length) != 0){
  60.         /* Checksum failed, ignore segment completely */
  61.         tcp_stat.checksum++;
  62.         free_p(bp);
  63.         return;
  64.     }
  65.     /* Form local copy of TCP header in host byte order */
  66.     if((hdrlen = ntohtcp(&seg,&bp)) < 0){
  67.         /* TCP header is too small */
  68.         tcp_stat.runt++;
  69.         free_p(bp);
  70.         return;
  71.     }
  72.     /*
  73.      * internally, we keep the urgent pointer in sequence space,
  74.      */
  75.     seg.up = seg.up + seg.seq;
  76.     length -= hdrlen;
  77.  
  78.     /* Fill in connection structure and find TCB */
  79.     conn.local.address = dest;
  80.     conn.local.port = seg.dest;
  81.     conn.remote.address = source;
  82.     conn.remote.port = seg.source;
  83.     
  84.     if((tcb = lookup_tcb(&conn)) == NULLTCB){
  85.         struct tcb *ntcb;
  86.         void link_tcb();
  87.  
  88.         /* Check that this segment carries a SYN, and that
  89.          * there's a LISTEN on this socket with
  90.          * unspecified source address and port
  91.          */
  92.         conn.remote.address = 0;
  93.         conn.remote.port = 0;
  94.         if(!(seg.flags & SYN) || (tcb = lookup_tcb(&conn)) == NULLTCB){
  95.             /* No unspecified LISTEN either, so reject */
  96.             free_p(bp);
  97.             reset(source,dest,tos,length,&seg);
  98.             return;
  99.         }
  100.         /* We've found an server listen socket, so clone the TCB */
  101.         if(tcb->flags & CLONE){
  102.             if((ntcb = (struct tcb *)malloc(sizeof (struct tcb))) == NULLTCB){
  103.                 free_p(bp);
  104.                 /* This may fail, but we should at least try */
  105.                 reset(source,dest,tos,length,&seg);
  106.                 return;
  107.             }
  108.             ASSIGN(*ntcb,*tcb);
  109.             tcb = ntcb;
  110.             tcb->timer.arg = (char *)tcb;
  111.         } else
  112.             unlink_tcb(tcb);    /* It'll be put back on later */
  113.  
  114.         /* Stuff the foreign socket into the TCB */
  115.         tcb->conn.remote.address = source;
  116.         tcb->conn.remote.port = seg.source;
  117.  
  118.         /* NOW put on right hash chain */
  119.         link_tcb(tcb);
  120.     }
  121.     /* Do unsynchronized-state processing (p. 65-68) */
  122.     switch(tcb->state){
  123.     case CLOSED:
  124.         free_p(bp);
  125.         reset(source,dest,tos,length,&seg);
  126.         return;
  127.     case LISTEN:
  128.         if(seg.flags & RST){
  129.             free_p(bp);
  130.             return;
  131.         }
  132.         if(seg.flags & ACK){
  133.             free_p(bp);
  134.             reset(source,dest,tos,length,&seg);
  135.             return;
  136.         }
  137.         if(seg.flags & SYN){
  138.             /* (Security check is bypassed) */
  139.             /* page 66 */
  140.             tcp_stat.conin++;
  141.             proc_syn(tcb,tos,&seg);
  142.             send_syn(tcb);
  143.             setstate(tcb,SYN_RECEIVED);        
  144.             if(length != 0 || (seg.flags & FIN)) {
  145.                 break;        /* Continue processing if there's more */
  146.             }
  147.             tcp_output(tcb);
  148.         }
  149.         free_p(bp);    /* Unlikely to get here directly */
  150.         return;
  151.     case SYN_SENT:
  152.         if(seg.flags & ACK){
  153.             if(!seq_within(seg.ack,tcb->iss+1,tcb->snd.nxt)){
  154.                 free_p(bp);
  155.                 reset(source,dest,tos,length,&seg);
  156.                 return;
  157.             }
  158.         }
  159.         if(seg.flags & RST){    /* p 67 */
  160.             if(seg.flags & ACK){
  161.                 /* The ack must be acceptable since we just checked it.
  162.                  * This is how the remote side refuses connect requests.
  163.                  */
  164.                 close_self(tcb,RESET);
  165.             }
  166.             free_p(bp);
  167.             return;
  168.         }
  169.         /* (Security check skipped here) */
  170.         /* Check incoming precedence; it must match if there's an ACK */
  171.         if((seg.flags & ACK) && PREC(tos) != PREC(tcb->tos)){
  172.             free_p(bp);
  173.             reset(source,dest,tos,length,&seg);
  174.             return;
  175.         }
  176.         if(seg.flags & SYN){
  177.             proc_syn(tcb,tos,&seg);
  178.             if(seg.flags & ACK){
  179.                 /* Our SYN has been acked, otherwise the ACK
  180.                  * wouldn't have been valid.
  181.                  */
  182.                 update(tcb,&seg,length);
  183.                 setstate(tcb,ESTABLISHED);
  184.             } else {
  185.                 setstate(tcb,SYN_RECEIVED);
  186.             }
  187.             if(length != 0 || (seg.flags & FIN)) {
  188.                 break;        /* Continue processing if there's more */
  189.             }
  190.             tcp_output(tcb);
  191.         } else {
  192.             free_p(bp);    /* Ignore if neither SYN or RST is set */
  193.         }
  194.         return;
  195.     }
  196.     /* We reach this point directly in any synchronized state. Note that
  197.      * if we fell through from LISTEN or SYN_SENT processing because of a
  198.      * data-bearing SYN, window trimming and sequence testing "cannot fail".
  199.      */
  200.  
  201.     /* Trim segment to fit receive window. */
  202.     if(trim(tcb,&seg,&bp,&length) == -1){
  203.         /* Segment is unacceptable */
  204.         if(!(seg.flags & RST)){
  205.             tcb->flags |= FORCE;
  206.             tcp_output(tcb);
  207.         }
  208.         return;
  209.     }
  210.     /* If segment isn't the next one expected, and there's data
  211.      * or flags associated with it, put it on the resequencing
  212.      * queue, ACK it and return.
  213.      *
  214.      * Processing the ACK in an out-of-sequence segment without
  215.      * flags or data should be safe, however.
  216.      */
  217.     if(seg.seq != tcb->rcv.nxt
  218.      && (length != 0 || (seg.flags & (SYN|FIN)) )){
  219.         add_reseq(tcb,tos,&seg,bp,length);
  220.         tcb->flags |= FORCE;
  221.         tcp_output(tcb);
  222.         return;
  223.     }
  224.     /* This loop first processes the current segment, and then
  225.      * repeats if it can process the resequencing queue.
  226.      */
  227.     for(;;){
  228.         /* We reach this point with an acceptable segment; all data and flags
  229.          * are in the window, and the starting sequence number equals rcv.nxt
  230.          * (p. 70)
  231.          */    
  232.         if(seg.flags & RST){
  233.             if(tcb->state == SYN_RECEIVED
  234.              && !(tcb->flags & (CLONE|ACTIVE))){
  235.                 /* Go back to listen state only if this was
  236.                  * not a cloned or active server TCB
  237.                  */
  238.                 setstate(tcb,LISTEN);
  239.             } else {
  240.                 close_self(tcb,RESET);
  241.             }
  242.             free_p(bp);
  243.             return;
  244.         }
  245.         /* (Security check skipped here) p. 71 */
  246.         /* Check for precedence mismatch or erroneous extra SYN */
  247.         if(PREC(tos) != PREC(tcb->tos) || (seg.flags & SYN)){
  248.             free_p(bp);
  249.             reset(source,dest,tos,length,&seg);
  250.             return;
  251.         }
  252.         /* Check ack field p. 72 */
  253.         if(!(seg.flags & ACK)){
  254.             free_p(bp);    /* All segments after synchronization must have ACK */
  255.             return;
  256.         }
  257.         /* Process ACK */
  258.         switch(tcb->state){
  259.         case SYN_RECEIVED:
  260.             if(seq_within(seg.ack,tcb->snd.una+1,tcb->snd.nxt)){
  261.                 update(tcb,&seg,length);
  262.                 setstate(tcb,ESTABLISHED);
  263.             } else {
  264.                 free_p(bp);
  265.                 reset(source,dest,tos,length,&seg);
  266.                 return;
  267.             }
  268.             break;
  269.         case ESTABLISHED:
  270.         case CLOSE_WAIT:
  271.             update(tcb,&seg,length);
  272.             break;
  273.         case FINWAIT1:    /* p. 73 */
  274.             update(tcb,&seg,length);
  275.             if(tcb->sndcnt == 0){
  276.                 /* Our FIN is acknowledged */
  277.                 setstate(tcb,FINWAIT2);
  278.             }
  279.             break;
  280.         case FINWAIT2:
  281.             update(tcb,&seg,length);
  282.             break;
  283.         case CLOSING:
  284.             update(tcb,&seg,length);
  285.             if(tcb->sndcnt == 0){
  286.                 /* Our FIN is acknowledged */
  287.                 setstate(tcb,TIME_WAIT);
  288.                 tcb->timer.start = MSL2 * (1000 / MSPTICK);
  289.                 start_timer(&tcb->timer);
  290.             }
  291.             break;
  292.         case LAST_ACK:
  293.             update(tcb,&seg,length);
  294.             if(tcb->sndcnt == 0){
  295.                 /* Our FIN is acknowledged, close connection */
  296.                 close_self(tcb,NORMAL);
  297.                 return;
  298.             }            
  299. /* I think this is wrong, and can cause permanent ACK-ACK loops.  dmf.
  300.         case TIME_WAIT:
  301.             tcb->flags |= FORCE;
  302.             start_timer(&tcb->timer);
  303. */
  304.         }
  305.  
  306.         /* URGent bit processing */
  307.  
  308.         if(seg.flags & URG){
  309.             if ((tcb->flags & URGCUR) == 0 ||
  310.                 seq_gt(seg.up, tcb->rcv.up)) {
  311.                 tcb->flags |= URGCUR;
  312.                 tcb->rcv.up = seg.up;
  313.             }
  314.         }
  315.  
  316.         /* Process the segment text, if any, beginning at rcv.nxt (p. 74) */
  317.         if(length != 0){
  318.             switch(tcb->state){
  319.             case SYN_RECEIVED:
  320.             case ESTABLISHED:
  321.             case FINWAIT1:
  322.             case FINWAIT2:
  323.                 /* Place on receive queue */
  324.                 append(&tcb->rcvq,bp);
  325.                 tcb->rcvcnt += length;
  326.                 tcb->rcv.nxt += length;
  327.                 tcb->rcv.wnd -= length;
  328.                 tcb->flags |= FORCE;
  329.                 break;
  330.             default:
  331.                 /* Ignore segment text */
  332.                 free_p(bp);
  333.                 break;
  334.             }
  335.         }
  336.         /* If the user has set up a r_upcall function and there's
  337.          * data to be read, notify him.
  338.          *
  339.          * This is done before sending an acknowledgement,
  340.          * to give the user a chance to piggyback some reply data.
  341.          * It's also done before processing FIN so that the state
  342.          * change upcall will occur after the user has had a chance
  343.          * to read the last of the incoming data.
  344.          */
  345.         if(tcb->r_upcall && tcb->rcvcnt != 0){
  346.             (*tcb->r_upcall)(tcb,tcb->rcvcnt);
  347.         }
  348.         /* process FIN bit (p 75) */
  349.         if(seg.flags & FIN){
  350.             tcb->flags |= FORCE;    /* Always respond with an ACK */
  351.  
  352.             switch(tcb->state){
  353.             case SYN_RECEIVED:
  354.             case ESTABLISHED:
  355.                 tcb->rcv.nxt++;
  356.                 setstate(tcb,CLOSE_WAIT);
  357.                 break;
  358.             case FINWAIT1:
  359.                 tcb->rcv.nxt++;
  360.                 if(tcb->sndcnt == 0){
  361.                     /* Our FIN has been acked; bypass CLOSING state */
  362.                     setstate(tcb,TIME_WAIT);
  363.                     tcb->timer.start = MSL2 * (1000/MSPTICK);
  364.                     start_timer(&tcb->timer);
  365.                 } else {
  366.                     setstate(tcb,CLOSING);
  367.                 }
  368.                 break;
  369.             case FINWAIT2:
  370.                 tcb->rcv.nxt++;
  371.                 setstate(tcb,TIME_WAIT);
  372.                 tcb->timer.start = MSL2 * (1000/MSPTICK);
  373.                 start_timer(&tcb->timer);
  374.                 break;
  375.             case CLOSE_WAIT:
  376.             case CLOSING:
  377.             case LAST_ACK:
  378.                 break;        /* Ignore */
  379.             case TIME_WAIT:    /* p 76 */
  380.                 start_timer(&tcb->timer);
  381.                 break;
  382.             }
  383.         }
  384.         /* Scan the resequencing queue, looking for a segment we can handle,
  385.          * and freeing all those that are now obsolete.
  386.          */
  387.         while(tcb->reseq != NULLRESEQ && seq_ge(tcb->rcv.nxt,tcb->reseq->seg.seq)){
  388.             get_reseq(tcb,&tos,&seg,&bp,&length);
  389.             if(trim(tcb,&seg,&bp,&length) == 0)
  390.                 goto gotone;
  391.             /* Segment is an old one; trim has freed it */
  392.         }
  393.         break;
  394. gotone:    ;
  395.     }
  396.     tcp_output(tcb);    /* Send any necessary ack */
  397. }
  398.  
  399. /* Process an incoming ICMP response */
  400. tcp_icmp(source,dest,type,code,bpp)
  401. int32 source;            /* Original IP datagram source (i.e. us) */
  402. int32 dest;            /* Original IP datagram dest (i.e., them) */
  403. char type,code;            /* ICMP error codes */
  404. struct mbuf **bpp;        /* First 8 bytes of TCP header */
  405. {
  406.     struct tcp seg;
  407.     struct connection conn;
  408.     register struct tcb *tcb;
  409.  
  410.     /* Extract the socket info from the returned TCP header fragment
  411.      * Note that since this is a datagram we sent, the source fields
  412.      * refer to the local side.
  413.      */
  414.     ntohtcp(&seg,bpp);
  415.     conn.local.port = seg.source;
  416.     conn.remote.port = seg.dest;
  417.     conn.local.address = source;
  418.     conn.remote.address = dest;
  419.     if((tcb = lookup_tcb(&conn)) == NULLTCB)
  420.         return;    /* Unknown connection, ignore */
  421.  
  422.     /* Verify that the sequence number in the returned segment corresponds
  423.      * to something currently unacknowledged. If not, it can safely
  424.      * be ignored.
  425.      */
  426.     if(!seq_within(seg.seq,tcb->snd.una,tcb->snd.nxt))
  427.         return;
  428.  
  429.     /* The strategy here is that Destination Unreachable and Time Exceeded
  430.      * messages that occur after a connection has been established are likely
  431.      * to be transient events, and shouldn't kill our connection (at least
  432.      * until after we've tried a few more times). On the other hand, if
  433.      * they occur on our very first attempt to send a datagram on a new
  434.      * connection, they're probably "for real". In any event, the info
  435.      * is saved.
  436.      */
  437.     switch(uchar(type)){
  438.     case DEST_UNREACH:
  439.     case TIME_EXCEED:
  440.         tcb->type = type;
  441.         tcb->code = code;
  442.         if(tcb->state == SYN_SENT || tcb->state == SYN_RECEIVED){
  443.             close_self(tcb,NETWORK);
  444.         }
  445.         break;
  446.     case QUENCH:
  447.         /* Source quench; cut the congestion window in half,
  448.          * but don't let it go below one packet
  449.          */
  450.         tcb->cwind /= 2;
  451.         tcb->cwind = max(tcb->mss,tcb->cwind);
  452.         break;
  453.     }
  454. }
  455. /* Send an acceptable reset (RST) response for this segment
  456.  * The RST reply is composed in place on the input segment
  457.  */
  458. static void
  459. reset(source,dest,tos,length,seg)
  460. int32 source;            /* Remote IP address */
  461. int32 dest;            /* Our IP address */
  462. char tos;            /* Type of Service */
  463. int16 length;            /* Length of data portion */
  464. register struct tcp *seg;    /* Offending TCP header */
  465. {
  466.     struct mbuf *hbp;
  467.     struct pseudo_header ph;
  468.     int16 tmp;
  469.     char rflags;
  470.  
  471.     if(seg->flags & RST)
  472.         return;    /* Never send an RST in response to an RST */
  473.  
  474.     tcp_stat.resets++;
  475.  
  476.     /* Compose the RST IP pseudo-header, swapping addresses */
  477.     ph.source = dest;
  478.     ph.dest = source;
  479.     ph.protocol = TCP_PTCL;
  480.     ph.length = TCPLEN;
  481.  
  482.     /* Swap port numbers */
  483.     tmp = seg->dest;
  484.     seg->dest = seg->source;
  485.     seg->source = tmp;
  486.  
  487.     rflags = RST;
  488.     if(seg->flags & ACK){
  489.         /* This reset is being sent to clear a half-open connection.
  490.          * Set the sequence number of the RST to the incoming ACK
  491.          * so it will be acceptable.
  492.          */
  493.         seg->seq = seg->ack;
  494.         seg->ack = 0;
  495.     } else {
  496.         /* We're rejecting a connect request (SYN) from LISTEN state
  497.          * so we have to "acknowledge" their SYN.
  498.          */
  499.         rflags |= ACK;
  500.         seg->ack = seg->seq;
  501.         seg->seq = 0;
  502.         if(seg->flags & SYN)
  503.             seg->ack++;
  504.         seg->ack += length;
  505.         if(seg->flags & FIN)
  506.             seg->ack++;
  507.     }
  508.     seg->flags = rflags;
  509.     seg->wnd = 0;
  510.     seg->up = 0;
  511.     seg->mss = 0;
  512.     if((hbp = htontcp(seg,NULLBUF,&ph)) == NULLBUF)
  513.         return;
  514.     /* Ship it out (note swap of addresses) */
  515.     ip_send(dest,source,TCP_PTCL,tos,0,hbp,ph.length,0,0);
  516. }
  517.  
  518. /* Process an incoming acknowledgement and window indication.
  519.  * From page 72.
  520.  */
  521. static void
  522. update(tcb,seg,length)
  523. register struct tcb *tcb;
  524. register struct tcp *seg;
  525. int16 length;
  526. {
  527.     int16 acked;
  528.     int16 expand;
  529.  
  530.     acked = 0;
  531.     if(seq_gt(seg->ack,tcb->snd.nxt)){
  532.         tcb->flags |= FORCE;    /* Acks something not yet sent */
  533.         return;
  534.     }
  535.     /* Decide if we need to do a window update.
  536.      * This is always checked whenever a legal ACK is received,
  537.      * even if it doesn't actually acknowledge anything,
  538.      * because it might be a spontaneous window reopening.
  539.      */
  540.     if(seq_gt(seg->seq,tcb->snd.wl1) || ((seg->seq == tcb->snd.wl1) 
  541.      && seq_ge(seg->ack,tcb->snd.wl2))){
  542.         /* If the window had been closed, crank back the
  543.          * send pointer so we'll immediately resume transmission.
  544.          * Otherwise we'd have to wait until the next probe.
  545.          */
  546.         if(tcb->snd.wnd == 0 && seg->wnd != 0)
  547.             tcb->snd.ptr = tcb->snd.una;
  548.         tcb->snd.wnd = seg->wnd;
  549.         tcb->snd.wl1 = seg->seq;
  550.         tcb->snd.wl2 = seg->ack;
  551.     }
  552.     /* See if anything new is being acknowledged */
  553.     if(!seq_gt(seg->ack,tcb->snd.una)) {
  554.         if(seg->ack != tcb->snd.una)
  555.             return;    /* Old ack, ignore */
  556.  
  557.         if(seg->flags & SYN)
  558.         if(length != 0 || (seg->flags & SYN) || (seg->flags & FIN))
  559.             return;    /* Nothing acked, but there is data */
  560.  
  561.         /* Van Jacobson "fast recovery" code */
  562.         if(++tcb->dupacks == TCPDUPACKS){
  563.             /* We've had a burst of do-nothing acks, so
  564.              * we almost certainly lost a packet.
  565.              * Resend it now to avoid a timeout. (This is
  566.              * Van Jacobson's 'quick recovery' algorithm.)
  567.              */
  568.             int32 ptrsave;
  569.  
  570.             /* Knock the threshold down just as though
  571.              * this were a timeout, since we've had
  572.              * network congestion.
  573.              */
  574.             tcb->ssthresh = tcb->cwind/2;
  575.             tcb->ssthresh = max(tcb->ssthresh,tcb->mss);
  576.  
  577.             /* Manipulate the machinery in tcp_output() to
  578.              * retransmit just the missing packet
  579.              */
  580.             ptrsave = tcb->snd.ptr;
  581.              tcb->snd.ptr = tcb->snd.una;
  582.             tcb->cwind = tcb->mss;
  583.             tcp_output(tcb);
  584.             tcb->snd.ptr = ptrsave;
  585.  
  586.             /* "Inflate" the congestion window, pretending as
  587.              * though the duplicate acks were normally acking
  588.              * the packets beyond the one that was lost.
  589.              */
  590.             tcb->cwind = tcb->ssthresh + TCPDUPACKS*tcb->mss;
  591.         } else if(tcb->dupacks > TCPDUPACKS){
  592.             /* Continue to inflate the congestion window
  593.              * until the acks finally get "unstuck".
  594.              */
  595.             tcb->cwind += tcb->mss;
  596.         }
  597.         return;
  598.     }
  599.     if(tcb->dupacks >= TCPDUPACKS && tcb->cwind > tcb->ssthresh){
  600.         /* The acks have finally gotten "unstuck". So now we
  601.          * can "deflate" the congestion window, i.e. take it
  602.          * back down to where it would be after slow start
  603.          * finishes.
  604.          */
  605.         tcb->cwind = tcb->ssthresh;
  606.     }
  607.     tcb->dupacks = 0;
  608.  
  609.     /* We're here, so the ACK must have actually acked something */
  610.     acked = seg->ack - tcb->snd.una;
  611.  
  612.     /* Expand congestion window if not already at limit */
  613.     if(tcb->cwind < tcb->snd.wnd && !(tcb->flags & RETRAN)) {
  614.         if(tcb->cwind < tcb->ssthresh){
  615.             /* Still doing slow start/CUTE, expand by amount acked */
  616.             expand = min(acked,tcb->mss);
  617.         } else {
  618.             /* Steady-state test of extra path capacity */
  619.             expand = ((long)tcb->mss * tcb->mss) / tcb->cwind;
  620.         }
  621.         /* Guard against arithmetic overflow */
  622.         if(tcb->cwind + expand < tcb->cwind)
  623.             expand = MAXINT16 - tcb->cwind;
  624.  
  625.         /* Don't expand beyond the offered window */
  626.         if(tcb->cwind + expand > tcb->snd.wnd)
  627.             expand = tcb->snd.wnd - tcb->cwind;
  628.  
  629.         if(expand != 0){
  630. #ifdef    notdef
  631.             /* Kick up the mean deviation estimate to prevent
  632.              * unnecessary retransmission should we already be
  633.              * bandwidth limited
  634.              */
  635.             tcb->mdev += ((long)tcb->srtt * expand) / tcb->cwind;
  636. #endif
  637.             tcb->cwind += expand;
  638.         }
  639.     }
  640.     /* Round trip time estimation */
  641.     if(run_timer(&tcb->rtt_timer) && seq_ge(seg->ack,tcb->rttseq)){
  642.         /* A timed sequence number has been acked */
  643.         stop_timer(&tcb->rtt_timer);
  644.         if(!(tcb->flags & RETRAN)){
  645.             int32 rtt;    /* measured round trip time */
  646.             int32 abserr;    /* abs(rtt - srtt) */
  647.  
  648.             /* This packet was sent only once and now
  649.              * it's been acked, so process the round trip time
  650.              */
  651.             rtt = tcb->rtt_timer.start - tcb->rtt_timer.count;
  652.             rtt *= MSPTICK;        /* milliseconds */
  653.  
  654.             /* If this ACKs our SYN, this is the first ACK
  655.              * we've received; base our entire SRTT estimate
  656.              * on it. Otherwise average it in with the prior
  657.              * history, also computing mean deviation.
  658.              */
  659.             if(rtt > tcb->srtt &&
  660.              (tcb->state == SYN_SENT || tcb->state == SYN_RECEIVED)){
  661.                 tcb->srtt = rtt;
  662.             } else {
  663.                 abserr = (rtt > tcb->srtt) ? rtt - tcb->srtt : tcb->srtt - rtt;
  664.                 tcb->srtt = ((AGAIN-1)*tcb->srtt + rtt) / AGAIN;
  665.                 tcb->mdev = ((DGAIN-1)*tcb->mdev + abserr) / DGAIN;
  666.             }
  667.             /* Reset the backoff level */
  668.             tcb->backoff = 0;
  669.         }
  670.     }
  671.     /* If we're waiting for an ack of our SYN, note it and adjust count */
  672.     if(!(tcb->flags & SYNACK)){
  673.         tcb->flags |= SYNACK;
  674.         acked--;
  675.         tcb->sndcnt--;
  676.     }
  677.     /* Remove acknowledged bytes from the send queue and update the
  678.      * unacknowledged pointer. If a FIN is being acked,
  679.      * pullup won't be able to remove it from the queue.
  680.      */
  681.     pullup(&tcb->sndq,NULLCHAR,acked);
  682.  
  683.     /* This will include the FIN if there is one */
  684.     tcb->sndcnt -= acked;
  685.     tcb->snd.una = seg->ack;
  686.  
  687.     /* Stop retransmission timer, but restart it if there is still
  688.      * unacknowledged data.
  689.      */    
  690.     stop_timer(&tcb->timer);
  691.     if(tcb->snd.una != tcb->snd.nxt)
  692.         start_timer(&tcb->timer);
  693.  
  694.     /* If retransmissions have been occurring, make sure the
  695.      * send pointer doesn't repeat ancient history
  696.      */
  697.     if(seq_lt(tcb->snd.ptr,tcb->snd.una))
  698.         tcb->snd.ptr = tcb->snd.una;
  699.  
  700.     /* Clear the retransmission flag since the oldest
  701.      * unacknowledged segment (the only one that is ever retransmitted)
  702.      * has now been acked.
  703.      */
  704.     tcb->flags &= ~RETRAN;
  705.  
  706.     /* If outgoing data was acked, notify the user so he can send more
  707.      * unless we've already sent a FIN.
  708.      */
  709.     if(acked != 0 && tcb->t_upcall){
  710.         switch(tcb->state){
  711.          case ESTABLISHED:
  712.         case CLOSE_WAIT:
  713.             (*tcb->t_upcall)(tcb,tcb->window - tcb->sndcnt);
  714.         }
  715.     }
  716. }
  717.  
  718. /* Determine if the given sequence number is in our receiver window.
  719.  * NB: must not be used when window is closed!
  720.  */
  721. static
  722. int
  723. in_window(tcb,seq)
  724. struct tcb *tcb;
  725. int32 seq;
  726. {
  727.     return seq_within(seq,tcb->rcv.nxt,(int32)(tcb->rcv.nxt+tcb->rcv.wnd-1));
  728. }
  729.  
  730. /* Process an incoming SYN */
  731. static void
  732. proc_syn(tcb,tos,seg)
  733. register struct tcb *tcb;
  734. char tos;
  735. struct tcp *seg;
  736. {
  737.     int16 mtu,ip_mtu();
  738.  
  739.     tcb->flags |= FORCE;    /* Always send a response */
  740.  
  741.     /* Note: It's not specified in RFC 793, but SND.WL1 and
  742.      * SND.WND are initialized here since it's possible for the
  743.      * window update routine in update() to fail depending on the
  744.      * IRS if they are left unitialized.
  745.      */
  746.     /* Check incoming precedence and increase if higher */
  747.     if(PREC(tos) > PREC(tcb->tos))
  748.         tcb->tos = tos;
  749.     tcb->rcv.nxt = seg->seq + 1;    /* p 68 */
  750.     tcb->snd.wl1 = tcb->irs = seg->seq;
  751.     tcb->snd.wnd = seg->wnd;
  752.     if(seg->mss != 0)
  753.         tcb->mss = min(seg->mss, tcp_mss);
  754.     /* Check the MTU of the interface we'll use to reach this guy
  755.      * and lower the MSS so that unnecessary fragmentation won't occur
  756.      */
  757.     if((mtu = ip_mtu(tcb->conn.remote.address)) != 0){
  758.         /* Allow space for the TCP and IP headers */
  759.         mtu -= TCPLEN + IPLEN;
  760.         tcb->cwind = tcb->mss = min(mtu,tcb->mss);
  761.     }
  762. }
  763.  
  764. /* Generate an initial sequence number and put a SYN on the send queue */
  765. void
  766. send_syn(tcb)
  767. register struct tcb *tcb;
  768. {
  769.     tcb->iss = iss();
  770.     tcb->rttseq = tcb->snd.wl2 = tcb->snd.una = tcb->iss;
  771.     tcb->snd.ptr = tcb->snd.nxt = tcb->rttseq;
  772.     tcb->sndcnt++;
  773.     tcb->flags |= FORCE;
  774. }
  775.  
  776. /* Add an entry to the resequencing queue in the proper place */
  777. static void
  778. add_reseq(tcb,tos,seg,bp,length)
  779. struct tcb *tcb;
  780. char tos;
  781. struct tcp *seg;
  782. struct mbuf *bp;
  783. int16 length;
  784. {
  785.     register struct reseq *rp,*rp1;
  786.  
  787.     /* Allocate reassembly descriptor */
  788.     if((rp = (struct reseq *)malloc(sizeof (struct reseq))) == NULLRESEQ){
  789.         /* No space, toss on floor */
  790.         free_p(bp);
  791.         return;
  792.     }
  793.     ASSIGN(rp->seg,*seg);
  794.     rp->tos = tos;
  795.     rp->bp = bp;
  796.     rp->length = length;
  797.  
  798.     /* Place on reassembly list sorting by starting seq number */
  799.     rp1 = tcb->reseq;
  800.     if(rp1 == NULLRESEQ || seq_lt(seg->seq,rp1->seg.seq)){
  801.         /* Either the list is empty, or we're less than all other
  802.          * entries; insert at beginning.
  803.          */
  804.         rp->next = rp1;
  805.         tcb->reseq = rp;
  806.     } else {
  807.         /* Find the last entry less than us */
  808.         for(;;){
  809.             if(rp1->next == NULLRESEQ || seq_lt(seg->seq,rp1->next->seg.seq)){
  810.                 /* We belong just after this one */
  811.                 rp->next = rp1->next;
  812.                 rp1->next = rp;
  813.                 break;
  814.             }
  815.             rp1 = rp1->next;
  816.         }
  817.     }
  818. }
  819.  
  820. /* Fetch the first entry off the resequencing queue */
  821. static void
  822. get_reseq(tcb,tos,seg,bp,length)
  823. register struct tcb *tcb;
  824. char *tos;
  825. struct tcp *seg;
  826. struct mbuf **bp;
  827. int16 *length;
  828. {
  829.     register struct reseq *rp;
  830.  
  831.     if((rp = tcb->reseq) == NULLRESEQ)
  832.         return;
  833.  
  834.     tcb->reseq = rp->next;
  835.  
  836.     *tos = rp->tos;
  837.     ASSIGN(*seg,rp->seg);
  838.     *bp = rp->bp;
  839.     *length = rp->length;
  840.     free((char *)rp);
  841. }
  842.  
  843. /* Trim segment to fit window. Return 0 if OK, -1 if segment is
  844.  * unacceptable.
  845.  */
  846. static int
  847. trim(tcb,seg,bp,length)
  848. register struct tcb *tcb;
  849. register struct tcp *seg;
  850. struct mbuf **bp;
  851. int16 *length;
  852. {
  853.     struct mbuf *nbp;
  854.     long dupcnt,excess;
  855.     int16 len;        /* Segment length including flags */
  856.     char accept;
  857.  
  858.     accept = 0;
  859.     len = *length;
  860.     if(seg->flags & SYN)
  861.         len++;
  862.     if(seg->flags & FIN)
  863.         len++;
  864.  
  865.     /* Acceptability tests */
  866.     if(tcb->rcv.wnd == 0){
  867.         /* Only in-order, zero-length segments are acceptable when our window
  868.          * is closed.
  869.          */
  870.         if(seg->seq == tcb->rcv.nxt && len == 0){
  871.             return 0;    /* Acceptable, no trimming needed */
  872.         }
  873.     } else {
  874.         /* Some part of the segment must be in the window */
  875.         if(in_window(tcb,seg->seq)){
  876.             accept++;    /* Beginning is */
  877.         } else if(len != 0){
  878.             if(in_window(tcb,(int32)(seg->seq+len-1)) || /* End is */
  879.              seq_within(tcb->rcv.nxt,seg->seq,(int32)(seg->seq+len-1))){ /* Straddles */
  880.                 accept++;
  881.             }
  882.         }
  883.     }
  884.     if(!accept){
  885.         free_p(*bp);
  886.         return -1;
  887.     }
  888.     dupcnt = tcb->rcv.nxt - seg->seq;
  889.     if(dupcnt > 0){
  890.         tcb->rerecv += dupcnt;
  891.         /* Trim off SYN if present */
  892.         if(seg->flags & SYN){
  893.             /* SYN is before first data byte */
  894.             seg->flags &= ~SYN;
  895.             seg->seq++;
  896.             dupcnt--;
  897.         }
  898.         if(dupcnt > 0){
  899.             pullup(bp,NULLCHAR,(int16)dupcnt);
  900.             seg->seq += dupcnt;
  901.             *length -= dupcnt;
  902.         }
  903.     }
  904.     excess = seg->seq + *length - (tcb->rcv.nxt + tcb->rcv.wnd);
  905.     if(excess > 0){
  906.         tcb->rerecv += excess;
  907.         /* Trim right edge */
  908.         *length -= excess;
  909.         nbp = copy_p(*bp,*length);
  910.         free_p(*bp);
  911.         *bp = nbp;
  912.         seg->flags &= ~FIN;    /* FIN follows last data byte */
  913.     }
  914.     return 0;
  915. }
  916.