Added random packet generator.
authorgram <gram@f5534014-38df-0310-8fa8-9805f1628bb7>
Fri, 10 Sep 1999 05:15:17 +0000 (05:15 +0000)
committergram <gram@f5534014-38df-0310-8fa8-9805f1628bb7>
Fri, 10 Sep 1999 05:15:17 +0000 (05:15 +0000)
git-svn-id: http://anonsvn.wireshark.org/wireshark/trunk@645 f5534014-38df-0310-8fa8-9805f1628bb7

Makefile.am
doc/randpkt.txt [new file with mode: 0644]
randpkt.c [new file with mode: 0644]

index 43fadc34ae21f2de13d0de8a009db7ad3a60b647..394302714d5d891a65fb19d7b21dc1b0c4c29c7d 100644 (file)
@@ -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 (file)
index 0000000..1de2929
--- /dev/null
@@ -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 (file)
index 0000000..213421c
--- /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);
+}