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