4 * Creates random packet traces. Useful for debugging sniffers by testing
5 * assumptions about the veracity of the data found in the packet.
7 * Copyright (C) 1999 by Gilbert Ramirez <gram@alumni.rice.edu>
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version 2
12 * of the License, or (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
34 #ifndef HAVE_GETOPT_LONG
35 #include "wsutil/wsgetopt.h"
49 #include "wiretap/wtap.h"
50 #include "wsutil/file_util.h"
51 #include <wsutil/ws_diag_control.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;
95 guint produce_max_bytes;
99 /* Ethernet, indicating ARP */
101 0xff, 0xff, 0xff, 0xff,
102 0xff, 0xff, 0x00, 0x00,
103 0x32, 0x25, 0x0f, 0xff,
107 /* Ethernet+IP+UDP, indicating DNS */
109 0xff, 0xff, 0xff, 0xff,
110 0xff, 0xff, 0x01, 0x01,
111 0x01, 0x01, 0x01, 0x01,
114 0x45, 0x00, 0x00, 0x3c,
115 0xc5, 0x9e, 0x40, 0x00,
116 0xff, 0x11, 0xd7, 0xe0,
117 0xd0, 0x15, 0x02, 0xb8,
118 0x0a, 0x01, 0x01, 0x63,
120 0x05, 0xe8, 0x00, 0x35,
121 0xff, 0xff, 0x2a, 0xb9,
125 /* Ethernet+IP, indicating ICMP */
126 guint8 pkt_icmp[] = {
127 0xff, 0xff, 0xff, 0xff,
128 0xff, 0xff, 0x01, 0x01,
129 0x01, 0x01, 0x01, 0x01,
132 0x45, 0x00, 0x00, 0x54,
133 0x8f, 0xb3, 0x40, 0x00,
134 0xfd, 0x01, 0x8a, 0x99,
135 0xcc, 0xfc, 0x66, 0x0b,
136 0xce, 0x41, 0x62, 0x12
139 /* Ethernet, indicating IP */
141 0xff, 0xff, 0xff, 0xff,
142 0xff, 0xff, 0x01, 0x01,
143 0x01, 0x01, 0x01, 0x01,
147 /* TR, indicating LLC */
149 0x10, 0x40, 0x68, 0x00,
150 0x19, 0x69, 0x95, 0x8b,
151 0x00, 0x01, 0xfa, 0x68,
155 /* Ethernet, indicating WiMAX M2M */
157 0xff, 0xff, 0xff, 0xff,
158 0xff, 0xff, 0x00, 0x00,
159 0x32, 0x25, 0x0f, 0xff,
163 /* Ethernet+IP+UDP, indicating NBNS */
164 guint8 pkt_nbns[] = {
165 0xff, 0xff, 0xff, 0xff,
166 0xff, 0xff, 0x01, 0x01,
167 0x01, 0x01, 0x01, 0x01,
170 0x45, 0x00, 0x00, 0x3c,
171 0xc5, 0x9e, 0x40, 0x00,
172 0xff, 0x11, 0xd7, 0xe0,
173 0xd0, 0x15, 0x02, 0xb8,
174 0x0a, 0x01, 0x01, 0x63,
176 0x00, 0x89, 0x00, 0x89,
177 0x00, 0x00, 0x2a, 0xb9,
181 /* Ethernet+IP+UDP, indicating syslog */
182 guint8 pkt_syslog[] = {
183 0xff, 0xff, 0xff, 0xff,
184 0xff, 0xff, 0x01, 0x01,
185 0x01, 0x01, 0x01, 0x01,
188 0x45, 0x00, 0x00, 0x64,
189 0x20, 0x48, 0x00, 0x00,
190 0xfc, 0x11, 0xf8, 0x03,
191 0xd0, 0x15, 0x02, 0xb8,
192 0x0a, 0x01, 0x01, 0x63,
194 0x05, 0xe8, 0x02, 0x02,
195 0x00, 0x50, 0x51, 0xe1,
199 /* TR+LLC+IP, indicating TCP */
201 0x10, 0x40, 0x68, 0x00,
202 0x19, 0x69, 0x95, 0x8b,
203 0x00, 0x01, 0xfa, 0x68,
206 0xaa, 0xaa, 0x03, 0x00,
207 0x00, 0x00, 0x08, 0x00,
209 0x45, 0x00, 0x00, 0x28,
210 0x0b, 0x0b, 0x40, 0x00,
211 0x20, 0x06, 0x85, 0x37,
212 0xc0, 0xa8, 0x27, 0x01,
213 0xc0, 0xa8, 0x22, 0x3c
216 /* Ethernet+IP, indicating UDP */
218 0xff, 0xff, 0xff, 0xff,
219 0xff, 0xff, 0x01, 0x01,
220 0x01, 0x01, 0x01, 0x01,
223 0x45, 0x00, 0x00, 0x3c,
224 0xc5, 0x9e, 0x40, 0x00,
225 0xff, 0x11, 0xd7, 0xe0,
226 0xd0, 0x15, 0x02, 0xb8,
227 0x0a, 0x01, 0x01, 0x63
230 /* Ethernet+IP+UDP, indicating BVLC */
231 guint8 pkt_bvlc[] = {
232 0xff, 0xff, 0xff, 0xff,
233 0xff, 0xff, 0x01, 0x01,
234 0x01, 0x01, 0x01, 0x01,
237 0x45, 0x00, 0x00, 0x3c,
238 0xc5, 0x9e, 0x40, 0x00,
239 0xff, 0x11, 0x01, 0xaa,
240 0xc1, 0xff, 0x19, 0x1e,
241 0xc1, 0xff, 0x19, 0xff,
242 0xba, 0xc0, 0xba, 0xc0,
243 0x00, 0xff, 0x2d, 0x5e,
247 /* TR+LLC+IPX, indicating NCP, with NCP Type == 0x2222 */
248 guint8 pkt_ncp2222[] = {
249 0x10, 0x40, 0x00, 0x00,
250 0xf6, 0x7c, 0x9b, 0x70,
251 0x68, 0x00, 0x19, 0x69,
252 0x95, 0x8b, 0xe0, 0xe0,
253 0x03, 0xff, 0xff, 0x00,
254 0x25, 0x02, 0x11, 0x00,
255 0x00, 0x74, 0x14, 0x00,
256 0x00, 0x00, 0x00, 0x00,
257 0x01, 0x04, 0x51, 0x00,
258 0x00, 0x00, 0x04, 0x00,
259 0x02, 0x16, 0x19, 0x7a,
260 0x84, 0x40, 0x01, 0x22,
264 /* Ethernet+IP+TCP, indicating GIOP */
265 guint8 pkt_giop[] = {
266 0xff, 0xff, 0xff, 0xff,
267 0xff, 0xff, 0x01, 0x01,
268 0x01, 0x01, 0x01, 0x01,
271 0x45, 0x00, 0x00, 0xa6,
272 0x00, 0x2f, 0x40, 0x00,
273 0x40, 0x06, 0x3c, 0x21,
274 0x7f, 0x00, 0x00, 0x01,
275 0x7f, 0x00, 0x00, 0x01,
277 0x30, 0x39, 0x04, 0x05,
278 0xac, 0x02, 0x1e, 0x69,
279 0xab, 0x74, 0xab, 0x64,
280 0x80, 0x18, 0x79, 0x60,
281 0xc4, 0xb8, 0x00, 0x00,
282 0x01, 0x01, 0x08, 0x0a,
283 0x00, 0x00, 0x48, 0xf5,
284 0x00, 0x00, 0x48, 0xf5,
286 0x47, 0x49, 0x4f, 0x50,
287 0x01, 0x00, 0x00, 0x00,
288 0x00, 0x00, 0x00, 0x30,
289 0x00, 0x00, 0x00, 0x00,
290 0x00, 0x00, 0x00, 0x01,
294 /* Ethernet+IP+TCP, indicating BGP */
296 0xff, 0xff, 0xff, 0xff,
297 0xff, 0xff, 0x01, 0x01,
298 0x01, 0x01, 0x01, 0x01,
301 0x45, 0x00, 0x00, 0xa6,
302 0x00, 0x2f, 0x40, 0x00,
303 0x40, 0x06, 0x3c, 0x21,
304 0x7f, 0x00, 0x00, 0x01,
305 0x7f, 0x00, 0x00, 0x01,
307 0x30, 0x39, 0x00, 0xb3,
308 0xac, 0x02, 0x1e, 0x69,
309 0xab, 0x74, 0xab, 0x64,
310 0x80, 0x18, 0x79, 0x60,
311 0xc4, 0xb8, 0x00, 0x00,
312 0x01, 0x01, 0x08, 0x0a,
313 0x00, 0x00, 0x48, 0xf5,
314 0x00, 0x00, 0x48, 0xf5,
316 0xff, 0xff, 0xff, 0xff,
317 0xff, 0xff, 0xff, 0xff,
318 0xff, 0xff, 0xff, 0xff,
319 0xff, 0xff, 0xff, 0xff,
322 /* Ethernet+IP+TCP, indicating TDS NetLib */
324 0x00, 0x50, 0x8b, 0x0d,
325 0x7a, 0xed, 0x00, 0x08,
326 0xa3, 0x98, 0x39, 0x81,
329 0x45, 0x00, 0x03, 0x8d,
330 0x90, 0xd4, 0x40, 0x00,
331 0x7c, 0x06, 0xc3, 0x1b,
332 0xac, 0x14, 0x02, 0x22,
333 0x0a, 0xc2, 0xee, 0x82,
335 0x05, 0x99, 0x08, 0xf8,
336 0xff, 0x4e, 0x85, 0x46,
337 0xa2, 0xb4, 0x42, 0xaa,
338 0x50, 0x18, 0x3c, 0x28,
339 0x0f, 0xda, 0x00, 0x00,
342 /* Ethernet+IP, indicating SCTP */
343 guint8 pkt_sctp[] = {
344 0x00, 0xa0, 0x80, 0x00,
345 0x5e, 0x46, 0x08, 0x00,
346 0x03, 0x4a, 0x00, 0x35,
349 0x45, 0x00, 0x00, 0x7c,
350 0x14, 0x1c, 0x00, 0x00,
351 0x3b, 0x84, 0x4a, 0x54,
352 0x0a, 0x1c, 0x06, 0x2b,
353 0x0a, 0x1c, 0x06, 0x2c,
357 /* Ethernet+IP+SCTP, indicating MEGACO */
358 guint8 pkt_megaco[] = {
359 0x00, 0xa0, 0x80, 0x00,
360 0x5e, 0x46, 0x08, 0x00,
361 0x03, 0x4a, 0x00, 0x35,
364 0x45, 0x00, 0x00, 0x7c,
365 0x14, 0x1c, 0x00, 0x00,
366 0x3b, 0x84, 0x4a, 0x54,
367 0x0a, 0x1c, 0x06, 0x2b,
368 0x0a, 0x1c, 0x06, 0x2c,
370 0x40, 0x00, 0x0b, 0x80,
371 0x00, 0x01, 0x6f, 0x0a,
372 0x6d, 0xb0, 0x18, 0x82,
373 0x00, 0x03, 0x00, 0x5b,
374 0x28, 0x02, 0x43, 0x45,
375 0x00, 0x00, 0xa0, 0xbd,
376 0x00, 0x00, 0x00, 0x07,
379 /* This little data table drives the whole program */
380 randpkt_example examples[] = {
381 { "arp", "Address Resolution Protocol",
382 PKT_ARP, WTAP_ENCAP_ETHERNET,
383 pkt_arp, array_length(pkt_arp),
388 { "bgp", "Border Gateway Protocol",
389 PKT_BGP, WTAP_ENCAP_ETHERNET,
390 pkt_bgp, array_length(pkt_bgp),
395 { "bvlc", "BACnet Virtual Link Control",
396 PKT_BVLC, WTAP_ENCAP_ETHERNET,
397 pkt_bvlc, array_length(pkt_bvlc),
402 { "dns", "Domain Name Service",
403 PKT_DNS, WTAP_ENCAP_ETHERNET,
404 pkt_dns, array_length(pkt_dns),
410 PKT_ETHERNET, WTAP_ENCAP_ETHERNET,
416 { "fddi", "Fiber Distributed Data Interface",
417 PKT_FDDI, WTAP_ENCAP_FDDI,
423 { "giop", "General Inter-ORB Protocol",
424 PKT_GIOP, WTAP_ENCAP_ETHERNET,
425 pkt_giop, array_length(pkt_giop),
430 { "icmp", "Internet Control Message Protocol",
431 PKT_ICMP, WTAP_ENCAP_ETHERNET,
432 pkt_icmp, array_length(pkt_icmp),
437 { "ip", "Internet Protocol",
438 PKT_IP, WTAP_ENCAP_ETHERNET,
439 pkt_ip, array_length(pkt_ip),
444 { "llc", "Logical Link Control",
445 PKT_LLC, WTAP_ENCAP_TOKEN_RING,
446 pkt_llc, array_length(pkt_llc),
451 { "m2m", "WiMAX M2M Encapsulation Protocol",
452 PKT_M2M, WTAP_ENCAP_ETHERNET,
453 pkt_m2m, array_length(pkt_m2m),
458 { "megaco", "MEGACO",
459 PKT_MEGACO, WTAP_ENCAP_ETHERNET,
460 pkt_megaco, array_length(pkt_megaco),
465 { "nbns", "NetBIOS-over-TCP Name Service",
466 PKT_NBNS, WTAP_ENCAP_ETHERNET,
467 pkt_nbns, array_length(pkt_nbns),
472 { "ncp2222", "NetWare Core Protocol",
473 PKT_NCP2222, WTAP_ENCAP_TOKEN_RING,
474 pkt_ncp2222, array_length(pkt_ncp2222),
479 { "sctp", "Stream Control Transmission Protocol",
480 PKT_SCTP, WTAP_ENCAP_ETHERNET,
481 pkt_sctp, array_length(pkt_sctp),
486 { "syslog", "Syslog message",
487 PKT_SYSLOG, WTAP_ENCAP_ETHERNET,
488 pkt_syslog, array_length(pkt_syslog),
493 { "tds", "TDS NetLib",
494 PKT_TDS, WTAP_ENCAP_ETHERNET,
495 pkt_tds, array_length(pkt_tds),
500 { "tcp", "Transmission Control Protocol",
501 PKT_TCP, WTAP_ENCAP_TOKEN_RING,
502 pkt_tcp, array_length(pkt_tcp),
507 { "tr", "Token-Ring",
508 PKT_TR, WTAP_ENCAP_TOKEN_RING,
514 { "udp", "User Datagram Protocol",
515 PKT_UDP, WTAP_ENCAP_ETHERNET,
516 pkt_udp, array_length(pkt_udp),
521 { "usb", "Universal Serial Bus",
522 PKT_USB, WTAP_ENCAP_USB,
528 { "usb-linux", "Universal Serial Bus with Linux specific header",
529 PKT_USB_LINUX, WTAP_ENCAP_USB_LINUX,
537 /* Parse command-line option "type" and return enum type */
539 int randpkt_parse_type(char *string)
541 int num_entries = array_length(examples);
544 /* Called with NULL, choose a random packet */
546 return examples[rand() % num_entries].produceable_type;
549 for (i = 0; i < num_entries; i++) {
550 if (g_strcmp0(examples[i].abbrev, string) == 0) {
551 return examples[i].produceable_type;
556 fprintf(stderr, "randpkt: Type %s not known.\n", string);
560 static void usage(gboolean is_error);
562 /* Seed the random-number generator */
566 unsigned int randomness;
572 #define RANDOM_DEV "/dev/urandom"
575 * Assume it's at least worth trying /dev/urandom on UN*X.
576 * If it doesn't exist, fall back on time().
578 * XXX - Use CryptGenRandom on Windows?
580 fd = ws_open(RANDOM_DEV, O_RDONLY);
582 if (errno != ENOENT) {
584 "randpkt: Could not open " RANDOM_DEV " for reading: %s\n",
591 ret = ws_read(fd, &randomness, sizeof randomness);
594 "randpkt: Could not read from " RANDOM_DEV ": %s\n",
598 if ((size_t)ret != sizeof randomness) {
600 "randpkt: Tried to read %lu bytes from " RANDOM_DEV ", got %ld\n",
601 (unsigned long)sizeof randomness, (long)ret);
611 randomness = (unsigned int) now;
616 static randpkt_example* randpkt_find_example(int type);
618 void randpkt_example_init(randpkt_example* example, char* produce_filename, int produce_max_bytes)
622 example->dump = wtap_dump_open(produce_filename, WTAP_FILE_TYPE_SUBTYPE_PCAP,
623 example->sample_wtap_encap, produce_max_bytes, FALSE /* compressed */, &err);
624 if (!example->dump) {
625 fprintf(stderr, "randpkt: Error writing to %s\n", produce_filename);
629 /* reduce max_bytes by # of bytes already in sample */
630 if (produce_max_bytes <= example->sample_length) {
631 fprintf(stderr, "randpkt: Sample packet length is %d, which is greater than "
632 "or equal to\n", example->sample_length);
633 fprintf(stderr, "your requested max_bytes value of %d\n", produce_max_bytes);
636 example->produce_max_bytes -= example->sample_length;
640 void randpkt_example_close(randpkt_example* example)
643 wtap_dump_close(example->dump, &err);
646 void randpkt_loop(randpkt_example* example, guint64 produce_count)
654 union wtap_pseudo_header* ps_header;
655 guint8 buffer[65536];
656 struct wtap_pkthdr* pkthdr;
658 pkthdr = g_new0(struct wtap_pkthdr, 1);
660 pkthdr->rec_type = REC_TYPE_PACKET;
661 pkthdr->presence_flags = WTAP_HAS_TS;
662 pkthdr->pkt_encap = example->sample_wtap_encap;
664 memset(pkthdr, 0, sizeof(struct wtap_pkthdr));
665 memset(buffer, 0, sizeof(buffer));
667 ps_header = &pkthdr->pseudo_header;
669 /* Load the sample pseudoheader into our pseudoheader buffer */
670 if (example->pseudo_buffer)
671 memcpy(ps_header, example->pseudo_buffer, example->pseudo_length);
673 /* Load the sample into our buffer */
674 if (example->sample_buffer)
675 memcpy(buffer, example->sample_buffer, example->sample_length);
677 /* Produce random packets */
678 for (i = 0; i < produce_count; i++) {
679 if (example->produce_max_bytes > 0) {
680 len_random = (rand() % example->produce_max_bytes + 1);
686 len_this_pkt = example->sample_length + len_random;
688 pkthdr->caplen = len_this_pkt;
689 pkthdr->len = len_this_pkt;
690 pkthdr->ts.secs = i; /* just for variety */
692 for (j = example->pseudo_length; j < (int) sizeof(*ps_header); j++) {
693 ((guint8*)ps_header)[j] = (rand() % 0x100);
696 for (j = example->sample_length; j < len_this_pkt; j++) {
697 /* Add format strings here and there */
698 if ((int) (100.0*rand()/(RAND_MAX+1.0)) < 3 && j < (len_random - 3)) {
699 memcpy(&buffer[j], "%s", 3);
702 buffer[j] = (rand() % 0x100);
706 /* XXX - report errors! */
707 if (!wtap_dump(example->dump, pkthdr, buffer, &err, &err_info)) {
708 if (err_info != NULL)
717 main(int argc, char **argv)
720 int produce_type = -1;
721 char *produce_filename = NULL;
722 int produce_max_bytes = 5000;
723 int produce_count = 1000;
724 randpkt_example *example;
726 int allrandom = FALSE;
727 wtap_dumper *savedump;
729 static const struct option long_options[] = {
730 {(char *)"help", no_argument, NULL, 'h'},
736 arg_list_utf_16to8(argc, argv);
737 create_app_running_mutex();
740 while ((opt = getopt_long(argc, argv, "b:c:ht:r", long_options, NULL)) != -1) {
742 case 'b': /* max bytes */
743 produce_max_bytes = atoi(optarg);
744 if (produce_max_bytes > 65536) {
745 fprintf(stderr, "randpkt: Max bytes is 65536\n");
750 case 'c': /* count */
751 produce_count = atoi(optarg);
754 case 't': /* type of packet to produce */
755 type = g_strdup(optarg);
772 /* any more command line parameters? */
774 produce_filename = argv[optind];
783 produce_type = randpkt_parse_type(type);
786 example = randpkt_find_example(produce_type);
790 randpkt_example_init(example, produce_filename, produce_max_bytes);
791 randpkt_loop(example, produce_count);
792 randpkt_example_close(example);
795 fprintf(stderr, "Can't set type in random mode\n");
799 produce_type = randpkt_parse_type(NULL);
800 example = randpkt_find_example(produce_type);
803 randpkt_example_init(example, produce_filename, produce_max_bytes);
805 while (produce_count-- > 0) {
806 randpkt_loop(example, 1);
807 produce_type = randpkt_parse_type(NULL);
809 savedump = example->dump;
811 example = randpkt_find_example(produce_type);
814 example->dump = savedump;
816 randpkt_example_close(example);
822 /* Print usage statement and exit program */
824 usage(gboolean is_error)
827 int num_entries = array_length(examples);
837 fprintf(output, "Usage: randpkt [-b maxbytes] [-c count] [-t type] [-r] filename\n");
838 fprintf(output, "Default max bytes (per packet) is 5000\n");
839 fprintf(output, "Default count is 1000.\n");
840 fprintf(output, "-r: random packet type selection\n");
841 fprintf(output, "\n");
842 fprintf(output, "Types:\n");
844 for (i = 0; i < num_entries; i++) {
845 fprintf(output, "\t%-16s%s\n", examples[i].abbrev, examples[i].longname);
848 fprintf(output, "\nIf type is not specified, a random packet will be chosen\n\n");
850 exit(is_error ? 1 : 0);
853 /* Find pkt_example record and return pointer to it */
855 randpkt_example* randpkt_find_example(int type)
857 int num_entries = array_length(examples);
860 for (i = 0; i < num_entries; i++) {
861 if (examples[i].produceable_type == type) {
866 fprintf(stderr, "randpkt: Internal error. Type %d has no entry in examples table.\n",
872 * Editor modelines - http://www.wireshark.org/tools/modelines.html
877 * indent-tabs-mode: t
880 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
881 * :indentSize=8:tabSize=8:noTabs=false: