forked from osmocom/wireshark
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
|
||||
# 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
|
||||
# By Gerald Combs <gerald@zing.org>
|
||||
|
@ -22,7 +22,7 @@
|
|||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
bin_PROGRAMS = ethereal
|
||||
bin_PROGRAMS = ethereal randpkt
|
||||
|
||||
man_MANS = ethereal.1
|
||||
|
||||
|
@ -155,6 +155,12 @@ ps.c: print.ps rdps
|
|||
rdps: rdps.c
|
||||
$(CC) -o rdps $(srcdir)/rdps.c
|
||||
|
||||
randpkt_SOURCES = \
|
||||
randpkt.c
|
||||
|
||||
randpkt_DEPENDENCIES = wiretap/libwiretap.a
|
||||
randpkt_LDADD = wiretap/libwiretap.a
|
||||
|
||||
DISTCLEANFILES = \
|
||||
rdps \
|
||||
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