X-Git-Url: http://git.samba.org/samba.git/?p=obnox%2Fwireshark%2Fwip.git;a=blobdiff_plain;f=editcap.c;h=56a33ae4fd93df1642425417a5fc024e5da88082;hp=264c915138525817caff277cdc7912fb07c4dff0;hb=403cd88b4a708e02131597cc7c9b5f8bfd384b9c;hpb=fa0b7f04bcf48e792f367b4d28b0fb87208597b9 diff --git a/editcap.c b/editcap.c index 264c915138..56a33ae4fd 100644 --- a/editcap.c +++ b/editcap.c @@ -1,174 +1,853 @@ -/* Edit capture files. We can delete records, or simply convert from one - * format to another format (at the moment, only output format is libpcap) +/* Edit capture files. We can delete packets, adjust timestamps, or + * simply convert from one format to another format. + * + * $Id$ * * Originally written by Richard Sharpe. * Improved by Guy Harris. + * Further improved by Richard Sharpe. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include +#include +#include +#include + +/* + * Just make sure we include the prototype for strptime as well + * (needed for glibc 2.2) but make sure we do this only if not + * yet defined. + */ + +#ifndef __USE_XOPEN +# define __USE_XOPEN +#endif + +#include #include + +#ifdef HAVE_UNISTD_H #include +#endif + + + +#ifdef HAVE_SYS_TIME_H #include +#endif + #include "wtap.h" +#ifdef NEED_GETOPT_H +#include "getopt.h" +#endif + +#ifdef _WIN32 +#include /* getpid */ +#endif + +#ifdef NEED_STRPTIME_H +# include "strptime.h" +#endif + +#include "epan/crypt/crypt-md5.h" +#include "epan/plugins.h" +#include "epan/report_err.h" +#include "epan/filesystem.h" +#include + +#include "svnversion.h" + /* * Some globals so we can pass things to various routines */ -int selectfrm[100], max_selected = -1; -static int count = 1; +struct select_item { + + int inclusive; + int first, second; + +}; + + +/* + * 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 */ +/* We should probably make these command-line arguments */ +/* XXX - Should we add a bit-level error? */ +#define ERR_WT_BIT 5 /* Flip a random bit */ +#define ERR_WT_BYTE 5 /* Substitute a random byte */ +#define ERR_WT_ALNUM 5 /* Substitute a random character in [A-Za-z0-9] */ +#define ERR_WT_FMT 2 /* Substitute "%s" */ +#define ERR_WT_AA 1 /* Fill the remainder of the buffer with 0xAA */ +#define ERR_WT_TOTAL (ERR_WT_BIT + ERR_WT_BYTE + ERR_WT_ALNUM + ERR_WT_FMT + ERR_WT_AA) + +#define ALNUM_CHARS "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" +#define ALNUM_LEN (sizeof(ALNUM_CHARS) - 1) + + +struct time_adjustment { + struct timeval tv; + int is_negative; +}; + +#define MAX_SELECTIONS 512 +static struct select_item selectfrm[MAX_SELECTIONS]; +static int max_selected = -1; static int keep_em = 0; -static int out_file_type = WTAP_FILE_PCAP; -static int out_frame_type = -2; /* Leave frame type alone */ +static int out_file_type = WTAP_FILE_PCAP; /* default to "libpcap" */ +static int out_frame_type = -2; /* Leave frame type alone */ +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; + +static int find_dct2000_real_data(guint8 *buf); + +/* Add a selection item, a simple parser for now */ +static gboolean +add_selection(char *sel) +{ + char *locn; + char *next; + + if (++max_selected >= MAX_SELECTIONS) { + /* Let the user know we stopped selecting */ + printf("Out of room for packet selections!\n"); + return(FALSE); + } + + printf("Add_Selected: %s\n", sel); + + if ((locn = strchr(sel, '-')) == NULL) { /* No dash, so a single number? */ + + printf("Not inclusive ..."); + + selectfrm[max_selected].inclusive = 0; + selectfrm[max_selected].first = atoi(sel); + + printf(" %i\n", selectfrm[max_selected].first); + + } + else { + + printf("Inclusive ..."); + + next = locn + 1; + selectfrm[max_selected].inclusive = 1; + selectfrm[max_selected].first = atoi(sel); + selectfrm[max_selected].second = atoi(next); + + printf(" %i, %i\n", selectfrm[max_selected].first, selectfrm[max_selected].second); -/* Was the record selected? */ + } + + return(TRUE); +} -int selected(int recno) +/* Was the packet selected? */ + +static int +selected(int recno) { int i = 0; for (i = 0; i<= max_selected; i++) { - if (recno == selectfrm[i]) return 1; - + if (selectfrm[i].inclusive) { + if (selectfrm[i].first <= recno && selectfrm[i].second >= recno) + return 1; + } + else { + if (recno == selectfrm[i].first) + return 1; + } } return 0; } -/* An argument to the callback routine */ - -typedef struct { - char *filename; - wtap_dumper *pdh; -} callback_arg; +/* is the packet in the selected timeframe */ +static gboolean +check_timestamp(wtap *wth) +{ + struct wtap_pkthdr* pkthdr = wtap_phdr(wth); -/* - *The callback routine that is called for each frame in the input file - */ + return ( pkthdr->ts.secs >= starttime ) && ( pkthdr->ts.secs <= stoptime ); +} static void -edit_callback(u_char *user, const struct wtap_pkthdr *phdr, int offset, - const u_char *buf) +set_time_adjustment(char *optarg) { - callback_arg *argp = (callback_arg *)user; - int err; + char *frac, *end; + long val; + int frac_digits; - if ((!selected(count) && !keep_em) || - (selected(count) && keep_em)) { + if (!optarg) + return; - printf("Record: %u\n", count); - - /* We simply write it, we could do other things, like modify it */ + /* skip leading whitespace */ + while (*optarg == ' ' || *optarg == '\t') { + optarg++; + } - if (!wtap_dump(argp->pdh, phdr, buf, &err)) { + /* check for a negative adjustment */ + if (*optarg == '-') { + time_adj.is_negative = 1; + optarg++; + } - fprintf(stderr, "editpcap: Error writing to %s: %s\n", argp->filename, - wtap_strerror(err)); + /* collect whole number of seconds, if any */ + if (*optarg == '.') { /* only fractional (i.e., .5 is ok) */ + val = 0; + frac = optarg; + } else { + val = strtol(optarg, &frac, 10); + if (frac == NULL || frac == optarg || val == LONG_MIN || val == LONG_MAX) { + fprintf(stderr, "editcap: \"%s\" isn't a valid time adjustment\n", + optarg); + exit(1); + } + if (val < 0) { /* implies '--' since we caught '-' above */ + fprintf(stderr, "editcap: \"%s\" isn't a valid time adjustment\n", + optarg); + exit(1); + } + } + time_adj.tv.tv_sec = val; + + /* now collect the partial seconds, if any */ + if (*frac != '\0') { /* chars left, so get fractional part */ + val = strtol(&(frac[1]), &end, 10); + if (*frac != '.' || end == NULL || end == frac + || val < 0 || val > ONE_MILLION || val == LONG_MIN || val == LONG_MAX) { + fprintf(stderr, "editcap: \"%s\" isn't a valid time adjustment\n", + optarg); exit(1); - } + } + else { + return; /* no fractional digits */ + } + /* adjust fractional portion from fractional to numerator + * e.g., in "1.5" from 5 to 500000 since .5*10^6 = 500000 */ + if (frac && end) { /* both are valid */ + frac_digits = end - frac - 1; /* fractional digit count (remember '.') */ + while(frac_digits < 6) { /* this is frac of 10^6 */ + val *= 10; + frac_digits++; + } } + 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; - count++; + 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; } -void usage() +static void +usage(void) { + fprintf(stderr, "Editcap %s" +#ifdef SVNVERSION + " (" SVNVERSION ")" +#endif + "\n", VERSION); + fprintf(stderr, "Edit and/or translate the format of capture files.\n"); + fprintf(stderr, "See http://www.wireshark.org for more information.\n"); + fprintf(stderr, "\n"); + fprintf(stderr, "Usage: editcap [options] ... [ [-] ... ]\n"); + fprintf(stderr, "\n"); + fprintf(stderr, "A single packet or a range of packets can be selected.\n"); + fprintf(stderr, "\n"); + fprintf(stderr, "Packet selection:\n"); + fprintf(stderr, " -r keep the selected packets, default is to delete them\n"); + fprintf(stderr, " -A 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 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, " -d remove duplicate packets\n"); + fprintf(stderr, "\n"); + fprintf(stderr, "Packet manipulation:\n"); + fprintf(stderr, " -s truncate each packet to max. bytes of data\n"); + fprintf(stderr, " -C chop each packet at the end by bytes\n"); + fprintf(stderr, " -t