aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGilbert Ramirez <gram@alumni.rice.edu>1999-09-10 05:15:17 +0000
committerGilbert Ramirez <gram@alumni.rice.edu>1999-09-10 05:15:17 +0000
commitc2bf152b019e8e5db6835fac90b4431ce32ff234 (patch)
treee245ca333afc8100c51125f85670683baeb8d183
parente425e372ca086922ff4ffba6321d4aec0f12f9f7 (diff)
Added random packet generator.
svn path=/trunk/; revision=645
-rw-r--r--Makefile.am10
-rw-r--r--doc/randpkt.txt115
-rw-r--r--randpkt.c293
3 files changed, 416 insertions, 2 deletions
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 <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 \
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 <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);
+}