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.5 1999/10/07 07:55:12 guy 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.
45 #include "wiretap/wtap.h"
47 #define array_length(x) (sizeof x / sizeof x[0])
49 /* Types of produceable packets */
68 guint8 *sample_buffer;
69 int sample_wtap_encap;
73 /* Ethernet, indicating ARP */
75 0xff, 0xff, 0xff, 0xff,
76 0xff, 0xff, 0x00, 0x00,
77 0x32, 0x25, 0x0f, 0xff,
81 /* Ethernet+IP+UP, indicating DNS */
83 0xff, 0xff, 0xff, 0xff,
84 0xff, 0xff, 0x01, 0x01,
85 0x01, 0x01, 0x01, 0x01,
88 0x45, 0x00, 0x00, 0x3c,
89 0xc5, 0x9e, 0x40, 0x00,
90 0xff, 0x11, 0xd7, 0xe0,
91 0xd0, 0x15, 0x02, 0xb8,
92 0x0a, 0x01, 0x01, 0x63,
94 0x05, 0xe8, 0x00, 0x35,
95 0x00, 0x00, 0x2a, 0xb9,
99 /* Ethernet+IP, indicating ICMP */
100 guint8 pkt_icmp[] = {
101 0xff, 0xff, 0xff, 0xff,
102 0xff, 0xff, 0x01, 0x01,
103 0x01, 0x01, 0x01, 0x01,
106 0x45, 0x00, 0x00, 0x54,
107 0x8f, 0xb3, 0x40, 0x00,
108 0xfd, 0x01, 0x8a, 0x99,
109 0xcc, 0xfc, 0x66, 0x0b,
110 0xce, 0x41, 0x62, 0x12
113 /* Ethernet, indicating IP */
115 0xff, 0xff, 0xff, 0xff,
116 0xff, 0xff, 0x01, 0x01,
117 0x01, 0x01, 0x01, 0x01,
121 /* TR, indicating LLC */
123 0x10, 0x40, 0x68, 0x00,
124 0x19, 0x69, 0x95, 0x8b,
125 0x00, 0x01, 0xfa, 0x68,
129 /* Ethernet+IP+UP, indicating NBNS */
130 guint8 pkt_nbns[] = {
131 0xff, 0xff, 0xff, 0xff,
132 0xff, 0xff, 0x01, 0x01,
133 0x01, 0x01, 0x01, 0x01,
136 0x45, 0x00, 0x00, 0x3c,
137 0xc5, 0x9e, 0x40, 0x00,
138 0xff, 0x11, 0xd7, 0xe0,
139 0xd0, 0x15, 0x02, 0xb8,
140 0x0a, 0x01, 0x01, 0x63,
142 0x00, 0x89, 0x00, 0x89,
143 0x00, 0x00, 0x2a, 0xb9,
147 /* TR+LLC+IP, indicating TCP */
149 0x10, 0x40, 0x68, 0x00,
150 0x19, 0x69, 0x95, 0x8b,
151 0x00, 0x01, 0xfa, 0x68,
154 0xaa, 0xaa, 0x03, 0x00,
155 0x00, 0x00, 0x08, 0x00,
157 0x45, 0x00, 0x00, 0x28,
158 0x0b, 0x0b, 0x40, 0x00,
159 0x20, 0x06, 0x85, 0x37,
160 0xc0, 0xa8, 0x27, 0x01,
161 0xc0, 0xa8, 0x22, 0x3c
164 /* Ethernet+IP, indicating UDP */
166 0xff, 0xff, 0xff, 0xff,
167 0xff, 0xff, 0x01, 0x01,
168 0x01, 0x01, 0x01, 0x01,
171 0x45, 0x00, 0x00, 0x3c,
172 0xc5, 0x9e, 0x40, 0x00,
173 0xff, 0x11, 0xd7, 0xe0,
174 0xd0, 0x15, 0x02, 0xb8,
175 0x0a, 0x01, 0x01, 0x63
178 /* This little data table drives the whole program */
179 pkt_example examples[] = {
180 { "arp", "Address Resolution Protocol",
181 PKT_ARP, pkt_arp, WTAP_ENCAP_ETHERNET, array_length(pkt_arp) },
183 { "dns", "Domain Name Service",
184 PKT_DNS, pkt_dns, WTAP_ENCAP_ETHERNET, array_length(pkt_dns) },
187 PKT_ETHERNET, NULL, WTAP_ENCAP_ETHERNET, 0 },
189 { "fddi", "Fiber Distributed Data Interface",
190 PKT_FDDI, NULL, WTAP_ENCAP_FDDI, 0 },
192 { "icmp", "Internet Control Message Protocol",
193 PKT_ICMP, pkt_icmp, WTAP_ENCAP_ETHERNET, array_length(pkt_icmp) },
195 { "ip", "Internet Protocol",
196 PKT_IP, pkt_ip, WTAP_ENCAP_ETHERNET, array_length(pkt_ip) },
198 { "llc", "Logical Link Control",
199 PKT_LLC, pkt_llc, WTAP_ENCAP_TR, array_length(pkt_llc) },
201 { "nbns", "NetBIOS-over-TCP Name Service",
202 PKT_NBNS, pkt_nbns, WTAP_ENCAP_ETHERNET, array_length(pkt_nbns) },
204 { "tcp", "Transmission Control Protocol",
205 PKT_TCP, pkt_tcp, WTAP_ENCAP_TR, array_length(pkt_tcp) },
207 { "tr", "Token-Ring",
208 PKT_TR, NULL, WTAP_ENCAP_TR, 0 },
210 { "udp", "User Datagram Protocol",
211 PKT_UDP, pkt_udp, WTAP_ENCAP_ETHERNET, array_length(pkt_udp) }
216 static int parse_type(char *string);
217 static void usage(void);
218 static void seed(void);
220 static pkt_example* find_example(int type);
223 main(int argc, char **argv)
227 struct wtap_pkthdr pkthdr;
228 int i, j, len_this_pkt, len_random, err;
229 guint8 buffer[65536];
235 int produce_count = 1000; /* number of pkts to produce */
236 int produce_type = PKT_ETHERNET;
237 char *produce_filename = NULL;
238 int produce_max_bytes = 5000;
239 pkt_example *example;
241 while ((opt = getopt(argc, argv, "b:c:t:")) != EOF) {
243 case 'b': /* max bytes */
244 produce_max_bytes = atoi(optarg);
245 if (produce_max_bytes > 65536) {
246 printf("Max bytes is 65536\n");
251 case 'c': /* count */
252 produce_count = atoi(optarg);
255 case 't': /* type of packet to produce */
256 produce_type = parse_type(optarg);
265 /* any more command line parameters? */
267 produce_filename = argv[optind];
273 example = find_example(produce_type);
275 pkthdr.ts.tv_sec = 0;
276 pkthdr.ts.tv_usec = 0;
277 pkthdr.pkt_encap = example->sample_wtap_encap;
279 dump = wtap_dump_open(produce_filename, WTAP_FILE_PCAP,
280 example->sample_wtap_encap, produce_max_bytes, &err);
284 /* reduce max_bytes by # of bytes already in sample */
285 if (produce_max_bytes <= example->sample_length) {
286 printf("Sample packet length is %d, which is greater than or equal to\n", example->sample_length);
287 printf("your requested max_bytes value of %d\n", produce_max_bytes);
291 produce_max_bytes -= example->sample_length;
294 /* Load the sample into our buffer */
295 if (example->sample_buffer)
296 memcpy(&buffer[0], example->sample_buffer, example->sample_length);
298 /* Produce random packets */
299 for (i = 0; i < produce_count; i++) {
300 if (produce_max_bytes > 0) {
301 len_random = (rand() % produce_max_bytes + 1);
307 len_this_pkt = example->sample_length + len_random;
309 pkthdr.caplen = len_this_pkt;
310 pkthdr.len = len_this_pkt;
311 pkthdr.ts.tv_sec = i; /* just for variety */
313 for (j = example->sample_length; j < len_random; j++) {
314 buffer[j] = (rand() % 0x100);
317 wtap_dump(dump, &pkthdr, &buffer[0], &err);
320 wtap_dump_close(dump, &err);
326 /* Print usage statement and exit program */
330 int num_entries = array_length(examples);
333 printf("Usage: randpkt [-b maxbytes] [-c count] [-t type] filename\n");
334 printf("Default max bytes (per packet) is 5000\n");
335 printf("Default count is 1000.\n");
338 for (i = 0; i < num_entries; i++) {
339 printf("\t%s\t%s\n", examples[i].abbrev, examples[i].longname);
347 /* Parse command-line option "type" and return enum type */
349 int parse_type(char *string)
351 int num_entries = array_length(examples);
354 for (i = 0; i < num_entries; i++) {
355 if (strcmp(examples[i].abbrev, string) == 0) {
356 return examples[i].produceable_type;
364 /* Find pkt_example record and return pointer to it */
366 pkt_example* find_example(int type)
368 int num_entries = array_length(examples);
371 for (i = 0; i < num_entries; i++) {
372 if (examples[i].produceable_type == type) {
377 printf("Internal error. Type %d has no entry in examples table.\n", type);
381 /* Seed the random-number generator */
385 unsigned int randomness;
388 /* Okay, I should use #ifdef HAVE_DEV_RANDOM, but this is a quick hack */
391 fd = open("/dev/random", O_RDONLY);
393 printf("Could not open /dev/random for reading: %s\n", strerror(errno));
397 read(fd, &randomness, sizeof(randomness));
402 randomness = (unsigned int) now;