home *** CD-ROM | disk | FTP | other *** search
/ ftp.wwiv.com / ftp.wwiv.com.zip / ftp.wwiv.com / pub / CEREBRUM / WAT9609.ZIP / SRC / FRAGMENT.C < prev    next >
Text File  |  1994-11-28  |  9KB  |  277 lines

  1.  
  2. /*
  3.  * Packet De-Fragmentaion code for WATTCP
  4.  * Written by and COPYRIGHT (c)1993 to Quentin Smart
  5.  *                               smart@actrix.gen.nz
  6.  * all rights reserved.
  7.  *
  8.  *   This software is distributed in the hope that it will be useful,
  9.  *   but without any warranty; without even the implied warranty of
  10.  *   merchantability or fitness for a particular purpose.
  11.  *
  12.  *   You may freely distribute this source code, but if distributed for
  13.  *   financial gain then only executables derived from the source may be
  14.  *   sold.
  15.  *
  16.  * Murf = Murf@perftech.com
  17.  * other fragfix = mdurkin@tsoft.net
  18.  *
  19.  * Based on RFC815
  20.  */
  21.  
  22. #include <mem.h>
  23. #include <stdlib.h>
  24. #include "wattcp.h"
  25.  
  26. /* Murf's code structuring macros */   /* add 94.09.16 */
  27. #define LOOP       for (;;)
  28. #define LOOPASSERT( c ) if (!(c)) break
  29.  
  30. /* Murf's macro to get a structure address from a member address */
  31. #define structure(S,m,p) ((S *)( (byte *)(p) - (byte *) &((S *)0)->m ))
  32. /*
  33. #define ANIMATE
  34.  */
  35.  
  36. #define MAXBUFS         5       /* maximum number of Ethernet buffers */
  37. #define MAXFRAGS        MAXBUFS-1
  38. #define FRAGHOLDTIME    15       /* 15 secs to hold before discarding */
  39. #define INFINITY        30000
  40. #define IP_HEADER_SIZE  20
  41. #define IP_MF           0x0020  // More fragment in INTEL form
  42.  
  43.  
  44. typedef struct {
  45.     longword    source;
  46. //      longword destination;
  47.         byte        proto;         // use proto now
  48.     word        identification;
  49.     } fragkey;
  50.  
  51. typedef struct hd {
  52.     struct hd   * next;
  53.     int           start;
  54.     int           end;
  55.     } hole_descr;
  56.  
  57. typedef struct {
  58.     byte         used;           // this position in table in use
  59.     fragkey      key;
  60.     hole_descr  *hole_first;
  61.     longword     timer;
  62.     in_Header   *ip;
  63.     byte        *data_offset;
  64.     } fraghdr;
  65.  
  66. static fraghdr fraglist[MAXFRAGS] = {{0,{0,0},NULL,0,NULL},
  67.                   {0,{0,0},NULL,0,NULL},
  68.                   {0,{0,0},NULL,0,NULL},
  69.                   {0,{0,0},NULL,0,NULL}};
  70.  
  71. int active_frags = 0;
  72. extern word _pktipofs;  /* offset from header to start of pkt */
  73.  
  74. /* Fragment is called if the frag section of the IP header is not zero and DF bit not set */
  75. byte *fragment( in_Header * ip )
  76. {
  77. //int        fc;
  78. fraghdr    *my_frag;
  79. hole_descr *hole = NULL;
  80. hole_descr *prev_hole = NULL;
  81.  
  82. fragkey     key;
  83. int         found = 0;
  84. int         got_hole = 0;
  85. int         data_start;
  86. int         data_end;
  87. int         data_length;
  88. int         temp,i;
  89. int         more_frags;   // Set to true if this is the last frag
  90. /*byte     * buffer; */
  91.  
  92. // Should check that the packet is actually valid and do a checksum on it.
  93. // Assemble key
  94. key.proto = ip->proto;     // use proto now
  95. key.source=ip->source;
  96. key.identification = ip->identification;
  97.  
  98. // Check if we have a match
  99.  
  100. for (i=0;i<MAXFRAGS && !found;i++)
  101.     if (fraglist[i].used && !memcmp(&key,&fraglist[i].key,sizeof(fragkey)))
  102.        {
  103.       found = TRUE;
  104.       my_frag = &fraglist[i];
  105.        }
  106.  
  107. if (!found && active_frags == MAXFRAGS) {
  108. #ifdef ANIMATE
  109.    printf( "NO_BUFS\n" );/*DEBUG STUFF*/
  110. #endif
  111.    // Can't handle any new frags, biff packet so that we can continue
  112.    // Could do direct!
  113.    pkt_buf_release((char*)ip);
  114.    return(NULL);  // We can't handle any new frags!
  115.    }
  116.                          // Should biff packet?
  117.  
  118. // Calc where data should go
  119.  
  120. // fragfix - next line replaces... no more bitfields
  121.    data_start  = intel16(ip->frags) << 3; //* 8
  122.    data_length = intel16(ip->length)-in_GetHdrlenBytes(ip);
  123.    data_end    = data_start + data_length - 1;  // Murf 94.09.16
  124.    more_frags = ip->frags & IP_MF;
  125. #ifdef ANIMATE
  126.    printf( "Data=%d..%d", data_start, data_end );/*DEBUG STUFF*/
  127. #endif
  128.  
  129.  
  130. if (!found)
  131.  {
  132.    // Mark as used
  133.    *((byte *)ip - (2 + _pktipofs)) = 2;
  134.    // Find first empty slot
  135.    for (i=0;i < MAXFRAGS && fraglist[i].used;i++);
  136.    my_frag = &fraglist[i];
  137.    // mark as used
  138.    my_frag->used = 1;
  139.    // inc active frags counter
  140.    active_frags++;
  141.    // Setup frag header data, first packet
  142.    memcpy(&my_frag->key,&key,sizeof(key));
  143.    my_frag->timer  = set_timeout(max(FRAGHOLDTIME,ip->ttl));
  144.    my_frag->ip = ip;
  145.    // Set pointers to beinging of IP packet data
  146.    my_frag->data_offset = (byte *)my_frag->ip + in_GetHdrlenBytes(ip);
  147.    // Setup initial hole table
  148.    if (data_start) // i.e. not Zero
  149.     {
  150.       memcpy(my_frag->data_offset + data_start,(byte *)ip+in_GetHdrlenBytes(ip),data_length);
  151.       // Bracket beginning of data
  152.       hole = my_frag->hole_first = (hole_descr *)my_frag->data_offset;
  153.       hole->start = 0;
  154.       hole->end = data_start-1;
  155.       if (more_frags) {
  156.          // data_start was missing in next line - Murf 94.09.16
  157.          hole->next = (hole_descr *)(my_frag->data_offset + data_start + data_length + 1);
  158.      hole = hole->next;
  159.      }
  160.       else
  161.     {
  162.      hole = my_frag->hole_first->next = NULL;
  163.      // Adjust length
  164.      ip->length = intel16(data_end + in_GetHdrlenBytes(ip));
  165.     }
  166.     }
  167.    else
  168.     {
  169.      // Setup
  170.      hole = my_frag->hole_first = (hole_descr*)(my_frag->data_offset + data_length + 1);
  171.     }
  172.    // Bracket end
  173.    if (hole) {
  174.      // data_start was missing in next line - Murf 94.09.16
  175.      hole->start = data_start + data_length;// + 1;
  176.      hole->end = INFINITY;
  177.      hole->next = NULL;
  178.     }
  179. #ifdef ANIMATE
  180.    printf( " new\n" );/*DEBUG STUFF*/
  181. #endif
  182.    return NULL; // Go back for more!
  183.  } // End !found
  184. // Adjust length
  185.    if (!more_frags)
  186.       my_frag->ip->length = intel16(data_end + 1 + in_GetHdrlenBytes(ip)); // Murf 94.09.16
  187.  
  188. // Hole handling
  189.    hole = structure( hole_descr, next, &my_frag->hole_first ); // Murf 94.09.16
  190.  
  191.    LOOP {                                                      // Murf 94.09.16
  192.       prev_hole = hole;                                        // Murf 94.09.16
  193.       hole = hole->next;                                       // Murf 94.09.16
  194.       LOOPASSERT (hole);                                       // Murf 94.09.16
  195. #ifdef ANIMATE
  196.       printf( " hole=%d..%d(%d)", hole->start, hole->end, hole->next );/*DEBUG STUFF*/
  197. #endif
  198.       if (!(data_start > hole->end) && !(data_end < hole->start)) {
  199.          // We've found the spot
  200.          // Mark as got.
  201.          got_hole =1;
  202.          // Find where to insert
  203.          // Check is there a hole before the new frag
  204.          temp = hole->end;   // Pick up old hole end for later;
  205.  
  206.          if (data_start > hole->start) {
  207.             hole->end = data_start-1;
  208.             prev_hole = hole;  // We have a new prev
  209. #ifdef ANIMATE
  210.             printf( "->%d..%d(%d)", hole->start, hole->end, hole->next );/*DEBUG STUFF*/
  211. #endif
  212.             }
  213.           else {
  214.             // No, delete current hole
  215. #ifdef ANIMATE
  216.             printf( " del" );/* DEBUG STUFF*/
  217. #endif
  218.             prev_hole->next = hole->next;
  219.             hole = prev_hole;     // Leave hole valid - Murf 94.09.16
  220.             }
  221.  
  222.          // Is there a hole after the current fragment
  223.          // Only if we're not last and more to come
  224.          if (data_end < temp && more_frags) {   // fragfix - Murf 94.09.14
  225.             hole = (hole_descr *)(data_end + 1 + my_frag->data_offset);
  226.             hole->start = data_end+1;
  227.             hole->end = temp;
  228.             hole->next = prev_hole->next;
  229.             prev_hole->next = hole;
  230. #ifdef ANIMATE
  231.             printf( ",%d..%d(%d)", hole->start, hole->end, hole->next );/*DEBUG STUFF*/
  232. #endif
  233.             }
  234.          }
  235.       }
  236.        // Thats all setup so copy in the data
  237.        if (got_hole)
  238.        memcpy(my_frag->data_offset + data_start,(byte *)ip+in_GetHdrlenBytes(ip),data_length);
  239.        // And release the buffer;
  240.        pkt_buf_release((byte *)ip);
  241.        // Now do we have all the parts?
  242.        if (!my_frag->hole_first)
  243.     {
  244. #ifdef ANIMATE
  245.       printf( " COMPLETE\n" );/*DEBUG STUFF*/
  246. #endif
  247.       my_frag->used = 0;
  248.       active_frags--;
  249.       // Redo checksum as we've changed the length in the header
  250.       my_frag->ip->checksum = 0; // Zero
  251.       my_frag->ip->checksum = ~ checksum( my_frag->ip, sizeof( in_Header ));
  252.       return((byte *)my_frag->ip - _pktipofs);
  253.     }
  254. #ifdef ANIMATE
  255.    printf( " MORE_TO_COME\n" );/*DEBUG STUFF*/
  256. #endif
  257. return NULL;
  258. }
  259.  
  260. void timeout_frags( void )
  261. {
  262. int i;
  263.  
  264. for (i=0;i<MAXFRAGS;i++)
  265.     if (fraglist[i].used)
  266.        if (chk_timeout(fraglist[i].timer))
  267.      {
  268. #ifdef ANIMATE
  269.           printf( "BUF timed out\n" );/*DEBUG STUFF*/
  270. #endif
  271.       fraglist[i].used = 0;
  272.       active_frags--;
  273.       pkt_buf_release((byte *)fraglist[i].ip);
  274.      }
  275. }
  276.  
  277.