Added random packet generator.
svn path=/trunk/; revision=645
This commit is contained in:
parent
e425e372ca
commit
c2bf152b01
10
Makefile.am
10
Makefile.am
|
@ -1,7 +1,7 @@
|
||||||
# Makefile.am
|
# Makefile.am
|
||||||
# Automake file for Ethereal
|
# Automake file for Ethereal
|
||||||
#
|
#
|
||||||
# $Id: Makefile.am,v 1.69 1999/09/09 03:45:57 guy Exp $
|
# $Id: Makefile.am,v 1.70 1999/09/10 05:15:09 gram Exp $
|
||||||
#
|
#
|
||||||
# Ethereal - Network traffic analyzer
|
# Ethereal - Network traffic analyzer
|
||||||
# By Gerald Combs <gerald@zing.org>
|
# By Gerald Combs <gerald@zing.org>
|
||||||
|
@ -22,7 +22,7 @@
|
||||||
# along with this program; if not, write to the Free Software
|
# along with this program; if not, write to the Free Software
|
||||||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
bin_PROGRAMS = ethereal
|
bin_PROGRAMS = ethereal randpkt
|
||||||
|
|
||||||
man_MANS = ethereal.1
|
man_MANS = ethereal.1
|
||||||
|
|
||||||
|
@ -155,6 +155,12 @@ ps.c: print.ps rdps
|
||||||
rdps: rdps.c
|
rdps: rdps.c
|
||||||
$(CC) -o rdps $(srcdir)/rdps.c
|
$(CC) -o rdps $(srcdir)/rdps.c
|
||||||
|
|
||||||
|
randpkt_SOURCES = \
|
||||||
|
randpkt.c
|
||||||
|
|
||||||
|
randpkt_DEPENDENCIES = wiretap/libwiretap.a
|
||||||
|
randpkt_LDADD = wiretap/libwiretap.a
|
||||||
|
|
||||||
DISTCLEANFILES = \
|
DISTCLEANFILES = \
|
||||||
rdps \
|
rdps \
|
||||||
ps.c \
|
ps.c \
|
||||||
|
|
|
@ -0,0 +1,115 @@
|
||||||
|
Random Packet Generator
|
||||||
|
-----------------------
|
||||||
|
$Id: randpkt.txt,v 1.1 1999/09/10 05:15:17 gram Exp $
|
||||||
|
|
||||||
|
This small utility creates a libpcap trace file full of random packets.
|
||||||
|
You can control the number of packets, the maximum size of each packet,
|
||||||
|
and the type of each packet.
|
||||||
|
|
||||||
|
By creating many randomized packets of a certain type, you can
|
||||||
|
test packet sniffers to see how well they handle malformed packets.
|
||||||
|
The sniffer can never trust the data that it sees in the packet because
|
||||||
|
you can always sniff a very bad packet that conforms to no standard.
|
||||||
|
Randpkt produces __very bad__ packets.
|
||||||
|
|
||||||
|
When creating packets of a certain type, randpkt uses a sample
|
||||||
|
packet that is stored internally to randpkt. It uses this as the
|
||||||
|
starting point for your random packets, and then adds extra random
|
||||||
|
bytes to the end of this sample packet.
|
||||||
|
|
||||||
|
For example, if you choose to create random ARP packets, randpkt
|
||||||
|
will create a packet which contains a predetermined Ethernet II header,
|
||||||
|
with the Type field set to ARP. After the Ethernet II header, it will
|
||||||
|
put a random number of bytes with random values.
|
||||||
|
|
||||||
|
Run 'randpkt' with no options to see the usage statement. As of the
|
||||||
|
writing of this text, the usage is:
|
||||||
|
|
||||||
|
Usage: randpkt [-b maxbytes] [-c count] [-t type] filename
|
||||||
|
|
||||||
|
The usage statement produced by randpkt will list the legal types.
|
||||||
|
|
||||||
|
If you choose a maxbytes value that is less than the size of the
|
||||||
|
sample packet, then your packets would contain only the sample
|
||||||
|
packet... not much variance there! Randpkt exits on that condition.
|
||||||
|
|
||||||
|
To add a new packet type to randpkt, you must add information
|
||||||
|
in the following locations.
|
||||||
|
|
||||||
|
1) Add the packet type name to the enum of produceable packets:
|
||||||
|
|
||||||
|
/* Types of produceable packets */
|
||||||
|
enum {
|
||||||
|
PKT_ARP,
|
||||||
|
PKT_ETHERNET,
|
||||||
|
PKT_FDDI,
|
||||||
|
PKT_LLC,
|
||||||
|
PKT_TR
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
2) Type in the bytes from your sample packet
|
||||||
|
|
||||||
|
/* Ethernet, indicating ARP */
|
||||||
|
guint8 pkt_arp[] = {
|
||||||
|
0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0x00, 0x00,
|
||||||
|
0x32, 0x25, 0x0f, 0xff,
|
||||||
|
0x08, 0x06
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
3) Add a record to the 'examples' array. The fields are
|
||||||
|
1. Abbreviation (for use in '-t' command line argument)
|
||||||
|
2. Full name (for use in usage statement)
|
||||||
|
3. Enum type
|
||||||
|
4. Array holding sample packet
|
||||||
|
5. Wiretap encapsulation type of datalink layer in your
|
||||||
|
sample packet
|
||||||
|
6. Length of sample packet. Use the handy array_length()
|
||||||
|
macro to avoid counting the bytes yourself.
|
||||||
|
|
||||||
|
|
||||||
|
pkt_example examples[] = {
|
||||||
|
{ "arp",
|
||||||
|
"Address Resolution Protocol",
|
||||||
|
PKT_ARP,
|
||||||
|
pkt_arp,
|
||||||
|
WTAP_ENCAP_ETHERNET,
|
||||||
|
array_length(pkt_arp) },
|
||||||
|
|
||||||
|
{ "eth",
|
||||||
|
"Ethernet",
|
||||||
|
PKT_ETHERNET,
|
||||||
|
NULL,
|
||||||
|
WTAP_ENCAP_ETHERNET,
|
||||||
|
0 },
|
||||||
|
|
||||||
|
{ "fddi",
|
||||||
|
"Fiber Distributed Data Interface",
|
||||||
|
PKT_FDDI,
|
||||||
|
NULL,
|
||||||
|
WTAP_ENCAP_FDDI,
|
||||||
|
0 },
|
||||||
|
|
||||||
|
{ "llc",
|
||||||
|
"Logical Link Control",
|
||||||
|
PKT_LLC,
|
||||||
|
pkt_llc,
|
||||||
|
WTAP_ENCAP_TR,
|
||||||
|
array_length(pkt_llc) },
|
||||||
|
|
||||||
|
{ "tr",
|
||||||
|
"Token-Ring",
|
||||||
|
PKT_TR,
|
||||||
|
NULL,
|
||||||
|
WTAP_ENCAP_TR,
|
||||||
|
0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
Note that packets that designate only their datalink type have no sample
|
||||||
|
arrays, since the only thing that needs to be set is the datalink type,
|
||||||
|
which is a field in the libpcap frame record; it's not a part of the
|
||||||
|
packet itself.
|
||||||
|
|
||||||
|
Enjoy!
|
|
@ -0,0 +1,293 @@
|
||||||
|
/*
|
||||||
|
* randpkt.c
|
||||||
|
* ---------
|
||||||
|
* Creates random packet traces. Useful for debugging sniffers by testing
|
||||||
|
* assumptions about the veracity of the data found in the packet.
|
||||||
|
*
|
||||||
|
* $Id: randpkt.c,v 1.1 1999/09/10 05:15:10 gram Exp $
|
||||||
|
*
|
||||||
|
* Copyright (C) 1999 by Gilbert Ramirez <gram@xiexie.org>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_UNISTD_H
|
||||||
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_FCNTL_H
|
||||||
|
#include <fcntl.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <time.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <glib.h>
|
||||||
|
#include <wtap.h>
|
||||||
|
|
||||||
|
#define array_length(x) (sizeof x / sizeof x[0])
|
||||||
|
|
||||||
|
/* Types of produceable packets */
|
||||||
|
enum {
|
||||||
|
PKT_ARP,
|
||||||
|
PKT_ETHERNET,
|
||||||
|
PKT_FDDI,
|
||||||
|
PKT_LLC,
|
||||||
|
PKT_TR
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char *abbrev;
|
||||||
|
char *longname;
|
||||||
|
int produceable_type;
|
||||||
|
guint8 *sample_buffer;
|
||||||
|
int sample_wtap_encap;
|
||||||
|
int sample_length;
|
||||||
|
} pkt_example;
|
||||||
|
|
||||||
|
/* Ethernet, indicating ARP */
|
||||||
|
guint8 pkt_arp[] = {
|
||||||
|
0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0x00, 0x00,
|
||||||
|
0x32, 0x25, 0x0f, 0xff,
|
||||||
|
0x08, 0x06
|
||||||
|
};
|
||||||
|
|
||||||
|
/* TR, indicating LLC */
|
||||||
|
guint8 pkt_llc[] = {
|
||||||
|
0x10, 0x40, 0x68, 0x00,
|
||||||
|
0x19, 0x69, 0x95, 0x8b,
|
||||||
|
0x00, 0x01, 0xfa, 0x68,
|
||||||
|
0xc4, 0x67
|
||||||
|
};
|
||||||
|
|
||||||
|
/* This little data table drives the whole program */
|
||||||
|
pkt_example examples[] = {
|
||||||
|
{ "arp", "Address Resolution Protocol",
|
||||||
|
PKT_ARP, pkt_arp, WTAP_ENCAP_ETHERNET, array_length(pkt_arp) },
|
||||||
|
|
||||||
|
{ "eth", "Ethernet",
|
||||||
|
PKT_ETHERNET, NULL, WTAP_ENCAP_ETHERNET, 0 },
|
||||||
|
|
||||||
|
{ "fddi", "Fiber Distributed Data Interface",
|
||||||
|
PKT_FDDI, NULL, WTAP_ENCAP_FDDI, 0 },
|
||||||
|
|
||||||
|
{ "llc", "Logical Link Control",
|
||||||
|
PKT_LLC, pkt_llc, WTAP_ENCAP_TR, array_length(pkt_llc) },
|
||||||
|
|
||||||
|
{ "tr", "Token-Ring",
|
||||||
|
PKT_TR, NULL, WTAP_ENCAP_TR, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static int parse_type(char *string);
|
||||||
|
static void usage(void);
|
||||||
|
static void seed(void);
|
||||||
|
|
||||||
|
static pkt_example* find_example(int type);
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
|
||||||
|
wtap_dumper *dump;
|
||||||
|
struct wtap_pkthdr pkthdr;
|
||||||
|
int i, j, len_this_pkt, len_random, err;
|
||||||
|
guint8 buffer[65536];
|
||||||
|
|
||||||
|
int opt;
|
||||||
|
extern char *optarg;
|
||||||
|
extern int optind;
|
||||||
|
|
||||||
|
int produce_count = 1000; /* number of pkts to produce */
|
||||||
|
int produce_type = PKT_ETHERNET;
|
||||||
|
char *produce_filename = NULL;
|
||||||
|
int produce_max_bytes = 5000;
|
||||||
|
pkt_example *example;
|
||||||
|
|
||||||
|
while ((opt = getopt(argc, argv, "b:c:t:")) != EOF) {
|
||||||
|
switch (opt) {
|
||||||
|
case 'b': /* max bytes */
|
||||||
|
produce_max_bytes = atoi(optarg);
|
||||||
|
if (produce_max_bytes > 65536) {
|
||||||
|
printf("Max bytes is 65536\n");
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'c': /* count */
|
||||||
|
produce_count = atoi(optarg);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 't': /* type of packet to produce */
|
||||||
|
produce_type = parse_type(optarg);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
usage();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* any more command line parameters? */
|
||||||
|
if (argc > optind) {
|
||||||
|
produce_filename = argv[optind];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
usage();
|
||||||
|
}
|
||||||
|
|
||||||
|
example = find_example(produce_type);
|
||||||
|
|
||||||
|
pkthdr.ts.tv_sec = 0;
|
||||||
|
pkthdr.ts.tv_usec = 0;
|
||||||
|
pkthdr.pkt_encap = example->sample_wtap_encap;
|
||||||
|
|
||||||
|
dump = wtap_dump_open(produce_filename, WTAP_FILE_PCAP,
|
||||||
|
example->sample_wtap_encap, produce_max_bytes, &err);
|
||||||
|
|
||||||
|
seed();
|
||||||
|
|
||||||
|
/* reduce max_bytes by # of bytes already in sample */
|
||||||
|
if (produce_max_bytes <= example->sample_length) {
|
||||||
|
printf("Sample packet length is %d, which is greater than or equal to\n", example->sample_length);
|
||||||
|
printf("your requested max_bytes value of %d\n", produce_max_bytes);
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
produce_max_bytes -= example->sample_length;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Load the sample into our buffer */
|
||||||
|
if (example->sample_buffer)
|
||||||
|
memcpy(&buffer[0], example->sample_buffer, example->sample_length);
|
||||||
|
|
||||||
|
/* Produce random packets */
|
||||||
|
for (i = 0; i < produce_count; i++) {
|
||||||
|
if (produce_max_bytes > 0) {
|
||||||
|
len_random = (rand() % produce_max_bytes + 1);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
len_random = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
len_this_pkt = example->sample_length + len_random;
|
||||||
|
|
||||||
|
pkthdr.caplen = len_this_pkt;
|
||||||
|
pkthdr.len = len_this_pkt;
|
||||||
|
pkthdr.ts.tv_sec = i; /* just for variety */
|
||||||
|
|
||||||
|
for (j = example->sample_length; j < len_random; j++) {
|
||||||
|
buffer[j] = (rand() % 0x100);
|
||||||
|
}
|
||||||
|
|
||||||
|
wtap_dump(dump, &pkthdr, &buffer[0], &err);
|
||||||
|
}
|
||||||
|
|
||||||
|
wtap_dump_close(dump, &err);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Print usage statement and exit program */
|
||||||
|
static
|
||||||
|
void usage(void)
|
||||||
|
{
|
||||||
|
int num_entries = array_length(examples);
|
||||||
|
int i;
|
||||||
|
|
||||||
|
printf("Usage: randpkt [-b maxbytes] [-c count] [-t type] filename\n");
|
||||||
|
printf("Default max bytes (per packet) is 5000\n");
|
||||||
|
printf("Default count is 1000.\n");
|
||||||
|
printf("Types:\n");
|
||||||
|
|
||||||
|
for (i = 0; i < num_entries; i++) {
|
||||||
|
printf("\t%s\t%s\n", examples[i].abbrev, examples[i].longname);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Parse command-line option "type" and return enum type */
|
||||||
|
static
|
||||||
|
int parse_type(char *string)
|
||||||
|
{
|
||||||
|
int num_entries = array_length(examples);
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < num_entries; i++) {
|
||||||
|
if (strcmp(examples[i].abbrev, string) == 0) {
|
||||||
|
return examples[i].produceable_type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* default type */
|
||||||
|
return PKT_ETHERNET;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Find pkt_example record and return pointer to it */
|
||||||
|
static
|
||||||
|
pkt_example* find_example(int type)
|
||||||
|
{
|
||||||
|
int num_entries = array_length(examples);
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < num_entries; i++) {
|
||||||
|
if (examples[i].produceable_type == type) {
|
||||||
|
return &examples[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Internal error. Type %d has no entry in examples table.\n", type);
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Seed the random-number generator */
|
||||||
|
void
|
||||||
|
seed(void)
|
||||||
|
{
|
||||||
|
unsigned int randomness;
|
||||||
|
|
||||||
|
#if defined(linux)
|
||||||
|
/* Okay, I should use #ifdef HAVE_DEV_RANDOM, but this is a quick hack */
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
fd = open("/dev/random", O_RDONLY);
|
||||||
|
if (fd < 0) {
|
||||||
|
printf("Could not open /dev/random for reading: %s\n", strerror(errno));
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
read(fd, &randomness, sizeof(randomness));
|
||||||
|
#else
|
||||||
|
time_t now;
|
||||||
|
|
||||||
|
now = time(NULL);
|
||||||
|
randomness = (unsigned int) now;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
srand(randomness);
|
||||||
|
}
|
Loading…
Reference in New Issue