#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#include <glib.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
+
+/*
+ * Just make sure we include the prototype for strptime as well
+ * (needed for glibc 2.2)
+ */
+#define __USE_XOPEN
+
#include <time.h>
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#include <process.h> /* getpid */
#endif
+#ifdef NEED_STRPTIME_H
+# include "strptime.h"
+#endif
+
+#include "epan/crypt-md5.h"
+
#include "svnversion.h"
/*
};
+
+/*
+ * Duplicate frame detection
+ */
+typedef struct _fd_hash_t {
+ md5_byte_t digest[16];
+ guint32 len;
+} fd_hash_t;
+
+#define DUP_DEPTH 5
+fd_hash_t fd_hash[DUP_DEPTH];
+int cur_dup = 0;
+
#define ONE_MILLION 1000000
/* Weights of different errors we can introduce */
static int verbose = 0; /* Not so verbose */
static struct time_adjustment time_adj = {{0, 0}, 0}; /* no adjustment */
static double err_prob = 0.0;
+static time_t starttime = 0;
+static time_t stoptime = 0;
+static gboolean check_startstop = FALSE;
+static gboolean dup_detect = FALSE;
/* Add a selection item, a simple parser for now */
}
+/* is the packet in the selected timeframe */
+static gboolean check_timestamp(wtap *wth) {
+ struct wtap_pkthdr* pkthdr = wtap_phdr(wth);
+ return ( (time_t) pkthdr->ts.secs >= starttime ) && ( (time_t) pkthdr->ts.secs <= stoptime );
+}
+
static void
set_time_adjustment(char *optarg)
{
time_adj.tv.tv_usec = val;
}
+static gboolean
+is_duplicate(guint8* fd, guint32 len) {
+ int i;
+ md5_state_t ms;
+
+ cur_dup++;
+ if (cur_dup >= DUP_DEPTH)
+ cur_dup = 0;
+
+ /* Calculate our digest */
+ md5_init(&ms);
+ md5_append(&ms, fd, len);
+ md5_finish(&ms, fd_hash[cur_dup].digest);
+
+ fd_hash[cur_dup].len = len;
+
+ /* Look for duplicates */
+ for (i = 0; i < DUP_DEPTH; i++) {
+ if (i == cur_dup)
+ continue;
+
+ if (fd_hash[i].len == fd_hash[cur_dup].len &&
+ memcmp(fd_hash[i].digest, fd_hash[cur_dup].digest, 16) == 0) {
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
static void usage(void)
{
fprintf(stderr, "Editcap %s"
#endif
"\n", VERSION);
fprintf(stderr, "Edit and/or translate the format of capture files.\n");
- fprintf(stderr, "See http://www.ethereal.com for more information.\n");
+ fprintf(stderr, "See http://www.wireshark.org for more information.\n");
fprintf(stderr, "\n");
fprintf(stderr, "Usage: editcap [options] ... <infile> <outfile> [ <packet#>[-<packet#>] ... ]\n");
fprintf(stderr, "\n");
fprintf(stderr, "\n");
fprintf(stderr, "Packets:\n");
fprintf(stderr, " -C <choplen> chop each packet at the end by <choplen> bytes\n");
+ fprintf(stderr, " -d remove duplicate packets\n");
fprintf(stderr, " -E <error probability> set the probability (between 0.0 and 1.0 incl.)\n");
fprintf(stderr, " that a particular packet byte will be randomly changed\n");
fprintf(stderr, " -r keep the selected packets, default is to delete them\n");
fprintf(stderr, " -s <snaplen> truncate packets to max. <snaplen> bytes of data\n");
fprintf(stderr, " -t <time adjustment> adjust the timestamp of selected packets,\n");
fprintf(stderr, " <time adjustment> is in relative seconds (e.g. -0.5)\n");
+ fprintf(stderr, " -A <start time> don't output packets whose timestamp is before the\n");
+ fprintf(stderr, " given time (format as YYYY-MM-DD hh:mm:ss)\n");
+ fprintf(stderr, " -B <stop time> don't output packets whose timestamp is after the\n");
+ fprintf(stderr, " given time (format as YYYY-MM-DD hh:mm:ss)\n");
fprintf(stderr, "\n");
fprintf(stderr, "Output File(s):\n");
fprintf(stderr, " -c <packets per file> split the packet output to different files,\n");
fprintf(stderr, "\n");
}
+static void list_capture_types(void) {
+ int i;
-static void bad_option_help(int bad_opt) {
- int i;
- const char *string;
-
-
- switch(bad_opt) {
- case'F':
- fprintf(stderr, "The available capture file types for \"F\":\n");
+ fprintf(stderr, "editcap: The available capture file types for \"F\":\n");
for (i = 0; i < WTAP_NUM_FILE_TYPES; i++) {
if (wtap_dump_can_open(i))
fprintf(stderr, " %s - %s\n",
wtap_file_type_short_string(i), wtap_file_type_string(i));
}
- break;
- case'T':
- fprintf(stderr, "The available encapsulation types for \"T\":\n");
+}
+
+static void list_encap_types(void) {
+ int i;
+ const char *string;
+
+ fprintf(stderr, "editcap: The available encapsulation types for \"T\":\n");
for (i = 0; i < WTAP_NUM_ENCAP_TYPES; i++) {
string = wtap_encap_short_string(i);
if (string != NULL)
fprintf(stderr, " %s - %s\n",
string, wtap_encap_string(i));
}
- break;
- default:
- usage();
- }
}
int main(int argc, char *argv[])
/* Process the options first */
- while ((opt = getopt(argc, argv, "c:C:E:F:hrs:t:T:v")) !=-1) {
+ while ((opt = getopt(argc, argv, "A:B:c:C:dE:F:hrs:t:T:v")) !=-1) {
switch (opt) {
case 'F':
out_file_type = wtap_short_string_to_file_type(optarg);
if (out_file_type < 0) {
- fprintf(stderr, "editcap: \"%s\" isn't a valid capture file type\n",
+ fprintf(stderr, "editcap: \"%s\" isn't a valid capture file type\n\n",
optarg);
+ list_capture_types();
exit(1);
}
break;
}
break;
+ case 'd':
+ dup_detect = TRUE;
+ for (i = 0; i < DUP_DEPTH; i++) {
+ memset(&fd_hash[i].digest, 0, 16);
+ fd_hash[i].len = 0;
+ }
+ break;
+
case '?': /* Bad options if GNU getopt */
- bad_option_help(optopt);
+ switch(optopt) {
+ case'F':
+ list_capture_types();
+ break;
+ case'T':
+ list_encap_types();
+ break;
+ default:
+ usage();
+ }
exit(1);
break;
case 'T':
out_frame_type = wtap_short_string_to_encap(optarg);
if (out_frame_type < 0) {
- fprintf(stderr, "editcap: \"%s\" isn't a valid encapsulation type\n",
+ fprintf(stderr, "editcap: \"%s\" isn't a valid encapsulation type\n\n",
optarg);
+ list_encap_types();
exit(1);
}
break;
verbose = !verbose; /* Just invert */
break;
+ case 'A':
+ {
+ struct tm starttm;
+
+ memset(&starttm,0,sizeof(struct tm));
+
+ if(!strptime(optarg,"%F %T",&starttm)) {
+ fprintf(stderr, "editcap: \"%s\" isn't a valid time format\n\n",
+ optarg);
+ exit(1);
+ }
+
+ check_startstop = TRUE;
+ starttime = mktime(&starttm);
+ break;
+ }
+ case 'B':
+ {
+ struct tm stoptm;
+
+ memset(&stoptm,0,sizeof(struct tm));
+
+ if(!strptime(optarg,"%F %T",&stoptm)) {
+ fprintf(stderr, "editcap: \"%s\" isn't a valid time format\n\n",
+ optarg);
+ exit(1);
+ }
+ check_startstop = TRUE;
+ stoptime = mktime(&stoptm);
+ break;
+ }
}
}
}
+ if (check_startstop && !stoptime) {
+ struct tm stoptm;
+ /* XXX: will work until 2035 */
+ memset(&stoptm,0,sizeof(struct tm));
+ stoptm.tm_year = 135;
+ stoptm.tm_mday = 31;
+ stoptm.tm_mon = 11;
+
+ stoptime = mktime(&stoptm);
+ }
+
+ if (starttime > stoptime) {
+ fprintf(stderr, "editcap: start time is after the stop time\n");
+ exit(1);
+ }
+
wth = wtap_open_offline(argv[optind], &err, &err_info, FALSE);
if (!wth) {
} else {
filename = argv[optind+1];
}
-
+
pdh = wtap_dump_open(filename, out_file_type,
out_frame_type, wtap_snapshot_length(wth), FALSE /* compressed */, &err);
if (pdh == NULL) {
pdh = wtap_dump_open(filename, out_file_type,
out_frame_type, wtap_snapshot_length(wth), FALSE /* compressed */, &err);
if (pdh == NULL) {
-
+
fprintf(stderr, "editcap: Can't open or create %s: %s\n", filename,
wtap_strerror(err));
exit(1);
-
+
}
}
- if ((!selected(count) && !keep_em) ||
- (selected(count) && keep_em)) {
+ if ( ((check_startstop && check_timestamp(wth)) || (!check_startstop && !check_timestamp(wth))) && ((!selected(count) && !keep_em) ||
+ (selected(count) && keep_em)) ) {
if (verbose)
printf("Packet: %u\n", count);
phdr = &snap_phdr;
}
+ if (dup_detect) {
+ buf = wtap_buf_ptr(wth);
+ if (is_duplicate(buf, phdr->caplen)) {
+ if (verbose)
+ printf("Skipping duplicate: %u\n", count);
+ count++;
+ continue;
+ }
+ }
+
if (err_prob > 0.0) {
buf = wtap_buf_ptr(wth);
for (i = 0; i < (int) phdr->caplen; i++) {
if (err_type < ERR_WT_FMT) {
if ((unsigned int)i < phdr->caplen - 2)
- strcpy(&buf[i], "%s");
+ strcpy((char*) &buf[i], "%s");
err_type = ERR_WT_TOTAL;
} else {
err_type -= ERR_WT_FMT;