home *** CD-ROM | disk | FTP | other *** search
/ ARM Club 3 / TheARMClub_PDCD3.iso / hensa / internet / tcpip / src205 / TCPIP_Src / TCP / c / TCPSUBR < prev    next >
Encoding:
Text File  |  1995-03-21  |  7.8 KB  |  271 lines

  1. #include <stdlib.h>
  2. #include "global.h"
  3. #include "timer.h"
  4. #include "mbuf.h"
  5. #include "misc.h"
  6. #include "netuser.h"
  7. #include "internet.h"
  8. #include "tcp.h"
  9.  
  10. static int16 hash_tcb(struct connection *);
  11.  
  12. struct tcb *tcbs[NTCB];
  13. int16 tcp_mss = DEF_MSS;        /* Maximum segment size to be sent with SYN */
  14. int32 tcp_irtt = DEF_RTT;       /* Initial guess at round trip time */
  15. int32 tcp_mrtt = DEF_MRTT/MSPTICK;      /* Maximum allowed round trip time after backoff */
  16.  
  17. /* Lookup connection, return TCB pointer or NULLTCB if nonexistant */
  18. struct tcb *lookup_tcb(struct connection *conn)
  19. {
  20.         register struct tcb *tcb;
  21.  
  22.         tcb = tcbs[hash_tcb(conn)];
  23.         while(tcb != NULLTCB){
  24.                 /* Yet another structure compatibility hack */
  25.                 if(conn->local.address == tcb->conn.local.address
  26.                  && conn->remote.address == tcb->conn.remote.address
  27.                  && conn->local.port == tcb->conn.local.port
  28.                  && conn->remote.port == tcb->conn.remote.port)
  29.                         break;
  30.                 tcb = tcb->next;
  31.         }
  32.         return tcb;
  33. }
  34.  
  35. /* Create a TCB, return pointer. Return pointer if TCB already exists. */
  36. struct tcb *create_tcb(struct connection *conn)
  37. {
  38.         register struct tcb *tcb;
  39.  
  40.         if((tcb = lookup_tcb(conn)) != NULLTCB)
  41.                 return tcb;
  42.         if((tcb = (struct tcb *)calloc(1,sizeof (struct tcb))) == NULLTCB)
  43.                 return NULLTCB;
  44.         tcb->conn = *conn;
  45.  
  46.         tcb->cwind = tcb->mss = tcp_mss;
  47.         tcb->ssthresh = 65535;
  48.         tcb->srtt = tcp_irtt;
  49.         /* Initialize timer intervals */
  50.         tcb->timer.start = tcb->srtt / MSPTICK;
  51.         tcb->timer.func = tcp_timeout;
  52.         tcb->timer.arg = (char *)tcb;
  53.         tcb->rtt_timer.start = MAX_TIME; /* Largest possible value */
  54.  
  55.         link_tcb(tcb);
  56.         return tcb;
  57. }
  58.  
  59. /* Close our TCB */
  60. void close_self(register struct tcb *tcb, char reason)
  61. {
  62.         struct reseq *rp,*rp1;
  63.  
  64.         stop_timer(&tcb->timer);
  65.         stop_timer(&tcb->rtt_timer);
  66.         tcb->reason = reason;
  67.  
  68.         /* Flush reassembly queue; nothing more can arrive */
  69.         for(rp = tcb->reseq;rp != NULLRESEQ;rp = rp1){
  70.                 rp1 = rp->next;
  71.                 free_p(rp->bp);
  72.                 free((char *)rp);
  73.         }
  74.         tcb->reseq = NULLRESEQ;
  75.         setstate(tcb,CLOSED);
  76. }
  77.  
  78. /* Determine initial sequence number */
  79. int32 iss(void)
  80. {
  81.         static int32 seq;
  82.  
  83.         seq += 250000;
  84.         return seq;
  85. }
  86.  
  87. /* Sequence number comparisons
  88.  * Return true if x is between low and high inclusive,
  89.  * false otherwise
  90.  */
  91. int seq_within(int32 x, int32 low, int32 high)
  92. {
  93.         if(low <= high){
  94.                 if(low <= x && x <= high)
  95.                         return 1;
  96.         } else {
  97.                 if(low >= x && x >= high)
  98.                         return 1;
  99.         }
  100.         return 0;
  101. }
  102. int seq_lt(int32 x, int32 y)
  103. {
  104.         return (long)(x-y) < 0;
  105. }
  106. int seq_le(int32 x, int32 y)
  107. {
  108.         return (long)(x-y) <= 0;
  109. }
  110. int seq_gt(int32 x, int32 y)
  111. {
  112.         return (long)(x-y) > 0;
  113. }
  114. int seq_ge(int32 x, int32 y)
  115. {
  116.         return (long)(x-y) >= 0;
  117. }
  118.  
  119. /* Hash a connect structure into the hash chain header array */
  120. static int16 hash_tcb(struct connection *conn)
  121. {
  122.         register int16 hval;
  123.  
  124.         /* Compute hash function on connection structure */
  125.         hval = hiword(conn->remote.address);
  126.         hval ^= loword(conn->remote.address);
  127.         hval ^= hiword(conn->local.address);
  128.         hval ^= loword(conn->local.address);
  129.         hval ^= conn->remote.port;
  130.         hval ^= conn->local.port;
  131.         hval %= NTCB;
  132.         return hval;
  133. }
  134. /* Insert TCB at head of proper hash chain */
  135. void link_tcb(register struct tcb *tcb)
  136. {
  137.         register struct tcb **tcbhead;
  138.  
  139.         tcb->prev = NULLTCB;
  140.         tcbhead = &tcbs[hash_tcb(&tcb->conn)];
  141.         tcb->next = *tcbhead;
  142.         if(tcb->next != NULLTCB){
  143.                 tcb->next->prev = tcb;
  144.         }
  145.         *tcbhead = tcb;
  146. }
  147. /* Remove TCB from whatever hash chain it may be on */
  148. void unlink_tcb(register struct tcb *tcb)
  149. {
  150.         register struct tcb **tcbhead;
  151.  
  152.         tcbhead = &tcbs[hash_tcb(&tcb->conn)];
  153.         if(*tcbhead == tcb)
  154.                 *tcbhead = tcb->next;   /* We're the first one on the chain */
  155.         if(tcb->prev != NULLTCB)
  156.                 tcb->prev->next = tcb->next;
  157.         if(tcb->next != NULLTCB)
  158.                 tcb->next->prev = tcb->prev;
  159. }
  160. void setstate(register struct tcb *tcb, register char newstate)
  161. {
  162.         extern void update_iconbar(void);
  163.         register char oldstate;
  164.  
  165.         oldstate = tcb->state;
  166.         tcb->state = newstate;
  167.         if (tcb->s_upcall) {
  168.                 (*tcb->s_upcall)(tcb,oldstate,newstate);
  169.         }
  170.         /* Notify the user that he can begin sending data */
  171.         if (tcb->t_upcall && newstate == ESTABLISHED) {
  172.                 (*tcb->t_upcall)(tcb,tcb->window - tcb->sndcnt);
  173.         }
  174.         update_iconbar();
  175. }
  176. /* Convert TCP header in host format into mbuf ready for transmission,
  177.  * link in data (if any), and compute checksum
  178.  */
  179. struct mbuf *htontcp(struct tcp *tcph, struct mbuf *data, struct pseudo_header *ph)
  180. {
  181.         int16 hdrlen;
  182.         struct mbuf *bp;
  183.         register char *cp;
  184.         int16 csum;
  185.  
  186.         hdrlen = (tcph->mss != 0) ? TCPLEN + MSS_LENGTH : TCPLEN;
  187.         
  188.         if((bp = pushdown(data,hdrlen)) == NULLBUF){
  189.                 free_p(data);
  190.                 return NULLBUF;
  191.         }
  192.         cp = bp->data;
  193.         cp = put16(cp,tcph->source);
  194.         cp = put16(cp,tcph->dest);
  195.         cp = put32(cp,tcph->seq);
  196.         cp = put32(cp,tcph->ack);
  197.         *cp++ = hdrlen << 2;    /* Offset field */
  198.         *cp++ = tcph->flags;
  199.         cp = put16(cp,tcph->wnd);
  200.         *cp++ = 0;      /* Zero out checksum field */
  201.         *cp++ = 0;
  202.         cp = put16(cp,tcph->up);
  203.  
  204.         if(tcph->mss != 0){
  205.                 *cp++ = MSS_KIND;
  206.                 *cp++ = MSS_LENGTH;
  207.                 cp = put16(cp,tcph->mss);
  208.         }
  209.         csum = cksum(ph,bp,ph->length);
  210.         cp = &bp->data[16];     /* Checksum field */    
  211.         *cp++ = csum >> 8;
  212.         *cp = csum;
  213.  
  214.         return bp;
  215. }
  216. /* Pull TCP header off mbuf */
  217. int ntohtcp(struct tcp *tcph, struct mbuf **bpp)
  218. {
  219.         int16 hdrlen;
  220.         int16 i,optlen;
  221.  
  222.         tcph->source = pull16(bpp);
  223.         tcph->dest = pull16(bpp);
  224.         tcph->seq = pull32(bpp);
  225.         tcph->ack = pull32(bpp);
  226.         if(*bpp == NULLBUF)
  227.                 /* Buffer too short to pull off header length */
  228.                 return -1;
  229.         hdrlen = (pullchar(bpp) & 0xf0) >> 2;
  230.         tcph->flags = pullchar(bpp);
  231.         tcph->wnd = pull16(bpp);
  232.         (void)pull16(bpp);      /* Skip checksum */
  233.         tcph->up = pull16(bpp);
  234.         tcph->mss = 0;
  235.  
  236.         /* Check for option field. Only space for one is allowed, but
  237.          * since there's only one TCP option (MSS) this isn't a problem
  238.          */
  239.         if(hdrlen < TCPLEN)
  240.                 return -1;      /* Header smaller than legal minimum */
  241.         if(hdrlen == TCPLEN)
  242.                 return hdrlen;  /* No options, all done */
  243.  
  244.         if(hdrlen > len_mbuf(*bpp) + TCPLEN){
  245.                 /* Remainder too short for options length specified */
  246.                 return -1;
  247.         }
  248.         /* Process options */
  249.         for(i=TCPLEN; i < hdrlen;){
  250.                 switch(pullchar(bpp)){
  251.                 case EOL_KIND:
  252.                         i++;
  253.                         goto eol;       /* End of options list */
  254.                 case NOOP_KIND:
  255.                         i++;
  256.                         break;
  257.                 case MSS_KIND:
  258.                         optlen = pullchar(bpp);
  259.                         if(optlen == MSS_LENGTH)
  260.                                 tcph->mss = pull16(bpp);
  261.                         i += optlen;
  262.                         break;
  263.                 }
  264.         }
  265. eol:
  266.         /* Get rid of any padding */
  267.         if(i < hdrlen)
  268.                 pullup(bpp,NULLCHAR,hdrlen - i);
  269.         return hdrlen;
  270. }
  271.