From 43c0f8299d341aacc92cfba72440b53558423c31 Mon Sep 17 00:00:00 2001 From: gram Date: Fri, 10 Sep 1999 05:15:17 +0000 Subject: [PATCH] Added random packet generator. git-svn-id: http://anonsvn.wireshark.org/wireshark/trunk@645 f5534014-38df-0310-8fa8-9805f1628bb7 --- Makefile.am | 10 +- doc/randpkt.txt | 115 +++++++++++++++++++ randpkt.c | 293 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 416 insertions(+), 2 deletions(-) create mode 100644 doc/randpkt.txt create mode 100644 randpkt.c diff --git a/Makefile.am b/Makefile.am index 43fadc34ae..394302714d 100644 --- a/Makefile.am +++ b/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 @@ -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 \ diff --git a/doc/randpkt.txt b/doc/randpkt.txt new file mode 100644 index 0000000000..1de2929859 --- /dev/null +++ b/doc/randpkt.txt @@ -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! diff --git a/randpkt.c b/randpkt.c new file mode 100644 index 0000000000..213421c977 --- /dev/null +++ b/randpkt.c @@ -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 + * + * 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 +#endif + +#ifdef HAVE_FCNTL_H +#include +#endif + +#include +#include + +#include +#include +#include +#include +#include + +#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); +} -- 2.34.1