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