home *** CD-ROM | disk | FTP | other *** search
/ Super Net 1 / SUPERNET_1.iso / PC / OTROS / MSDOS / WATTCP / WATTCP.ZIP / SRC / FRAGMENT.C < prev    next >
Encoding:
C/C++ Source or Header  |  1993-08-04  |  6.7 KB  |  251 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.  *
  17.  * Based on RFC815
  18.  */
  19.  
  20. #include <mem.h>
  21. #include <stdlib.h>
  22. #include "wattcp.h"
  23.  
  24.  
  25. #define MAXBUFS         5       /* maximum number of Ethernet buffers */
  26. #define MAXFRAGS        MAXBUFS-1
  27. #define FRAGHOLDTIME    15       /* 15 secs to hold before discarding */
  28. #define INFINITY        30000
  29. #define IP_HEADER_SIZE  20
  30. #define IP_MF           0x0020  // More fragment in INTEL form
  31. //#define IP_DF           0x2000  // Don't fragments
  32.  
  33.  
  34.  
  35. typedef struct {
  36.     longword    source;
  37. //      longword destination;
  38. //    byte        proto;           My app only does TCP so don't care
  39.     word        identification;
  40.     } fragkey;
  41.  
  42. typedef struct hd {
  43.     struct hd   * next;
  44.     int           start;
  45.     int           end;
  46.     } hole_descr;
  47.  
  48. typedef struct {
  49.     byte         used;           // this position in table in use
  50.     fragkey      key;
  51.     hole_descr  *hole_first;
  52.     longword     timer;
  53.     in_Header   *ip;
  54.     byte        *data_offset;
  55.     } fraghdr;
  56.  
  57. static fraghdr fraglist[MAXFRAGS] = {{0,{0,0},NULL,0,NULL},
  58.                   {0,{0,0},NULL,0,NULL},
  59.                   {0,{0,0},NULL,0,NULL},
  60.                   {0,{0,0},NULL,0,NULL}};
  61.  
  62. int active_frags = 0;
  63. extern word _pktipofs;  /* offset from header to start of pkt */
  64.  
  65. /* Fragment is called if the frag section of the IP header is not zero and DF bit not set */
  66. byte * fragment(in_Header * ip)
  67. {
  68. //int        fc;
  69. fraghdr    *my_frag;
  70. hole_descr *hole = NULL;
  71. hole_descr *prev_hole = NULL;
  72.  
  73. fragkey     key;
  74. int         found = 0;
  75. int         got_hole = 0;
  76. int         data_start;
  77. int         data_end;
  78. int         data_length;
  79. int         temp,i;
  80. int         more_frags;   // Set to true if this is the last frag
  81. byte     * buffer;
  82.  
  83. // Should check that the packet is actually valid and do a checksum on it.
  84. // Assemble key
  85. //key.proto = ip->proto;
  86. key.source=ip->source;
  87. key.identification = ip->identification;
  88.  
  89. // Check if we have a match
  90.  
  91. for (i=0;i<MAXFRAGS && !found;i++)
  92.     if (fraglist[i].used && !memcmp(&key,&fraglist[i].key,sizeof(fragkey)))
  93.        {
  94.       found = TRUE;
  95.       my_frag = &fraglist[i];
  96.        }
  97.  
  98. if (!found && active_frags == MAXFRAGS) {
  99.    // Can't handle any new frags, biff packet so that we can continue
  100.    // Could do direct!
  101.    pkt_buf_release((char*)ip);
  102.    return(NULL);  // We can't handle any new frags!
  103.    }
  104.                          // Should biff packet?
  105.  
  106. // Calc where data should go
  107.  
  108.    data_start  = intel16(ip->fo ) << 3; //* 8
  109.    data_length = intel16(ip->length)-in_GetHdrlenBytes(ip);
  110.    data_end    = data_start + data_length;
  111.    more_frags = ip->frags & IP_MF;
  112.  
  113.  
  114.  
  115. if (!found)
  116.  {
  117.    // Mark as used
  118.    *((byte *)ip - (2 + _pktipofs)) = 2;
  119.    // Find first empty slot
  120.    for (i=0;i < MAXFRAGS && fraglist[i].used;i++);
  121.    my_frag = &fraglist[i];
  122.    // mark as used
  123.    my_frag->used = 1;
  124.    // inc active frags counter
  125.    active_frags++;
  126.    // Setup frag header data, first packet
  127.    memcpy(&my_frag->key,&key,sizeof(key));
  128.    my_frag->timer  = set_timeout(max(FRAGHOLDTIME,ip->ttl));
  129.    my_frag->ip = ip;
  130.    // Set pointers to beinging of IP packet data
  131.    my_frag->data_offset = (byte *)my_frag->ip + in_GetHdrlenBytes(ip);
  132.    // Setup initial hole table
  133.    if (data_start) // i.e. not Zero
  134.     {
  135.       memcpy(my_frag->data_offset + data_start,(byte *)ip+in_GetHdrlenBytes(ip),data_length);
  136.       // Bracket beginning of data
  137.       hole = my_frag->hole_first = my_frag->data_offset;
  138.       hole->start = 0;
  139.       hole->end = data_start-1;
  140.       if (more_frags) {
  141.      hole->next = my_frag->data_offset + data_length + 1;
  142.      hole = hole->next;
  143.      }
  144.       else
  145.     {
  146.      hole = my_frag->hole_first->next = NULL;
  147.      // Adjust length
  148.      ip->length = intel16(data_end + in_GetHdrlenBytes(ip));
  149.     }
  150.     }
  151.    else
  152.     {
  153.      // Setup
  154.      hole = my_frag->hole_first = my_frag->data_offset + data_length + 1;
  155.     }
  156.    // Bracket end
  157.    if (hole) {
  158.      hole->start = data_length;// + 1;
  159.      hole->end = INFINITY;
  160.      hole->next = NULL;
  161.     }
  162.    return NULL; // Go back for more!
  163.  } // End !found
  164. // Adjust length
  165.    if (!more_frags)
  166.       my_frag->ip->length = intel16(data_end + in_GetHdrlenBytes(ip));
  167.  
  168. // Hole handling
  169.    hole = my_frag->hole_first;
  170.  
  171.    do {
  172.       if (!(data_start > hole->end))
  173.      if (!(data_end < hole->start))  // We've found the spot
  174.         {
  175.          // Mark as got.
  176.          got_hole =1;
  177.          // Find where to insert
  178.          // Check is there a hole before the new frag
  179.          temp = hole->end;   // Pick up old hole end for later;
  180.  
  181.          if (data_start > hole->start)
  182.            {
  183.          hole->end = data_start-1;
  184.          prev_hole = hole;  // We have a new prev
  185.            }
  186.           else
  187.            {
  188.         // No, delete current hole
  189.         if (!prev_hole)
  190.            my_frag->hole_first=hole->next;
  191.         else
  192.            prev_hole->next = hole->next;
  193.            }
  194.  
  195.          // Is there a hole after the current fragment
  196.          // Only if we're not last and more to come
  197.          if (data_end < hole->end && more_frags)
  198.            {
  199.          hole = data_end + 1 + my_frag->data_offset;
  200.          hole->start = data_end+1;
  201.          hole->end = temp;
  202.          // prev_hole = NULL if first
  203.          if (!prev_hole)
  204.           {
  205.            hole->next = my_frag->hole_first;
  206.            my_frag->hole_first = hole;
  207.           }
  208.          else
  209.           {
  210.            hole->next = prev_hole->next;
  211.            prev_hole->next = hole;
  212.           }
  213.         }
  214.         }
  215.         prev_hole = hole;
  216.         hole = hole->next;
  217.     }
  218.     while (!hole && !got_hole); // Until we got to the end or found
  219.        // Thats all setup so copy in the data
  220.        if (got_hole)
  221.        memcpy(my_frag->data_offset + data_start,(byte *)ip+in_GetHdrlenBytes(ip),data_length);
  222.        // And release the buffer;
  223.        pkt_buf_release((byte *)ip);
  224.        // Now do we have all the parts?
  225.        if (!my_frag->hole_first)
  226.     {
  227.       my_frag->used = 0;
  228.       active_frags--;
  229.       // Redo checksum as we've changed the length in the header
  230.       my_frag->ip->checksum = 0; // Zero
  231.       my_frag->ip->checksum = ~ checksum( my_frag->ip, sizeof( in_Header ));
  232.       return((byte *)my_frag->ip - _pktipofs);
  233.     }
  234. return NULL;
  235. }
  236.  
  237. void timeout_frags(void)
  238. {
  239. int i;
  240.  
  241. for (i=0;i<MAXFRAGS;i++)
  242.     if (fraglist[i].used)
  243.        if (chk_timeout(fraglist[i].timer))
  244.      {
  245.       fraglist[i].used = 0;
  246.       active_frags--;
  247.       pkt_buf_release((byte *)fraglist[i].ip);
  248.      }
  249. }
  250.  
  251.