Make sure that wiretap plugins are loaded before dissectors are (if a new encap type...
[obnox/wireshark/wip.git] / editcap.c
1 /* Edit capture files.  We can delete packets, adjust timestamps, or
2  * simply convert from one format to another format.
3  *
4  * $Id$
5  *
6  * Originally written by Richard Sharpe.
7  * Improved by Guy Harris.
8  * Further improved by Richard Sharpe.
9  */
10
11 #ifdef HAVE_CONFIG_H
12 #include "config.h"
13 #endif
14
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <string.h>
18 #include <stdarg.h>
19
20 /*
21  * Just make sure we include the prototype for strptime as well
22  * (needed for glibc 2.2) but make sure we do this only if not
23  * yet defined.
24  */
25
26 #ifndef __USE_XOPEN
27 #  define __USE_XOPEN
28 #endif
29
30 #include <time.h>
31 #include <glib.h>
32
33 #ifdef HAVE_UNISTD_H
34 #include <unistd.h>
35 #endif
36
37
38
39 #ifdef HAVE_SYS_TIME_H
40 #include <sys/time.h>
41 #endif
42
43 #include "wtap.h"
44
45 #ifdef NEED_GETOPT_H
46 #include "getopt.h"
47 #endif
48
49 #ifdef _WIN32
50 #include <process.h>    /* getpid */
51 #endif
52
53 #ifdef NEED_STRPTIME_H
54 # include "strptime.h"
55 #endif
56
57 #include "epan/crypt/crypt-md5.h"
58 #include "epan/plugins.h"
59 #include "epan/report_err.h"
60 #include "epan/filesystem.h"
61
62 #include "svnversion.h"
63
64 /*
65  * Some globals so we can pass things to various routines
66  */
67
68 struct select_item {
69
70   int inclusive;
71   int first, second;
72
73 };
74
75
76 /*
77  * Duplicate frame detection
78  */
79 typedef struct _fd_hash_t {
80   md5_byte_t digest[16];
81   guint32 len;
82 } fd_hash_t;
83
84 #define DUP_DEPTH 5
85 fd_hash_t fd_hash[DUP_DEPTH];
86 int cur_dup = 0;
87
88 #define ONE_MILLION 1000000
89
90 /* Weights of different errors we can introduce */
91 /* We should probably make these command-line arguments */
92 /* XXX - Should we add a bit-level error? */
93 #define ERR_WT_BIT   5  /* Flip a random bit */
94 #define ERR_WT_BYTE  5  /* Substitute a random byte */
95 #define ERR_WT_ALNUM 5  /* Substitute a random character in [A-Za-z0-9] */
96 #define ERR_WT_FMT   2  /* Substitute "%s" */
97 #define ERR_WT_AA    1  /* Fill the remainder of the buffer with 0xAA */
98 #define ERR_WT_TOTAL (ERR_WT_BIT + ERR_WT_BYTE + ERR_WT_ALNUM + ERR_WT_FMT + ERR_WT_AA)
99
100 #define ALNUM_CHARS "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
101 #define ALNUM_LEN (sizeof(ALNUM_CHARS) - 1)
102
103
104 struct time_adjustment {
105   struct timeval tv;
106   int is_negative;
107 };
108
109 #define MAX_SELECTIONS 512
110 static struct select_item selectfrm[MAX_SELECTIONS];
111 static int max_selected = -1;
112 static int keep_em = 0;
113 static int out_file_type = WTAP_FILE_PCAP;   /* default to "libpcap"   */
114 static int out_frame_type = -2;              /* Leave frame type alone */
115 static int verbose = 0;                      /* Not so verbose         */
116 static struct time_adjustment time_adj = {{0, 0}, 0}; /* no adjustment */
117 static double err_prob = 0.0;
118 static time_t starttime = 0;
119 static time_t stoptime = 0;
120 static gboolean check_startstop = FALSE;
121 static gboolean dup_detect = FALSE;
122
123 /* Add a selection item, a simple parser for now */
124 static gboolean
125 add_selection(char *sel)
126 {
127   char *locn;
128   char *next;
129
130   if (++max_selected >= MAX_SELECTIONS) {
131     /* Let the user know we stopped selecting */
132     printf("Out of room for packet selections!\n");
133     return(FALSE);
134   }
135
136   printf("Add_Selected: %s\n", sel);
137
138   if ((locn = strchr(sel, '-')) == NULL) { /* No dash, so a single number? */
139
140     printf("Not inclusive ...");
141
142     selectfrm[max_selected].inclusive = 0;
143     selectfrm[max_selected].first = atoi(sel);
144
145     printf(" %i\n", selectfrm[max_selected].first);
146
147   }
148   else {
149
150     printf("Inclusive ...");
151
152     next = locn + 1;
153     selectfrm[max_selected].inclusive = 1;
154     selectfrm[max_selected].first = atoi(sel);
155     selectfrm[max_selected].second = atoi(next);
156
157     printf(" %i, %i\n", selectfrm[max_selected].first, selectfrm[max_selected].second);
158
159   }
160
161   return(TRUE);
162 }
163
164 /* Was the packet selected? */
165
166 static int
167 selected(int recno)
168 {
169   int i = 0;
170
171   for (i = 0; i<= max_selected; i++) {
172
173     if (selectfrm[i].inclusive) {
174       if (selectfrm[i].first <= recno && selectfrm[i].second >= recno)
175         return 1;
176     }
177     else {
178       if (recno == selectfrm[i].first)
179         return 1;
180     }
181   }
182
183   return 0;
184
185 }
186
187 /* is the packet in the selected timeframe */
188 static gboolean check_timestamp(wtap *wth) {
189         static int i = 0;
190         struct wtap_pkthdr* pkthdr = wtap_phdr(wth);
191         if (!((i++)%250)) printf("== %d starttime=%lu stoptime=%lu ts=%lu",i,starttime,stoptime,pkthdr->ts.secs);
192         return ( (time_t) pkthdr->ts.secs >= starttime ) && ( (time_t) pkthdr->ts.secs <= stoptime );
193 }
194
195 static void
196 set_time_adjustment(char *optarg)
197 {
198   char *frac, *end;
199   long val;
200   int frac_digits;
201
202   if (!optarg)
203     return;
204
205   /* skip leading whitespace */
206   while (*optarg == ' ' || *optarg == '\t') {
207       optarg++;
208   }
209
210   /* check for a negative adjustment */
211   if (*optarg == '-') {
212       time_adj.is_negative = 1;
213       optarg++;
214   }
215
216   /* collect whole number of seconds, if any */
217   if (*optarg == '.') {         /* only fractional (i.e., .5 is ok) */
218       val  = 0;
219       frac = optarg;
220   } else {
221       val = strtol(optarg, &frac, 10);
222       if (frac == NULL || frac == optarg || val == LONG_MIN || val == LONG_MAX) {
223           fprintf(stderr, "editcap: \"%s\" isn't a valid time adjustment\n",
224                   optarg);
225           exit(1);
226       }
227       if (val < 0) {            /* implies '--' since we caught '-' above  */
228           fprintf(stderr, "editcap: \"%s\" isn't a valid time adjustment\n",
229                   optarg);
230           exit(1);
231       }
232   }
233   time_adj.tv.tv_sec = val;
234
235   /* now collect the partial seconds, if any */
236   if (*frac != '\0') {             /* chars left, so get fractional part */
237     val = strtol(&(frac[1]), &end, 10);
238     if (*frac != '.' || end == NULL || end == frac
239         || val < 0 || val > ONE_MILLION || val == LONG_MIN || val == LONG_MAX) {
240       fprintf(stderr, "editcap: \"%s\" isn't a valid time adjustment\n",
241               optarg);
242       exit(1);
243     }
244   }
245   else {
246     return;                     /* no fractional digits */
247   }
248
249   /* adjust fractional portion from fractional to numerator
250    * e.g., in "1.5" from 5 to 500000 since .5*10^6 = 500000 */
251   if (frac && end) {            /* both are valid */
252     frac_digits = end - frac - 1;   /* fractional digit count (remember '.') */
253     while(frac_digits < 6) {    /* this is frac of 10^6 */
254       val *= 10;
255       frac_digits++;
256     }
257   }
258   time_adj.tv.tv_usec = val;
259 }
260
261 static gboolean
262 is_duplicate(guint8* fd, guint32 len) {
263   int i;
264   md5_state_t ms;
265
266   cur_dup++;
267   if (cur_dup >= DUP_DEPTH)
268     cur_dup = 0;
269
270   /* Calculate our digest */
271   md5_init(&ms);
272   md5_append(&ms, fd, len);
273   md5_finish(&ms, fd_hash[cur_dup].digest);
274
275   fd_hash[cur_dup].len = len;
276
277   /* Look for duplicates */
278   for (i = 0; i < DUP_DEPTH; i++) {
279     if (i == cur_dup)
280       continue;
281
282     if (fd_hash[i].len == fd_hash[cur_dup].len &&
283         memcmp(fd_hash[i].digest, fd_hash[cur_dup].digest, 16) == 0) {
284       return TRUE;
285     }
286   }
287
288   return FALSE;
289 }
290
291 static void usage(void)
292 {
293   fprintf(stderr, "Editcap %s"
294 #ifdef SVNVERSION
295           " (" SVNVERSION ")"
296 #endif
297           "\n", VERSION);
298   fprintf(stderr, "Edit and/or translate the format of capture files.\n");
299   fprintf(stderr, "See http://www.wireshark.org for more information.\n");
300   fprintf(stderr, "\n");
301   fprintf(stderr, "Usage: editcap [options] ... <infile> <outfile> [ <packet#>[-<packet#>] ... ]\n");
302   fprintf(stderr, "\n");
303   fprintf(stderr, "A single packet or a range of packets can be selected.\n");
304   fprintf(stderr, "\n");
305   fprintf(stderr, "Packets:\n");
306   fprintf(stderr, "  -C <choplen>           chop each packet at the end by <choplen> bytes\n");
307   fprintf(stderr, "  -d                     remove duplicate packets\n");
308   fprintf(stderr, "  -E <error probability> set the probability (between 0.0 and 1.0 incl.)\n");
309   fprintf(stderr, "                         that a particular packet byte will be randomly changed\n");
310   fprintf(stderr, "  -r                     keep the selected packets, default is to delete them\n");
311   fprintf(stderr, "  -s <snaplen>           truncate packets to max. <snaplen> bytes of data\n");
312   fprintf(stderr, "  -t <time adjustment>   adjust the timestamp of selected packets,\n");
313   fprintf(stderr, "                         <time adjustment> is in relative seconds (e.g. -0.5)\n");
314   fprintf(stderr, "  -A <start time>        don't output packets whose timestamp is before the\n");
315   fprintf(stderr, "                         given time (format as YYYY-MM-DD hh:mm:ss)\n");
316   fprintf(stderr, "  -B <stop time>         don't output packets whose timestamp is after the\n");
317   fprintf(stderr, "                         given time (format as YYYY-MM-DD hh:mm:ss)\n");
318   fprintf(stderr, "\n");
319   fprintf(stderr, "Output File(s):\n");
320   fprintf(stderr, "  -c <packets per file>  split the packet output to different files,\n");
321   fprintf(stderr, "                         with a maximum of <packets per file> each\n");
322   fprintf(stderr, "  -F <capture type>      set the output file type, default is libpcap\n");
323   fprintf(stderr, "                         an empty \"-F\" option will list the file types\n");
324   fprintf(stderr, "  -T <encap type>        set the output file encapsulation type,\n");
325   fprintf(stderr, "                         default is the same as the input file\n");
326   fprintf(stderr, "                         an empty \"-T\" option will list the encapsulation types\n");
327   fprintf(stderr, "\n");
328   fprintf(stderr, "Miscellaneous:\n");
329   fprintf(stderr, "  -h                     display this help and exit\n");
330   fprintf(stderr, "  -v                     verbose output\n");
331   fprintf(stderr, "\n");
332 }
333
334 static void list_capture_types(void) {
335     int i;
336
337     fprintf(stderr, "editcap: The available capture file types for \"F\":\n");
338     for (i = 0; i < WTAP_NUM_FILE_TYPES; i++) {
339       if (wtap_dump_can_open(i))
340         fprintf(stderr, "    %s - %s\n",
341           wtap_file_type_short_string(i), wtap_file_type_string(i));
342     }
343 }
344
345 static void list_encap_types(void) {
346     int i;
347     const char *string;
348
349     fprintf(stderr, "editcap: The available encapsulation types for \"T\":\n");
350     for (i = 0; i < WTAP_NUM_ENCAP_TYPES; i++) {
351         string = wtap_encap_short_string(i);
352         if (string != NULL)
353           fprintf(stderr, "    %s - %s\n",
354             string, wtap_encap_string(i));
355     }
356 }
357
358 static void
359 failure_message(const char *msg_format, va_list ap)
360 {
361         fprintf(stderr, "editcap: ");
362         vfprintf(stderr, msg_format, ap);
363         fprintf(stderr, "\n");
364 }
365
366 int main(int argc, char *argv[])
367
368 {
369   wtap *wth;
370   int i, j, err;
371   gchar *err_info;
372   extern char *optarg;
373   extern int optind;
374   int opt;
375   char *p;
376   unsigned int snaplen = 0;             /* No limit               */
377   unsigned int choplen = 0;             /* No chop                */
378   wtap_dumper *pdh;
379   int count = 1;
380   gint64 data_offset;
381   struct wtap_pkthdr snap_phdr;
382   const struct wtap_pkthdr *phdr;
383   int err_type;
384   guint8 *buf;
385   int split_packet_count = 0;
386   int written_count = 0;
387   char *filename;
388 #ifdef HAVE_PLUGINS
389   char* init_progfile_dir_error;
390   gboolean check_ts;
391   
392   /* Register wiretap plugins */
393   if ((init_progfile_dir_error = init_progfile_dir(argv[0]))) {
394           g_warning("capinfos: init_progfile_dir(): %s", init_progfile_dir_error);
395           g_free(init_progfile_dir_error);
396     } else {
397                 init_report_err(failure_message,NULL,NULL);
398                 init_plugins();
399     }
400 #endif
401   
402   /* Process the options */
403   while ((opt = getopt(argc, argv, "A:B:c:C:dE:F:hrs:t:T:v")) !=-1) {
404
405     switch (opt) {
406
407     case 'E':
408       err_prob = strtod(optarg, &p);
409       if (p == optarg || err_prob < 0.0 || err_prob > 1.0) {
410         fprintf(stderr, "editcap: probability \"%s\" must be between 0.0 and 1.0\n",
411             optarg);
412         exit(1);
413       }
414       srand( (unsigned int) (time(NULL) + getpid()) );
415       break;
416
417     case 'F':
418       out_file_type = wtap_short_string_to_file_type(optarg);
419       if (out_file_type < 0) {
420         fprintf(stderr, "editcap: \"%s\" isn't a valid capture file type\n\n",
421             optarg);
422         list_capture_types();
423         exit(1);
424       }
425       break;
426
427     case 'c':
428       split_packet_count = strtol(optarg, &p, 10);
429       if (p == optarg || *p != '\0') {
430         fprintf(stderr, "editcap: \"%s\" isn't a valid packet count\n",
431             optarg);
432         exit(1);
433       }
434       if (split_packet_count <= 0) {
435         fprintf(stderr, "editcap: \"%d\" packet count must be larger than zero\n",
436                 split_packet_count);
437         exit(1);
438       }
439       break;
440
441     case 'C':
442       choplen = strtol(optarg, &p, 10);
443       if (p == optarg || *p != '\0') {
444         fprintf(stderr, "editcap: \"%s\" isn't a valid chop length\n",
445             optarg);
446         exit(1);
447       }
448       break;
449
450     case 'd':
451       dup_detect = TRUE;
452       for (i = 0; i < DUP_DEPTH; i++) {
453         memset(&fd_hash[i].digest, 0, 16);
454         fd_hash[i].len = 0;
455       }
456       break;
457
458     case '?':              /* Bad options if GNU getopt */
459       switch(optopt) {
460       case'F':
461         list_capture_types();
462         break;
463       case'T':
464         list_encap_types();
465         break;
466       default:
467         usage();
468       }
469       exit(1);
470       break;
471
472     case 'h':
473       usage();
474       exit(1);
475       break;
476
477     case 'r':
478       keep_em = !keep_em;  /* Just invert */
479       break;
480
481     case 's':
482       snaplen = strtol(optarg, &p, 10);
483       if (p == optarg || *p != '\0') {
484         fprintf(stderr, "editcap: \"%s\" isn't a valid snapshot length\n",
485             optarg);
486         exit(1);
487       }
488       break;
489
490     case 't':
491       set_time_adjustment(optarg);
492       break;
493
494     case 'T':
495       out_frame_type = wtap_short_string_to_encap(optarg);
496       if (out_frame_type < 0) {
497         fprintf(stderr, "editcap: \"%s\" isn't a valid encapsulation type\n\n",
498             optarg);
499         list_encap_types();
500         exit(1);
501       }
502       break;
503
504     case 'v':
505       verbose = !verbose;  /* Just invert */
506       break;
507
508         case 'A':
509         {
510                 struct tm starttm;
511
512                 memset(&starttm,0,sizeof(struct tm));
513
514                 if(!strptime(optarg,"%F %T",&starttm)) {
515                         fprintf(stderr, "editcap: \"%s\" isn't a valid time format\n\n",
516                                         optarg);
517                         exit(1);
518                 }
519
520                 check_startstop = TRUE;
521                 starttm.tm_isdst = -1;
522
523                 starttime = mktime(&starttm);
524                 printf("=START=> given='%s' stoptime=%lu\n",optarg,starttime);
525                 break;
526         }
527         case 'B':
528         {
529                 struct tm stoptm;
530
531                 memset(&stoptm,0,sizeof(struct tm));
532
533                 if(!strptime(optarg,"%F %T",&stoptm)) {
534                         fprintf(stderr, "editcap: \"%s\" isn't a valid time format\n\n",
535                                         optarg);
536                         exit(1);
537                 }
538                 check_startstop = TRUE;
539                 stoptm.tm_isdst = -1;
540                 stoptime = mktime(&stoptm);
541                 printf("=STOP=> given='%s' stoptime=%lu\n",optarg,stoptime);
542                 break;
543         }
544     }
545
546   }
547
548 #ifdef DEBUG
549   printf("Optind = %i, argc = %i\n", optind, argc);
550 #endif
551
552   if ((argc - optind) < 1) {
553
554     usage();
555     exit(1);
556
557   }
558
559   if (check_startstop && !stoptime) {
560           struct tm stoptm;
561           /* XXX: will work until 2035 */
562           memset(&stoptm,0,sizeof(struct tm));
563           stoptm.tm_year = 135;
564           stoptm.tm_mday = 31;
565           stoptm.tm_mon = 11;
566
567           stoptime = mktime(&stoptm);
568           printf("=STOP=NEVER=> stoptime=%lu\n",stoptime);
569   }
570
571   if (starttime > stoptime) {
572           fprintf(stderr, "editcap: start time is after the stop time\n");
573           exit(1);
574   }
575   printf("==> stoptime=%lu stoptime=%lu\n",starttime,stoptime);
576
577   wth = wtap_open_offline(argv[optind], &err, &err_info, FALSE);
578
579   if (!wth) {
580     fprintf(stderr, "editcap: Can't open %s: %s\n", argv[optind],
581         wtap_strerror(err));
582     switch (err) {
583
584     case WTAP_ERR_UNSUPPORTED:
585     case WTAP_ERR_UNSUPPORTED_ENCAP:
586     case WTAP_ERR_BAD_RECORD:
587       fprintf(stderr, "(%s)\n", err_info);
588       g_free(err_info);
589       break;
590     }
591     exit(1);
592
593   }
594
595   if (verbose) {
596
597     fprintf(stderr, "File %s is a %s capture file.\n", argv[optind],
598             wtap_file_type_string(wtap_file_type(wth)));
599
600   }
601
602   /*
603    * Now, process the rest, if any ... we only write if there is an extra
604    * argument or so ...
605    */
606
607   if ((argc - optind) >= 2) {
608
609     if (out_frame_type == -2)
610       out_frame_type = wtap_file_encap(wth);
611
612     if (split_packet_count > 0) {
613       filename = (char *) malloc(strlen(argv[optind+1]) + 20);
614       if (!filename) {
615         exit(5);
616       }
617       sprintf(filename, "%s-%05d", argv[optind+1], 0);
618     } else {
619       filename = argv[optind+1];
620     }
621
622     pdh = wtap_dump_open(filename, out_file_type,
623                          out_frame_type, wtap_snapshot_length(wth), FALSE /* compressed */, &err);
624     if (pdh == NULL) {
625
626       fprintf(stderr, "editcap: Can't open or create %s: %s\n", filename,
627               wtap_strerror(err));
628       exit(1);
629
630     }
631
632     for (i = optind + 2; i < argc; i++)
633       if (add_selection(argv[i]) == FALSE)
634         break;
635
636     while (wtap_read(wth, &err, &err_info, &data_offset)) {
637
638       if (split_packet_count > 0 && (written_count % split_packet_count == 0)) {
639         if (!wtap_dump_close(pdh, &err)) {
640
641           fprintf(stderr, "editcap: Error writing to %s: %s\n", filename,
642                   wtap_strerror(err));
643           exit(1);
644         }
645
646         sprintf(filename, "%s-%05d",argv[optind+1], count / split_packet_count);
647
648         if (verbose) {
649           fprintf(stderr, "Continuing writing in file %s\n", filename);
650         }
651
652         pdh = wtap_dump_open(filename, out_file_type,
653                              out_frame_type, wtap_snapshot_length(wth), FALSE /* compressed */, &err);
654         if (pdh == NULL) {
655
656           fprintf(stderr, "editcap: Can't open or create %s: %s\n", filename,
657                   wtap_strerror(err));
658           exit(1);
659
660         }
661       }
662         
663       check_ts = check_timestamp(wth);
664                 
665       if ( ((check_startstop && check_ts) || (!check_startstop && !check_ts)) && ((!selected(count) && !keep_em) ||
666           (selected(count) && keep_em)) ) {
667
668         if (verbose)
669           printf("Packet: %u\n", count);
670
671         /* We simply write it, perhaps after truncating it; we could do other
672            things, like modify it. */
673
674         phdr = wtap_phdr(wth);
675
676         if (choplen != 0 && phdr->caplen > choplen) {
677           snap_phdr = *phdr;
678           snap_phdr.caplen -= choplen;
679           phdr = &snap_phdr;
680         }
681
682         if (snaplen != 0 && phdr->caplen > snaplen) {
683           snap_phdr = *phdr;
684           snap_phdr.caplen = snaplen;
685           phdr = &snap_phdr;
686         }
687
688         /* assume that if the frame's tv_sec is 0, then
689          * the timestamp isn't supported */
690         if (phdr->ts.secs > 0 && time_adj.tv.tv_sec != 0) {
691           snap_phdr = *phdr;
692           if (time_adj.is_negative)
693             snap_phdr.ts.secs -= time_adj.tv.tv_sec;
694           else
695             snap_phdr.ts.secs += time_adj.tv.tv_sec;
696           phdr = &snap_phdr;
697         }
698
699         /* assume that if the frame's tv_sec is 0, then
700          * the timestamp isn't supported */
701         if (phdr->ts.secs > 0 && time_adj.tv.tv_usec != 0) {
702           snap_phdr = *phdr;
703           if (time_adj.is_negative) { /* subtract */
704             if (snap_phdr.ts.nsecs/1000 < time_adj.tv.tv_usec) { /* borrow */
705               snap_phdr.ts.secs--;
706               snap_phdr.ts.nsecs += ONE_MILLION * 1000;
707             }
708             snap_phdr.ts.nsecs -= time_adj.tv.tv_usec * 1000;
709           } else {                  /* add */
710             if (snap_phdr.ts.nsecs + time_adj.tv.tv_usec * 1000 > ONE_MILLION * 1000) {
711               /* carry */
712               snap_phdr.ts.secs++;
713               snap_phdr.ts.nsecs += (time_adj.tv.tv_usec - ONE_MILLION) * 1000;
714             } else {
715               snap_phdr.ts.nsecs += time_adj.tv.tv_usec * 1000;
716             }
717           }
718           phdr = &snap_phdr;
719         }
720
721         if (dup_detect) {
722           buf = wtap_buf_ptr(wth);
723           if (is_duplicate(buf, phdr->caplen)) {
724             if (verbose)
725               printf("Skipping duplicate: %u\n", count);
726             count++;
727             continue;
728           }
729         }
730
731         if (err_prob > 0.0) {
732           buf = wtap_buf_ptr(wth);
733           for (i = 0; i < (int) phdr->caplen; i++) {
734             if (rand() <= err_prob * RAND_MAX) {
735               err_type = rand() / (RAND_MAX / ERR_WT_TOTAL + 1);
736
737               if (err_type < ERR_WT_BIT) {
738                 buf[i] ^= 1 << (rand() / (RAND_MAX / 8 + 1));
739                 err_type = ERR_WT_TOTAL;
740               } else {
741                 err_type -= ERR_WT_BYTE;
742               }
743
744               if (err_type < ERR_WT_BYTE) {
745                 buf[i] = rand() / (RAND_MAX / 255 + 1);
746                 err_type = ERR_WT_TOTAL;
747               } else {
748                 err_type -= ERR_WT_BYTE;
749               }
750
751               if (err_type < ERR_WT_ALNUM) {
752                 buf[i] = ALNUM_CHARS[rand() / (RAND_MAX / ALNUM_LEN + 1)];
753                 err_type = ERR_WT_TOTAL;
754               } else {
755                 err_type -= ERR_WT_ALNUM;
756               }
757
758               if (err_type < ERR_WT_FMT) {
759                 if ((unsigned int)i < phdr->caplen - 2)
760                   strcpy((char*) &buf[i],  "%s");
761                 err_type = ERR_WT_TOTAL;
762               } else {
763                 err_type -= ERR_WT_FMT;
764               }
765
766               if (err_type < ERR_WT_AA) {
767                 for (j = i; j < (int) phdr->caplen; j++) {
768                   buf[j] = 0xAA;
769                 }
770                 i = phdr->caplen;
771               }
772             }
773           }
774         }
775
776         if (!wtap_dump(pdh, phdr, wtap_pseudoheader(wth), wtap_buf_ptr(wth),
777                        &err)) {
778
779           fprintf(stderr, "editcap: Error writing to %s: %s\n",
780                   filename, wtap_strerror(err));
781           exit(1);
782
783         }
784
785         written_count++;
786
787       }
788
789       count++;
790
791     }
792
793     if (err != 0) {
794       /* Print a message noting that the read failed somewhere along the line. */
795       fprintf(stderr,
796               "editcap: An error occurred while reading \"%s\": %s.\n",
797               argv[optind], wtap_strerror(err));
798       switch (err) {
799
800       case WTAP_ERR_UNSUPPORTED:
801       case WTAP_ERR_UNSUPPORTED_ENCAP:
802       case WTAP_ERR_BAD_RECORD:
803         fprintf(stderr, "(%s)\n", err_info);
804         break;
805       }
806     }
807
808     if (!wtap_dump_close(pdh, &err)) {
809
810       fprintf(stderr, "editcap: Error writing to %s: %s\n", filename,
811               wtap_strerror(err));
812       exit(1);
813
814     }
815   }
816
817   return 0;
818 }
819