Add initial support for GIOP.
[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: randpkt.c,v 1.14 2002/05/18 14:58:00 gerald Exp $
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 HAVE_UNISTD_H
31 #include <unistd.h>
32 #endif
33
34 #ifdef HAVE_FCNTL_H
35 #include <fcntl.h>
36 #endif
37
38 #include <time.h>
39 #include <errno.h>
40
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <string.h>
44 #include <glib.h>
45 #include "wiretap/wtap.h"
46
47 #define array_length(x) (sizeof x / sizeof x[0])
48
49 /* Types of produceable packets */
50 enum {
51         PKT_ARP,
52         PKT_DNS,
53         PKT_ETHERNET,
54         PKT_FDDI,
55         PKT_ICMP,
56         PKT_IP,
57         PKT_LLC,
58         PKT_NBNS,
59         PKT_SYSLOG,
60         PKT_TCP,
61         PKT_TR,
62         PKT_UDP,
63         PKT_BVLC,
64         PKT_NCP2222,
65         PKT_GIOP
66 };
67
68 typedef struct {
69         char    *abbrev;
70         char    *longname;
71         int     produceable_type;
72         guint8  *sample_buffer;
73         int     sample_wtap_encap;
74         int     sample_length;
75 } pkt_example;
76
77 /* Ethernet, indicating ARP */
78 guint8 pkt_arp[] = {
79         0xff, 0xff, 0xff, 0xff,
80         0xff, 0xff, 0x00, 0x00,
81         0x32, 0x25, 0x0f, 0xff,
82         0x08, 0x06
83 };
84
85 /* Ethernet+IP+UDP, indicating DNS */
86 guint8 pkt_dns[] = {
87         0xff, 0xff, 0xff, 0xff,
88         0xff, 0xff, 0x01, 0x01,
89         0x01, 0x01, 0x01, 0x01,
90         0x08, 0x00,
91
92         0x45, 0x00, 0x00, 0x3c,
93         0xc5, 0x9e, 0x40, 0x00,
94         0xff, 0x11, 0xd7, 0xe0,
95         0xd0, 0x15, 0x02, 0xb8,
96         0x0a, 0x01, 0x01, 0x63,
97
98         0x05, 0xe8, 0x00, 0x35,
99         0x00, 0x00, 0x2a, 0xb9,
100         0x30
101 };
102
103 /* Ethernet+IP, indicating ICMP */
104 guint8 pkt_icmp[] = {
105         0xff, 0xff, 0xff, 0xff,
106         0xff, 0xff, 0x01, 0x01,
107         0x01, 0x01, 0x01, 0x01,
108         0x08, 0x00,
109
110         0x45, 0x00, 0x00, 0x54,
111         0x8f, 0xb3, 0x40, 0x00,
112         0xfd, 0x01, 0x8a, 0x99,
113         0xcc, 0xfc, 0x66, 0x0b,
114         0xce, 0x41, 0x62, 0x12
115 };
116
117 /* Ethernet, indicating IP */
118 guint8 pkt_ip[] = {
119         0xff, 0xff, 0xff, 0xff,
120         0xff, 0xff, 0x01, 0x01,
121         0x01, 0x01, 0x01, 0x01,
122         0x08, 0x00
123 };
124
125 /* TR, indicating LLC */
126 guint8 pkt_llc[] = {
127         0x10, 0x40, 0x68, 0x00,
128         0x19, 0x69, 0x95, 0x8b,
129         0x00, 0x01, 0xfa, 0x68,
130         0xc4, 0x67
131 };
132
133 /* Ethernet+IP+UDP, indicating NBNS */
134 guint8 pkt_nbns[] = {
135         0xff, 0xff, 0xff, 0xff,
136         0xff, 0xff, 0x01, 0x01,
137         0x01, 0x01, 0x01, 0x01,
138         0x08, 0x00,
139
140         0x45, 0x00, 0x00, 0x3c,
141         0xc5, 0x9e, 0x40, 0x00,
142         0xff, 0x11, 0xd7, 0xe0,
143         0xd0, 0x15, 0x02, 0xb8,
144         0x0a, 0x01, 0x01, 0x63,
145
146         0x00, 0x89, 0x00, 0x89,
147         0x00, 0x00, 0x2a, 0xb9,
148         0x30
149 };
150
151 /* Ethernet+IP+UDP, indicating syslog */
152 guint8 pkt_syslog[] = {
153         0xff, 0xff, 0xff, 0xff,
154         0xff, 0xff, 0x01, 0x01,
155         0x01, 0x01, 0x01, 0x01,
156         0x08, 0x00,
157
158         0x45, 0x00, 0x00, 0x64,
159         0x20, 0x48, 0x00, 0x00,
160         0xfc, 0x11, 0xf8, 0x03,
161         0xd0, 0x15, 0x02, 0xb8,
162         0x0a, 0x01, 0x01, 0x63,
163
164         0x05, 0xe8, 0x02, 0x02,
165         0x00, 0x50, 0x51, 0xe1,
166         0x3c
167 };
168
169 /* TR+LLC+IP, indicating TCP */
170 guint8 pkt_tcp[] = {
171         0x10, 0x40, 0x68, 0x00,
172         0x19, 0x69, 0x95, 0x8b,
173         0x00, 0x01, 0xfa, 0x68,
174         0xc4, 0x67,
175
176         0xaa, 0xaa, 0x03, 0x00,
177         0x00, 0x00, 0x08, 0x00,
178
179         0x45, 0x00, 0x00, 0x28,
180         0x0b, 0x0b, 0x40, 0x00,
181         0x20, 0x06, 0x85, 0x37,
182         0xc0, 0xa8, 0x27, 0x01,
183         0xc0, 0xa8, 0x22, 0x3c
184 };
185
186 /* Ethernet+IP, indicating UDP */
187 guint8 pkt_udp[] = {
188         0xff, 0xff, 0xff, 0xff,
189         0xff, 0xff, 0x01, 0x01,
190         0x01, 0x01, 0x01, 0x01,
191         0x08, 0x00,
192
193         0x45, 0x00, 0x00, 0x3c,
194         0xc5, 0x9e, 0x40, 0x00,
195         0xff, 0x11, 0xd7, 0xe0,
196         0xd0, 0x15, 0x02, 0xb8,
197         0x0a, 0x01, 0x01, 0x63
198 };
199
200 /* Ethernet+IP+UDP, indicating BVLC */
201 guint8 pkt_bvlc[] = {
202         0xff, 0xff, 0xff, 0xff,
203         0xff, 0xff, 0x01, 0x01,
204         0x01, 0x01, 0x01, 0x01,
205         0x08, 0x00,
206
207         0x45, 0x00, 0x00, 0x3c,
208         0xc5, 0x9e, 0x40, 0x00,
209         0xff, 0x11, 0x01, 0xaa,
210         0xc1, 0xff, 0x19, 0x1e,
211         0xc1, 0xff, 0x19, 0xff,
212         0xba, 0xc0, 0xba, 0xc0,
213         0x00, 0xff, 0x2d, 0x5e,
214         0x81
215 };
216
217 /* TR+LLC+IPX, indicating NCP, with NCP Type == 0x2222 */
218 guint8 pkt_ncp2222[] = {
219         0x10, 0x40, 0x00, 0x00,
220         0xf6, 0x7c, 0x9b, 0x70,
221         0x68, 0x00, 0x19, 0x69,
222         0x95, 0x8b, 0xe0, 0xe0,
223         0x03, 0xff, 0xff, 0x00,
224         0x25, 0x02, 0x11, 0x00,
225         0x00, 0x74, 0x14, 0x00,
226         0x00, 0x00, 0x00, 0x00,
227         0x01, 0x04, 0x51, 0x00,
228         0x00, 0x00, 0x04, 0x00,
229         0x02, 0x16, 0x19, 0x7a,
230         0x84, 0x40, 0x01, 0x22,
231         0x22
232 };
233
234 /* Ethernet+IP+TCP, indicating GIOP */
235 guint8 pkt_giop[] = {
236         0xff, 0xff, 0xff, 0xff,
237         0xff, 0xff, 0x01, 0x01,
238         0x01, 0x01, 0x01, 0x01,
239         0x08, 0x00,
240
241         0x45, 0x00, 0x00, 0xa6,
242         0x00, 0x2f, 0x40, 0x00,
243         0x40, 0x06, 0x3c, 0x21,
244         0x7f, 0x00, 0x00, 0x01,
245         0x7f, 0x00, 0x00, 0x01,
246
247         0x30, 0x39, 0x04, 0x05,
248         0xac, 0x02, 0x1e, 0x69,
249         0xab, 0x74, 0xab, 0x64,
250         0x80, 0x18, 0x79, 0x60,
251         0xc4, 0xb8, 0x00, 0x00,
252         0x01, 0x01, 0x08, 0x0a,
253         0x00, 0x00, 0x48, 0xf5,
254         0x00, 0x00, 0x48, 0xf5,
255
256         0x47, 0x49, 0x4f, 0x50,
257         0x01, 0x00, 0x00, 0x00,
258         0x00, 0x00, 0x00, 0x30,
259         0x00, 0x00, 0x00, 0x00,
260         0x00, 0x00, 0x00, 0x01,
261         0x01
262 };
263
264 /* This little data table drives the whole program */
265 pkt_example examples[] = {
266         { "arp", "Address Resolution Protocol",
267                 PKT_ARP,        pkt_arp,        WTAP_ENCAP_ETHERNET,    array_length(pkt_arp) },
268
269         { "dns", "Domain Name Service",
270                 PKT_DNS,        pkt_dns,        WTAP_ENCAP_ETHERNET,    array_length(pkt_dns) },
271
272         { "eth", "Ethernet",
273                 PKT_ETHERNET,   NULL,           WTAP_ENCAP_ETHERNET,    0 },
274
275         { "fddi", "Fiber Distributed Data Interface",
276                 PKT_FDDI,       NULL,           WTAP_ENCAP_FDDI,        0 },
277
278         { "icmp", "Internet Control Message Protocol",
279                 PKT_ICMP,       pkt_icmp,       WTAP_ENCAP_ETHERNET,    array_length(pkt_icmp) },
280
281         { "ip", "Internet Protocol",
282                 PKT_IP,         pkt_ip,         WTAP_ENCAP_ETHERNET,    array_length(pkt_ip) },
283
284         { "llc", "Logical Link Control",
285                 PKT_LLC,        pkt_llc,        WTAP_ENCAP_TOKEN_RING,  array_length(pkt_llc) },
286
287         { "nbns", "NetBIOS-over-TCP Name Service",
288                 PKT_NBNS,       pkt_nbns,       WTAP_ENCAP_ETHERNET,    array_length(pkt_nbns) },
289
290         { "syslog", "Syslog message",
291                 PKT_SYSLOG,     pkt_syslog,     WTAP_ENCAP_ETHERNET,    array_length(pkt_syslog) },
292
293         { "tcp", "Transmission Control Protocol",
294                 PKT_TCP,        pkt_tcp,        WTAP_ENCAP_TOKEN_RING,  array_length(pkt_tcp) },
295
296         { "tr",  "Token-Ring",
297                 PKT_TR,         NULL,           WTAP_ENCAP_TOKEN_RING,  0 },
298
299         { "udp", "User Datagram Protocol",
300                 PKT_UDP,        pkt_udp,        WTAP_ENCAP_ETHERNET,    array_length(pkt_udp) },
301
302         { "bvlc", "BACnet Virtual Link Control",
303                 PKT_BVLC,       pkt_bvlc,       WTAP_ENCAP_ETHERNET,    array_length(pkt_bvlc) },
304
305         { "ncp2222", "NetWare Core Protocol",
306                 PKT_NCP2222,    pkt_ncp2222,    WTAP_ENCAP_TOKEN_RING,  array_length(pkt_ncp2222) },
307
308         { "giop", "General Inter-ORB Protocol",
309                 PKT_GIOP,       pkt_giop,       WTAP_ENCAP_ETHERNET,    array_length(pkt_giop) },
310
311 };
312
313
314
315 static int parse_type(char *string);
316 static void usage(void);
317 static void seed(void);
318
319 static pkt_example* find_example(int type);
320
321 int
322 main(int argc, char **argv)
323 {
324
325         wtap_dumper             *dump;
326         struct wtap_pkthdr      pkthdr;
327         union wtap_pseudo_header        ps_header;
328         int                     i, j, len_this_pkt, len_random, err;
329         guint8                  buffer[65536];
330
331         int                     opt;
332         extern char             *optarg;
333         extern int              optind;
334
335         int                     produce_count = 1000; /* number of pkts to produce */
336         int                     produce_type = PKT_ETHERNET;
337         char                    *produce_filename = NULL;
338         int                     produce_max_bytes = 5000;
339         pkt_example             *example;
340
341         while ((opt = getopt(argc, argv, "b:c:t:")) != -1) {
342                 switch (opt) {
343                         case 'b':       /* max bytes */
344                                 produce_max_bytes = atoi(optarg);
345                                 if (produce_max_bytes > 65536) {
346                                         printf("Max bytes is 65536\n");
347                                         exit(0);
348                                 }
349                                 break;
350
351                         case 'c':       /* count */
352                                 produce_count = atoi(optarg);
353                                 break;
354
355                         case 't':       /* type of packet to produce */
356                                 produce_type = parse_type(optarg);
357                                 break;
358
359                         default:
360                                 usage();
361                                 break;
362                 }
363         }
364
365         /* any more command line parameters? */
366         if (argc > optind) {
367                 produce_filename = argv[optind];
368         }
369         else {
370                 usage();
371         }
372
373         example = find_example(produce_type);
374
375         pkthdr.ts.tv_sec = 0;
376         pkthdr.ts.tv_usec = 0;
377         pkthdr.pkt_encap = example->sample_wtap_encap;
378
379         dump = wtap_dump_open(produce_filename, WTAP_FILE_PCAP,
380                 example->sample_wtap_encap, produce_max_bytes, &err);
381
382         seed();
383
384         /* reduce max_bytes by # of bytes already in sample */
385         if (produce_max_bytes <= example->sample_length) {
386                 printf("Sample packet length is %d, which is greater than or equal to\n", example->sample_length);
387                 printf("your requested max_bytes value of %d\n", produce_max_bytes);
388                 exit(0);
389         }
390         else {
391                 produce_max_bytes -= example->sample_length;
392         }
393
394         /* Load the sample into our buffer */
395         if (example->sample_buffer)
396                 memcpy(&buffer[0], example->sample_buffer, example->sample_length);
397
398         /* Produce random packets */
399         for (i = 0; i < produce_count; i++) {
400                 if (produce_max_bytes > 0) {
401                         len_random = (rand() % produce_max_bytes + 1);
402                 }
403                 else {
404                         len_random = 0;
405                 }
406
407                 len_this_pkt = example->sample_length + len_random;
408
409                 pkthdr.caplen = len_this_pkt;
410                 pkthdr.len = len_this_pkt;
411                 pkthdr.ts.tv_sec = i; /* just for variety */
412
413                 for (j = example->sample_length; j < len_random; j++) {
414                         buffer[j] = (rand() % 0x100);
415                 }
416
417                 wtap_dump(dump, &pkthdr, &ps_header, &buffer[0], &err);
418         }
419
420         wtap_dump_close(dump, &err);
421
422         return 0;
423
424 }
425
426 /* Print usage statement and exit program */
427 static
428 void usage(void)
429 {
430         int     num_entries = array_length(examples);
431         int     i;
432
433         printf("Usage: randpkt [-b maxbytes] [-c count] [-t type] filename\n");
434         printf("Default max bytes (per packet) is 5000\n");
435         printf("Default count is 1000.\n");
436         printf("Types:\n");
437
438         for (i = 0; i < num_entries; i++) {
439                 printf("\t%s\t%s\n", examples[i].abbrev, examples[i].longname);
440         }
441
442         printf("\n");
443
444         exit(0);
445 }
446
447 /* Parse command-line option "type" and return enum type */
448 static
449 int parse_type(char *string)
450 {
451         int     num_entries = array_length(examples);
452         int     i;
453
454         for (i = 0; i < num_entries; i++) {
455                 if (strcmp(examples[i].abbrev, string) == 0) {
456                         return examples[i].produceable_type;
457                 }
458         }
459
460         /* Complain */
461         printf("Type %s not known.\n", string);
462         exit(1);
463 }
464
465 /* Find pkt_example record and return pointer to it */
466 static
467 pkt_example* find_example(int type)
468 {
469         int     num_entries = array_length(examples);
470         int     i;
471
472         for (i = 0; i < num_entries; i++) {
473                 if (examples[i].produceable_type == type) {
474                         return &examples[i];
475                 }
476         }
477
478         printf("Internal error. Type %d has no entry in examples table.\n", type);
479         exit(1);
480 }
481
482 /* Seed the random-number generator */
483 void
484 seed(void)
485 {
486         unsigned int    randomness;
487
488 #if defined(linux)
489         /* Okay, I should use #ifdef HAVE_DEV_RANDOM, but this is a quick hack */
490         int             fd;
491
492         fd = open("/dev/random", O_RDONLY);
493         if (fd < 0) {
494                 printf("Could not open /dev/random for reading: %s\n", strerror(errno));
495                 exit(0);
496         }
497
498         read(fd, &randomness, sizeof(randomness));
499 #else
500         time_t now;
501
502         now = time(NULL);
503         randomness = (unsigned int) now;
504 #endif
505
506         srand(randomness);
507 }