fragment.c

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 747 行 · 第 1/2 页

C
747
字号
      hole = hole->next;
    }
    else
    {
      hole = frag->hole_first->next = NULL;
      /* Adjust length */
      frag->ip->length = intel16 ((WORD)(data_end + in_GetHdrLen(ip)));
    }
  }

  if (hole)
  {
    hole->start = data_length;
    hole->end   = MAX_FRAG_SIZE;
    hole->next  = NULL;

    MSG (("hole %lX, start %lu, end %lu\n",
         (DWORD)hole, hole->start, hole->end));
  }
}


/*
 *  Check and report if fragment data-offset is okay
 */
static int check_data_start (const in_Header *ip, DWORD ofs, DWORD len)
{
  if (len % 8)                /* length must be multiple of 8 */
     return (0);              /* ofs is allready multiple of 8 */

  if (ofs <= MAX_FRAG_SIZE && /* fragment offset okay, < 65528 */
      ofs <= USHRT_MAX-8)
     return (1);

#if defined(USE_DEBUG)
  if (debug_on)
  {
    char src[20];
    char dst[20];
    (*_printf) (_LANG("Bad frag-ofs: fo %lu, ip-prot %u (%s->%s)\r\n"),
                ofs, ip->proto,
                _inet_ntoa (src,intel(ip->source)),
                _inet_ntoa (dst,intel(ip->destination)));
  }
#else
  ARGSUSED (ip);
  ARGSUSED (ip);
#endif
  return (0);
}


/*
 *  Allocate a bucket for doing fragment reassembly
 */
static in_Header *alloc_frag_buffer (const in_Header *ip)
{
  BYTE *p = NULL;
  int   i;

  for (i = 0; i < MAX_IP_FRAGS; i++)
  {
    if (frag_buckets[i].used)
       continue;

    if (!frag_buckets[i].ip)
    {
      p = calloc (BUCKET_SIZE + _pkt_ip_ofs, 1);
      if (!p)
      {
        MSG (("calloc() failed\n"));
        return (NULL);
      }
      frag_buckets[i].ip = (HugeIP*) (p + _pkt_ip_ofs);
      ((HugeIP*)p)->marker = BUCKET_MARKER;
    }
    else
    {
      p = (BYTE*)frag_buckets[i].ip - _pkt_ip_ofs;
      if (((HugeIP*)p)->marker != BUCKET_MARKER)
      {
        (*_printf) ("frag_buckets[%d] destroyed\r\n!", i);
     /* free (p);    heap probably corrupt, don't free */
        frag_buckets[i].ip = NULL;
        continue;
      }
    }
    MSG (("alloc_frag() = %lX\n", (DWORD)frag_buckets[i].ip));

    frag_buckets[i].used = 1;

    if (!_pktserial)
       memcpy (p, MAC_HDR(ip), _pkt_ip_ofs);  /* remember MAC-head */
    return (&frag_buckets[i].ip->hdr);
  }
  MSG (("all buckets full\n"));
  return (NULL);
}


/*
 *  Free/release the reassembled IP-packet.
 *  Note: we don't free it to the heap.
 */
int free_fragment (const in_Header *ip)
{
  int i, j;

  for (j = 0; j < MAX_IP_FRAGS; j++)
      if (ip == &frag_buckets[j].ip->hdr &&
          frag_buckets[j].used)
      {
        frag_buckets[j].used   = 0;
        frag_buckets[j].active = 0;
        for (i = 0; i < MAX_FRAGMENTS; i++)
            frag_list[j][i].used = 0;

        MSG (("free_fragment(%lX), bucket=%d\n", (DWORD)ip, j));
        return (1);
      }
  return (0);
}


/*
 *  Check if each fragment has timed-out
 */
void chk_timeout_frags (void)
{
  int j;

  for (j = 0; j < MAX_IP_FRAGS; j++)
  {
    int i;

    for (i = 0; i < MAX_FRAGMENTS; i++)
    {
      if (frag_buckets[j].active &&
          frag_list[j][i].used   &&
          chk_timeout(frag_list[j][i].timer))
      {
        const in_Header *ip = frag_list[j][i].ip;
        
        if (!_pktserial)    /* send a ICMP_TIMXCEED (code 1) */
             icmp_timexceed (ip, (void*) &frag_buckets[j].mac_src);
        else icmp_timexceed (ip, NULL);

        STAT (ipstats.ips_fragtimeout++);
        MSG (("chk_timeout_frags(), ip = %lX\n", (DWORD)ip));
        if (free_fragment(ip))
           break;
      }
    }
  }
}
#endif /* USE_FRAGMENTS */


/*----------------------------------------------------------------------*/

#if defined(TEST_PROG)  /* a small djgpp test program */
#undef FP_OFF
#undef enable
#undef disable

#include <unistd.h>
#include <assert.h>
#include <dos.h>

#include "sock_ini.h"
#include "udp_nds.h"
#include "loopback.h"
#include "pcarp.h"
#include "pcdbug.h"

static DWORD to_host   = 0;
static WORD  frag_ofs  = 0;
static int   max_frags = 5;
static int   frag_size = 1000;
static int   rand_frag = 0;
static int   time_frag = 0;

void usage (char *argv0)
{
  printf ("%s [-n num] [-s size] [-h ip] [-r] [-t]\n"
          "Send fragmented ICMP Echo Request (ping)\n\n"
          "options:\n"
          "  -n  number of fragments to send   (default %d)\n"
          "  -s  size of each fragment         (default %d)\n"
          "  -h  specify destination IP        (default 127.0.0.1)\n"
          "  -r  send fragment in random order (default %s)\n"
          "  -t  simulate fragment timeout     (default %s)\n",
          argv0, max_frags, frag_size,
          rand_frag ? "yes" : "no",
          time_frag ? "yes" : "no");
  exit (0);
}

BYTE *init_frag (int argc, char **argv)
{
  int   i, ch;
  BYTE *data;

  while ((ch = getopt(argc, argv, "h:n:s:rt?")) != EOF)
     switch (ch)
     {
       case 'h': to_host = inet_addr (optarg);
                 if (to_host == INADDR_NONE)
                 {
                   printf ("Illegal IP-address\n");
                   exit (-1);
                 }
                 break;
       case 'n': max_frags = atoi (optarg);
                 break;
       case 's': frag_size = atoi (optarg) / 8;  /* multiples of 8 */
                 frag_size <<= 3;
                 break;
       case 'r': rand_frag = 1;
                 break;
       case 't': time_frag = 1;   /* !! to-do */
                 break;
       case '?':
       default : usage (argv[0]);
     }

  if (max_frags < 1 || max_frags > FD_SETSIZE)
  {
    printf ("# of fragments is 1 - %d\n", FD_SETSIZE);
    exit (-1);
  }

  if (frag_size < 8 || frag_size > MAX_IP_DATA)
  {
    printf ("Fragsize range is 8 - %ld\n", MAX_IP_DATA);
    exit (-1);
  }

  if (frag_size * max_frags > USHRT_MAX)
  {
    printf ("Total fragsize > 64kB!\n");
    exit (-1);
  }

  data = calloc (frag_size * max_frags, 1);
  if (!data)
  {
    printf ("no memory\n");
    exit (-1);
  }

  for (i = 0; i < max_frags; i++)
     memset (data + i*frag_size, 'a'+i, frag_size);

  loopback_enable = 1;
  dbug_init();
  sock_init();

  if (!to_host)
     to_host = htonl (INADDR_LOOPBACK);
  return (data);
}

/*----------------------------------------------------------------------*/

int rand_packet (fd_set *fd, int max)
{
  int count = 0;

  while (1)
  {
    int i = Random (0, max);
    if (i < max && !FD_ISSET(i,fd))
    {
      FD_SET (i, fd);
      return (i);
    }
    if (++count == 10*max)
       return (-1);
  }
}

/*----------------------------------------------------------------------*/

int main (int argc, char **argv)
{
  fd_set      is_sent;
  int         i;
  eth_address eth;
  in_Header  *ip;
  ICMP_PKT   *icmp;
  WORD        frag_flag;
  BYTE       *data = init_frag (argc, argv);

  if (!_arp_resolve (ntohl(to_host), &eth, 0))
  {
    printf ("ARP failed\n");
    return (-1);
  }

  ip   = (in_Header*) _eth_formatpacket (&eth, IP_TYPE);
  icmp = (ICMP_PKT*) data;

  ip->hdrlen         = sizeof(*ip)/4;
  ip->ver            = 4;
  ip->tos            = 0;
  ip->identification = _get_ip_id();
  ip->ttl            = 15;           /* max 15sec reassembly time */
  ip->proto          = ICMP_PROTO;

  icmp->echo.type       = ICMP_ECHO;
  icmp->echo.code       = 0;
  icmp->echo.identifier = 0;
  icmp->echo.index      = 1;
  icmp->echo.sequence   = set_timeout (1);  /* "random" id */
  icmp->echo.checksum   = 0;
  icmp->echo.checksum   = ~checksum (icmp, max_frags*frag_size);

  FD_ZERO (&is_sent);

#if 0  /* test random generation */
  if (rand_frag)
     for (i = 0; i < max_frags; i++)
     {
       int j = rand_packet (&is_sent, max_frags);
       printf ("index %d\n", j);
     }
  exit (0);
#endif

  for (i = 0; i < max_frags; i++)
  {
    int j = rand_frag ? rand_packet (&is_sent,max_frags) : i;

    if (j < 0)
       break;
    if (i == max_frags-1)
         frag_flag = 0;
    else frag_flag = IP_MF;

    frag_ofs = (j * frag_size);
    memcpy ((BYTE*)(ip+1), data+frag_ofs, frag_size);

    /* The loopback device swaps src/dest IP; hence we must set them
     * on each iteration of the loop
     */
    ip->source      = intel (my_ip_addr);
    ip->destination = to_host;
    ip->frag_ofs    = intel16 (frag_ofs/8 | frag_flag);
    ip->length      = intel16 (frag_size + sizeof(*ip));
    ip->checksum    = 0;
    ip->checksum    = ~checksum (ip, sizeof(*ip));

    DEBUG_TX (NULL, ip);

    _eth_send (frag_size+sizeof(*ip));
    STAT (ipstats.ips_ofragments++);
    tcp_tick (NULL);
  }

  outsnl ("tcp_tick()");

  /* poll the IP-queue, reassemble fragments and
   * dump reassembled IP/ICMP packet to debugger (look in wattcp.dbg)
   */
  if (to_host != htonl (INADDR_LOOPBACK))
     usleep (1000000 + 100*max_frags*frag_size); /* wait for reply */

  tcp_tick (NULL);
  return (0);
}
#endif  /* TEST_PROG */

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?