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