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.6 2000/05/19 02:42:16 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.
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 union pseudo_header ps_header;
229 int i, j, len_this_pkt, len_random, err;
230 guint8 buffer[65536];
236 int produce_count = 1000; /* number of pkts to produce */
237 int produce_type = PKT_ETHERNET;
238 char *produce_filename = NULL;
239 int produce_max_bytes = 5000;
240 pkt_example *example;
242 while ((opt = getopt(argc, argv, "b:c:t:")) != EOF) {
244 case 'b': /* max bytes */
245 produce_max_bytes = atoi(optarg);
246 if (produce_max_bytes > 65536) {
247 printf("Max bytes is 65536\n");
252 case 'c': /* count */
253 produce_count = atoi(optarg);
256 case 't': /* type of packet to produce */
257 produce_type = parse_type(optarg);
266 /* any more command line parameters? */
268 produce_filename = argv[optind];
274 example = find_example(produce_type);
276 pkthdr.ts.tv_sec = 0;
277 pkthdr.ts.tv_usec = 0;
278 pkthdr.pkt_encap = example->sample_wtap_encap;
280 dump = wtap_dump_open(produce_filename, WTAP_FILE_PCAP,
281 example->sample_wtap_encap, produce_max_bytes, &err);
285 /* reduce max_bytes by # of bytes already in sample */
286 if (produce_max_bytes <= example->sample_length) {
287 printf("Sample packet length is %d, which is greater than or equal to\n", example->sample_length);
288 printf("your requested max_bytes value of %d\n", produce_max_bytes);
292 produce_max_bytes -= example->sample_length;
295 /* Load the sample into our buffer */
296 if (example->sample_buffer)
297 memcpy(&buffer[0], example->sample_buffer, example->sample_length);
299 /* Produce random packets */
300 for (i = 0; i < produce_count; i++) {
301 if (produce_max_bytes > 0) {
302 len_random = (rand() % produce_max_bytes + 1);
308 len_this_pkt = example->sample_length + len_random;
310 pkthdr.caplen = len_this_pkt;
311 pkthdr.len = len_this_pkt;
312 pkthdr.ts.tv_sec = i; /* just for variety */
314 for (j = example->sample_length; j < len_random; j++) {
315 buffer[j] = (rand() % 0x100);
318 wtap_dump(dump, &pkthdr, &ps_header, &buffer[0], &err);
321 wtap_dump_close(dump, &err);
327 /* Print usage statement and exit program */
331 int num_entries = array_length(examples);
334 printf("Usage: randpkt [-b maxbytes] [-c count] [-t type] filename\n");
335 printf("Default max bytes (per packet) is 5000\n");
336 printf("Default count is 1000.\n");
339 for (i = 0; i < num_entries; i++) {
340 printf("\t%s\t%s\n", examples[i].abbrev, examples[i].longname);
348 /* Parse command-line option "type" and return enum type */
350 int parse_type(char *string)
352 int num_entries = array_length(examples);
355 for (i = 0; i < num_entries; i++) {
356 if (strcmp(examples[i].abbrev, string) == 0) {
357 return examples[i].produceable_type;
365 /* Find pkt_example record and return pointer to it */
367 pkt_example* find_example(int type)
369 int num_entries = array_length(examples);
372 for (i = 0; i < num_entries; i++) {
373 if (examples[i].produceable_type == type) {
378 printf("Internal error. Type %d has no entry in examples table.\n", type);
382 /* Seed the random-number generator */
386 unsigned int randomness;
389 /* Okay, I should use #ifdef HAVE_DEV_RANDOM, but this is a quick hack */
392 fd = open("/dev/random", O_RDONLY);
394 printf("Could not open /dev/random for reading: %s\n", strerror(errno));
398 read(fd, &randomness, sizeof(randomness));
403 randomness = (unsigned int) now;