Fix for bug 6009:
[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 HAVE_GETOPT_H
31 #include <getopt.h>
32 #else
33 #include "wsutil/wsgetopt.h"
34 #endif
35
36 #ifdef HAVE_UNISTD_H
37 #include <unistd.h>
38 #endif
39
40 #ifdef HAVE_FCNTL_H
41 #include <fcntl.h>
42 #endif
43
44 #include <time.h>
45 #include <errno.h>
46
47 #include <stdio.h>
48 #include <stdlib.h>
49 #include <string.h>
50 #include <glib.h>
51 #include "wiretap/wtap.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(void);
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;
505         int                     i, j, len_this_pkt, len_random, err;
506         guint8                  buffer[65536];
507
508         int                     opt;
509
510         int                     produce_count = 1000; /* number of pkts to produce */
511         int                     produce_type = PKT_ETHERNET;
512         char                    *produce_filename = NULL;
513         int                     produce_max_bytes = 5000;
514         pkt_example             *example;
515
516 #ifdef _WIN32
517         arg_list_utf_16to8(argc, argv);
518 #endif /* _WIN32 */
519
520         while ((opt = getopt(argc, argv, "b:c:ht:")) != -1) {
521                 switch (opt) {
522                         case 'b':       /* max bytes */
523                                 produce_max_bytes = atoi(optarg);
524                                 if (produce_max_bytes > 65536) {
525                                         fprintf(stderr,
526                                             "randpkt: Max bytes is 65536\n");
527                                         exit(1);
528                                 }
529                                 break;
530
531                         case 'c':       /* count */
532                                 produce_count = atoi(optarg);
533                                 break;
534
535                         case 't':       /* type of packet to produce */
536                                 produce_type = parse_type(optarg);
537                                 break;
538
539                         case 'h':
540                         default:
541                                 usage();
542                                 break;
543                 }
544         }
545
546         /* any more command line parameters? */
547         if (argc > optind) {
548                 produce_filename = argv[optind];
549         }
550         else {
551                 usage();
552         }
553
554         example = find_example(produce_type);
555
556
557         dump = wtap_dump_open(produce_filename, WTAP_FILE_PCAP,
558                 example->sample_wtap_encap, produce_max_bytes, FALSE /* compressed */, &err);
559         if (!dump) {
560                 fprintf(stderr,
561                     "randpkt: Error writing to %s\n", produce_filename);
562                 exit(2);
563         }
564
565         seed();
566
567         /* reduce max_bytes by # of bytes already in sample */
568         if (produce_max_bytes <= example->sample_length) {
569                 fprintf(stderr,
570                     "randpkt: Sample packet length is %d, which is greater than or equal to\n",
571                     example->sample_length);
572                 fprintf(stderr, "your requested max_bytes value of %d\n",
573                     produce_max_bytes);
574                 exit(1);
575         }
576         else {
577                 produce_max_bytes -= example->sample_length;
578         }
579
580         memset(&pkthdr, 0, sizeof(pkthdr));
581         memset(&ps_header, 0, sizeof(ps_header));
582         memset(buffer, 0, sizeof(buffer));
583
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                 wtap_dump(dump, &pkthdr, &ps_header, &buffer[0], &err);
624         }
625
626         wtap_dump_close(dump, &err);
627
628         return 0;
629
630 }
631
632 /* Print usage statement and exit program */
633 static
634 void usage(void)
635 {
636         int     num_entries = array_length(examples);
637         int     i;
638
639         printf("Usage: randpkt [-b maxbytes] [-c count] [-t type] filename\n");
640         printf("Default max bytes (per packet) is 5000\n");
641         printf("Default count is 1000.\n");
642         printf("Types:\n");
643
644         for (i = 0; i < num_entries; i++) {
645                 printf("\t%s\t%s\n", examples[i].abbrev, examples[i].longname);
646         }
647
648         printf("\n");
649
650         exit(0);
651 }
652
653 /* Parse command-line option "type" and return enum type */
654 static
655 int parse_type(char *string)
656 {
657         int     num_entries = array_length(examples);
658         int     i;
659
660         for (i = 0; i < num_entries; i++) {
661                 if (strcmp(examples[i].abbrev, string) == 0) {
662                         return examples[i].produceable_type;
663                 }
664         }
665
666         /* Complain */
667         fprintf(stderr, "randpkt: Type %s not known.\n", string);
668         exit(1);
669 }
670
671 /* Find pkt_example record and return pointer to it */
672 static
673 pkt_example* find_example(int type)
674 {
675         int     num_entries = array_length(examples);
676         int     i;
677
678         for (i = 0; i < num_entries; i++) {
679                 if (examples[i].produceable_type == type) {
680                         return &examples[i];
681                 }
682         }
683
684         fprintf(stderr,
685             "randpkt: Internal error. Type %d has no entry in examples table.\n",
686             type);
687         exit(1);
688 }
689
690 /* Seed the random-number generator */
691 void
692 seed(void)
693 {
694         unsigned int    randomness;
695         time_t now;
696 #ifndef _WIN32
697         int             fd;
698         ssize_t         ret;
699
700 #define RANDOM_DEV "/dev/urandom"
701
702         /*
703          * Assume it's at least worth trying /dev/urandom on UN*X.
704          * If it doesn't exist, fall back on time().
705          *
706          * XXX - Use CryptGenRandom on Windows?
707          */
708         fd = open(RANDOM_DEV, O_RDONLY);
709         if (fd == -1) {
710                 if (errno != ENOENT) {
711                         fprintf(stderr,
712                             "randpkt: Could not open " RANDOM_DEV " for reading: %s\n",
713                             strerror(errno));
714                         exit(2);
715                 }
716                 goto fallback;
717         }
718
719         ret = read(fd, &randomness, sizeof randomness);
720         if (ret == -1) {
721                 fprintf(stderr,
722                     "randpkt: Could not read from " RANDOM_DEV ": %s\n",
723                     strerror(errno));
724                 exit(2);
725         }
726         if ((size_t)ret != sizeof randomness) {
727                 fprintf(stderr,
728                     "randpkt: Tried to read %lu bytes from " RANDOM_DEV ", got %ld\n",
729                     (unsigned long)sizeof randomness, (long)ret);
730                 exit(2);
731         }
732         srand(randomness);
733         return;
734
735 fallback:
736 #endif
737         now = time(NULL);
738         randomness = (unsigned int) now;
739
740         srand(randomness);
741 }