Fix a typo.
[obnox/wireshark/wip.git] / randpkt.c
1 /*
2  * randpkt.c
3  * ---------
4  * Creates random packet traces. Useful for debugging sniffers by testing
5  * assumptions about the veracity of the data found in the packet.
6  *
7  * $Id$
8  *
9  * Copyright (C) 1999 by Gilbert Ramirez <gram@alumni.rice.edu>
10  *
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.
15  *
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.
20  *
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.
24  */
25
26 #ifdef HAVE_CONFIG_H
27 #include "config.h"
28 #endif
29
30 #ifdef NEED_GETOPT_H
31 #include "getopt.h"
32 #endif
33
34 #ifdef HAVE_UNISTD_H
35 #include <unistd.h>
36 #endif
37
38 #ifdef HAVE_FCNTL_H
39 #include <fcntl.h>
40 #endif
41
42 #include <time.h>
43 #include <errno.h>
44
45 #include <stdio.h>
46 #include <stdlib.h>
47 #include <string.h>
48 #include <glib.h>
49 #include "wiretap/wtap.h"
50
51 #define array_length(x) (sizeof x / sizeof x[0])
52
53 /* Types of produceable packets */
54 enum {
55         PKT_ARP,
56         PKT_BGP,
57         PKT_BVLC,
58         PKT_DNS,
59         PKT_ETHERNET,
60         PKT_FDDI,
61         PKT_GIOP,
62         PKT_ICMP,
63         PKT_IP,
64         PKT_LLC,
65         PKT_M2M,
66         PKT_MEGACO,
67         PKT_NBNS,
68         PKT_NCP2222,
69         PKT_SCTP,
70         PKT_SYSLOG,
71         PKT_TCP,
72         PKT_TDS,
73         PKT_TR,
74         PKT_UDP
75 };
76
77 typedef struct {
78         const char      *abbrev;
79         const char      *longname;
80         int             produceable_type;
81         guint8          *sample_buffer;
82         int             sample_wtap_encap;
83         int             sample_length;
84 } pkt_example;
85
86 /* Ethernet, indicating ARP */
87 guint8 pkt_arp[] = {
88         0xff, 0xff, 0xff, 0xff,
89         0xff, 0xff, 0x00, 0x00,
90         0x32, 0x25, 0x0f, 0xff,
91         0x08, 0x06
92 };
93
94 /* Ethernet+IP+UDP, indicating DNS */
95 guint8 pkt_dns[] = {
96         0xff, 0xff, 0xff, 0xff,
97         0xff, 0xff, 0x01, 0x01,
98         0x01, 0x01, 0x01, 0x01,
99         0x08, 0x00,
100
101         0x45, 0x00, 0x00, 0x3c,
102         0xc5, 0x9e, 0x40, 0x00,
103         0xff, 0x11, 0xd7, 0xe0,
104         0xd0, 0x15, 0x02, 0xb8,
105         0x0a, 0x01, 0x01, 0x63,
106
107         0x05, 0xe8, 0x00, 0x35,
108         0xff, 0xff, 0x2a, 0xb9,
109         0x30
110 };
111
112 /* Ethernet+IP, indicating ICMP */
113 guint8 pkt_icmp[] = {
114         0xff, 0xff, 0xff, 0xff,
115         0xff, 0xff, 0x01, 0x01,
116         0x01, 0x01, 0x01, 0x01,
117         0x08, 0x00,
118
119         0x45, 0x00, 0x00, 0x54,
120         0x8f, 0xb3, 0x40, 0x00,
121         0xfd, 0x01, 0x8a, 0x99,
122         0xcc, 0xfc, 0x66, 0x0b,
123         0xce, 0x41, 0x62, 0x12
124 };
125
126 /* Ethernet, indicating IP */
127 guint8 pkt_ip[] = {
128         0xff, 0xff, 0xff, 0xff,
129         0xff, 0xff, 0x01, 0x01,
130         0x01, 0x01, 0x01, 0x01,
131         0x08, 0x00
132 };
133
134 /* TR, indicating LLC */
135 guint8 pkt_llc[] = {
136         0x10, 0x40, 0x68, 0x00,
137         0x19, 0x69, 0x95, 0x8b,
138         0x00, 0x01, 0xfa, 0x68,
139         0xc4, 0x67
140 };
141
142 /* Ethernet, indicating WiMAX M2M */
143 guint8 pkt_m2m[] = {
144         0xff, 0xff, 0xff, 0xff,
145         0xff, 0xff, 0x00, 0x00,
146         0x32, 0x25, 0x0f, 0xff,
147         0x08, 0xf0
148 };
149
150 /* Ethernet+IP+UDP, indicating NBNS */
151 guint8 pkt_nbns[] = {
152         0xff, 0xff, 0xff, 0xff,
153         0xff, 0xff, 0x01, 0x01,
154         0x01, 0x01, 0x01, 0x01,
155         0x08, 0x00,
156
157         0x45, 0x00, 0x00, 0x3c,
158         0xc5, 0x9e, 0x40, 0x00,
159         0xff, 0x11, 0xd7, 0xe0,
160         0xd0, 0x15, 0x02, 0xb8,
161         0x0a, 0x01, 0x01, 0x63,
162
163         0x00, 0x89, 0x00, 0x89,
164         0x00, 0x00, 0x2a, 0xb9,
165         0x30
166 };
167
168 /* Ethernet+IP+UDP, indicating syslog */
169 guint8 pkt_syslog[] = {
170         0xff, 0xff, 0xff, 0xff,
171         0xff, 0xff, 0x01, 0x01,
172         0x01, 0x01, 0x01, 0x01,
173         0x08, 0x00,
174
175         0x45, 0x00, 0x00, 0x64,
176         0x20, 0x48, 0x00, 0x00,
177         0xfc, 0x11, 0xf8, 0x03,
178         0xd0, 0x15, 0x02, 0xb8,
179         0x0a, 0x01, 0x01, 0x63,
180
181         0x05, 0xe8, 0x02, 0x02,
182         0x00, 0x50, 0x51, 0xe1,
183         0x3c
184 };
185
186 /* TR+LLC+IP, indicating TCP */
187 guint8 pkt_tcp[] = {
188         0x10, 0x40, 0x68, 0x00,
189         0x19, 0x69, 0x95, 0x8b,
190         0x00, 0x01, 0xfa, 0x68,
191         0xc4, 0x67,
192
193         0xaa, 0xaa, 0x03, 0x00,
194         0x00, 0x00, 0x08, 0x00,
195
196         0x45, 0x00, 0x00, 0x28,
197         0x0b, 0x0b, 0x40, 0x00,
198         0x20, 0x06, 0x85, 0x37,
199         0xc0, 0xa8, 0x27, 0x01,
200         0xc0, 0xa8, 0x22, 0x3c
201 };
202
203 /* Ethernet+IP, indicating UDP */
204 guint8 pkt_udp[] = {
205         0xff, 0xff, 0xff, 0xff,
206         0xff, 0xff, 0x01, 0x01,
207         0x01, 0x01, 0x01, 0x01,
208         0x08, 0x00,
209
210         0x45, 0x00, 0x00, 0x3c,
211         0xc5, 0x9e, 0x40, 0x00,
212         0xff, 0x11, 0xd7, 0xe0,
213         0xd0, 0x15, 0x02, 0xb8,
214         0x0a, 0x01, 0x01, 0x63
215 };
216
217 /* Ethernet+IP+UDP, indicating BVLC */
218 guint8 pkt_bvlc[] = {
219         0xff, 0xff, 0xff, 0xff,
220         0xff, 0xff, 0x01, 0x01,
221         0x01, 0x01, 0x01, 0x01,
222         0x08, 0x00,
223
224         0x45, 0x00, 0x00, 0x3c,
225         0xc5, 0x9e, 0x40, 0x00,
226         0xff, 0x11, 0x01, 0xaa,
227         0xc1, 0xff, 0x19, 0x1e,
228         0xc1, 0xff, 0x19, 0xff,
229         0xba, 0xc0, 0xba, 0xc0,
230         0x00, 0xff, 0x2d, 0x5e,
231         0x81
232 };
233
234 /* TR+LLC+IPX, indicating NCP, with NCP Type == 0x2222 */
235 guint8 pkt_ncp2222[] = {
236         0x10, 0x40, 0x00, 0x00,
237         0xf6, 0x7c, 0x9b, 0x70,
238         0x68, 0x00, 0x19, 0x69,
239         0x95, 0x8b, 0xe0, 0xe0,
240         0x03, 0xff, 0xff, 0x00,
241         0x25, 0x02, 0x11, 0x00,
242         0x00, 0x74, 0x14, 0x00,
243         0x00, 0x00, 0x00, 0x00,
244         0x01, 0x04, 0x51, 0x00,
245         0x00, 0x00, 0x04, 0x00,
246         0x02, 0x16, 0x19, 0x7a,
247         0x84, 0x40, 0x01, 0x22,
248         0x22
249 };
250
251 /* Ethernet+IP+TCP, indicating GIOP */
252 guint8 pkt_giop[] = {
253         0xff, 0xff, 0xff, 0xff,
254         0xff, 0xff, 0x01, 0x01,
255         0x01, 0x01, 0x01, 0x01,
256         0x08, 0x00,
257
258         0x45, 0x00, 0x00, 0xa6,
259         0x00, 0x2f, 0x40, 0x00,
260         0x40, 0x06, 0x3c, 0x21,
261         0x7f, 0x00, 0x00, 0x01,
262         0x7f, 0x00, 0x00, 0x01,
263
264         0x30, 0x39, 0x04, 0x05,
265         0xac, 0x02, 0x1e, 0x69,
266         0xab, 0x74, 0xab, 0x64,
267         0x80, 0x18, 0x79, 0x60,
268         0xc4, 0xb8, 0x00, 0x00,
269         0x01, 0x01, 0x08, 0x0a,
270         0x00, 0x00, 0x48, 0xf5,
271         0x00, 0x00, 0x48, 0xf5,
272
273         0x47, 0x49, 0x4f, 0x50,
274         0x01, 0x00, 0x00, 0x00,
275         0x00, 0x00, 0x00, 0x30,
276         0x00, 0x00, 0x00, 0x00,
277         0x00, 0x00, 0x00, 0x01,
278         0x01
279 };
280
281 /* Ethernet+IP+TCP, indicating BGP */
282 guint8 pkt_bgp[] = {
283         0xff, 0xff, 0xff, 0xff,
284         0xff, 0xff, 0x01, 0x01,
285         0x01, 0x01, 0x01, 0x01,
286         0x08, 0x00,
287
288         0x45, 0x00, 0x00, 0xa6,
289         0x00, 0x2f, 0x40, 0x00,
290         0x40, 0x06, 0x3c, 0x21,
291         0x7f, 0x00, 0x00, 0x01,
292         0x7f, 0x00, 0x00, 0x01,
293
294         0x30, 0x39, 0x00, 0xb3,
295         0xac, 0x02, 0x1e, 0x69,
296         0xab, 0x74, 0xab, 0x64,
297         0x80, 0x18, 0x79, 0x60,
298         0xc4, 0xb8, 0x00, 0x00,
299         0x01, 0x01, 0x08, 0x0a,
300         0x00, 0x00, 0x48, 0xf5,
301         0x00, 0x00, 0x48, 0xf5,
302
303         0xff, 0xff, 0xff, 0xff,
304         0xff, 0xff, 0xff, 0xff,
305         0xff, 0xff, 0xff, 0xff,
306         0xff, 0xff, 0xff, 0xff,
307 };
308
309 /* Ethernet+IP+TCP, indicating TDS NetLib */
310 guint8 pkt_tds[] = {
311         0x00, 0x50, 0x8b, 0x0d,
312         0x7a, 0xed, 0x00, 0x08,
313         0xa3, 0x98, 0x39, 0x81,
314         0x08, 0x00,
315
316         0x45, 0x00, 0x03, 0x8d,
317         0x90, 0xd4, 0x40, 0x00,
318         0x7c, 0x06, 0xc3, 0x1b,
319         0xac, 0x14, 0x02, 0x22,
320         0x0a, 0xc2, 0xee, 0x82,
321
322         0x05, 0x99, 0x08, 0xf8,
323         0xff, 0x4e, 0x85, 0x46,
324         0xa2, 0xb4, 0x42, 0xaa,
325         0x50, 0x18, 0x3c, 0x28,
326         0x0f, 0xda, 0x00, 0x00,
327 };
328
329 /* Ethernet+IP, indicating SCTP */
330 guint8 pkt_sctp[] = {
331         0x00, 0xa0, 0x80, 0x00,
332         0x5e, 0x46, 0x08, 0x00,
333         0x03, 0x4a, 0x00, 0x35,
334         0x08, 0x00,
335
336         0x45, 0x00, 0x00, 0x7c,
337         0x14, 0x1c, 0x00, 0x00,
338         0x3b, 0x84, 0x4a, 0x54,
339         0x0a, 0x1c, 0x06, 0x2b,
340         0x0a, 0x1c, 0x06, 0x2c,
341 };
342
343
344 /* Ethernet+IP+SCTP, indicating MEGACO */
345 guint8 pkt_megaco[] = {
346         0x00, 0xa0, 0x80, 0x00,
347         0x5e, 0x46, 0x08, 0x00,
348         0x03, 0x4a, 0x00, 0x35,
349         0x08, 0x00,
350
351         0x45, 0x00, 0x00, 0x7c,
352         0x14, 0x1c, 0x00, 0x00,
353         0x3b, 0x84, 0x4a, 0x54,
354         0x0a, 0x1c, 0x06, 0x2b,
355         0x0a, 0x1c, 0x06, 0x2c,
356
357         0x40, 0x00, 0x0b, 0x80,
358         0x00, 0x01, 0x6f, 0x0a,
359         0x6d, 0xb0, 0x18, 0x82,
360         0x00, 0x03, 0x00, 0x5b,
361         0x28, 0x02, 0x43, 0x45,
362         0x00, 0x00, 0xa0, 0xbd,
363         0x00, 0x00, 0x00, 0x07,
364 };
365
366 /* This little data table drives the whole program */
367 pkt_example examples[] = {
368         { "arp", "Address Resolution Protocol",
369                 PKT_ARP,        pkt_arp,        WTAP_ENCAP_ETHERNET,    array_length(pkt_arp) },
370
371         { "bgp", "Border Gateway Protocol",
372                 PKT_BGP,        pkt_bgp,        WTAP_ENCAP_ETHERNET,    array_length(pkt_bgp) },
373
374         { "bvlc", "BACnet Virtual Link Control",
375                 PKT_BVLC,       pkt_bvlc,       WTAP_ENCAP_ETHERNET,    array_length(pkt_bvlc) },
376
377         { "dns", "Domain Name Service",
378                 PKT_DNS,        pkt_dns,        WTAP_ENCAP_ETHERNET,    array_length(pkt_dns) },
379
380         { "eth", "Ethernet",
381                 PKT_ETHERNET,   NULL,           WTAP_ENCAP_ETHERNET,    0 },
382
383         { "fddi", "Fiber Distributed Data Interface",
384                 PKT_FDDI,       NULL,           WTAP_ENCAP_FDDI,        0 },
385
386         { "giop", "General Inter-ORB Protocol",
387                 PKT_GIOP,       pkt_giop,       WTAP_ENCAP_ETHERNET,    array_length(pkt_giop) },
388
389         { "icmp", "Internet Control Message Protocol",
390                 PKT_ICMP,       pkt_icmp,       WTAP_ENCAP_ETHERNET,    array_length(pkt_icmp) },
391
392         { "ip", "Internet Protocol",
393                 PKT_IP,         pkt_ip,         WTAP_ENCAP_ETHERNET,    array_length(pkt_ip) },
394
395         { "llc", "Logical Link Control",
396                 PKT_LLC,        pkt_llc,        WTAP_ENCAP_TOKEN_RING,  array_length(pkt_llc) },
397
398         { "m2m", "WiMAX M2M Encapsulation Protocol",
399                 PKT_M2M,        pkt_m2m,        WTAP_ENCAP_ETHERNET,    array_length(pkt_m2m) },
400
401         { "megaco", "MEGACO",
402                 PKT_MEGACO,     pkt_megaco,     WTAP_ENCAP_ETHERNET,    array_length(pkt_megaco) },
403
404         { "nbns", "NetBIOS-over-TCP Name Service",
405                 PKT_NBNS,       pkt_nbns,       WTAP_ENCAP_ETHERNET,    array_length(pkt_nbns) },
406
407         { "ncp2222", "NetWare Core Protocol",
408                 PKT_NCP2222,    pkt_ncp2222,    WTAP_ENCAP_TOKEN_RING,  array_length(pkt_ncp2222) },
409
410         { "sctp", "Stream Control Transmission Protocol",
411                 PKT_SCTP,       pkt_sctp,       WTAP_ENCAP_ETHERNET,    array_length(pkt_sctp) },
412
413         { "syslog", "Syslog message",
414                 PKT_SYSLOG,     pkt_syslog,     WTAP_ENCAP_ETHERNET,    array_length(pkt_syslog) },
415
416         { "tds", "TDS NetLib",
417                 PKT_TDS,        pkt_tds,        WTAP_ENCAP_ETHERNET,    array_length(pkt_tds) },
418
419         { "tcp", "Transmission Control Protocol",
420                 PKT_TCP,        pkt_tcp,        WTAP_ENCAP_TOKEN_RING,  array_length(pkt_tcp) },
421
422         { "tr",  "Token-Ring",
423                 PKT_TR,         NULL,           WTAP_ENCAP_TOKEN_RING,  0 },
424
425         { "udp", "User Datagram Protocol",
426                 PKT_UDP,        pkt_udp,        WTAP_ENCAP_ETHERNET,    array_length(pkt_udp) },
427
428 };
429
430
431
432 static int parse_type(char *string);
433 static void usage(void);
434 static void seed(void);
435
436 static pkt_example* find_example(int type);
437
438 int
439 main(int argc, char **argv)
440 {
441
442         wtap_dumper             *dump;
443         struct wtap_pkthdr      pkthdr;
444         union wtap_pseudo_header        ps_header;
445         int                     i, j, len_this_pkt, len_random, err;
446         guint8                  buffer[65536];
447
448         int                     opt;
449         extern char             *optarg;
450         extern int              optind;
451
452         int                     produce_count = 1000; /* number of pkts to produce */
453         int                     produce_type = PKT_ETHERNET;
454         char                    *produce_filename = NULL;
455         int                     produce_max_bytes = 5000;
456         pkt_example             *example;
457
458         while ((opt = getopt(argc, argv, "b:c:t:")) != -1) {
459                 switch (opt) {
460                         case 'b':       /* max bytes */
461                                 produce_max_bytes = atoi(optarg);
462                                 if (produce_max_bytes > 65536) {
463                                         printf("Max bytes is 65536\n");
464                                         exit(0);
465                                 }
466                                 break;
467
468                         case 'c':       /* count */
469                                 produce_count = atoi(optarg);
470                                 break;
471
472                         case 't':       /* type of packet to produce */
473                                 produce_type = parse_type(optarg);
474                                 break;
475
476                         default:
477                                 usage();
478                                 break;
479                 }
480         }
481
482         /* any more command line parameters? */
483         if (argc > optind) {
484                 produce_filename = argv[optind];
485         }
486         else {
487                 usage();
488         }
489
490         example = find_example(produce_type);
491
492         pkthdr.ts.secs = 0;
493         pkthdr.ts.nsecs = 0;
494         pkthdr.pkt_encap = example->sample_wtap_encap;
495
496         dump = wtap_dump_open(produce_filename, WTAP_FILE_PCAP,
497                 example->sample_wtap_encap, produce_max_bytes, FALSE /* compressed */, &err);
498     if (!dump) {
499         printf("Error writing to %s\n", produce_filename);
500         exit(1);
501     }
502
503         seed();
504
505         /* reduce max_bytes by # of bytes already in sample */
506         if (produce_max_bytes <= example->sample_length) {
507                 printf("Sample packet length is %d, which is greater than or equal to\n", example->sample_length);
508                 printf("your requested max_bytes value of %d\n", produce_max_bytes);
509                 exit(0);
510         }
511         else {
512                 produce_max_bytes -= example->sample_length;
513         }
514
515         /* Load the sample into our buffer */
516         if (example->sample_buffer)
517                 memcpy(&buffer[0], example->sample_buffer, example->sample_length);
518
519         /* Produce random packets */
520         for (i = 0; i < produce_count; i++) {
521                 if (produce_max_bytes > 0) {
522                         len_random = (rand() % produce_max_bytes + 1);
523                 }
524                 else {
525                         len_random = 0;
526                 }
527
528                 len_this_pkt = example->sample_length + len_random;
529
530                 pkthdr.caplen = len_this_pkt;
531                 pkthdr.len = len_this_pkt;
532                 pkthdr.ts.secs = i; /* just for variety */
533
534                 for (j = example->sample_length; j < len_this_pkt; j++) {
535                         /* Add format strings here and there */
536                         if ((int) (100.0*rand()/(RAND_MAX+1.0)) < 3 && j < (len_random - 3)) {
537                                 memcpy(&buffer[j], "%s", 3);
538                                 j += 2;
539                         } else {
540                                 buffer[j] = (rand() % 0x100);
541                         }
542                 }
543
544                 wtap_dump(dump, &pkthdr, &ps_header, &buffer[0], &err);
545         }
546
547         wtap_dump_close(dump, &err);
548
549         return 0;
550
551 }
552
553 /* Print usage statement and exit program */
554 static
555 void usage(void)
556 {
557         int     num_entries = array_length(examples);
558         int     i;
559
560         printf("Usage: randpkt [-b maxbytes] [-c count] [-t type] filename\n");
561         printf("Default max bytes (per packet) is 5000\n");
562         printf("Default count is 1000.\n");
563         printf("Types:\n");
564
565         for (i = 0; i < num_entries; i++) {
566                 printf("\t%s\t%s\n", examples[i].abbrev, examples[i].longname);
567         }
568
569         printf("\n");
570
571         exit(0);
572 }
573
574 /* Parse command-line option "type" and return enum type */
575 static
576 int parse_type(char *string)
577 {
578         int     num_entries = array_length(examples);
579         int     i;
580
581         for (i = 0; i < num_entries; i++) {
582                 if (strcmp(examples[i].abbrev, string) == 0) {
583                         return examples[i].produceable_type;
584                 }
585         }
586
587         /* Complain */
588         printf("Type %s not known.\n", string);
589         exit(1);
590 }
591
592 /* Find pkt_example record and return pointer to it */
593 static
594 pkt_example* find_example(int type)
595 {
596         int     num_entries = array_length(examples);
597         int     i;
598
599         for (i = 0; i < num_entries; i++) {
600                 if (examples[i].produceable_type == type) {
601                         return &examples[i];
602                 }
603         }
604
605         printf("Internal error. Type %d has no entry in examples table.\n", type);
606         exit(1);
607 }
608
609 /* Seed the random-number generator */
610 void
611 seed(void)
612 {
613         unsigned int    randomness;
614
615 #if defined(linux)
616         /* Okay, I should use #ifdef HAVE_DEV_RANDOM, but this is a quick hack */
617         int             fd;
618
619         fd = open("/dev/random", O_RDONLY);
620         if (fd < 0) {
621                 printf("Could not open /dev/random for reading: %s\n", strerror(errno));
622                 exit(0);
623         }
624
625         read(fd, &randomness, sizeof(randomness));
626 #else
627         time_t now;
628
629         now = time(NULL);
630         randomness = (unsigned int) now;
631 #endif
632
633         srand(randomness);
634 }