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