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