Make sure err_info is always set, and print it iff it's non-null.
[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 #ifndef HAVE_GETOPT
31 #include "wsutil/wsgetopt.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 #include "wsutil/file_util.h"
47
48 #ifdef _WIN32
49 #include <wsutil/unicode-utils.h>
50 #endif /* _WIN32 */
51
52 #define array_length(x) (sizeof x / sizeof x[0])
53
54 /* Types of produceable packets */
55 enum {
56         PKT_ARP,
57         PKT_BGP,
58         PKT_BVLC,
59         PKT_DNS,
60         PKT_ETHERNET,
61         PKT_FDDI,
62         PKT_GIOP,
63         PKT_ICMP,
64         PKT_IP,
65         PKT_LLC,
66         PKT_M2M,
67         PKT_MEGACO,
68         PKT_NBNS,
69         PKT_NCP2222,
70         PKT_SCTP,
71         PKT_SYSLOG,
72         PKT_TCP,
73         PKT_TDS,
74         PKT_TR,
75         PKT_UDP,
76         PKT_USB,
77         PKT_USB_LINUX
78 };
79
80 typedef struct {
81         const char      *abbrev;
82         const char      *longname;
83         int             produceable_type;
84         int             sample_wtap_encap;
85         guint8          *sample_buffer;
86         int             sample_length;
87         guint8          *pseudo_buffer;
88         int             pseudo_length;
89 } pkt_example;
90
91 /* Ethernet, indicating ARP */
92 guint8 pkt_arp[] = {
93         0xff, 0xff, 0xff, 0xff,
94         0xff, 0xff, 0x00, 0x00,
95         0x32, 0x25, 0x0f, 0xff,
96         0x08, 0x06
97 };
98
99 /* Ethernet+IP+UDP, indicating DNS */
100 guint8 pkt_dns[] = {
101         0xff, 0xff, 0xff, 0xff,
102         0xff, 0xff, 0x01, 0x01,
103         0x01, 0x01, 0x01, 0x01,
104         0x08, 0x00,
105
106         0x45, 0x00, 0x00, 0x3c,
107         0xc5, 0x9e, 0x40, 0x00,
108         0xff, 0x11, 0xd7, 0xe0,
109         0xd0, 0x15, 0x02, 0xb8,
110         0x0a, 0x01, 0x01, 0x63,
111
112         0x05, 0xe8, 0x00, 0x35,
113         0xff, 0xff, 0x2a, 0xb9,
114         0x30
115 };
116
117 /* Ethernet+IP, indicating ICMP */
118 guint8 pkt_icmp[] = {
119         0xff, 0xff, 0xff, 0xff,
120         0xff, 0xff, 0x01, 0x01,
121         0x01, 0x01, 0x01, 0x01,
122         0x08, 0x00,
123
124         0x45, 0x00, 0x00, 0x54,
125         0x8f, 0xb3, 0x40, 0x00,
126         0xfd, 0x01, 0x8a, 0x99,
127         0xcc, 0xfc, 0x66, 0x0b,
128         0xce, 0x41, 0x62, 0x12
129 };
130
131 /* Ethernet, indicating IP */
132 guint8 pkt_ip[] = {
133         0xff, 0xff, 0xff, 0xff,
134         0xff, 0xff, 0x01, 0x01,
135         0x01, 0x01, 0x01, 0x01,
136         0x08, 0x00
137 };
138
139 /* TR, indicating LLC */
140 guint8 pkt_llc[] = {
141         0x10, 0x40, 0x68, 0x00,
142         0x19, 0x69, 0x95, 0x8b,
143         0x00, 0x01, 0xfa, 0x68,
144         0xc4, 0x67
145 };
146
147 /* Ethernet, indicating WiMAX M2M */
148 guint8 pkt_m2m[] = {
149         0xff, 0xff, 0xff, 0xff,
150         0xff, 0xff, 0x00, 0x00,
151         0x32, 0x25, 0x0f, 0xff,
152         0x08, 0xf0
153 };
154
155 /* Ethernet+IP+UDP, indicating NBNS */
156 guint8 pkt_nbns[] = {
157         0xff, 0xff, 0xff, 0xff,
158         0xff, 0xff, 0x01, 0x01,
159         0x01, 0x01, 0x01, 0x01,
160         0x08, 0x00,
161
162         0x45, 0x00, 0x00, 0x3c,
163         0xc5, 0x9e, 0x40, 0x00,
164         0xff, 0x11, 0xd7, 0xe0,
165         0xd0, 0x15, 0x02, 0xb8,
166         0x0a, 0x01, 0x01, 0x63,
167
168         0x00, 0x89, 0x00, 0x89,
169         0x00, 0x00, 0x2a, 0xb9,
170         0x30
171 };
172
173 /* Ethernet+IP+UDP, indicating syslog */
174 guint8 pkt_syslog[] = {
175         0xff, 0xff, 0xff, 0xff,
176         0xff, 0xff, 0x01, 0x01,
177         0x01, 0x01, 0x01, 0x01,
178         0x08, 0x00,
179
180         0x45, 0x00, 0x00, 0x64,
181         0x20, 0x48, 0x00, 0x00,
182         0xfc, 0x11, 0xf8, 0x03,
183         0xd0, 0x15, 0x02, 0xb8,
184         0x0a, 0x01, 0x01, 0x63,
185
186         0x05, 0xe8, 0x02, 0x02,
187         0x00, 0x50, 0x51, 0xe1,
188         0x3c
189 };
190
191 /* TR+LLC+IP, indicating TCP */
192 guint8 pkt_tcp[] = {
193         0x10, 0x40, 0x68, 0x00,
194         0x19, 0x69, 0x95, 0x8b,
195         0x00, 0x01, 0xfa, 0x68,
196         0xc4, 0x67,
197
198         0xaa, 0xaa, 0x03, 0x00,
199         0x00, 0x00, 0x08, 0x00,
200
201         0x45, 0x00, 0x00, 0x28,
202         0x0b, 0x0b, 0x40, 0x00,
203         0x20, 0x06, 0x85, 0x37,
204         0xc0, 0xa8, 0x27, 0x01,
205         0xc0, 0xa8, 0x22, 0x3c
206 };
207
208 /* Ethernet+IP, indicating UDP */
209 guint8 pkt_udp[] = {
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, 0xd7, 0xe0,
218         0xd0, 0x15, 0x02, 0xb8,
219         0x0a, 0x01, 0x01, 0x63
220 };
221
222 /* Ethernet+IP+UDP, indicating BVLC */
223 guint8 pkt_bvlc[] = {
224         0xff, 0xff, 0xff, 0xff,
225         0xff, 0xff, 0x01, 0x01,
226         0x01, 0x01, 0x01, 0x01,
227         0x08, 0x00,
228
229         0x45, 0x00, 0x00, 0x3c,
230         0xc5, 0x9e, 0x40, 0x00,
231         0xff, 0x11, 0x01, 0xaa,
232         0xc1, 0xff, 0x19, 0x1e,
233         0xc1, 0xff, 0x19, 0xff,
234         0xba, 0xc0, 0xba, 0xc0,
235         0x00, 0xff, 0x2d, 0x5e,
236         0x81
237 };
238
239 /* TR+LLC+IPX, indicating NCP, with NCP Type == 0x2222 */
240 guint8 pkt_ncp2222[] = {
241         0x10, 0x40, 0x00, 0x00,
242         0xf6, 0x7c, 0x9b, 0x70,
243         0x68, 0x00, 0x19, 0x69,
244         0x95, 0x8b, 0xe0, 0xe0,
245         0x03, 0xff, 0xff, 0x00,
246         0x25, 0x02, 0x11, 0x00,
247         0x00, 0x74, 0x14, 0x00,
248         0x00, 0x00, 0x00, 0x00,
249         0x01, 0x04, 0x51, 0x00,
250         0x00, 0x00, 0x04, 0x00,
251         0x02, 0x16, 0x19, 0x7a,
252         0x84, 0x40, 0x01, 0x22,
253         0x22
254 };
255
256 /* Ethernet+IP+TCP, indicating GIOP */
257 guint8 pkt_giop[] = {
258         0xff, 0xff, 0xff, 0xff,
259         0xff, 0xff, 0x01, 0x01,
260         0x01, 0x01, 0x01, 0x01,
261         0x08, 0x00,
262
263         0x45, 0x00, 0x00, 0xa6,
264         0x00, 0x2f, 0x40, 0x00,
265         0x40, 0x06, 0x3c, 0x21,
266         0x7f, 0x00, 0x00, 0x01,
267         0x7f, 0x00, 0x00, 0x01,
268
269         0x30, 0x39, 0x04, 0x05,
270         0xac, 0x02, 0x1e, 0x69,
271         0xab, 0x74, 0xab, 0x64,
272         0x80, 0x18, 0x79, 0x60,
273         0xc4, 0xb8, 0x00, 0x00,
274         0x01, 0x01, 0x08, 0x0a,
275         0x00, 0x00, 0x48, 0xf5,
276         0x00, 0x00, 0x48, 0xf5,
277
278         0x47, 0x49, 0x4f, 0x50,
279         0x01, 0x00, 0x00, 0x00,
280         0x00, 0x00, 0x00, 0x30,
281         0x00, 0x00, 0x00, 0x00,
282         0x00, 0x00, 0x00, 0x01,
283         0x01
284 };
285
286 /* Ethernet+IP+TCP, indicating BGP */
287 guint8 pkt_bgp[] = {
288         0xff, 0xff, 0xff, 0xff,
289         0xff, 0xff, 0x01, 0x01,
290         0x01, 0x01, 0x01, 0x01,
291         0x08, 0x00,
292
293         0x45, 0x00, 0x00, 0xa6,
294         0x00, 0x2f, 0x40, 0x00,
295         0x40, 0x06, 0x3c, 0x21,
296         0x7f, 0x00, 0x00, 0x01,
297         0x7f, 0x00, 0x00, 0x01,
298
299         0x30, 0x39, 0x00, 0xb3,
300         0xac, 0x02, 0x1e, 0x69,
301         0xab, 0x74, 0xab, 0x64,
302         0x80, 0x18, 0x79, 0x60,
303         0xc4, 0xb8, 0x00, 0x00,
304         0x01, 0x01, 0x08, 0x0a,
305         0x00, 0x00, 0x48, 0xf5,
306         0x00, 0x00, 0x48, 0xf5,
307
308         0xff, 0xff, 0xff, 0xff,
309         0xff, 0xff, 0xff, 0xff,
310         0xff, 0xff, 0xff, 0xff,
311         0xff, 0xff, 0xff, 0xff,
312 };
313
314 /* Ethernet+IP+TCP, indicating TDS NetLib */
315 guint8 pkt_tds[] = {
316         0x00, 0x50, 0x8b, 0x0d,
317         0x7a, 0xed, 0x00, 0x08,
318         0xa3, 0x98, 0x39, 0x81,
319         0x08, 0x00,
320
321         0x45, 0x00, 0x03, 0x8d,
322         0x90, 0xd4, 0x40, 0x00,
323         0x7c, 0x06, 0xc3, 0x1b,
324         0xac, 0x14, 0x02, 0x22,
325         0x0a, 0xc2, 0xee, 0x82,
326
327         0x05, 0x99, 0x08, 0xf8,
328         0xff, 0x4e, 0x85, 0x46,
329         0xa2, 0xb4, 0x42, 0xaa,
330         0x50, 0x18, 0x3c, 0x28,
331         0x0f, 0xda, 0x00, 0x00,
332 };
333
334 /* Ethernet+IP, indicating SCTP */
335 guint8 pkt_sctp[] = {
336         0x00, 0xa0, 0x80, 0x00,
337         0x5e, 0x46, 0x08, 0x00,
338         0x03, 0x4a, 0x00, 0x35,
339         0x08, 0x00,
340
341         0x45, 0x00, 0x00, 0x7c,
342         0x14, 0x1c, 0x00, 0x00,
343         0x3b, 0x84, 0x4a, 0x54,
344         0x0a, 0x1c, 0x06, 0x2b,
345         0x0a, 0x1c, 0x06, 0x2c,
346 };
347
348
349 /* Ethernet+IP+SCTP, indicating MEGACO */
350 guint8 pkt_megaco[] = {
351         0x00, 0xa0, 0x80, 0x00,
352         0x5e, 0x46, 0x08, 0x00,
353         0x03, 0x4a, 0x00, 0x35,
354         0x08, 0x00,
355
356         0x45, 0x00, 0x00, 0x7c,
357         0x14, 0x1c, 0x00, 0x00,
358         0x3b, 0x84, 0x4a, 0x54,
359         0x0a, 0x1c, 0x06, 0x2b,
360         0x0a, 0x1c, 0x06, 0x2c,
361
362         0x40, 0x00, 0x0b, 0x80,
363         0x00, 0x01, 0x6f, 0x0a,
364         0x6d, 0xb0, 0x18, 0x82,
365         0x00, 0x03, 0x00, 0x5b,
366         0x28, 0x02, 0x43, 0x45,
367         0x00, 0x00, 0xa0, 0xbd,
368         0x00, 0x00, 0x00, 0x07,
369 };
370
371 /* This little data table drives the whole program */
372 pkt_example examples[] = {
373         { "arp", "Address Resolution Protocol",
374                 PKT_ARP,        WTAP_ENCAP_ETHERNET,
375                 pkt_arp,        array_length(pkt_arp),
376                 NULL,           0 },
377
378         { "bgp", "Border Gateway Protocol",
379                 PKT_BGP,        WTAP_ENCAP_ETHERNET,
380                 pkt_bgp,        array_length(pkt_bgp),
381                 NULL,           0 },
382
383         { "bvlc", "BACnet Virtual Link Control",
384                 PKT_BVLC,       WTAP_ENCAP_ETHERNET,
385                 pkt_bvlc,       array_length(pkt_bvlc),
386                 NULL,           0 },
387
388         { "dns", "Domain Name Service",
389                 PKT_DNS,        WTAP_ENCAP_ETHERNET,
390                 pkt_dns,        array_length(pkt_dns),
391                 NULL,           0 },
392
393         { "eth", "Ethernet",
394                 PKT_ETHERNET,   WTAP_ENCAP_ETHERNET,
395                 NULL,           0,
396                 NULL,           0 },
397
398         { "fddi", "Fiber Distributed Data Interface",
399                 PKT_FDDI,       WTAP_ENCAP_FDDI,
400                 NULL,           0,
401                 NULL,           0 },
402
403         { "giop", "General Inter-ORB Protocol",
404                 PKT_GIOP,       WTAP_ENCAP_ETHERNET,
405                 pkt_giop,       array_length(pkt_giop),
406                 NULL,           0 },
407
408         { "icmp", "Internet Control Message Protocol",
409                 PKT_ICMP,       WTAP_ENCAP_ETHERNET,
410                 pkt_icmp,       array_length(pkt_icmp),
411                 NULL,           0 },
412
413         { "ip", "Internet Protocol",
414                 PKT_IP,         WTAP_ENCAP_ETHERNET,
415                 pkt_ip,         array_length(pkt_ip),
416                 NULL,           0 },
417
418         { "llc", "Logical Link Control",
419                 PKT_LLC,        WTAP_ENCAP_TOKEN_RING,
420                 pkt_llc,        array_length(pkt_llc),
421                 NULL,           0 },
422
423         { "m2m", "WiMAX M2M Encapsulation Protocol",
424                 PKT_M2M,        WTAP_ENCAP_ETHERNET,
425                 pkt_m2m,        array_length(pkt_m2m),
426                 NULL,           0 },
427
428         { "megaco", "MEGACO",
429                 PKT_MEGACO,     WTAP_ENCAP_ETHERNET,
430                 pkt_megaco,     array_length(pkt_megaco),
431                 NULL,           0 },
432
433         { "nbns", "NetBIOS-over-TCP Name Service",
434                 PKT_NBNS,       WTAP_ENCAP_ETHERNET,
435                 pkt_nbns,       array_length(pkt_nbns),
436                 NULL,           0 },
437
438         { "ncp2222", "NetWare Core Protocol",
439                 PKT_NCP2222,    WTAP_ENCAP_TOKEN_RING,
440                 pkt_ncp2222,    array_length(pkt_ncp2222),
441                 NULL,           0 },
442
443         { "sctp", "Stream Control Transmission Protocol",
444                 PKT_SCTP,       WTAP_ENCAP_ETHERNET,
445                 pkt_sctp,       array_length(pkt_sctp),
446                 NULL,           0 },
447
448         { "syslog", "Syslog message",
449                 PKT_SYSLOG,     WTAP_ENCAP_ETHERNET,
450                 pkt_syslog,     array_length(pkt_syslog),
451                 NULL,           0 },
452
453         { "tds", "TDS NetLib",
454                 PKT_TDS,        WTAP_ENCAP_ETHERNET,
455                 pkt_tds,        array_length(pkt_tds),
456                 NULL,           0 },
457
458         { "tcp", "Transmission Control Protocol",
459                 PKT_TCP,        WTAP_ENCAP_TOKEN_RING,
460                 pkt_tcp,        array_length(pkt_tcp),
461                 NULL,           0 },
462
463         { "tr",  "Token-Ring",
464                 PKT_TR,         WTAP_ENCAP_TOKEN_RING,
465                 NULL,           0,
466                 NULL,           0 },
467
468         { "udp", "User Datagram Protocol",
469                 PKT_UDP,        WTAP_ENCAP_ETHERNET,
470                 pkt_udp,        array_length(pkt_udp),
471                 NULL,           0 },
472
473         { "usb", "Universal Serial Bus",
474                 PKT_USB,        WTAP_ENCAP_USB,
475                 NULL,           0,
476                 NULL,           0 },
477
478         { "usb-linux", "Universal Serial Bus with Linux specific header",
479                 PKT_USB_LINUX,  WTAP_ENCAP_USB_LINUX,
480                 NULL,           0,
481                 NULL,           0 },
482
483 };
484
485
486
487 static int parse_type(char *string);
488 static void usage(gboolean is_error);
489 static void seed(void);
490
491 static pkt_example* find_example(int type);
492
493 int
494 main(int argc, char **argv)
495 {
496
497         wtap_dumper             *dump;
498         struct wtap_pkthdr      pkthdr;
499         union wtap_pseudo_header *ps_header = &pkthdr.pseudo_header;
500         int                     i, j, len_this_pkt, len_random, err;
501         gchar                   *err_info;
502         guint8                  buffer[65536];
503
504         int                     opt;
505
506         int                     produce_count = 1000; /* number of pkts to produce */
507         int                     produce_type = PKT_ETHERNET;
508         char                    *produce_filename = NULL;
509         int                     produce_max_bytes = 5000;
510         pkt_example             *example;
511
512 #ifdef _WIN32
513         arg_list_utf_16to8(argc, argv);
514         create_app_running_mutex();
515 #endif /* _WIN32 */
516
517         while ((opt = getopt(argc, argv, "b:c:ht:")) != -1) {
518                 switch (opt) {
519                         case 'b':       /* max bytes */
520                                 produce_max_bytes = atoi(optarg);
521                                 if (produce_max_bytes > 65536) {
522                                         fprintf(stderr,
523                                             "randpkt: Max bytes is 65536\n");
524                                         exit(1);
525                                 }
526                                 break;
527
528                         case 'c':       /* count */
529                                 produce_count = atoi(optarg);
530                                 break;
531
532                         case 't':       /* type of packet to produce */
533                                 produce_type = parse_type(optarg);
534                                 break;
535
536                         case 'h':
537                                 usage(FALSE);
538                                 break;
539                         default:
540                                 usage(TRUE);
541                                 break;
542                 }
543         }
544
545         /* any more command line parameters? */
546         if (argc > optind) {
547                 produce_filename = argv[optind];
548         }
549         else {
550                 usage(TRUE);
551         }
552
553         example = find_example(produce_type);
554
555
556         dump = wtap_dump_open(produce_filename, WTAP_FILE_TYPE_SUBTYPE_PCAP,
557                 example->sample_wtap_encap, produce_max_bytes, FALSE /* compressed */, &err);
558         if (!dump) {
559                 fprintf(stderr,
560                     "randpkt: Error writing to %s\n", produce_filename);
561                 exit(2);
562         }
563
564         seed();
565
566         /* reduce max_bytes by # of bytes already in sample */
567         if (produce_max_bytes <= example->sample_length) {
568                 fprintf(stderr,
569                     "randpkt: Sample packet length is %d, which is greater than or equal to\n",
570                     example->sample_length);
571                 fprintf(stderr, "your requested max_bytes value of %d\n",
572                     produce_max_bytes);
573                 exit(1);
574         }
575         else {
576                 produce_max_bytes -= example->sample_length;
577         }
578
579         memset(&pkthdr, 0, sizeof(pkthdr));
580         memset(buffer, 0, sizeof(buffer));
581
582         pkthdr.rec_type = REC_TYPE_PACKET;
583         pkthdr.presence_flags = WTAP_HAS_TS;
584         pkthdr.pkt_encap = example->sample_wtap_encap;
585
586         /* Load the sample pseudoheader into our pseudoheader buffer */
587         if (example->pseudo_buffer)
588                 memcpy(ps_header, example->pseudo_buffer, example->pseudo_length);
589
590         /* Load the sample into our buffer */
591         if (example->sample_buffer)
592                 memcpy(&buffer[0], example->sample_buffer, example->sample_length);
593
594         /* Produce random packets */
595         for (i = 0; i < produce_count; i++) {
596                 if (produce_max_bytes > 0) {
597                         len_random = (rand() % produce_max_bytes + 1);
598                 }
599                 else {
600                         len_random = 0;
601                 }
602
603                 len_this_pkt = example->sample_length + len_random;
604
605                 pkthdr.caplen = len_this_pkt;
606                 pkthdr.len = len_this_pkt;
607                 pkthdr.ts.secs = i; /* just for variety */
608
609                 for (j = example->pseudo_length; j < (int) sizeof(*ps_header); j++) {
610                         ((guint8*)ps_header)[j] = (rand() % 0x100);
611                 }
612
613                 for (j = example->sample_length; j < len_this_pkt; j++) {
614                         /* Add format strings here and there */
615                         if ((int) (100.0*rand()/(RAND_MAX+1.0)) < 3 && j < (len_random - 3)) {
616                                 memcpy(&buffer[j], "%s", 3);
617                                 j += 2;
618                         } else {
619                                 buffer[j] = (rand() % 0x100);
620                         }
621                 }
622
623                 /* XXX - report errors! */
624                 if (!wtap_dump(dump, &pkthdr, &buffer[0], &err, &err_info)) {
625                         if (err_info != NULL)
626                                 g_free(err_info);
627                 }
628         }
629
630         wtap_dump_close(dump, &err);
631
632         return 0;
633
634 }
635
636 /* Print usage statement and exit program */
637 static void
638 usage(gboolean is_error)
639 {
640         FILE    *output;
641         int      num_entries = array_length(examples);
642         int      i;
643
644         if (!is_error) {
645                 output = stdout;
646         }
647         else {
648                 output = stderr;
649         }
650
651         fprintf(output, "Usage: randpkt [-b maxbytes] [-c count] [-t type] filename\n");
652         fprintf(output, "Default max bytes (per packet) is 5000\n");
653         fprintf(output, "Default count is 1000.\n");
654         fprintf(output, "Types:\n");
655
656         for (i = 0; i < num_entries; i++) {
657                 fprintf(output, "\t%-16s%s\n", examples[i].abbrev, examples[i].longname);
658         }
659
660         fprintf(output, "\n");
661
662         exit(is_error ? 1 : 0);
663 }
664
665 /* Parse command-line option "type" and return enum type */
666 static
667 int parse_type(char *string)
668 {
669         int     num_entries = array_length(examples);
670         int     i;
671
672         for (i = 0; i < num_entries; i++) {
673                 if (strcmp(examples[i].abbrev, string) == 0) {
674                         return examples[i].produceable_type;
675                 }
676         }
677
678         /* Complain */
679         fprintf(stderr, "randpkt: Type %s not known.\n", string);
680         exit(1);
681 }
682
683 /* Find pkt_example record and return pointer to it */
684 static
685 pkt_example* find_example(int type)
686 {
687         int     num_entries = array_length(examples);
688         int     i;
689
690         for (i = 0; i < num_entries; i++) {
691                 if (examples[i].produceable_type == type) {
692                         return &examples[i];
693                 }
694         }
695
696         fprintf(stderr,
697             "randpkt: Internal error. Type %d has no entry in examples table.\n",
698             type);
699         exit(1);
700 }
701
702 /* Seed the random-number generator */
703 void
704 seed(void)
705 {
706         unsigned int    randomness;
707         time_t          now;
708 #ifndef _WIN32
709         int             fd;
710         ssize_t         ret;
711
712 #define RANDOM_DEV "/dev/urandom"
713
714         /*
715          * Assume it's at least worth trying /dev/urandom on UN*X.
716          * If it doesn't exist, fall back on time().
717          *
718          * XXX - Use CryptGenRandom on Windows?
719          */
720         fd = ws_open(RANDOM_DEV, O_RDONLY);
721         if (fd == -1) {
722                 if (errno != ENOENT) {
723                         fprintf(stderr,
724                             "randpkt: Could not open " RANDOM_DEV " for reading: %s\n",
725                             g_strerror(errno));
726                         exit(2);
727                 }
728                 goto fallback;
729         }
730
731         ret = ws_read(fd, &randomness, sizeof randomness);
732         if (ret == -1) {
733                 fprintf(stderr,
734                     "randpkt: Could not read from " RANDOM_DEV ": %s\n",
735                     g_strerror(errno));
736                 exit(2);
737         }
738         if ((size_t)ret != sizeof randomness) {
739                 fprintf(stderr,
740                     "randpkt: Tried to read %lu bytes from " RANDOM_DEV ", got %ld\n",
741                     (unsigned long)sizeof randomness, (long)ret);
742                 exit(2);
743         }
744         srand(randomness);
745         ws_close(fd);
746         return;
747
748 fallback:
749 #endif
750         now = time(NULL);
751         randomness = (unsigned int) now;
752
753         srand(randomness);
754 }
755
756 /*
757  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
758  *
759  * Local variables:
760  * c-basic-offset: 8
761  * tab-width: 8
762  * indent-tabs-mode: t
763  * End:
764  *
765  * vi: set shiftwidth=8 tabstop=8 noexpandtab:
766  * :indentSize=8:tabSize=8:noTabs=false:
767  */