4 * Creates random packet traces. Useful for debugging sniffers by testing
5 * assumptions about the veracity of the data found in the packet.
7 * $Id: randpkt.c,v 1.2 1999/09/10 15:38:48 gram Exp $
9 * Copyright (C) 1999 by Gilbert Ramirez <gram@xiexie.org>
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
47 #define array_length(x) (sizeof x / sizeof x[0])
49 /* Types of produceable packets */
65 guint8 *sample_buffer;
66 int sample_wtap_encap;
70 /* Ethernet, indicating ARP */
72 0xff, 0xff, 0xff, 0xff,
73 0xff, 0xff, 0x00, 0x00,
74 0x32, 0x25, 0x0f, 0xff,
78 /* Ethernet, indicating IP */
80 0xff, 0xff, 0xff, 0xff,
81 0xff, 0xff, 0x01, 0x01,
82 0x01, 0x01, 0x01, 0x01,
86 /* TR, indicating LLC */
88 0x10, 0x40, 0x68, 0x00,
89 0x19, 0x69, 0x95, 0x8b,
90 0x00, 0x01, 0xfa, 0x68,
94 /* TR+LLC+IP, indicating TCP */
96 0x10, 0x40, 0x68, 0x00,
97 0x19, 0x69, 0x95, 0x8b,
98 0x00, 0x01, 0xfa, 0x68,
101 0xaa, 0xaa, 0x03, 0x00,
102 0x00, 0x00, 0x08, 0x00,
104 0x45, 0x00, 0x00, 0x28,
105 0x0b, 0x0b, 0x40, 0x00,
106 0x20, 0x06, 0x85, 0x37,
107 0xc0, 0xa8, 0x27, 0x01,
108 0xc0, 0xa8, 0x22, 0x3c
111 /* Ethernet+IP, indicating UDP */
113 0xff, 0xff, 0xff, 0xff,
114 0xff, 0xff, 0x01, 0x01,
115 0x01, 0x01, 0x01, 0x01,
118 0x45, 0x00, 0x00, 0x3c,
119 0xc5, 0x9e, 0x40, 0x00,
120 0xff, 0x11, 0xd7, 0xe0,
121 0xd0, 0x15, 0x02, 0xb8,
122 0x0a, 0x01, 0x01, 0x63
125 /* This little data table drives the whole program */
126 pkt_example examples[] = {
127 { "arp", "Address Resolution Protocol",
128 PKT_ARP, pkt_arp, WTAP_ENCAP_ETHERNET, array_length(pkt_arp) },
131 PKT_ETHERNET, NULL, WTAP_ENCAP_ETHERNET, 0 },
133 { "fddi", "Fiber Distributed Data Interface",
134 PKT_FDDI, NULL, WTAP_ENCAP_FDDI, 0 },
136 { "ip", "Internet Protocol",
137 PKT_IP, pkt_ip, WTAP_ENCAP_ETHERNET, array_length(pkt_ip) },
139 { "llc", "Logical Link Control",
140 PKT_LLC, pkt_llc, WTAP_ENCAP_TR, array_length(pkt_llc) },
142 { "tcp", "Transmission Control Protocol",
143 PKT_TCP, pkt_tcp, WTAP_ENCAP_TR, array_length(pkt_tcp) },
145 { "tr", "Token-Ring",
146 PKT_TR, NULL, WTAP_ENCAP_TR, 0 },
148 { "udp", "User Datagram Protocol",
149 PKT_UDP, pkt_udp, WTAP_ENCAP_ETHERNET, array_length(pkt_udp) }
154 static int parse_type(char *string);
155 static void usage(void);
156 static void seed(void);
158 static pkt_example* find_example(int type);
161 main(int argc, char **argv)
165 struct wtap_pkthdr pkthdr;
166 int i, j, len_this_pkt, len_random, err;
167 guint8 buffer[65536];
173 int produce_count = 1000; /* number of pkts to produce */
174 int produce_type = PKT_ETHERNET;
175 char *produce_filename = NULL;
176 int produce_max_bytes = 5000;
177 pkt_example *example;
179 while ((opt = getopt(argc, argv, "b:c:t:")) != EOF) {
181 case 'b': /* max bytes */
182 produce_max_bytes = atoi(optarg);
183 if (produce_max_bytes > 65536) {
184 printf("Max bytes is 65536\n");
189 case 'c': /* count */
190 produce_count = atoi(optarg);
193 case 't': /* type of packet to produce */
194 produce_type = parse_type(optarg);
203 /* any more command line parameters? */
205 produce_filename = argv[optind];
211 example = find_example(produce_type);
213 pkthdr.ts.tv_sec = 0;
214 pkthdr.ts.tv_usec = 0;
215 pkthdr.pkt_encap = example->sample_wtap_encap;
217 dump = wtap_dump_open(produce_filename, WTAP_FILE_PCAP,
218 example->sample_wtap_encap, produce_max_bytes, &err);
222 /* reduce max_bytes by # of bytes already in sample */
223 if (produce_max_bytes <= example->sample_length) {
224 printf("Sample packet length is %d, which is greater than or equal to\n", example->sample_length);
225 printf("your requested max_bytes value of %d\n", produce_max_bytes);
229 produce_max_bytes -= example->sample_length;
232 /* Load the sample into our buffer */
233 if (example->sample_buffer)
234 memcpy(&buffer[0], example->sample_buffer, example->sample_length);
236 /* Produce random packets */
237 for (i = 0; i < produce_count; i++) {
238 if (produce_max_bytes > 0) {
239 len_random = (rand() % produce_max_bytes + 1);
245 len_this_pkt = example->sample_length + len_random;
247 pkthdr.caplen = len_this_pkt;
248 pkthdr.len = len_this_pkt;
249 pkthdr.ts.tv_sec = i; /* just for variety */
251 for (j = example->sample_length; j < len_random; j++) {
252 buffer[j] = (rand() % 0x100);
255 wtap_dump(dump, &pkthdr, &buffer[0], &err);
258 wtap_dump_close(dump, &err);
264 /* Print usage statement and exit program */
268 int num_entries = array_length(examples);
271 printf("Usage: randpkt [-b maxbytes] [-c count] [-t type] filename\n");
272 printf("Default max bytes (per packet) is 5000\n");
273 printf("Default count is 1000.\n");
276 for (i = 0; i < num_entries; i++) {
277 printf("\t%s\t%s\n", examples[i].abbrev, examples[i].longname);
285 /* Parse command-line option "type" and return enum type */
287 int parse_type(char *string)
289 int num_entries = array_length(examples);
292 for (i = 0; i < num_entries; i++) {
293 if (strcmp(examples[i].abbrev, string) == 0) {
294 return examples[i].produceable_type;
302 /* Find pkt_example record and return pointer to it */
304 pkt_example* find_example(int type)
306 int num_entries = array_length(examples);
309 for (i = 0; i < num_entries; i++) {
310 if (examples[i].produceable_type == type) {
315 printf("Internal error. Type %d has no entry in examples table.\n", type);
319 /* Seed the random-number generator */
323 unsigned int randomness;
326 /* Okay, I should use #ifdef HAVE_DEV_RANDOM, but this is a quick hack */
329 fd = open("/dev/random", O_RDONLY);
331 printf("Could not open /dev/random for reading: %s\n", strerror(errno));
335 read(fd, &randomness, sizeof(randomness));
340 randomness = (unsigned int) now;