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