X-Git-Url: http://git.samba.org/?a=blobdiff_plain;f=editcap.c;h=cc1a0c9d386f87b002ef616468bfd467e049a4e4;hb=692f0145f45f93b67be2a2ee4067de84f78cc6f7;hp=61ca7771308e913f637d5f11c3c5bb214faafdec;hpb=8ab9c55618a99417b4972f37ab3ee7da58cca0cf;p=metze%2Fwireshark%2Fwip.git diff --git a/editcap.c b/editcap.c index 61ca777130..cc1a0c9d38 100644 --- a/editcap.c +++ b/editcap.c @@ -1,4 +1,5 @@ -/* Edit capture files. We can delete packets, adjust timestamps, or +/* editcap.c + * Edit capture files. We can delete packets, adjust timestamps, or * simply convert from one format to another format. * * Originally written by Richard Sharpe. @@ -7,8 +8,6 @@ * * Copyright 2013, Richard Sharpe * - * $Id$ - * * Wireshark - Network traffic analyzer * By Gerald Combs * Copyright 1998 Gerald Combs @@ -28,7 +27,7 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#include "config.h" +#include #include #include @@ -52,18 +51,19 @@ #include #endif -#ifdef HAVE_SYS_TIME_H -#include +#ifdef HAVE_GETOPT_H +#include #endif -#include "wtap.h" +#include + +#include "epan/etypes.h" -#ifndef HAVE_GETOPT +#ifndef HAVE_GETOPT_LONG #include "wsutil/wsgetopt.h" #endif #ifdef _WIN32 -#include #include #include /* getpid */ #ifdef HAVE_WINSOCK2_H @@ -71,18 +71,23 @@ #endif #endif -#ifdef NEED_STRPTIME_H +#ifndef HAVE_STRPTIME # include "wsutil/strptime.h" #endif -#include +#include #include -#include -#include +#include #include #include - -#include "svnversion.h" +#include +#include +#include +#include +#include +#include +#include +#include #include "ringbuffer.h" /* For RINGBUFFER_MAX_NUM_FILES */ @@ -91,8 +96,8 @@ */ struct select_item { - int inclusive; - int first, second; + gboolean inclusive; + guint first, second; }; /* @@ -100,18 +105,19 @@ struct select_item { */ typedef struct _fd_hash_t { md5_byte_t digest[16]; - guint32 len; - nstime_t time; + guint32 len; + nstime_t frame_time; } fd_hash_t; -#define DEFAULT_DUP_DEPTH 5 /* Used with -d */ -#define MAX_DUP_DEPTH 1000000 /* the maximum window (and actual size of fd_hash[]) for de-duplication */ +#define DEFAULT_DUP_DEPTH 5 /* Used with -d */ +#define MAX_DUP_DEPTH 1000000 /* the maximum window (and actual size of fd_hash[]) for de-duplication */ static fd_hash_t fd_hash[MAX_DUP_DEPTH]; -static int dup_window = DEFAULT_DUP_DEPTH; -static int cur_dup_entry = 0; +static int dup_window = DEFAULT_DUP_DEPTH; +static int cur_dup_entry = 0; + +static int ignored_bytes = 0; /* Used with -I */ -#define ONE_MILLION 1000000 #define ONE_BILLION 1000000000 /* Weights of different errors we can introduce */ @@ -128,7 +134,7 @@ static int cur_dup_entry = 0; #define ALNUM_LEN (sizeof(ALNUM_CHARS) - 1) struct time_adjustment { - struct timeval tv; + nstime_t tv; int is_negative; }; @@ -141,29 +147,34 @@ typedef struct _chop_t { int off_end_neg; } chop_t; -#define MAX_SELECTIONS 512 -static struct select_item selectfrm[MAX_SELECTIONS]; -static int max_selected = -1; -static int keep_em = 0; + +/* Table of user comments */ +GTree *frames_user_comments = NULL; + +#define MAX_SELECTIONS 512 +static struct select_item selectfrm[MAX_SELECTIONS]; +static guint max_selected = 0; +static int keep_em = 0; #ifdef PCAP_NG_DEFAULT -static int out_file_type_subtype = WTAP_FILE_TYPE_SUBTYPE_PCAPNG; /* default to pcapng */ +static int out_file_type_subtype = WTAP_FILE_TYPE_SUBTYPE_PCAPNG; /* default to pcapng */ #else -static int out_file_type_subtype = WTAP_FILE_TYPE_SUBTYPE_PCAP; /* default to pcap */ +static int out_file_type_subtype = WTAP_FILE_TYPE_SUBTYPE_PCAP; /* default to pcap */ #endif -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 nstime_t relative_time_window = {0, 0}; /* de-dup time window */ -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 gboolean dup_detect_by_time = FALSE; - -static int do_strict_time_adjustment = FALSE; -static struct time_adjustment strict_time_adj = {{0, 0}, 0}; /* strict time adjustment */ -static nstime_t previous_time = {0, 0}; /* previous time */ +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 nstime_t relative_time_window = {0, 0}; /* de-dup time window */ +static double err_prob = 0.0; +static time_t starttime = 0; +static time_t stoptime = 0; +static gboolean check_startstop = FALSE; +static gboolean rem_vlan = FALSE; +static gboolean dup_detect = FALSE; +static gboolean dup_detect_by_time = FALSE; + +static int do_strict_time_adjustment = FALSE; +static struct time_adjustment strict_time_adj = {{0, 0}, 0}; /* strict time adjustment */ +static nstime_t previous_time = {0, 0}; /* previous time */ static int find_dct2000_real_data(guint8 *buf); static void handle_chopping(chop_t chop, struct wtap_pkthdr *out_phdr, @@ -174,17 +185,9 @@ static gchar * abs_time_to_str_with_sec_resolution(const nstime_t *abs_time) { struct tm *tmp; - gchar *buf = (gchar *)g_malloc(16); - -#if (defined _WIN32) && (_MSC_VER < 1500) - /* calling localtime() on MSVC 2005 with huge values causes it to crash */ - /* XXX - find the exact value that still does work */ - /* XXX - using _USE_32BIT_TIME_T might be another way to circumvent this problem */ - if (abs_time->secs > 2000000000) - tmp = NULL; - else -#endif - tmp = localtime(&abs_time->secs); + gchar *buf = (gchar *)g_malloc(16); + + tmp = localtime(&abs_time->secs); if (tmp) { g_snprintf(buf, 16, "%d%02d%02d%02d%02d%02d", @@ -201,18 +204,21 @@ abs_time_to_str_with_sec_resolution(const nstime_t *abs_time) return buf; } -static gchar* -fileset_get_filename_by_pattern(guint idx, const nstime_t *time_val, +static gchar * +fileset_get_filename_by_pattern(guint idx, const struct wtap_pkthdr *phdr, gchar *fprefix, gchar *fsuffix) { - gchar filenum[5+1]; + gchar filenum[5+1]; gchar *timestr; gchar *abs_str; - timestr = abs_time_to_str_with_sec_resolution(time_val); g_snprintf(filenum, sizeof(filenum), "%05u", idx % RINGBUFFER_MAX_NUM_FILES); - abs_str = g_strconcat(fprefix, "_", filenum, "_", timestr, fsuffix, NULL); - g_free(timestr); + if (phdr->presence_flags & WTAP_HAS_TS) { + timestr = abs_time_to_str_with_sec_resolution(&phdr->ts); + abs_str = g_strconcat(fprefix, "_", filenum, "_", timestr, fsuffix, NULL); + g_free(timestr); + } else + abs_str = g_strconcat(fprefix, "_", filenum, fsuffix, NULL); return abs_str; } @@ -258,12 +264,12 @@ fileset_extract_prefix_suffix(const char *fname, gchar **fprefix, gchar **fsuffi /* Add a selection item, a simple parser for now */ static gboolean -add_selection(char *sel) +add_selection(char *sel, guint* max_selection) { char *locn; char *next; - if (++max_selected >= MAX_SELECTIONS) { + if (max_selected >= MAX_SELECTIONS) { /* Let the user know we stopped selecting */ fprintf(stderr, "Out of room for packet selections!\n"); return(FALSE); @@ -276,36 +282,47 @@ add_selection(char *sel) if (verbose) fprintf(stderr, "Not inclusive ..."); - selectfrm[max_selected].inclusive = 0; - selectfrm[max_selected].first = atoi(sel); + selectfrm[max_selected].inclusive = FALSE; + selectfrm[max_selected].first = (guint)strtoul(sel, NULL, 10); + if (selectfrm[max_selected].first > *max_selection) + *max_selection = selectfrm[max_selected].first; if (verbose) - fprintf(stderr, " %i\n", selectfrm[max_selected].first); + fprintf(stderr, " %u\n", selectfrm[max_selected].first); } else { if (verbose) fprintf(stderr, "Inclusive ..."); next = locn + 1; - selectfrm[max_selected].inclusive = 1; - selectfrm[max_selected].first = atoi(sel); - selectfrm[max_selected].second = atoi(next); + selectfrm[max_selected].inclusive = TRUE; + selectfrm[max_selected].first = (guint)strtoul(sel, NULL, 10); + selectfrm[max_selected].second = (guint)strtoul(next, NULL, 10); + + if (selectfrm[max_selected].second == 0) + { + /* Not a valid number, presume all */ + selectfrm[max_selected].second = *max_selection = G_MAXUINT; + } + else if (selectfrm[max_selected].second > *max_selection) + *max_selection = selectfrm[max_selected].second; if (verbose) - fprintf(stderr, " %i, %i\n", selectfrm[max_selected].first, + fprintf(stderr, " %u, %u\n", selectfrm[max_selected].first, selectfrm[max_selected].second); } + max_selected++; return(TRUE); } /* Was the packet selected? */ static int -selected(int recno) +selected(guint recno) { - int i; + guint i; - for (i = 0; i <= max_selected; i++) { + for (i = 0; i < max_selected; i++) { if (selectfrm[i].inclusive) { if (selectfrm[i].first <= recno && selectfrm[i].second >= recno) return 1; @@ -318,21 +335,12 @@ selected(int recno) return 0; } -/* is the packet in the selected timeframe */ -static gboolean -check_timestamp(wtap *wth) -{ - struct wtap_pkthdr* pkthdr = wtap_phdr(wth); - - return (pkthdr->ts.secs >= starttime) && (pkthdr->ts.secs < stoptime); -} - static void set_time_adjustment(char *optarg_str_p) { - char *frac, *end; - long val; - size_t frac_digits; + char *frac, *end; + long val; + size_t frac_digits; if (!optarg_str_p) return; @@ -365,18 +373,18 @@ set_time_adjustment(char *optarg_str_p) exit(1); } } - time_adj.tv.tv_sec = val; + time_adj.tv.secs = val; /* now collect the partial seconds, if any */ if (*frac != '\0') { /* chars left, so get fractional part */ val = strtol(&(frac[1]), &end, 10); - /* if more than 6 fractional digits truncate to 6 */ - if ((end - &(frac[1])) > 6) { - frac[7] = 't'; /* 't' for truncate */ + /* if more than 9 fractional digits truncate to 9 */ + if ((end - &(frac[1])) > 9) { + frac[10] = 't'; /* 't' for truncate */ val = strtol(&(frac[1]), &end, 10); } if (*frac != '.' || end == NULL || end == frac || val < 0 - || val > ONE_MILLION || val == LONG_MIN || val == LONG_MAX) { + || val > ONE_BILLION || val == LONG_MIN || val == LONG_MAX) { fprintf(stderr, "editcap: \"%s\" isn't a valid time adjustment\n", optarg_str_p); exit(1); @@ -386,23 +394,22 @@ set_time_adjustment(char *optarg_str_p) } /* 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++; - } + * e.g., in "1.5" from 5 to 500000000 since .5*10^9 = 500000000 */ + frac_digits = end - frac - 1; /* fractional digit count (remember '.') */ + while(frac_digits < 9) { /* this is frac of 10^9 */ + val *= 10; + frac_digits++; } - time_adj.tv.tv_usec = (int)val; + + time_adj.tv.nsecs = (int)val; } static void set_strict_time_adj(char *optarg_str_p) { - char *frac, *end; - long val; - size_t frac_digits; + char *frac, *end; + long val; + size_t frac_digits; if (!optarg_str_p) return; @@ -439,18 +446,18 @@ set_strict_time_adj(char *optarg_str_p) exit(1); } } - strict_time_adj.tv.tv_sec = val; + strict_time_adj.tv.secs = val; /* now collect the partial seconds, if any */ if (*frac != '\0') { /* chars left, so get fractional part */ val = strtol(&(frac[1]), &end, 10); - /* if more than 6 fractional digits truncate to 6 */ - if ((end - &(frac[1])) > 6) { - frac[7] = 't'; /* 't' for truncate */ + /* if more than 9 fractional digits truncate to 9 */ + if ((end - &(frac[1])) > 9) { + frac[10] = 't'; /* 't' for truncate */ val = strtol(&(frac[1]), &end, 10); } if (*frac != '.' || end == NULL || end == frac || val < 0 - || val > ONE_MILLION || val == LONG_MIN || val == LONG_MAX) { + || val > ONE_BILLION || val == LONG_MIN || val == LONG_MAX) { fprintf(stderr, "editcap: \"%s\" isn't a valid time adjustment\n", optarg_str_p); exit(1); @@ -460,23 +467,22 @@ set_strict_time_adj(char *optarg_str_p) } /* 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++; - } + * e.g., in "1.5" from 5 to 500000000 since .5*10^9 = 500000000 */ + frac_digits = end - frac - 1; /* fractional digit count (remember '.') */ + while(frac_digits < 9) { /* this is frac of 10^9 */ + val *= 10; + frac_digits++; } - strict_time_adj.tv.tv_usec = (int)val; + + strict_time_adj.tv.nsecs = (int)val; } static void set_rel_time(char *optarg_str_p) { - char *frac, *end; - long val; - size_t frac_digits; + char *frac, *end; + long val; + size_t frac_digits; if (!optarg_str_p) return; @@ -529,28 +535,62 @@ set_rel_time(char *optarg_str_p) /* adjust fractional portion from fractional to numerator * e.g., in "1.5" from 5 to 500000000 since .5*10^9 = 500000000 */ - if (frac && end) { /* both are valid */ - frac_digits = end - frac - 1; /* fractional digit count (remember '.') */ - while(frac_digits < 9) { /* this is frac of 10^9 */ - val *= 10; - frac_digits++; - } + frac_digits = end - frac - 1; /* fractional digit count (remember '.') */ + while(frac_digits < 9) { /* this is frac of 10^9 */ + val *= 10; + frac_digits++; } + relative_time_window.nsecs = (int)val; } +#define LINUX_SLL_OFFSETP 14 +#define VLAN_SIZE 4 +static void +sll_remove_vlan_info(guint8* fd, guint32* len) { + if (pntoh16(fd + LINUX_SLL_OFFSETP) == ETHERTYPE_VLAN) { + int rest_len; + /* point to start of vlan */ + fd = fd + LINUX_SLL_OFFSETP; + /* bytes to read after vlan info */ + rest_len = *len - (LINUX_SLL_OFFSETP + VLAN_SIZE); + /* remove vlan info from packet */ + memmove(fd, fd + VLAN_SIZE, rest_len); + *len -= 4; + } +} + +static void +remove_vlan_info(const struct wtap_pkthdr *phdr, guint8* fd, guint32* len) { + switch (phdr->pkt_encap) { + case WTAP_ENCAP_SLL: + sll_remove_vlan_info(fd, len); + break; + default: + /* no support for current pkt_encap */ + break; + } +} + static gboolean is_duplicate(guint8* fd, guint32 len) { int i; md5_state_t ms; + /*Hint to ignore some bytes at the start of the frame for the digest calculation(-I option) */ + guint32 new_len; + guint8 *new_fd; + + new_fd = &fd[ignored_bytes]; + new_len = len - (ignored_bytes); + cur_dup_entry++; if (cur_dup_entry >= dup_window) cur_dup_entry = 0; /* Calculate our digest */ md5_init(&ms); - md5_append(&ms, fd, len); + md5_append(&ms, new_fd, new_len); md5_finish(&ms, fd_hash[cur_dup_entry].digest); fd_hash[cur_dup_entry].len = len; @@ -574,18 +614,25 @@ is_duplicate_rel_time(guint8* fd, guint32 len, const nstime_t *current) { int i; md5_state_t ms; + /*Hint to ignore some bytes at the start of the frame for the digest calculation(-I option) */ + guint32 new_len; + guint8 *new_fd; + + new_fd = &fd[ignored_bytes]; + new_len = len - (ignored_bytes); + cur_dup_entry++; if (cur_dup_entry >= dup_window) cur_dup_entry = 0; /* Calculate our digest */ md5_init(&ms); - md5_append(&ms, fd, len); + md5_append(&ms, new_fd, new_len); md5_finish(&ms, fd_hash[cur_dup_entry].digest); fd_hash[cur_dup_entry].len = len; - fd_hash[cur_dup_entry].time.secs = current->secs; - fd_hash[cur_dup_entry].time.nsecs = current->nsecs; + fd_hash[cur_dup_entry].frame_time.secs = current->secs; + fd_hash[cur_dup_entry].frame_time.nsecs = current->nsecs; /* * Look for relative time related duplicates. @@ -623,7 +670,7 @@ is_duplicate_rel_time(guint8* fd, guint32 len, const nstime_t *current) { break; } - if (nstime_is_unset(&(fd_hash[i].time))) { + if (nstime_is_unset(&(fd_hash[i].frame_time))) { /* * We've decremented to an unused fd_hash[] entry. * Check no more! @@ -631,7 +678,7 @@ is_duplicate_rel_time(guint8* fd, guint32 len, const nstime_t *current) { break; } - nstime_delta(&delta, current, &fd_hash[i].time); + nstime_delta(&delta, current, &fd_hash[i].frame_time); if (delta.secs < 0 || delta.nsecs < 0) { /* @@ -674,22 +721,8 @@ is_duplicate_rel_time(guint8* fd, guint32 len, const nstime_t *current) { } static void -usage(gboolean is_error) +print_usage(FILE *output) { - FILE *output; - - if (!is_error) - output = stdout; - else - output = stderr; - - fprintf(output, "Editcap %s" -#ifdef SVNVERSION - " (" SVNVERSION " from " SVNPATH ")" -#endif - "\n", VERSION); - fprintf(output, "Edit and/or translate the format of capture files.\n"); - fprintf(output, "See http://www.wireshark.org for more information.\n"); fprintf(output, "\n"); fprintf(output, "Usage: editcap [options] ... [ [-] ... ]\n"); fprintf(output, "\n"); @@ -704,8 +737,9 @@ usage(gboolean is_error) fprintf(output, " given time (format as YYYY-MM-DD hh:mm:ss).\n"); fprintf(output, "\n"); fprintf(output, "Duplicate packet removal:\n"); + fprintf(output, " --novlan remove vlan info from packets before checking for duplicates.\n"); fprintf(output, " -d remove packet if duplicate (window == %d).\n", DEFAULT_DUP_DEPTH); - fprintf(output, " -D remove packet if duplicate; configurable \n"); + fprintf(output, " -D remove packet if duplicate; configurable .\n"); fprintf(output, " Valid values are 0 to %d.\n", MAX_DUP_DEPTH); fprintf(output, " NOTE: A of 0 with -v (verbose option) is\n"); fprintf(output, " useful to print MD5 hashes.\n"); @@ -713,6 +747,15 @@ usage(gboolean is_error) fprintf(output, " LESS THAN prior to current packet.\n"); fprintf(output, " A is specified in relative seconds\n"); fprintf(output, " (e.g. 0.000001).\n"); + fprintf(output, " -a : Add or replace comment for given frame number\n"); + fprintf(output, "\n"); + fprintf(output, " -I ignore the specified bytes at the beginning of\n"); + fprintf(output, " the frame during MD5 hash calculation.\n"); + fprintf(output, " Useful to remove duplicated packets taken on\n"); + fprintf(output, " several routers (different mac addresses for\n"); + fprintf(output, " example).\n"); + fprintf(output, " e.g. -I 26 in case of Ether/IP/ will ignore\n"); + fprintf(output, " ether(14) and IP header(20 - 4(src ip) - 4(dst ip)).\n"); fprintf(output, "\n"); fprintf(output, " NOTE: The use of the 'Duplicate packet removal' options with\n"); fprintf(output, " other editcap options except -v may not always work as expected.\n"); @@ -730,8 +773,9 @@ usage(gboolean is_error) fprintf(output, " this option more than once, allowing up to 2 chopping\n"); fprintf(output, " regions within a packet provided that at least 1\n"); fprintf(output, " choplen is positive and at least 1 is negative.\n"); - fprintf(output, " -L adjust the frame length when chopping and/or snapping\n"); - fprintf(output, " -t