4 * Creates random packet traces. Useful for debugging sniffers by testing
5 * assumptions about the veracity of the data found in the packet.
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.
33 #include "wsutil/wsgetopt.h"
51 #include "wiretap/wtap.h"
54 #include <wsutil/unicode-utils.h>
57 #define array_length(x) (sizeof x / sizeof x[0])
59 /* Types of produceable packets */
89 int sample_wtap_encap;
90 guint8 *sample_buffer;
92 guint8 *pseudo_buffer;
96 /* Ethernet, indicating ARP */
98 0xff, 0xff, 0xff, 0xff,
99 0xff, 0xff, 0x00, 0x00,
100 0x32, 0x25, 0x0f, 0xff,
104 /* Ethernet+IP+UDP, indicating DNS */
106 0xff, 0xff, 0xff, 0xff,
107 0xff, 0xff, 0x01, 0x01,
108 0x01, 0x01, 0x01, 0x01,
111 0x45, 0x00, 0x00, 0x3c,
112 0xc5, 0x9e, 0x40, 0x00,
113 0xff, 0x11, 0xd7, 0xe0,
114 0xd0, 0x15, 0x02, 0xb8,
115 0x0a, 0x01, 0x01, 0x63,
117 0x05, 0xe8, 0x00, 0x35,
118 0xff, 0xff, 0x2a, 0xb9,
122 /* Ethernet+IP, indicating ICMP */
123 guint8 pkt_icmp[] = {
124 0xff, 0xff, 0xff, 0xff,
125 0xff, 0xff, 0x01, 0x01,
126 0x01, 0x01, 0x01, 0x01,
129 0x45, 0x00, 0x00, 0x54,
130 0x8f, 0xb3, 0x40, 0x00,
131 0xfd, 0x01, 0x8a, 0x99,
132 0xcc, 0xfc, 0x66, 0x0b,
133 0xce, 0x41, 0x62, 0x12
136 /* Ethernet, indicating IP */
138 0xff, 0xff, 0xff, 0xff,
139 0xff, 0xff, 0x01, 0x01,
140 0x01, 0x01, 0x01, 0x01,
144 /* TR, indicating LLC */
146 0x10, 0x40, 0x68, 0x00,
147 0x19, 0x69, 0x95, 0x8b,
148 0x00, 0x01, 0xfa, 0x68,
152 /* Ethernet, indicating WiMAX M2M */
154 0xff, 0xff, 0xff, 0xff,
155 0xff, 0xff, 0x00, 0x00,
156 0x32, 0x25, 0x0f, 0xff,
160 /* Ethernet+IP+UDP, indicating NBNS */
161 guint8 pkt_nbns[] = {
162 0xff, 0xff, 0xff, 0xff,
163 0xff, 0xff, 0x01, 0x01,
164 0x01, 0x01, 0x01, 0x01,
167 0x45, 0x00, 0x00, 0x3c,
168 0xc5, 0x9e, 0x40, 0x00,
169 0xff, 0x11, 0xd7, 0xe0,
170 0xd0, 0x15, 0x02, 0xb8,
171 0x0a, 0x01, 0x01, 0x63,
173 0x00, 0x89, 0x00, 0x89,
174 0x00, 0x00, 0x2a, 0xb9,
178 /* Ethernet+IP+UDP, indicating syslog */
179 guint8 pkt_syslog[] = {
180 0xff, 0xff, 0xff, 0xff,
181 0xff, 0xff, 0x01, 0x01,
182 0x01, 0x01, 0x01, 0x01,
185 0x45, 0x00, 0x00, 0x64,
186 0x20, 0x48, 0x00, 0x00,
187 0xfc, 0x11, 0xf8, 0x03,
188 0xd0, 0x15, 0x02, 0xb8,
189 0x0a, 0x01, 0x01, 0x63,
191 0x05, 0xe8, 0x02, 0x02,
192 0x00, 0x50, 0x51, 0xe1,
196 /* TR+LLC+IP, indicating TCP */
198 0x10, 0x40, 0x68, 0x00,
199 0x19, 0x69, 0x95, 0x8b,
200 0x00, 0x01, 0xfa, 0x68,
203 0xaa, 0xaa, 0x03, 0x00,
204 0x00, 0x00, 0x08, 0x00,
206 0x45, 0x00, 0x00, 0x28,
207 0x0b, 0x0b, 0x40, 0x00,
208 0x20, 0x06, 0x85, 0x37,
209 0xc0, 0xa8, 0x27, 0x01,
210 0xc0, 0xa8, 0x22, 0x3c
213 /* Ethernet+IP, indicating UDP */
215 0xff, 0xff, 0xff, 0xff,
216 0xff, 0xff, 0x01, 0x01,
217 0x01, 0x01, 0x01, 0x01,
220 0x45, 0x00, 0x00, 0x3c,
221 0xc5, 0x9e, 0x40, 0x00,
222 0xff, 0x11, 0xd7, 0xe0,
223 0xd0, 0x15, 0x02, 0xb8,
224 0x0a, 0x01, 0x01, 0x63
227 /* Ethernet+IP+UDP, indicating BVLC */
228 guint8 pkt_bvlc[] = {
229 0xff, 0xff, 0xff, 0xff,
230 0xff, 0xff, 0x01, 0x01,
231 0x01, 0x01, 0x01, 0x01,
234 0x45, 0x00, 0x00, 0x3c,
235 0xc5, 0x9e, 0x40, 0x00,
236 0xff, 0x11, 0x01, 0xaa,
237 0xc1, 0xff, 0x19, 0x1e,
238 0xc1, 0xff, 0x19, 0xff,
239 0xba, 0xc0, 0xba, 0xc0,
240 0x00, 0xff, 0x2d, 0x5e,
244 /* TR+LLC+IPX, indicating NCP, with NCP Type == 0x2222 */
245 guint8 pkt_ncp2222[] = {
246 0x10, 0x40, 0x00, 0x00,
247 0xf6, 0x7c, 0x9b, 0x70,
248 0x68, 0x00, 0x19, 0x69,
249 0x95, 0x8b, 0xe0, 0xe0,
250 0x03, 0xff, 0xff, 0x00,
251 0x25, 0x02, 0x11, 0x00,
252 0x00, 0x74, 0x14, 0x00,
253 0x00, 0x00, 0x00, 0x00,
254 0x01, 0x04, 0x51, 0x00,
255 0x00, 0x00, 0x04, 0x00,
256 0x02, 0x16, 0x19, 0x7a,
257 0x84, 0x40, 0x01, 0x22,
261 /* Ethernet+IP+TCP, indicating GIOP */
262 guint8 pkt_giop[] = {
263 0xff, 0xff, 0xff, 0xff,
264 0xff, 0xff, 0x01, 0x01,
265 0x01, 0x01, 0x01, 0x01,
268 0x45, 0x00, 0x00, 0xa6,
269 0x00, 0x2f, 0x40, 0x00,
270 0x40, 0x06, 0x3c, 0x21,
271 0x7f, 0x00, 0x00, 0x01,
272 0x7f, 0x00, 0x00, 0x01,
274 0x30, 0x39, 0x04, 0x05,
275 0xac, 0x02, 0x1e, 0x69,
276 0xab, 0x74, 0xab, 0x64,
277 0x80, 0x18, 0x79, 0x60,
278 0xc4, 0xb8, 0x00, 0x00,
279 0x01, 0x01, 0x08, 0x0a,
280 0x00, 0x00, 0x48, 0xf5,
281 0x00, 0x00, 0x48, 0xf5,
283 0x47, 0x49, 0x4f, 0x50,
284 0x01, 0x00, 0x00, 0x00,
285 0x00, 0x00, 0x00, 0x30,
286 0x00, 0x00, 0x00, 0x00,
287 0x00, 0x00, 0x00, 0x01,
291 /* Ethernet+IP+TCP, indicating BGP */
293 0xff, 0xff, 0xff, 0xff,
294 0xff, 0xff, 0x01, 0x01,
295 0x01, 0x01, 0x01, 0x01,
298 0x45, 0x00, 0x00, 0xa6,
299 0x00, 0x2f, 0x40, 0x00,
300 0x40, 0x06, 0x3c, 0x21,
301 0x7f, 0x00, 0x00, 0x01,
302 0x7f, 0x00, 0x00, 0x01,
304 0x30, 0x39, 0x00, 0xb3,
305 0xac, 0x02, 0x1e, 0x69,
306 0xab, 0x74, 0xab, 0x64,
307 0x80, 0x18, 0x79, 0x60,
308 0xc4, 0xb8, 0x00, 0x00,
309 0x01, 0x01, 0x08, 0x0a,
310 0x00, 0x00, 0x48, 0xf5,
311 0x00, 0x00, 0x48, 0xf5,
313 0xff, 0xff, 0xff, 0xff,
314 0xff, 0xff, 0xff, 0xff,
315 0xff, 0xff, 0xff, 0xff,
316 0xff, 0xff, 0xff, 0xff,
319 /* Ethernet+IP+TCP, indicating TDS NetLib */
321 0x00, 0x50, 0x8b, 0x0d,
322 0x7a, 0xed, 0x00, 0x08,
323 0xa3, 0x98, 0x39, 0x81,
326 0x45, 0x00, 0x03, 0x8d,
327 0x90, 0xd4, 0x40, 0x00,
328 0x7c, 0x06, 0xc3, 0x1b,
329 0xac, 0x14, 0x02, 0x22,
330 0x0a, 0xc2, 0xee, 0x82,
332 0x05, 0x99, 0x08, 0xf8,
333 0xff, 0x4e, 0x85, 0x46,
334 0xa2, 0xb4, 0x42, 0xaa,
335 0x50, 0x18, 0x3c, 0x28,
336 0x0f, 0xda, 0x00, 0x00,
339 /* Ethernet+IP, indicating SCTP */
340 guint8 pkt_sctp[] = {
341 0x00, 0xa0, 0x80, 0x00,
342 0x5e, 0x46, 0x08, 0x00,
343 0x03, 0x4a, 0x00, 0x35,
346 0x45, 0x00, 0x00, 0x7c,
347 0x14, 0x1c, 0x00, 0x00,
348 0x3b, 0x84, 0x4a, 0x54,
349 0x0a, 0x1c, 0x06, 0x2b,
350 0x0a, 0x1c, 0x06, 0x2c,
354 /* Ethernet+IP+SCTP, indicating MEGACO */
355 guint8 pkt_megaco[] = {
356 0x00, 0xa0, 0x80, 0x00,
357 0x5e, 0x46, 0x08, 0x00,
358 0x03, 0x4a, 0x00, 0x35,
361 0x45, 0x00, 0x00, 0x7c,
362 0x14, 0x1c, 0x00, 0x00,
363 0x3b, 0x84, 0x4a, 0x54,
364 0x0a, 0x1c, 0x06, 0x2b,
365 0x0a, 0x1c, 0x06, 0x2c,
367 0x40, 0x00, 0x0b, 0x80,
368 0x00, 0x01, 0x6f, 0x0a,
369 0x6d, 0xb0, 0x18, 0x82,
370 0x00, 0x03, 0x00, 0x5b,
371 0x28, 0x02, 0x43, 0x45,
372 0x00, 0x00, 0xa0, 0xbd,
373 0x00, 0x00, 0x00, 0x07,
376 /* This little data table drives the whole program */
377 pkt_example examples[] = {
378 { "arp", "Address Resolution Protocol",
379 PKT_ARP, WTAP_ENCAP_ETHERNET,
380 pkt_arp, array_length(pkt_arp),
383 { "bgp", "Border Gateway Protocol",
384 PKT_BGP, WTAP_ENCAP_ETHERNET,
385 pkt_bgp, array_length(pkt_bgp),
388 { "bvlc", "BACnet Virtual Link Control",
389 PKT_BVLC, WTAP_ENCAP_ETHERNET,
390 pkt_bvlc, array_length(pkt_bvlc),
393 { "dns", "Domain Name Service",
394 PKT_DNS, WTAP_ENCAP_ETHERNET,
395 pkt_dns, array_length(pkt_dns),
399 PKT_ETHERNET, WTAP_ENCAP_ETHERNET,
403 { "fddi", "Fiber Distributed Data Interface",
404 PKT_FDDI, WTAP_ENCAP_FDDI,
408 { "giop", "General Inter-ORB Protocol",
409 PKT_GIOP, WTAP_ENCAP_ETHERNET,
410 pkt_giop, array_length(pkt_giop),
413 { "icmp", "Internet Control Message Protocol",
414 PKT_ICMP, WTAP_ENCAP_ETHERNET,
415 pkt_icmp, array_length(pkt_icmp),
418 { "ip", "Internet Protocol",
419 PKT_IP, WTAP_ENCAP_ETHERNET,
420 pkt_ip, array_length(pkt_ip),
423 { "llc", "Logical Link Control",
424 PKT_LLC, WTAP_ENCAP_TOKEN_RING,
425 pkt_llc, array_length(pkt_llc),
428 { "m2m", "WiMAX M2M Encapsulation Protocol",
429 PKT_M2M, WTAP_ENCAP_ETHERNET,
430 pkt_m2m, array_length(pkt_m2m),
433 { "megaco", "MEGACO",
434 PKT_MEGACO, WTAP_ENCAP_ETHERNET,
435 pkt_megaco, array_length(pkt_megaco),
438 { "nbns", "NetBIOS-over-TCP Name Service",
439 PKT_NBNS, WTAP_ENCAP_ETHERNET,
440 pkt_nbns, array_length(pkt_nbns),
443 { "ncp2222", "NetWare Core Protocol",
444 PKT_NCP2222, WTAP_ENCAP_TOKEN_RING,
445 pkt_ncp2222, array_length(pkt_ncp2222),
448 { "sctp", "Stream Control Transmission Protocol",
449 PKT_SCTP, WTAP_ENCAP_ETHERNET,
450 pkt_sctp, array_length(pkt_sctp),
453 { "syslog", "Syslog message",
454 PKT_SYSLOG, WTAP_ENCAP_ETHERNET,
455 pkt_syslog, array_length(pkt_syslog),
458 { "tds", "TDS NetLib",
459 PKT_TDS, WTAP_ENCAP_ETHERNET,
460 pkt_tds, array_length(pkt_tds),
463 { "tcp", "Transmission Control Protocol",
464 PKT_TCP, WTAP_ENCAP_TOKEN_RING,
465 pkt_tcp, array_length(pkt_tcp),
468 { "tr", "Token-Ring",
469 PKT_TR, WTAP_ENCAP_TOKEN_RING,
473 { "udp", "User Datagram Protocol",
474 PKT_UDP, WTAP_ENCAP_ETHERNET,
475 pkt_udp, array_length(pkt_udp),
478 { "usb", "Universal Serial Bus",
479 PKT_USB, WTAP_ENCAP_USB,
483 { "usb-linux", "Universal Serial Bus with Linux specific header",
484 PKT_USB_LINUX, WTAP_ENCAP_USB_LINUX,
492 static int parse_type(char *string);
493 static void usage(void);
494 static void seed(void);
496 static pkt_example* find_example(int type);
499 main(int argc, char **argv)
503 struct wtap_pkthdr pkthdr;
504 union wtap_pseudo_header ps_header;
505 int i, j, len_this_pkt, len_random, err;
506 guint8 buffer[65536];
510 int produce_count = 1000; /* number of pkts to produce */
511 int produce_type = PKT_ETHERNET;
512 char *produce_filename = NULL;
513 int produce_max_bytes = 5000;
514 pkt_example *example;
517 arg_list_utf_16to8(argc, argv);
520 while ((opt = getopt(argc, argv, "b:c:ht:")) != -1) {
522 case 'b': /* max bytes */
523 produce_max_bytes = atoi(optarg);
524 if (produce_max_bytes > 65536) {
526 "randpkt: Max bytes is 65536\n");
531 case 'c': /* count */
532 produce_count = atoi(optarg);
535 case 't': /* type of packet to produce */
536 produce_type = parse_type(optarg);
546 /* any more command line parameters? */
548 produce_filename = argv[optind];
554 example = find_example(produce_type);
557 dump = wtap_dump_open(produce_filename, WTAP_FILE_PCAP,
558 example->sample_wtap_encap, produce_max_bytes, FALSE /* compressed */, &err);
561 "randpkt: Error writing to %s\n", produce_filename);
567 /* reduce max_bytes by # of bytes already in sample */
568 if (produce_max_bytes <= example->sample_length) {
570 "randpkt: Sample packet length is %d, which is greater than or equal to\n",
571 example->sample_length);
572 fprintf(stderr, "your requested max_bytes value of %d\n",
577 produce_max_bytes -= example->sample_length;
580 memset(&pkthdr, 0, sizeof(pkthdr));
581 memset(&ps_header, 0, sizeof(ps_header));
582 memset(buffer, 0, sizeof(buffer));
584 pkthdr.pkt_encap = example->sample_wtap_encap;
586 /* Load the sample pseudoheader into our pseudoheader buffer */
587 if (example->pseudo_buffer)
588 memcpy(&ps_header, example->pseudo_buffer, example->pseudo_length);
590 /* Load the sample into our buffer */
591 if (example->sample_buffer)
592 memcpy(&buffer[0], example->sample_buffer, example->sample_length);
594 /* Produce random packets */
595 for (i = 0; i < produce_count; i++) {
596 if (produce_max_bytes > 0) {
597 len_random = (rand() % produce_max_bytes + 1);
603 len_this_pkt = example->sample_length + len_random;
605 pkthdr.caplen = len_this_pkt;
606 pkthdr.len = len_this_pkt;
607 pkthdr.ts.secs = i; /* just for variety */
609 for (j = example->pseudo_length; j < (int) sizeof(ps_header); j++) {
610 ((guint8*)&ps_header)[j] = (rand() % 0x100);
613 for (j = example->sample_length; j < len_this_pkt; j++) {
614 /* Add format strings here and there */
615 if ((int) (100.0*rand()/(RAND_MAX+1.0)) < 3 && j < (len_random - 3)) {
616 memcpy(&buffer[j], "%s", 3);
619 buffer[j] = (rand() % 0x100);
623 wtap_dump(dump, &pkthdr, &ps_header, &buffer[0], &err);
626 wtap_dump_close(dump, &err);
632 /* Print usage statement and exit program */
636 int num_entries = array_length(examples);
639 printf("Usage: randpkt [-b maxbytes] [-c count] [-t type] filename\n");
640 printf("Default max bytes (per packet) is 5000\n");
641 printf("Default count is 1000.\n");
644 for (i = 0; i < num_entries; i++) {
645 printf("\t%s\t%s\n", examples[i].abbrev, examples[i].longname);
653 /* Parse command-line option "type" and return enum type */
655 int parse_type(char *string)
657 int num_entries = array_length(examples);
660 for (i = 0; i < num_entries; i++) {
661 if (strcmp(examples[i].abbrev, string) == 0) {
662 return examples[i].produceable_type;
667 fprintf(stderr, "randpkt: Type %s not known.\n", string);
671 /* Find pkt_example record and return pointer to it */
673 pkt_example* find_example(int type)
675 int num_entries = array_length(examples);
678 for (i = 0; i < num_entries; i++) {
679 if (examples[i].produceable_type == type) {
685 "randpkt: Internal error. Type %d has no entry in examples table.\n",
690 /* Seed the random-number generator */
694 unsigned int randomness;
700 #define RANDOM_DEV "/dev/urandom"
703 * Assume it's at least worth trying /dev/urandom on UN*X.
704 * If it doesn't exist, fall back on time().
706 * XXX - Use CryptGenRandom on Windows?
708 fd = open(RANDOM_DEV, O_RDONLY);
710 if (errno != ENOENT) {
712 "randpkt: Could not open " RANDOM_DEV " for reading: %s\n",
719 ret = read(fd, &randomness, sizeof randomness);
722 "randpkt: Could not read from " RANDOM_DEV ": %s\n",
726 if ((size_t)ret != sizeof randomness) {
728 "randpkt: Tried to read %lu bytes from " RANDOM_DEV ", got %ld\n",
729 (unsigned long)sizeof randomness, (long)ret);
738 randomness = (unsigned int) now;