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