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), ð, 0))
{
printf ("ARP failed\n");
return (-1);
}
ip = (in_Header*) _eth_formatpacket (ð, 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 + -
显示快捷键?