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