Convert "macro checks" to use expert info in line with dissectors with comparable...
[metze/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  * Copyright (C) 1999 by Gilbert Ramirez <gram@alumni.rice.edu>
8  *
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.
13  *
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.
18  *
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.
22  */
23
24 #include <config.h>
25
26 #ifdef HAVE_UNISTD_H
27 #include <unistd.h>
28 #endif
29
30 #ifdef HAVE_GETOPT_H
31 #include <getopt.h>
32 #endif
33
34 #ifndef HAVE_GETOPT_LONG
35 #include "wsutil/wsgetopt.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 #include "wsutil/file_util.h"
51 #include <wsutil/ws_diag_control.h>
52
53 #ifdef _WIN32
54 #include <wsutil/unicode-utils.h>
55 #endif /* _WIN32 */
56
57 #define array_length(x) (sizeof x / sizeof x[0])
58
59 /* Types of produceable packets */
60 enum {
61         PKT_ARP,
62         PKT_BGP,
63         PKT_BVLC,
64         PKT_DNS,
65         PKT_ETHERNET,
66         PKT_FDDI,
67         PKT_GIOP,
68         PKT_ICMP,
69         PKT_IP,
70         PKT_LLC,
71         PKT_M2M,
72         PKT_MEGACO,
73         PKT_NBNS,
74         PKT_NCP2222,
75         PKT_SCTP,
76         PKT_SYSLOG,
77         PKT_TCP,
78         PKT_TDS,
79         PKT_TR,
80         PKT_UDP,
81         PKT_USB,
82         PKT_USB_LINUX
83 };
84
85 typedef struct {
86         const char      *abbrev;
87         const char      *longname;
88         int             produceable_type;
89         int             sample_wtap_encap;
90         guint8          *sample_buffer;
91         int             sample_length;
92         guint8          *pseudo_buffer;
93         int             pseudo_length;
94 } pkt_example;
95
96 /* Ethernet, indicating ARP */
97 guint8 pkt_arp[] = {
98         0xff, 0xff, 0xff, 0xff,
99         0xff, 0xff, 0x00, 0x00,
100         0x32, 0x25, 0x0f, 0xff,
101         0x08, 0x06
102 };
103
104 /* Ethernet+IP+UDP, indicating DNS */
105 guint8 pkt_dns[] = {
106         0xff, 0xff, 0xff, 0xff,
107         0xff, 0xff, 0x01, 0x01,
108         0x01, 0x01, 0x01, 0x01,
109         0x08, 0x00,
110
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,
116
117         0x05, 0xe8, 0x00, 0x35,
118         0xff, 0xff, 0x2a, 0xb9,
119         0x30
120 };
121
122 /* Ethernet+IP, indicating ICMP */
123 guint8 pkt_icmp[] = {
124         0xff, 0xff, 0xff, 0xff,
125         0xff, 0xff, 0x01, 0x01,
126         0x01, 0x01, 0x01, 0x01,
127         0x08, 0x00,
128
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
134 };
135
136 /* Ethernet, indicating IP */
137 guint8 pkt_ip[] = {
138         0xff, 0xff, 0xff, 0xff,
139         0xff, 0xff, 0x01, 0x01,
140         0x01, 0x01, 0x01, 0x01,
141         0x08, 0x00
142 };
143
144 /* TR, indicating LLC */
145 guint8 pkt_llc[] = {
146         0x10, 0x40, 0x68, 0x00,
147         0x19, 0x69, 0x95, 0x8b,
148         0x00, 0x01, 0xfa, 0x68,
149         0xc4, 0x67
150 };
151
152 /* Ethernet, indicating WiMAX M2M */
153 guint8 pkt_m2m[] = {
154         0xff, 0xff, 0xff, 0xff,
155         0xff, 0xff, 0x00, 0x00,
156         0x32, 0x25, 0x0f, 0xff,
157         0x08, 0xf0
158 };
159
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,
165         0x08, 0x00,
166
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,
172
173         0x00, 0x89, 0x00, 0x89,
174         0x00, 0x00, 0x2a, 0xb9,
175         0x30
176 };
177
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,
183         0x08, 0x00,
184
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,
190
191         0x05, 0xe8, 0x02, 0x02,
192         0x00, 0x50, 0x51, 0xe1,
193         0x3c
194 };
195
196 /* TR+LLC+IP, indicating TCP */
197 guint8 pkt_tcp[] = {
198         0x10, 0x40, 0x68, 0x00,
199         0x19, 0x69, 0x95, 0x8b,
200         0x00, 0x01, 0xfa, 0x68,
201         0xc4, 0x67,
202
203         0xaa, 0xaa, 0x03, 0x00,
204         0x00, 0x00, 0x08, 0x00,
205
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
211 };
212
213 /* Ethernet+IP, indicating UDP */
214 guint8 pkt_udp[] = {
215         0xff, 0xff, 0xff, 0xff,
216         0xff, 0xff, 0x01, 0x01,
217         0x01, 0x01, 0x01, 0x01,
218         0x08, 0x00,
219
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
225 };
226
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,
232         0x08, 0x00,
233
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,
241         0x81
242 };
243
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,
258         0x22
259 };
260
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,
266         0x08, 0x00,
267
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,
273
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,
282
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,
288         0x01
289 };
290
291 /* Ethernet+IP+TCP, indicating BGP */
292 guint8 pkt_bgp[] = {
293         0xff, 0xff, 0xff, 0xff,
294         0xff, 0xff, 0x01, 0x01,
295         0x01, 0x01, 0x01, 0x01,
296         0x08, 0x00,
297
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,
303
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,
312
313         0xff, 0xff, 0xff, 0xff,
314         0xff, 0xff, 0xff, 0xff,
315         0xff, 0xff, 0xff, 0xff,
316         0xff, 0xff, 0xff, 0xff,
317 };
318
319 /* Ethernet+IP+TCP, indicating TDS NetLib */
320 guint8 pkt_tds[] = {
321         0x00, 0x50, 0x8b, 0x0d,
322         0x7a, 0xed, 0x00, 0x08,
323         0xa3, 0x98, 0x39, 0x81,
324         0x08, 0x00,
325
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,
331
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,
337 };
338
339 /* Ethernet+IP, indicating SCTP */
340 guint8 pkt_sctp[] = {
341         0x00, 0xa0, 0x80, 0x00,
342         0x5e, 0x46, 0x08, 0x00,
343         0x03, 0x4a, 0x00, 0x35,
344         0x08, 0x00,
345
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,
351 };
352
353
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,
359         0x08, 0x00,
360
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,
366
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,
374 };
375
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),
381                 NULL,           0 },
382
383         { "bgp", "Border Gateway Protocol",
384                 PKT_BGP,        WTAP_ENCAP_ETHERNET,
385                 pkt_bgp,        array_length(pkt_bgp),
386                 NULL,           0 },
387
388         { "bvlc", "BACnet Virtual Link Control",
389                 PKT_BVLC,       WTAP_ENCAP_ETHERNET,
390                 pkt_bvlc,       array_length(pkt_bvlc),
391                 NULL,           0 },
392
393         { "dns", "Domain Name Service",
394                 PKT_DNS,        WTAP_ENCAP_ETHERNET,
395                 pkt_dns,        array_length(pkt_dns),
396                 NULL,           0 },
397
398         { "eth", "Ethernet",
399                 PKT_ETHERNET,   WTAP_ENCAP_ETHERNET,
400                 NULL,           0,
401                 NULL,           0 },
402
403         { "fddi", "Fiber Distributed Data Interface",
404                 PKT_FDDI,       WTAP_ENCAP_FDDI,
405                 NULL,           0,
406                 NULL,           0 },
407
408         { "giop", "General Inter-ORB Protocol",
409                 PKT_GIOP,       WTAP_ENCAP_ETHERNET,
410                 pkt_giop,       array_length(pkt_giop),
411                 NULL,           0 },
412
413         { "icmp", "Internet Control Message Protocol",
414                 PKT_ICMP,       WTAP_ENCAP_ETHERNET,
415                 pkt_icmp,       array_length(pkt_icmp),
416                 NULL,           0 },
417
418         { "ip", "Internet Protocol",
419                 PKT_IP,         WTAP_ENCAP_ETHERNET,
420                 pkt_ip,         array_length(pkt_ip),
421                 NULL,           0 },
422
423         { "llc", "Logical Link Control",
424                 PKT_LLC,        WTAP_ENCAP_TOKEN_RING,
425                 pkt_llc,        array_length(pkt_llc),
426                 NULL,           0 },
427
428         { "m2m", "WiMAX M2M Encapsulation Protocol",
429                 PKT_M2M,        WTAP_ENCAP_ETHERNET,
430                 pkt_m2m,        array_length(pkt_m2m),
431                 NULL,           0 },
432
433         { "megaco", "MEGACO",
434                 PKT_MEGACO,     WTAP_ENCAP_ETHERNET,
435                 pkt_megaco,     array_length(pkt_megaco),
436                 NULL,           0 },
437
438         { "nbns", "NetBIOS-over-TCP Name Service",
439                 PKT_NBNS,       WTAP_ENCAP_ETHERNET,
440                 pkt_nbns,       array_length(pkt_nbns),
441                 NULL,           0 },
442
443         { "ncp2222", "NetWare Core Protocol",
444                 PKT_NCP2222,    WTAP_ENCAP_TOKEN_RING,
445                 pkt_ncp2222,    array_length(pkt_ncp2222),
446                 NULL,           0 },
447
448         { "sctp", "Stream Control Transmission Protocol",
449                 PKT_SCTP,       WTAP_ENCAP_ETHERNET,
450                 pkt_sctp,       array_length(pkt_sctp),
451                 NULL,           0 },
452
453         { "syslog", "Syslog message",
454                 PKT_SYSLOG,     WTAP_ENCAP_ETHERNET,
455                 pkt_syslog,     array_length(pkt_syslog),
456                 NULL,           0 },
457
458         { "tds", "TDS NetLib",
459                 PKT_TDS,        WTAP_ENCAP_ETHERNET,
460                 pkt_tds,        array_length(pkt_tds),
461                 NULL,           0 },
462
463         { "tcp", "Transmission Control Protocol",
464                 PKT_TCP,        WTAP_ENCAP_TOKEN_RING,
465                 pkt_tcp,        array_length(pkt_tcp),
466                 NULL,           0 },
467
468         { "tr",  "Token-Ring",
469                 PKT_TR,         WTAP_ENCAP_TOKEN_RING,
470                 NULL,           0,
471                 NULL,           0 },
472
473         { "udp", "User Datagram Protocol",
474                 PKT_UDP,        WTAP_ENCAP_ETHERNET,
475                 pkt_udp,        array_length(pkt_udp),
476                 NULL,           0 },
477
478         { "usb", "Universal Serial Bus",
479                 PKT_USB,        WTAP_ENCAP_USB,
480                 NULL,           0,
481                 NULL,           0 },
482
483         { "usb-linux", "Universal Serial Bus with Linux specific header",
484                 PKT_USB_LINUX,  WTAP_ENCAP_USB_LINUX,
485                 NULL,           0,
486                 NULL,           0 },
487
488 };
489
490
491
492 static int parse_type(char *string);
493 static void usage(gboolean is_error);
494 static void seed(void);
495
496 static pkt_example* find_example(int type);
497
498 int
499 main(int argc, char **argv)
500 {
501
502         wtap_dumper             *dump;
503         struct wtap_pkthdr      pkthdr;
504         union wtap_pseudo_header *ps_header = &pkthdr.pseudo_header;
505         int                     i, j, len_this_pkt, len_random, err;
506         gchar                   *err_info;
507         guint8                  buffer[65536];
508
509         int                     opt;
510
511         int                     produce_count = 1000; /* number of pkts to produce */
512         int                     produce_type = PKT_ETHERNET;
513         char                    *produce_filename = NULL;
514         int                     produce_max_bytes = 5000;
515         pkt_example             *example;
516 DIAG_OFF(cast-qual)
517         static const struct option long_options[] = {
518                 {(char *)"help", no_argument, NULL, 'h'},
519                 {0, 0, 0, 0 }
520         };
521 DIAG_ON(cast-qual)
522
523 #ifdef _WIN32
524         arg_list_utf_16to8(argc, argv);
525         create_app_running_mutex();
526 #endif /* _WIN32 */
527
528         while ((opt = getopt_long(argc, argv, "b:c:ht:", long_options, NULL)) != -1) {
529                 switch (opt) {
530                         case 'b':       /* max bytes */
531                                 produce_max_bytes = atoi(optarg);
532                                 if (produce_max_bytes > 65536) {
533                                         fprintf(stderr,
534                                             "randpkt: Max bytes is 65536\n");
535                                         exit(1);
536                                 }
537                                 break;
538
539                         case 'c':       /* count */
540                                 produce_count = atoi(optarg);
541                                 break;
542
543                         case 't':       /* type of packet to produce */
544                                 produce_type = parse_type(optarg);
545                                 break;
546
547                         case 'h':
548                                 usage(FALSE);
549                                 break;
550                         default:
551                                 usage(TRUE);
552                                 break;
553                 }
554         }
555
556         /* any more command line parameters? */
557         if (argc > optind) {
558                 produce_filename = argv[optind];
559         }
560         else {
561                 usage(TRUE);
562         }
563
564         example = find_example(produce_type);
565
566
567         dump = wtap_dump_open(produce_filename, WTAP_FILE_TYPE_SUBTYPE_PCAP,
568                 example->sample_wtap_encap, produce_max_bytes, FALSE /* compressed */, &err);
569         if (!dump) {
570                 fprintf(stderr,
571                     "randpkt: Error writing to %s\n", produce_filename);
572                 exit(2);
573         }
574
575         seed();
576
577         /* reduce max_bytes by # of bytes already in sample */
578         if (produce_max_bytes <= example->sample_length) {
579                 fprintf(stderr,
580                     "randpkt: Sample packet length is %d, which is greater than or equal to\n",
581                     example->sample_length);
582                 fprintf(stderr, "your requested max_bytes value of %d\n",
583                     produce_max_bytes);
584                 exit(1);
585         }
586         else {
587                 produce_max_bytes -= example->sample_length;
588         }
589
590         memset(&pkthdr, 0, sizeof(pkthdr));
591         memset(buffer, 0, sizeof(buffer));
592
593         pkthdr.rec_type = REC_TYPE_PACKET;
594         pkthdr.presence_flags = WTAP_HAS_TS;
595         pkthdr.pkt_encap = example->sample_wtap_encap;
596
597         /* Load the sample pseudoheader into our pseudoheader buffer */
598         if (example->pseudo_buffer)
599                 memcpy(ps_header, example->pseudo_buffer, example->pseudo_length);
600
601         /* Load the sample into our buffer */
602         if (example->sample_buffer)
603                 memcpy(&buffer[0], example->sample_buffer, example->sample_length);
604
605         /* Produce random packets */
606         for (i = 0; i < produce_count; i++) {
607                 if (produce_max_bytes > 0) {
608                         len_random = (rand() % produce_max_bytes + 1);
609                 }
610                 else {
611                         len_random = 0;
612                 }
613
614                 len_this_pkt = example->sample_length + len_random;
615
616                 pkthdr.caplen = len_this_pkt;
617                 pkthdr.len = len_this_pkt;
618                 pkthdr.ts.secs = i; /* just for variety */
619
620                 for (j = example->pseudo_length; j < (int) sizeof(*ps_header); j++) {
621                         ((guint8*)ps_header)[j] = (rand() % 0x100);
622                 }
623
624                 for (j = example->sample_length; j < len_this_pkt; j++) {
625                         /* Add format strings here and there */
626                         if ((int) (100.0*rand()/(RAND_MAX+1.0)) < 3 && j < (len_random - 3)) {
627                                 memcpy(&buffer[j], "%s", 3);
628                                 j += 2;
629                         } else {
630                                 buffer[j] = (rand() % 0x100);
631                         }
632                 }
633
634                 /* XXX - report errors! */
635                 if (!wtap_dump(dump, &pkthdr, &buffer[0], &err, &err_info)) {
636                         if (err_info != NULL)
637                                 g_free(err_info);
638                 }
639         }
640
641         wtap_dump_close(dump, &err);
642
643         return 0;
644
645 }
646
647 /* Print usage statement and exit program */
648 static void
649 usage(gboolean is_error)
650 {
651         FILE    *output;
652         int      num_entries = array_length(examples);
653         int      i;
654
655         if (!is_error) {
656                 output = stdout;
657         }
658         else {
659                 output = stderr;
660         }
661
662         fprintf(output, "Usage: randpkt [-b maxbytes] [-c count] [-t type] filename\n");
663         fprintf(output, "Default max bytes (per packet) is 5000\n");
664         fprintf(output, "Default count is 1000.\n");
665         fprintf(output, "Types:\n");
666
667         for (i = 0; i < num_entries; i++) {
668                 fprintf(output, "\t%-16s%s\n", examples[i].abbrev, examples[i].longname);
669         }
670
671         fprintf(output, "\n");
672
673         exit(is_error ? 1 : 0);
674 }
675
676 /* Parse command-line option "type" and return enum type */
677 static
678 int parse_type(char *string)
679 {
680         int     num_entries = array_length(examples);
681         int     i;
682
683         for (i = 0; i < num_entries; i++) {
684                 if (strcmp(examples[i].abbrev, string) == 0) {
685                         return examples[i].produceable_type;
686                 }
687         }
688
689         /* Complain */
690         fprintf(stderr, "randpkt: Type %s not known.\n", string);
691         exit(1);
692 }
693
694 /* Find pkt_example record and return pointer to it */
695 static
696 pkt_example* find_example(int type)
697 {
698         int     num_entries = array_length(examples);
699         int     i;
700
701         for (i = 0; i < num_entries; i++) {
702                 if (examples[i].produceable_type == type) {
703                         return &examples[i];
704                 }
705         }
706
707         fprintf(stderr,
708             "randpkt: Internal error. Type %d has no entry in examples table.\n",
709             type);
710         exit(1);
711 }
712
713 /* Seed the random-number generator */
714 void
715 seed(void)
716 {
717         unsigned int    randomness;
718         time_t          now;
719 #ifndef _WIN32
720         int             fd;
721         ssize_t         ret;
722
723 #define RANDOM_DEV "/dev/urandom"
724
725         /*
726          * Assume it's at least worth trying /dev/urandom on UN*X.
727          * If it doesn't exist, fall back on time().
728          *
729          * XXX - Use CryptGenRandom on Windows?
730          */
731         fd = ws_open(RANDOM_DEV, O_RDONLY);
732         if (fd == -1) {
733                 if (errno != ENOENT) {
734                         fprintf(stderr,
735                             "randpkt: Could not open " RANDOM_DEV " for reading: %s\n",
736                             g_strerror(errno));
737                         exit(2);
738                 }
739                 goto fallback;
740         }
741
742         ret = ws_read(fd, &randomness, sizeof randomness);
743         if (ret == -1) {
744                 fprintf(stderr,
745                     "randpkt: Could not read from " RANDOM_DEV ": %s\n",
746                     g_strerror(errno));
747                 exit(2);
748         }
749         if ((size_t)ret != sizeof randomness) {
750                 fprintf(stderr,
751                     "randpkt: Tried to read %lu bytes from " RANDOM_DEV ", got %ld\n",
752                     (unsigned long)sizeof randomness, (long)ret);
753                 exit(2);
754         }
755         srand(randomness);
756         ws_close(fd);
757         return;
758
759 fallback:
760 #endif
761         now = time(NULL);
762         randomness = (unsigned int) now;
763
764         srand(randomness);
765 }
766
767 /*
768  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
769  *
770  * Local variables:
771  * c-basic-offset: 8
772  * tab-width: 8
773  * indent-tabs-mode: t
774  * End:
775  *
776  * vi: set shiftwidth=8 tabstop=8 noexpandtab:
777  * :indentSize=8:tabSize=8:noTabs=false:
778  */