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