X-Git-Url: http://git.samba.org/?a=blobdiff_plain;f=editcap.c;h=ba924ae33ceafa18633efe1d1e29b0b2208ea151;hb=9180c27c5e47ce4fc8f92113c9e51a5b7294da9b;hp=6919eb992057db4061df01dd5f8cead6ede6faa0;hpb=665b95d15468761a577420593c017824d57f16c1;p=metze%2Fwireshark%2Fwip.git diff --git a/editcap.c b/editcap.c index 6919eb9920..ba924ae33c 100644 --- a/editcap.c +++ b/editcap.c @@ -1,16 +1,32 @@ /* 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. + * + * Copyright 2013, Richard Sharpe + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif +#include #include #include @@ -34,19 +50,22 @@ #include #endif +#ifdef HAVE_GETOPT_H +#include +#endif - -#ifdef HAVE_SYS_TIME_H -#include +#ifdef HAVE_LIBZ +#include /* to get the libz version number */ #endif #include "wtap.h" -#ifndef HAVE_GETOPT +#ifndef HAVE_GETOPT_LONG #include "wsutil/wsgetopt.h" #endif #ifdef _WIN32 +#include #include #include /* getpid */ #ifdef HAVE_WINSOCK2_H @@ -54,110 +73,119 @@ #endif #endif -#ifdef NEED_STRPTIME_H +#ifndef HAVE_STRPTIME # include "wsutil/strptime.h" #endif -#include "epan/crypt/md5.h" -#include "epan/plugins.h" -#include "epan/report_err.h" -#include "epan/filesystem.h" +#include +#include +#include +#include #include -#include "epan/nstime.h" +#include +#include +#include +#include -#include "svnversion.h" +#include "ringbuffer.h" /* For RINGBUFFER_MAX_NUM_FILES */ /* * Some globals so we can pass things to various routines */ struct select_item { - - int inclusive; - int first, second; - + int inclusive; + int first, second; }; - /* * Duplicate frame detection */ typedef struct _fd_hash_t { - md5_byte_t digest[16]; - guint32 len; - nstime_t time; + md5_byte_t digest[16]; + 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; -fd_hash_t fd_hash[MAX_DUP_DEPTH]; -int dup_window = DEFAULT_DUP_DEPTH; -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 */ /* 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) +#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; + nstime_t tv; + int is_negative; }; +typedef struct _chop_t { + int len_begin; + int off_begin_pos; + int off_begin_neg; + int len_end; + int off_end_pos; + int off_end_neg; +} chop_t; + + +/* Table of user comments */ +GTree *frames_user_comments = NULL; + #define MAX_SELECTIONS 512 -static struct select_item selectfrm[MAX_SELECTIONS]; -static int max_selected = -1; -static int keep_em = 0; +static struct select_item selectfrm[MAX_SELECTIONS]; +static int max_selected = -1; +static int keep_em = 0; #ifdef PCAP_NG_DEFAULT -static int out_file_type = WTAP_FILE_PCAPNG; /* default to pcapng */ +static int out_file_type_subtype = WTAP_FILE_TYPE_SUBTYPE_PCAPNG; /* default to pcapng */ #else -static int out_file_type = WTAP_FILE_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 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, + const struct wtap_pkthdr *in_phdr, guint8 **buf, + gboolean adjlen); static gchar * -abs_time_to_str_with_sec_resolution(const struct wtap_nstime *abs_time) +abs_time_to_str_with_sec_resolution(const nstime_t *abs_time) { struct tm *tmp; - gchar *buf = g_malloc(16); - -#ifdef _MSC_VER - /* 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 + gchar *buf = (gchar *)g_malloc(16); + tmp = localtime(&abs_time->secs); + if (tmp) { g_snprintf(buf, 16, "%d%02d%02d%02d%02d%02d", tmp->tm_year + 1900, @@ -166,24 +194,28 @@ abs_time_to_str_with_sec_resolution(const struct wtap_nstime *abs_time) tmp->tm_hour, tmp->tm_min, tmp->tm_sec); - } else + } else { buf[0] = '\0'; + } return buf; } -static gchar* -fileset_get_filename_by_pattern(guint idx, const struct wtap_nstime *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); - abs_str = g_strconcat(fprefix, "_", filenum, "_", timestr, fsuffix, NULL); - g_free(timestr); + g_snprintf(filenum, sizeof(filenum), "%05u", idx % RINGBUFFER_MAX_NUM_FILES); + 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; } @@ -196,32 +228,32 @@ fileset_extract_prefix_suffix(const char *fname, gchar **fprefix, gchar **fsuffi save_file = g_strdup(fname); if (save_file == NULL) { - fprintf(stderr, "editcap: Out of memory\n"); - return FALSE; + fprintf(stderr, "editcap: Out of memory\n"); + return FALSE; } last_pathsep = strrchr(save_file, G_DIR_SEPARATOR); pfx = strrchr(save_file,'.'); if (pfx != NULL && (last_pathsep == NULL || pfx > last_pathsep)) { - /* The pathname has a "." in it, and it's in the last component - of the pathname (because there is either only one component, - i.e. last_pathsep is null as there are no path separators, - or the "." is after the path separator before the last - component. - - Treat it as a separator between the rest of the file name and - the file name suffix, and arrange that the names given to the - ring buffer files have the specified suffix, i.e. put the - changing part of the name *before* the suffix. */ - pfx[0] = '\0'; - *fprefix = g_strdup(save_file); - pfx[0] = '.'; /* restore capfile_name */ - *fsuffix = g_strdup(pfx); + /* The pathname has a "." in it, and it's in the last component + * of the pathname (because there is either only one component, + * i.e. last_pathsep is null as there are no path separators, + * or the "." is after the path separator before the last + * component. + + * Treat it as a separator between the rest of the file name and + * the file name suffix, and arrange that the names given to the + * ring buffer files have the specified suffix, i.e. put the + * changing part of the name *before* the suffix. */ + pfx[0] = '\0'; + *fprefix = g_strdup(save_file); + pfx[0] = '.'; /* restore capfile_name */ + *fsuffix = g_strdup(pfx); } else { - /* Either there's no "." in the pathname, or it's in a directory - component, so the last component has no suffix. */ - *fprefix = g_strdup(save_file); - *fsuffix = NULL; + /* Either there's no "." in the pathname, or it's in a directory + * component, so the last component has no suffix. */ + *fprefix = g_strdup(save_file); + *fsuffix = NULL; } g_free(save_file); return TRUE; @@ -231,41 +263,42 @@ fileset_extract_prefix_suffix(const char *fname, gchar **fprefix, gchar **fsuffi 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 ..."); + char *locn; + char *next; - selectfrm[max_selected].inclusive = 0; - selectfrm[max_selected].first = atoi(sel); + if (++max_selected >= MAX_SELECTIONS) { + /* Let the user know we stopped selecting */ + fprintf(stderr, "Out of room for packet selections!\n"); + return(FALSE); + } - printf(" %i\n", selectfrm[max_selected].first); + if (verbose) + fprintf(stderr, "Add_Selected: %s\n", sel); - } - else { + if ((locn = strchr(sel, '-')) == NULL) { /* No dash, so a single number? */ + if (verbose) + fprintf(stderr, "Not inclusive ..."); - printf("Inclusive ..."); + selectfrm[max_selected].inclusive = 0; + selectfrm[max_selected].first = atoi(sel); - next = locn + 1; - selectfrm[max_selected].inclusive = 1; - selectfrm[max_selected].first = atoi(sel); - selectfrm[max_selected].second = atoi(next); + if (verbose) + fprintf(stderr, " %i\n", selectfrm[max_selected].first); + } else { + if (verbose) + fprintf(stderr, "Inclusive ..."); - printf(" %i, %i\n", selectfrm[max_selected].first, selectfrm[max_selected].second); + next = locn + 1; + selectfrm[max_selected].inclusive = 1; + selectfrm[max_selected].first = atoi(sel); + selectfrm[max_selected].second = atoi(next); - } + if (verbose) + fprintf(stderr, " %i, %i\n", selectfrm[max_selected].first, + selectfrm[max_selected].second); + } - return(TRUE); + return(TRUE); } /* Was the packet selected? */ @@ -273,469 +306,471 @@ add_selection(char *sel) static int selected(int recno) { - int i = 0; - - for (i = 0; i<= max_selected; i++) { + int i; - if (selectfrm[i].inclusive) { - if (selectfrm[i].first <= recno && selectfrm[i].second >= recno) - return 1; - } - else { - if (recno == selectfrm[i].first) - return 1; + for (i = 0; i <= max_selected; i++) { + 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; - -} - -/* 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; - - if (!optarg_str_p) - return; - - /* skip leading whitespace */ - while (*optarg_str_p == ' ' || *optarg_str_p == '\t') { - optarg_str_p++; - } - - /* check for a negative adjustment */ - if (*optarg_str_p == '-') { - time_adj.is_negative = 1; - optarg_str_p++; - } - - /* collect whole number of seconds, if any */ - if (*optarg_str_p == '.') { /* only fractional (i.e., .5 is ok) */ - val = 0; - frac = optarg_str_p; - } else { - val = strtol(optarg_str_p, &frac, 10); - if (frac == NULL || frac == optarg_str_p || val == LONG_MIN || val == LONG_MAX) { - fprintf(stderr, "editcap: \"%s\" isn't a valid time adjustment\n", - optarg_str_p); - exit(1); - } - if (val < 0) { /* implies '--' since we caught '-' above */ - fprintf(stderr, "editcap: \"%s\" isn't a valid time adjustment\n", - optarg_str_p); - 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 more than 6 fractional digits truncate to 6 */ - if((end - &(frac[1])) > 6) { - frac[7] = 't'; /* 't' for truncate */ - val = strtol(&(frac[1]), &end, 10); + char *frac, *end; + long val; + size_t frac_digits; + + if (!optarg_str_p) + return; + + /* skip leading whitespace */ + while (*optarg_str_p == ' ' || *optarg_str_p == '\t') + optarg_str_p++; + + /* check for a negative adjustment */ + if (*optarg_str_p == '-') { + time_adj.is_negative = 1; + optarg_str_p++; + } + + /* collect whole number of seconds, if any */ + if (*optarg_str_p == '.') { /* only fractional (i.e., .5 is ok) */ + val = 0; + frac = optarg_str_p; + } else { + val = strtol(optarg_str_p, &frac, 10); + if (frac == NULL || frac == optarg_str_p + || val == LONG_MIN || val == LONG_MAX) { + fprintf(stderr, "editcap: \"%s\" isn't a valid time adjustment\n", + optarg_str_p); + exit(1); + } + if (val < 0) { /* implies '--' since we caught '-' above */ + fprintf(stderr, "editcap: \"%s\" isn't a valid time adjustment\n", + optarg_str_p); + exit(1); + } } - 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_str_p); - exit(1); + 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 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_BILLION || val == LONG_MIN || val == LONG_MAX) { + fprintf(stderr, "editcap: \"%s\" isn't a valid time adjustment\n", + optarg_str_p); + exit(1); + } + } else { + return; /* no fractional digits */ } - } - 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++; + + /* 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++; + } } - } - time_adj.tv.tv_usec = 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; - - if (!optarg_str_p) - return; - - /* skip leading whitespace */ - while (*optarg_str_p == ' ' || *optarg_str_p == '\t') { - optarg_str_p++; - } - - /* - * check for a negative adjustment - * A negative strict adjustment value is a flag - * to adjust all frames by the specifed delta time. - */ - if (*optarg_str_p == '-') { - strict_time_adj.is_negative = 1; - optarg_str_p++; - } - - /* collect whole number of seconds, if any */ - if (*optarg_str_p == '.') { /* only fractional (i.e., .5 is ok) */ - val = 0; - frac = optarg_str_p; - } else { - val = strtol(optarg_str_p, &frac, 10); - if (frac == NULL || frac == optarg_str_p || val == LONG_MIN || val == LONG_MAX) { - fprintf(stderr, "editcap: \"%s\" isn't a valid time adjustment\n", - optarg_str_p); - exit(1); - } - if (val < 0) { /* implies '--' since we caught '-' above */ - fprintf(stderr, "editcap: \"%s\" isn't a valid time adjustment\n", - optarg_str_p); - exit(1); - } - } - strict_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 more than 6 fractional digits truncate to 6 */ - if((end - &(frac[1])) > 6) { - frac[7] = 't'; /* 't' for truncate */ - val = strtol(&(frac[1]), &end, 10); + char *frac, *end; + long val; + size_t frac_digits; + + if (!optarg_str_p) + return; + + /* skip leading whitespace */ + while (*optarg_str_p == ' ' || *optarg_str_p == '\t') + optarg_str_p++; + + /* + * check for a negative adjustment + * A negative strict adjustment value is a flag + * to adjust all frames by the specifed delta time. + */ + if (*optarg_str_p == '-') { + strict_time_adj.is_negative = 1; + optarg_str_p++; } - 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_str_p); - exit(1); + + /* collect whole number of seconds, if any */ + if (*optarg_str_p == '.') { /* only fractional (i.e., .5 is ok) */ + val = 0; + frac = optarg_str_p; + } else { + val = strtol(optarg_str_p, &frac, 10); + if (frac == NULL || frac == optarg_str_p + || val == LONG_MIN || val == LONG_MAX) { + fprintf(stderr, "editcap: \"%s\" isn't a valid time adjustment\n", + optarg_str_p); + exit(1); + } + if (val < 0) { /* implies '--' since we caught '-' above */ + fprintf(stderr, "editcap: \"%s\" isn't a valid time adjustment\n", + optarg_str_p); + 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++; + 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 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_BILLION || val == LONG_MIN || val == LONG_MAX) { + fprintf(stderr, "editcap: \"%s\" isn't a valid time adjustment\n", + optarg_str_p); + exit(1); + } + } else { + return; /* no fractional digits */ } - } - strict_time_adj.tv.tv_usec = val; + + /* 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++; + } + } + 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; - - if (!optarg_str_p) - return; - - /* skip leading whitespace */ - while (*optarg_str_p == ' ' || *optarg_str_p == '\t') { - optarg_str_p++; - } - - /* ignore negative adjustment */ - if (*optarg_str_p == '-') { - optarg_str_p++; - } - - /* collect whole number of seconds, if any */ - if (*optarg_str_p == '.') { /* only fractional (i.e., .5 is ok) */ - val = 0; - frac = optarg_str_p; - } else { - val = strtol(optarg_str_p, &frac, 10); - if (frac == NULL || frac == optarg_str_p || val == LONG_MIN || val == LONG_MAX) { - fprintf(stderr, "1: editcap: \"%s\" isn't a valid rel time value\n", - optarg_str_p); - exit(1); - } - if (val < 0) { /* implies '--' since we caught '-' above */ - fprintf(stderr, "2: editcap: \"%s\" isn't a valid rel time value\n", - optarg_str_p); - exit(1); - } - } - relative_time_window.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 9 fractional digits truncate to 9 */ - if((end - &(frac[1])) > 9) { - frac[10] = 't'; /* 't' for truncate */ - val = strtol(&(frac[1]), &end, 10); + char *frac, *end; + long val; + size_t frac_digits; + + if (!optarg_str_p) + return; + + /* skip leading whitespace */ + while (*optarg_str_p == ' ' || *optarg_str_p == '\t') + optarg_str_p++; + + /* ignore negative adjustment */ + if (*optarg_str_p == '-') + optarg_str_p++; + + /* collect whole number of seconds, if any */ + if (*optarg_str_p == '.') { /* only fractional (i.e., .5 is ok) */ + val = 0; + frac = optarg_str_p; + } else { + val = strtol(optarg_str_p, &frac, 10); + if (frac == NULL || frac == optarg_str_p + || val == LONG_MIN || val == LONG_MAX) { + fprintf(stderr, "1: editcap: \"%s\" isn't a valid rel time value\n", + optarg_str_p); + exit(1); + } + if (val < 0) { /* implies '--' since we caught '-' above */ + fprintf(stderr, "2: editcap: \"%s\" isn't a valid rel time value\n", + optarg_str_p); + exit(1); + } } - if (*frac != '.' || end == NULL || end == frac - || val < 0 || val > ONE_BILLION || val == LONG_MIN || val == LONG_MAX) { - fprintf(stderr, "3: editcap: \"%s\" isn't a valid rel time value\n", - optarg_str_p); - exit(1); + relative_time_window.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 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_BILLION || val == LONG_MIN || val == LONG_MAX) { + fprintf(stderr, "3: editcap: \"%s\" isn't a valid rel time value\n", + optarg_str_p); + exit(1); + } + } else { + return; /* no fractional digits */ } - } - else { - return; /* no fractional digits */ - } - - /* 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++; + + /* 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++; + } } - } - relative_time_window.nsecs = val; + relative_time_window.nsecs = (int)val; } static gboolean is_duplicate(guint8* fd, guint32 len) { - int i; - md5_state_t ms; + int i; + md5_state_t ms; - cur_dup_entry++; - if (cur_dup_entry >= dup_window) - cur_dup_entry = 0; + /*Hint to ignore some bytes at the start of the frame for the digest calculation(-I option) */ + guint32 new_len; + guint8 *new_fd; - /* Calculate our digest */ - md5_init(&ms); - md5_append(&ms, fd, len); - md5_finish(&ms, fd_hash[cur_dup_entry].digest); + new_fd = &fd[ignored_bytes]; + new_len = len - (ignored_bytes); - fd_hash[cur_dup_entry].len = len; + cur_dup_entry++; + if (cur_dup_entry >= dup_window) + cur_dup_entry = 0; - /* Look for duplicates */ - for (i = 0; i < dup_window; i++) { - if (i == cur_dup_entry) - continue; + /* Calculate our digest */ + md5_init(&ms); + md5_append(&ms, new_fd, new_len); + md5_finish(&ms, fd_hash[cur_dup_entry].digest); - if (fd_hash[i].len == fd_hash[cur_dup_entry].len && - memcmp(fd_hash[i].digest, fd_hash[cur_dup_entry].digest, 16) == 0) { - return TRUE; + fd_hash[cur_dup_entry].len = len; + + /* Look for duplicates */ + for (i = 0; i < dup_window; i++) { + if (i == cur_dup_entry) + continue; + + if (fd_hash[i].len == fd_hash[cur_dup_entry].len + && memcmp(fd_hash[i].digest, fd_hash[cur_dup_entry].digest, 16) == 0) { + return TRUE; + } } - } - return FALSE; + return FALSE; } static gboolean is_duplicate_rel_time(guint8* fd, guint32 len, const nstime_t *current) { - int i; - md5_state_t ms; - - 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_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; - - /* - * Look for relative time related duplicates. - * This is hopefully a reasonably efficient mechanism for - * finding duplicates by rel time in the fd_hash[] cache. - * We check starting from the most recently added hash - * entries and work backwards towards older packets. - * This approach allows the dup test to be terminated - * when the relative time of a cached entry is found to - * be beyond the dup time window. - * - * Of course this assumes that the input trace file is - * "well-formed" in the sense that the packet timestamps are - * in strict chronologically increasing order (which is NOT - * always the case!!). - * - * The fd_hash[] table was deliberatly created large (1,000,000). - * Looking for time related duplicates in large trace files with - * non-fractional dup time window values can potentially take - * a long time to complete. - */ - - for (i = cur_dup_entry - 1;; i--) { - nstime_t delta; - int cmp; - - if (i < 0) { - i = dup_window - 1; - } + 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, 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].frame_time.secs = current->secs; + fd_hash[cur_dup_entry].frame_time.nsecs = current->nsecs; + + /* + * Look for relative time related duplicates. + * This is hopefully a reasonably efficient mechanism for + * finding duplicates by rel time in the fd_hash[] cache. + * We check starting from the most recently added hash + * entries and work backwards towards older packets. + * This approach allows the dup test to be terminated + * when the relative time of a cached entry is found to + * be beyond the dup time window. + * + * Of course this assumes that the input trace file is + * "well-formed" in the sense that the packet timestamps are + * in strict chronologically increasing order (which is NOT + * always the case!!). + * + * The fd_hash[] table was deliberately created large (1,000,000). + * Looking for time related duplicates in large trace files with + * non-fractional dup time window values can potentially take + * a long time to complete. + */ + + for (i = cur_dup_entry - 1;; i--) { + nstime_t delta; + int cmp; + + if (i < 0) + i = dup_window - 1; + + if (i == cur_dup_entry) { + /* + * We've decremented back to where we started. + * Check no more! + */ + break; + } - if (i == cur_dup_entry) { - /* - * We've decremented back to where we started. - * Check no more! - */ - break; - } + if (nstime_is_unset(&(fd_hash[i].frame_time))) { + /* + * We've decremented to an unused fd_hash[] entry. + * Check no more! + */ + break; + } - if (nstime_is_unset(&(fd_hash[i].time))) { - /* - * We've decremented to an unused fd_hash[] entry. - * Check no more! - */ - break; - } + nstime_delta(&delta, current, &fd_hash[i].frame_time); - nstime_delta(&delta, current, &fd_hash[i].time); - - if(delta.secs < 0 || delta.nsecs < 0) - { - /* - * A negative delta implies that the current packet - * has an absolute timestamp less than the cached packet - * that it is being compared to. This is NOT a normal - * situation since trace files usually have packets in - * chronological order (oldest to newest). - * - * There are several possible ways to deal with this: - * 1. 'continue' dup checking with the next cached frame. - * 2. 'break' from looking for a duplicate of the current frame. - * 3. Take the absolute value of the delta and see if that - * falls within the specifed dup time window. - * - * Currently this code does option 1. But it would pretty - * easy to add yet-another-editcap-option to select one of - * the other behaviors for dealing with out-of-sequence - * packets. - */ - continue; - } + if (delta.secs < 0 || delta.nsecs < 0) { + /* + * A negative delta implies that the current packet + * has an absolute timestamp less than the cached packet + * that it is being compared to. This is NOT a normal + * situation since trace files usually have packets in + * chronological order (oldest to newest). + * + * There are several possible ways to deal with this: + * 1. 'continue' dup checking with the next cached frame. + * 2. 'break' from looking for a duplicate of the current frame. + * 3. Take the absolute value of the delta and see if that + * falls within the specifed dup time window. + * + * Currently this code does option 1. But it would pretty + * easy to add yet-another-editcap-option to select one of + * the other behaviors for dealing with out-of-sequence + * packets. + */ + continue; + } + + cmp = nstime_cmp(&delta, &relative_time_window); - cmp = nstime_cmp(&delta, &relative_time_window); - - if(cmp > 0) { - /* - * The delta time indicates that we are now looking at - * cached packets beyond the specified dup time window. - * Check no more! - */ - break; - } else if (fd_hash[i].len == fd_hash[cur_dup_entry].len && - memcmp(fd_hash[i].digest, fd_hash[cur_dup_entry].digest, 16) == 0) { - return TRUE; + if (cmp > 0) { + /* + * The delta time indicates that we are now looking at + * cached packets beyond the specified dup time window. + * Check no more! + */ + break; + } else if (fd_hash[i].len == fd_hash[cur_dup_entry].len + && memcmp(fd_hash[i].digest, fd_hash[cur_dup_entry].digest, 16) == 0) { + return TRUE; + } } - } - return FALSE; + return FALSE; } 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"); - fprintf(output, " and must both be present.\n"); - fprintf(output, "A single packet or a range of packets can be selected.\n"); - fprintf(output, "\n"); - fprintf(output, "Packet selection:\n"); - fprintf(output, " -r keep the selected packets; default is to delete them.\n"); - fprintf(output, " -A only output packets whose timestamp is after (or equal\n"); - fprintf(output, " to) the given time (format as YYYY-MM-DD hh:mm:ss).\n"); - fprintf(output, " -B only output packets whose timestamp is before the\n"); - fprintf(output, " given time (format as YYYY-MM-DD hh:mm:ss).\n"); - fprintf(output, "\n"); - fprintf(output, "Duplicate packet removal:\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, " 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"); - fprintf(output, " -w remove packet if duplicate packet is found EQUAL TO OR\n"); - 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, "\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"); - fprintf(output, " Specifically the -r, -t or -S options will very likely NOT have the\n"); - fprintf(output, " desired effect if combined with the -d, -D or -w.\n"); - fprintf(output, "\n"); - fprintf(output, "Packet manipulation:\n"); - fprintf(output, " -s truncate each packet to max. bytes of data.\n"); - fprintf(output, " -C chop each packet by bytes. Positive values\n"); - fprintf(output, " chop at the packet beginning, negative values at the\n"); - fprintf(output, " packet end.\n"); - fprintf(output, " -t