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.10 2001/03/31 10:13:11 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 */
70 guint8 *sample_buffer;
71 int sample_wtap_encap;
75 /* Ethernet, indicating ARP */
77 0xff, 0xff, 0xff, 0xff,
78 0xff, 0xff, 0x00, 0x00,
79 0x32, 0x25, 0x0f, 0xff,
83 /* Ethernet+IP+UDP, indicating DNS */
85 0xff, 0xff, 0xff, 0xff,
86 0xff, 0xff, 0x01, 0x01,
87 0x01, 0x01, 0x01, 0x01,
90 0x45, 0x00, 0x00, 0x3c,
91 0xc5, 0x9e, 0x40, 0x00,
92 0xff, 0x11, 0xd7, 0xe0,
93 0xd0, 0x15, 0x02, 0xb8,
94 0x0a, 0x01, 0x01, 0x63,
96 0x05, 0xe8, 0x00, 0x35,
97 0x00, 0x00, 0x2a, 0xb9,
101 /* Ethernet+IP, indicating ICMP */
102 guint8 pkt_icmp[] = {
103 0xff, 0xff, 0xff, 0xff,
104 0xff, 0xff, 0x01, 0x01,
105 0x01, 0x01, 0x01, 0x01,
108 0x45, 0x00, 0x00, 0x54,
109 0x8f, 0xb3, 0x40, 0x00,
110 0xfd, 0x01, 0x8a, 0x99,
111 0xcc, 0xfc, 0x66, 0x0b,
112 0xce, 0x41, 0x62, 0x12
115 /* Ethernet, indicating IP */
117 0xff, 0xff, 0xff, 0xff,
118 0xff, 0xff, 0x01, 0x01,
119 0x01, 0x01, 0x01, 0x01,
123 /* TR, indicating LLC */
125 0x10, 0x40, 0x68, 0x00,
126 0x19, 0x69, 0x95, 0x8b,
127 0x00, 0x01, 0xfa, 0x68,
131 /* Ethernet+IP+UP, indicating NBNS */
132 guint8 pkt_nbns[] = {
133 0xff, 0xff, 0xff, 0xff,
134 0xff, 0xff, 0x01, 0x01,
135 0x01, 0x01, 0x01, 0x01,
138 0x45, 0x00, 0x00, 0x3c,
139 0xc5, 0x9e, 0x40, 0x00,
140 0xff, 0x11, 0xd7, 0xe0,
141 0xd0, 0x15, 0x02, 0xb8,
142 0x0a, 0x01, 0x01, 0x63,
144 0x00, 0x89, 0x00, 0x89,
145 0x00, 0x00, 0x2a, 0xb9,
149 /* Ethernet+IP+UDP, indicating syslog */
150 guint8 pkt_syslog[] = {
151 0xff, 0xff, 0xff, 0xff,
152 0xff, 0xff, 0x01, 0x01,
153 0x01, 0x01, 0x01, 0x01,
156 0x45, 0x00, 0x00, 0x64,
157 0x20, 0x48, 0x00, 0x00,
158 0xfc, 0x11, 0xf8, 0x03,
159 0xd0, 0x15, 0x02, 0xb8,
160 0x0a, 0x01, 0x01, 0x63,
162 0x05, 0xe8, 0x02, 0x02,
163 0x00, 0x50, 0x51, 0xe1,
167 /* TR+LLC+IP, indicating TCP */
169 0x10, 0x40, 0x68, 0x00,
170 0x19, 0x69, 0x95, 0x8b,
171 0x00, 0x01, 0xfa, 0x68,
174 0xaa, 0xaa, 0x03, 0x00,
175 0x00, 0x00, 0x08, 0x00,
177 0x45, 0x00, 0x00, 0x28,
178 0x0b, 0x0b, 0x40, 0x00,
179 0x20, 0x06, 0x85, 0x37,
180 0xc0, 0xa8, 0x27, 0x01,
181 0xc0, 0xa8, 0x22, 0x3c
184 /* Ethernet+IP, indicating UDP */
186 0xff, 0xff, 0xff, 0xff,
187 0xff, 0xff, 0x01, 0x01,
188 0x01, 0x01, 0x01, 0x01,
191 0x45, 0x00, 0x00, 0x3c,
192 0xc5, 0x9e, 0x40, 0x00,
193 0xff, 0x11, 0xd7, 0xe0,
194 0xd0, 0x15, 0x02, 0xb8,
195 0x0a, 0x01, 0x01, 0x63
198 /* Ethernet+IP+UDP, indicating BVLC */
199 guint8 pkt_bvlc[] = {
200 0xff, 0xff, 0xff, 0xff,
201 0xff, 0xff, 0x01, 0x01,
202 0x01, 0x01, 0x01, 0x01,
205 0x45, 0x00, 0x00, 0x3c,
206 0xc5, 0x9e, 0x40, 0x00,
207 0xff, 0x11, 0x01, 0xaa,
208 0xc1, 0xff, 0x19, 0x1e,
209 0xc1, 0xff, 0x19, 0xff,
210 0xba, 0xc0, 0xba, 0xc0,
211 0x00, 0xff, 0x2d, 0x5e,
215 /* This little data table drives the whole program */
216 pkt_example examples[] = {
217 { "arp", "Address Resolution Protocol",
218 PKT_ARP, pkt_arp, WTAP_ENCAP_ETHERNET, array_length(pkt_arp) },
220 { "dns", "Domain Name Service",
221 PKT_DNS, pkt_dns, WTAP_ENCAP_ETHERNET, array_length(pkt_dns) },
224 PKT_ETHERNET, NULL, WTAP_ENCAP_ETHERNET, 0 },
226 { "fddi", "Fiber Distributed Data Interface",
227 PKT_FDDI, NULL, WTAP_ENCAP_FDDI, 0 },
229 { "icmp", "Internet Control Message Protocol",
230 PKT_ICMP, pkt_icmp, WTAP_ENCAP_ETHERNET, array_length(pkt_icmp) },
232 { "ip", "Internet Protocol",
233 PKT_IP, pkt_ip, WTAP_ENCAP_ETHERNET, array_length(pkt_ip) },
235 { "llc", "Logical Link Control",
236 PKT_LLC, pkt_llc, WTAP_ENCAP_TOKEN_RING, array_length(pkt_llc) },
238 { "nbns", "NetBIOS-over-TCP Name Service",
239 PKT_NBNS, pkt_nbns, WTAP_ENCAP_ETHERNET, array_length(pkt_nbns) },
241 { "syslog", "Syslog message",
242 PKT_SYSLOG, pkt_syslog, WTAP_ENCAP_ETHERNET, array_length(pkt_syslog) },
244 { "tcp", "Transmission Control Protocol",
245 PKT_TCP, pkt_tcp, WTAP_ENCAP_TOKEN_RING, array_length(pkt_tcp) },
247 { "tr", "Token-Ring",
248 PKT_TR, NULL, WTAP_ENCAP_TOKEN_RING, 0 },
250 { "udp", "User Datagram Protocol",
251 PKT_UDP, pkt_udp, WTAP_ENCAP_ETHERNET, array_length(pkt_udp) },
252 { "bvlc", "BACnet Virtual Link Control",
253 PKT_BVLC, pkt_bvlc, WTAP_ENCAP_ETHERNET, array_length(pkt_bvlc) }
259 static int parse_type(char *string);
260 static void usage(void);
261 static void seed(void);
263 static pkt_example* find_example(int type);
266 main(int argc, char **argv)
270 struct wtap_pkthdr pkthdr;
271 union wtap_pseudo_header ps_header;
272 int i, j, len_this_pkt, len_random, err;
273 guint8 buffer[65536];
279 int produce_count = 1000; /* number of pkts to produce */
280 int produce_type = PKT_ETHERNET;
281 char *produce_filename = NULL;
282 int produce_max_bytes = 5000;
283 pkt_example *example;
285 while ((opt = getopt(argc, argv, "b:c:t:")) != EOF) {
287 case 'b': /* max bytes */
288 produce_max_bytes = atoi(optarg);
289 if (produce_max_bytes > 65536) {
290 printf("Max bytes is 65536\n");
295 case 'c': /* count */
296 produce_count = atoi(optarg);
299 case 't': /* type of packet to produce */
300 produce_type = parse_type(optarg);
309 /* any more command line parameters? */
311 produce_filename = argv[optind];
317 example = find_example(produce_type);
319 pkthdr.ts.tv_sec = 0;
320 pkthdr.ts.tv_usec = 0;
321 pkthdr.pkt_encap = example->sample_wtap_encap;
323 dump = wtap_dump_open(produce_filename, WTAP_FILE_PCAP,
324 example->sample_wtap_encap, produce_max_bytes, &err);
328 /* reduce max_bytes by # of bytes already in sample */
329 if (produce_max_bytes <= example->sample_length) {
330 printf("Sample packet length is %d, which is greater than or equal to\n", example->sample_length);
331 printf("your requested max_bytes value of %d\n", produce_max_bytes);
335 produce_max_bytes -= example->sample_length;
338 /* Load the sample into our buffer */
339 if (example->sample_buffer)
340 memcpy(&buffer[0], example->sample_buffer, example->sample_length);
342 /* Produce random packets */
343 for (i = 0; i < produce_count; i++) {
344 if (produce_max_bytes > 0) {
345 len_random = (rand() % produce_max_bytes + 1);
351 len_this_pkt = example->sample_length + len_random;
353 pkthdr.caplen = len_this_pkt;
354 pkthdr.len = len_this_pkt;
355 pkthdr.ts.tv_sec = i; /* just for variety */
357 for (j = example->sample_length; j < len_random; j++) {
358 buffer[j] = (rand() % 0x100);
361 wtap_dump(dump, &pkthdr, &ps_header, &buffer[0], &err);
364 wtap_dump_close(dump, &err);
370 /* Print usage statement and exit program */
374 int num_entries = array_length(examples);
377 printf("Usage: randpkt [-b maxbytes] [-c count] [-t type] filename\n");
378 printf("Default max bytes (per packet) is 5000\n");
379 printf("Default count is 1000.\n");
382 for (i = 0; i < num_entries; i++) {
383 printf("\t%s\t%s\n", examples[i].abbrev, examples[i].longname);
391 /* Parse command-line option "type" and return enum type */
393 int parse_type(char *string)
395 int num_entries = array_length(examples);
398 for (i = 0; i < num_entries; i++) {
399 if (strcmp(examples[i].abbrev, string) == 0) {
400 return examples[i].produceable_type;
408 /* Find pkt_example record and return pointer to it */
410 pkt_example* find_example(int type)
412 int num_entries = array_length(examples);
415 for (i = 0; i < num_entries; i++) {
416 if (examples[i].produceable_type == type) {
421 printf("Internal error. Type %d has no entry in examples table.\n", type);
425 /* Seed the random-number generator */
429 unsigned int randomness;
432 /* Okay, I should use #ifdef HAVE_DEV_RANDOM, but this is a quick hack */
435 fd = open("/dev/random", O_RDONLY);
437 printf("Could not open /dev/random for reading: %s\n", strerror(errno));
441 read(fd, &randomness, sizeof(randomness));
446 randomness = (unsigned int) now;