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.13 2002/02/24 01:26:42 guy Exp $
9 * Copyright (C) 1999 by Gilbert Ramirez <gram@alumni.rice.edu>
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 */
71 guint8 *sample_buffer;
72 int sample_wtap_encap;
76 /* Ethernet, indicating ARP */
78 0xff, 0xff, 0xff, 0xff,
79 0xff, 0xff, 0x00, 0x00,
80 0x32, 0x25, 0x0f, 0xff,
84 /* Ethernet+IP+UDP, indicating DNS */
86 0xff, 0xff, 0xff, 0xff,
87 0xff, 0xff, 0x01, 0x01,
88 0x01, 0x01, 0x01, 0x01,
91 0x45, 0x00, 0x00, 0x3c,
92 0xc5, 0x9e, 0x40, 0x00,
93 0xff, 0x11, 0xd7, 0xe0,
94 0xd0, 0x15, 0x02, 0xb8,
95 0x0a, 0x01, 0x01, 0x63,
97 0x05, 0xe8, 0x00, 0x35,
98 0x00, 0x00, 0x2a, 0xb9,
102 /* Ethernet+IP, indicating ICMP */
103 guint8 pkt_icmp[] = {
104 0xff, 0xff, 0xff, 0xff,
105 0xff, 0xff, 0x01, 0x01,
106 0x01, 0x01, 0x01, 0x01,
109 0x45, 0x00, 0x00, 0x54,
110 0x8f, 0xb3, 0x40, 0x00,
111 0xfd, 0x01, 0x8a, 0x99,
112 0xcc, 0xfc, 0x66, 0x0b,
113 0xce, 0x41, 0x62, 0x12
116 /* Ethernet, indicating IP */
118 0xff, 0xff, 0xff, 0xff,
119 0xff, 0xff, 0x01, 0x01,
120 0x01, 0x01, 0x01, 0x01,
124 /* TR, indicating LLC */
126 0x10, 0x40, 0x68, 0x00,
127 0x19, 0x69, 0x95, 0x8b,
128 0x00, 0x01, 0xfa, 0x68,
132 /* Ethernet+IP+UP, indicating NBNS */
133 guint8 pkt_nbns[] = {
134 0xff, 0xff, 0xff, 0xff,
135 0xff, 0xff, 0x01, 0x01,
136 0x01, 0x01, 0x01, 0x01,
139 0x45, 0x00, 0x00, 0x3c,
140 0xc5, 0x9e, 0x40, 0x00,
141 0xff, 0x11, 0xd7, 0xe0,
142 0xd0, 0x15, 0x02, 0xb8,
143 0x0a, 0x01, 0x01, 0x63,
145 0x00, 0x89, 0x00, 0x89,
146 0x00, 0x00, 0x2a, 0xb9,
150 /* Ethernet+IP+UDP, indicating syslog */
151 guint8 pkt_syslog[] = {
152 0xff, 0xff, 0xff, 0xff,
153 0xff, 0xff, 0x01, 0x01,
154 0x01, 0x01, 0x01, 0x01,
157 0x45, 0x00, 0x00, 0x64,
158 0x20, 0x48, 0x00, 0x00,
159 0xfc, 0x11, 0xf8, 0x03,
160 0xd0, 0x15, 0x02, 0xb8,
161 0x0a, 0x01, 0x01, 0x63,
163 0x05, 0xe8, 0x02, 0x02,
164 0x00, 0x50, 0x51, 0xe1,
168 /* TR+LLC+IP, indicating TCP */
170 0x10, 0x40, 0x68, 0x00,
171 0x19, 0x69, 0x95, 0x8b,
172 0x00, 0x01, 0xfa, 0x68,
175 0xaa, 0xaa, 0x03, 0x00,
176 0x00, 0x00, 0x08, 0x00,
178 0x45, 0x00, 0x00, 0x28,
179 0x0b, 0x0b, 0x40, 0x00,
180 0x20, 0x06, 0x85, 0x37,
181 0xc0, 0xa8, 0x27, 0x01,
182 0xc0, 0xa8, 0x22, 0x3c
185 /* Ethernet+IP, indicating UDP */
187 0xff, 0xff, 0xff, 0xff,
188 0xff, 0xff, 0x01, 0x01,
189 0x01, 0x01, 0x01, 0x01,
192 0x45, 0x00, 0x00, 0x3c,
193 0xc5, 0x9e, 0x40, 0x00,
194 0xff, 0x11, 0xd7, 0xe0,
195 0xd0, 0x15, 0x02, 0xb8,
196 0x0a, 0x01, 0x01, 0x63
199 /* Ethernet+IP+UDP, indicating BVLC */
200 guint8 pkt_bvlc[] = {
201 0xff, 0xff, 0xff, 0xff,
202 0xff, 0xff, 0x01, 0x01,
203 0x01, 0x01, 0x01, 0x01,
206 0x45, 0x00, 0x00, 0x3c,
207 0xc5, 0x9e, 0x40, 0x00,
208 0xff, 0x11, 0x01, 0xaa,
209 0xc1, 0xff, 0x19, 0x1e,
210 0xc1, 0xff, 0x19, 0xff,
211 0xba, 0xc0, 0xba, 0xc0,
212 0x00, 0xff, 0x2d, 0x5e,
216 /* TR+LLC+IPX, indicating NCP, with NCP Type == 0x2222 */
217 guint8 pkt_ncp2222[] = {
218 0x10, 0x40, 0x00, 0x00,
219 0xf6, 0x7c, 0x9b, 0x70,
220 0x68, 0x00, 0x19, 0x69,
221 0x95, 0x8b, 0xe0, 0xe0,
222 0x03, 0xff, 0xff, 0x00,
223 0x25, 0x02, 0x11, 0x00,
224 0x00, 0x74, 0x14, 0x00,
225 0x00, 0x00, 0x00, 0x00,
226 0x01, 0x04, 0x51, 0x00,
227 0x00, 0x00, 0x04, 0x00,
228 0x02, 0x16, 0x19, 0x7a,
229 0x84, 0x40, 0x01, 0x22,
233 /* This little data table drives the whole program */
234 pkt_example examples[] = {
235 { "arp", "Address Resolution Protocol",
236 PKT_ARP, pkt_arp, WTAP_ENCAP_ETHERNET, array_length(pkt_arp) },
238 { "dns", "Domain Name Service",
239 PKT_DNS, pkt_dns, WTAP_ENCAP_ETHERNET, array_length(pkt_dns) },
242 PKT_ETHERNET, NULL, WTAP_ENCAP_ETHERNET, 0 },
244 { "fddi", "Fiber Distributed Data Interface",
245 PKT_FDDI, NULL, WTAP_ENCAP_FDDI, 0 },
247 { "icmp", "Internet Control Message Protocol",
248 PKT_ICMP, pkt_icmp, WTAP_ENCAP_ETHERNET, array_length(pkt_icmp) },
250 { "ip", "Internet Protocol",
251 PKT_IP, pkt_ip, WTAP_ENCAP_ETHERNET, array_length(pkt_ip) },
253 { "llc", "Logical Link Control",
254 PKT_LLC, pkt_llc, WTAP_ENCAP_TOKEN_RING, array_length(pkt_llc) },
256 { "nbns", "NetBIOS-over-TCP Name Service",
257 PKT_NBNS, pkt_nbns, WTAP_ENCAP_ETHERNET, array_length(pkt_nbns) },
259 { "syslog", "Syslog message",
260 PKT_SYSLOG, pkt_syslog, WTAP_ENCAP_ETHERNET, array_length(pkt_syslog) },
262 { "tcp", "Transmission Control Protocol",
263 PKT_TCP, pkt_tcp, WTAP_ENCAP_TOKEN_RING, array_length(pkt_tcp) },
265 { "tr", "Token-Ring",
266 PKT_TR, NULL, WTAP_ENCAP_TOKEN_RING, 0 },
268 { "udp", "User Datagram Protocol",
269 PKT_UDP, pkt_udp, WTAP_ENCAP_ETHERNET, array_length(pkt_udp) },
271 { "bvlc", "BACnet Virtual Link Control",
272 PKT_BVLC, pkt_bvlc, WTAP_ENCAP_ETHERNET, array_length(pkt_bvlc) },
274 { "ncp2222", "NetWare Core Protocol",
275 PKT_NCP2222, pkt_ncp2222, WTAP_ENCAP_TOKEN_RING, array_length(pkt_ncp2222) },
281 static int parse_type(char *string);
282 static void usage(void);
283 static void seed(void);
285 static pkt_example* find_example(int type);
288 main(int argc, char **argv)
292 struct wtap_pkthdr pkthdr;
293 union wtap_pseudo_header ps_header;
294 int i, j, len_this_pkt, len_random, err;
295 guint8 buffer[65536];
301 int produce_count = 1000; /* number of pkts to produce */
302 int produce_type = PKT_ETHERNET;
303 char *produce_filename = NULL;
304 int produce_max_bytes = 5000;
305 pkt_example *example;
307 while ((opt = getopt(argc, argv, "b:c:t:")) != -1) {
309 case 'b': /* max bytes */
310 produce_max_bytes = atoi(optarg);
311 if (produce_max_bytes > 65536) {
312 printf("Max bytes is 65536\n");
317 case 'c': /* count */
318 produce_count = atoi(optarg);
321 case 't': /* type of packet to produce */
322 produce_type = parse_type(optarg);
331 /* any more command line parameters? */
333 produce_filename = argv[optind];
339 example = find_example(produce_type);
341 pkthdr.ts.tv_sec = 0;
342 pkthdr.ts.tv_usec = 0;
343 pkthdr.pkt_encap = example->sample_wtap_encap;
345 dump = wtap_dump_open(produce_filename, WTAP_FILE_PCAP,
346 example->sample_wtap_encap, produce_max_bytes, &err);
350 /* reduce max_bytes by # of bytes already in sample */
351 if (produce_max_bytes <= example->sample_length) {
352 printf("Sample packet length is %d, which is greater than or equal to\n", example->sample_length);
353 printf("your requested max_bytes value of %d\n", produce_max_bytes);
357 produce_max_bytes -= example->sample_length;
360 /* Load the sample into our buffer */
361 if (example->sample_buffer)
362 memcpy(&buffer[0], example->sample_buffer, example->sample_length);
364 /* Produce random packets */
365 for (i = 0; i < produce_count; i++) {
366 if (produce_max_bytes > 0) {
367 len_random = (rand() % produce_max_bytes + 1);
373 len_this_pkt = example->sample_length + len_random;
375 pkthdr.caplen = len_this_pkt;
376 pkthdr.len = len_this_pkt;
377 pkthdr.ts.tv_sec = i; /* just for variety */
379 for (j = example->sample_length; j < len_random; j++) {
380 buffer[j] = (rand() % 0x100);
383 wtap_dump(dump, &pkthdr, &ps_header, &buffer[0], &err);
386 wtap_dump_close(dump, &err);
392 /* Print usage statement and exit program */
396 int num_entries = array_length(examples);
399 printf("Usage: randpkt [-b maxbytes] [-c count] [-t type] filename\n");
400 printf("Default max bytes (per packet) is 5000\n");
401 printf("Default count is 1000.\n");
404 for (i = 0; i < num_entries; i++) {
405 printf("\t%s\t%s\n", examples[i].abbrev, examples[i].longname);
413 /* Parse command-line option "type" and return enum type */
415 int parse_type(char *string)
417 int num_entries = array_length(examples);
420 for (i = 0; i < num_entries; i++) {
421 if (strcmp(examples[i].abbrev, string) == 0) {
422 return examples[i].produceable_type;
427 printf("Type %s not known.\n", string);
431 /* Find pkt_example record and return pointer to it */
433 pkt_example* find_example(int type)
435 int num_entries = array_length(examples);
438 for (i = 0; i < num_entries; i++) {
439 if (examples[i].produceable_type == type) {
444 printf("Internal error. Type %d has no entry in examples table.\n", type);
448 /* Seed the random-number generator */
452 unsigned int randomness;
455 /* Okay, I should use #ifdef HAVE_DEV_RANDOM, but this is a quick hack */
458 fd = open("/dev/random", O_RDONLY);
460 printf("Could not open /dev/random for reading: %s\n", strerror(errno));
464 read(fd, &randomness, sizeof(randomness));
469 randomness = (unsigned int) now;