2006-01-09 21:14:32 +00:00
|
|
|
/* Edit capture files. We can delete packets, adjust timestamps, or
|
2001-07-12 08:16:45 +00:00
|
|
|
* simply convert from one format to another format.
|
1999-12-04 21:42:56 +00:00
|
|
|
*
|
1999-12-04 12:53:52 +00:00
|
|
|
* Originally written by Richard Sharpe.
|
|
|
|
* Improved by Guy Harris.
|
2000-01-17 20:21:40 +00:00
|
|
|
* Further improved by Richard Sharpe.
|
2013-01-14 15:25:49 +00:00
|
|
|
*
|
|
|
|
* Copyright 2013, Richard Sharpe <realrichardsharpe[AT]gmail.com>
|
|
|
|
*
|
|
|
|
* Wireshark - Network traffic analyzer
|
|
|
|
* By Gerald Combs <gerald@wireshark.org>
|
|
|
|
* 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.
|
1999-12-04 12:53:52 +00:00
|
|
|
*/
|
|
|
|
|
2014-08-22 21:13:05 +00:00
|
|
|
#include <config.h>
|
2000-04-12 21:52:11 +00:00
|
|
|
|
2012-02-24 05:17:46 +00:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <stdarg.h>
|
|
|
|
|
2007-01-16 19:13:09 +00:00
|
|
|
/*
|
|
|
|
* Just make sure we include the prototype for strptime as well
|
2007-04-22 20:04:34 +00:00
|
|
|
* (needed for glibc 2.2) but make sure we do this only if not
|
|
|
|
* yet defined.
|
2007-01-16 19:13:09 +00:00
|
|
|
*/
|
|
|
|
|
2007-04-22 20:04:34 +00:00
|
|
|
#ifndef __USE_XOPEN
|
|
|
|
# define __USE_XOPEN
|
|
|
|
#endif
|
|
|
|
|
2007-01-16 19:13:09 +00:00
|
|
|
#include <time.h>
|
1999-12-04 12:53:52 +00:00
|
|
|
#include <glib.h>
|
2000-04-12 21:52:11 +00:00
|
|
|
|
|
|
|
#ifdef HAVE_UNISTD_H
|
1999-12-04 12:53:52 +00:00
|
|
|
#include <unistd.h>
|
2000-04-12 21:52:11 +00:00
|
|
|
#endif
|
|
|
|
|
2014-07-03 04:50:54 +00:00
|
|
|
#ifdef HAVE_GETOPT_H
|
|
|
|
#include <getopt.h>
|
|
|
|
#endif
|
|
|
|
|
2014-07-03 08:45:32 +00:00
|
|
|
#ifdef HAVE_LIBZ
|
2014-08-05 20:10:44 +00:00
|
|
|
#include <zlib.h> /* to get the libz version number */
|
2014-07-03 08:45:32 +00:00
|
|
|
#endif
|
|
|
|
|
2016-01-06 00:24:52 +00:00
|
|
|
#include <wiretap/wtap.h>
|
1999-12-04 12:53:52 +00:00
|
|
|
|
2016-01-19 13:04:10 +00:00
|
|
|
#include "epan/etypes.h"
|
|
|
|
|
2014-12-25 01:10:40 +00:00
|
|
|
#ifndef HAVE_GETOPT_LONG
|
2010-05-28 20:19:55 +00:00
|
|
|
#include "wsutil/wsgetopt.h"
|
2000-04-12 21:52:11 +00:00
|
|
|
#endif
|
|
|
|
|
2005-07-26 09:34:49 +00:00
|
|
|
#ifdef _WIN32
|
2013-02-20 01:19:42 +00:00
|
|
|
#include <wsutil/file_util.h>
|
2011-05-24 00:07:56 +00:00
|
|
|
#include <wsutil/unicode-utils.h>
|
2005-07-26 09:34:49 +00:00
|
|
|
#include <process.h> /* getpid */
|
2008-10-24 00:42:09 +00:00
|
|
|
#ifdef HAVE_WINSOCK2_H
|
|
|
|
#include <winsock2.h>
|
|
|
|
#endif
|
2005-07-26 09:34:49 +00:00
|
|
|
#endif
|
|
|
|
|
Clean up handling of missing functions.
With autotools, CMake, and nmake, if we have a function, #define
HAVE_{function_name_in_all_caps}, otherwise don't #define it.
If we provide our own version of a function in libwsutil, make sure we
have a header that declares it, and *ONLY* include that header if
HAVE_{function_name_in_all_caps} is *NOT* defined, so that we don't have
the system declaration and our declaration colliding.
Check for inet_aton, strncasecmp, and strptime with CMake, just as we do
with autotools.
Simplify the addition of {function_name_in_all_caps}_LO to libwsutil in
autotools.
Change-Id: Id5be5c73f79f81919a3a865324e400eca7b88889
Reviewed-on: https://code.wireshark.org/review/2903
Reviewed-by: Guy Harris <guy@alum.mit.edu>
2014-07-06 21:02:39 +00:00
|
|
|
#ifndef HAVE_STRPTIME
|
2010-05-28 20:19:55 +00:00
|
|
|
# include "wsutil/strptime.h"
|
2006-03-13 22:20:07 +00:00
|
|
|
#endif
|
|
|
|
|
2015-02-20 00:05:49 +00:00
|
|
|
#include <wsutil/crash_info.h>
|
2013-11-17 02:55:14 +00:00
|
|
|
#include <wsutil/filesystem.h>
|
2013-08-01 23:34:47 +00:00
|
|
|
#include <wsutil/md5.h>
|
2013-12-02 08:30:29 +00:00
|
|
|
#include <wsutil/plugins.h>
|
2015-02-20 00:05:49 +00:00
|
|
|
#include <wsutil/privileges.h>
|
|
|
|
#include <wsutil/report_err.h>
|
|
|
|
#include <wsutil/strnatcmp.h>
|
2015-11-04 08:45:54 +00:00
|
|
|
#include <wsutil/str_util.h>
|
2015-02-20 00:05:49 +00:00
|
|
|
#include <wsutil/ws_diag_control.h>
|
2014-07-03 08:45:32 +00:00
|
|
|
#include <wsutil/ws_version_info.h>
|
2016-03-06 17:23:32 +00:00
|
|
|
#include <wsutil/pint.h>
|
2016-01-26 01:17:21 +00:00
|
|
|
#include <wiretap/wtap_opttypes.h>
|
|
|
|
#include <wiretap/pcapng.h>
|
2006-07-27 17:53:29 +00:00
|
|
|
|
2012-10-15 08:40:43 +00:00
|
|
|
#include "ringbuffer.h" /* For RINGBUFFER_MAX_NUM_FILES */
|
|
|
|
|
1999-12-04 12:53:52 +00:00
|
|
|
/*
|
|
|
|
* Some globals so we can pass things to various routines
|
|
|
|
*/
|
|
|
|
|
2000-01-17 08:06:03 +00:00
|
|
|
struct select_item {
|
2016-01-14 14:52:27 +00:00
|
|
|
gboolean inclusive;
|
|
|
|
guint first, second;
|
2002-03-14 04:32:35 +00:00
|
|
|
};
|
2000-01-17 08:06:03 +00:00
|
|
|
|
2006-07-27 17:53:29 +00:00
|
|
|
/*
|
|
|
|
* Duplicate frame detection
|
|
|
|
*/
|
|
|
|
typedef struct _fd_hash_t {
|
2013-09-09 06:26:42 +00:00
|
|
|
md5_byte_t digest[16];
|
2014-01-03 14:30:09 +00:00
|
|
|
guint32 len;
|
2015-09-28 13:11:44 +00:00
|
|
|
nstime_t frame_time;
|
2006-07-27 17:53:29 +00:00
|
|
|
} fd_hash_t;
|
|
|
|
|
2014-01-03 14:30:09 +00:00
|
|
|
#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 */
|
2009-04-17 15:21:46 +00:00
|
|
|
|
2013-09-09 06:26:42 +00:00
|
|
|
static fd_hash_t fd_hash[MAX_DUP_DEPTH];
|
2014-01-03 14:30:09 +00:00
|
|
|
static int dup_window = DEFAULT_DUP_DEPTH;
|
|
|
|
static int cur_dup_entry = 0;
|
2006-07-27 17:53:29 +00:00
|
|
|
|
2014-09-14 01:01:05 +00:00
|
|
|
static int ignored_bytes = 0; /* Used with -I */
|
|
|
|
|
2009-04-17 15:21:46 +00:00
|
|
|
#define ONE_BILLION 1000000000
|
2001-07-12 08:16:45 +00:00
|
|
|
|
2005-04-10 23:12:48 +00:00
|
|
|
/* Weights of different errors we can introduce */
|
|
|
|
/* We should probably make these command-line arguments */
|
|
|
|
/* XXX - Should we add a bit-level error? */
|
2013-09-09 06:26:42 +00:00
|
|
|
#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)
|
2005-04-10 23:12:48 +00:00
|
|
|
|
2013-09-09 06:26:42 +00:00
|
|
|
#define ALNUM_CHARS "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
|
|
|
|
#define ALNUM_LEN (sizeof(ALNUM_CHARS) - 1)
|
2005-04-10 23:12:48 +00:00
|
|
|
|
2001-07-12 08:16:45 +00:00
|
|
|
struct time_adjustment {
|
2014-09-28 23:41:43 +00:00
|
|
|
nstime_t tv;
|
2013-09-09 06:26:42 +00:00
|
|
|
int is_negative;
|
2001-07-12 08:16:45 +00:00
|
|
|
};
|
|
|
|
|
2013-09-09 19:39:45 +00:00
|
|
|
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;
|
|
|
|
|
2015-06-25 22:36:54 +00:00
|
|
|
|
|
|
|
/* Table of user comments */
|
|
|
|
GTree *frames_user_comments = NULL;
|
|
|
|
|
2014-01-03 14:30:09 +00:00
|
|
|
#define MAX_SELECTIONS 512
|
|
|
|
static struct select_item selectfrm[MAX_SELECTIONS];
|
2016-01-14 14:52:27 +00:00
|
|
|
static guint max_selected = 0;
|
2014-01-03 14:30:09 +00:00
|
|
|
static int keep_em = 0;
|
2011-06-20 23:31:26 +00:00
|
|
|
#ifdef PCAP_NG_DEFAULT
|
2014-01-03 14:30:09 +00:00
|
|
|
static int out_file_type_subtype = WTAP_FILE_TYPE_SUBTYPE_PCAPNG; /* default to pcapng */
|
2011-06-20 23:31:26 +00:00
|
|
|
#else
|
2014-01-03 14:30:09 +00:00
|
|
|
static int out_file_type_subtype = WTAP_FILE_TYPE_SUBTYPE_PCAP; /* default to pcap */
|
2011-06-20 23:31:26 +00:00
|
|
|
#endif
|
2014-01-03 14:30:09 +00:00
|
|
|
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;
|
2016-01-19 13:04:10 +00:00
|
|
|
static gboolean rem_vlan = FALSE;
|
2014-01-03 14:30:09 +00:00
|
|
|
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 */
|
2010-06-02 00:30:25 +00:00
|
|
|
|
2008-02-20 14:13:15 +00:00
|
|
|
static int find_dct2000_real_data(guint8 *buf);
|
2013-09-09 19:39:45 +00:00
|
|
|
static void handle_chopping(chop_t chop, struct wtap_pkthdr *out_phdr,
|
2013-11-15 22:31:11 +00:00
|
|
|
const struct wtap_pkthdr *in_phdr, guint8 **buf,
|
2013-09-09 19:39:45 +00:00
|
|
|
gboolean adjlen);
|
2008-02-20 14:13:15 +00:00
|
|
|
|
2009-05-23 07:59:23 +00:00
|
|
|
static gchar *
|
2013-11-09 10:38:02 +00:00
|
|
|
abs_time_to_str_with_sec_resolution(const nstime_t *abs_time)
|
2009-05-23 07:59:23 +00:00
|
|
|
{
|
|
|
|
struct tm *tmp;
|
2014-01-03 14:30:09 +00:00
|
|
|
gchar *buf = (gchar *)g_malloc(16);
|
2010-05-28 20:19:55 +00:00
|
|
|
|
2014-01-26 12:56:32 +00:00
|
|
|
tmp = localtime(&abs_time->secs);
|
2013-09-09 06:26:42 +00:00
|
|
|
|
2009-05-23 07:59:23 +00:00
|
|
|
if (tmp) {
|
|
|
|
g_snprintf(buf, 16, "%d%02d%02d%02d%02d%02d",
|
|
|
|
tmp->tm_year + 1900,
|
|
|
|
tmp->tm_mon+1,
|
|
|
|
tmp->tm_mday,
|
|
|
|
tmp->tm_hour,
|
|
|
|
tmp->tm_min,
|
|
|
|
tmp->tm_sec);
|
2013-09-09 06:26:42 +00:00
|
|
|
} else {
|
2011-04-12 18:43:44 +00:00
|
|
|
buf[0] = '\0';
|
2013-09-09 06:26:42 +00:00
|
|
|
}
|
2009-05-23 07:59:23 +00:00
|
|
|
|
|
|
|
return buf;
|
|
|
|
}
|
|
|
|
|
2014-01-03 14:30:09 +00:00
|
|
|
static gchar *
|
2014-05-23 21:03:42 +00:00
|
|
|
fileset_get_filename_by_pattern(guint idx, const struct wtap_pkthdr *phdr,
|
2010-11-01 14:33:14 +00:00
|
|
|
gchar *fprefix, gchar *fsuffix)
|
2009-05-23 07:59:23 +00:00
|
|
|
{
|
2014-01-03 14:30:09 +00:00
|
|
|
gchar filenum[5+1];
|
2009-05-23 07:59:23 +00:00
|
|
|
gchar *timestr;
|
|
|
|
gchar *abs_str;
|
|
|
|
|
2012-10-15 08:40:43 +00:00
|
|
|
g_snprintf(filenum, sizeof(filenum), "%05u", idx % RINGBUFFER_MAX_NUM_FILES);
|
2014-05-23 21:03:42 +00:00
|
|
|
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);
|
2009-05-23 07:59:23 +00:00
|
|
|
|
|
|
|
return abs_str;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
fileset_extract_prefix_suffix(const char *fname, gchar **fprefix, gchar **fsuffix)
|
|
|
|
{
|
|
|
|
char *pfx, *last_pathsep;
|
|
|
|
gchar *save_file;
|
|
|
|
|
|
|
|
save_file = g_strdup(fname);
|
2009-05-23 20:29:12 +00:00
|
|
|
if (save_file == NULL) {
|
2013-09-09 06:26:42 +00:00
|
|
|
fprintf(stderr, "editcap: Out of memory\n");
|
|
|
|
return FALSE;
|
2009-05-23 20:29:12 +00:00
|
|
|
}
|
2009-05-23 07:59:23 +00:00
|
|
|
|
|
|
|
last_pathsep = strrchr(save_file, G_DIR_SEPARATOR);
|
|
|
|
pfx = strrchr(save_file,'.');
|
|
|
|
if (pfx != NULL && (last_pathsep == NULL || pfx > last_pathsep)) {
|
2013-09-09 06:26:42 +00:00
|
|
|
/* 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);
|
2009-05-23 07:59:23 +00:00
|
|
|
} else {
|
2013-09-09 06:26:42 +00:00
|
|
|
/* 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;
|
2009-05-23 07:59:23 +00:00
|
|
|
}
|
|
|
|
g_free(save_file);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2000-01-17 08:06:03 +00:00
|
|
|
/* Add a selection item, a simple parser for now */
|
2007-06-20 20:02:52 +00:00
|
|
|
static gboolean
|
2016-01-14 14:52:27 +00:00
|
|
|
add_selection(char *sel, guint* max_selection)
|
2000-01-17 08:06:03 +00:00
|
|
|
{
|
2013-09-09 06:26:42 +00:00
|
|
|
char *locn;
|
|
|
|
char *next;
|
2000-01-17 08:06:03 +00:00
|
|
|
|
2016-01-14 14:52:27 +00:00
|
|
|
if (max_selected >= MAX_SELECTIONS) {
|
2013-09-09 06:26:42 +00:00
|
|
|
/* Let the user know we stopped selecting */
|
2013-10-29 08:34:35 +00:00
|
|
|
fprintf(stderr, "Out of room for packet selections!\n");
|
2013-09-09 06:26:42 +00:00
|
|
|
return(FALSE);
|
|
|
|
}
|
2000-01-17 08:06:03 +00:00
|
|
|
|
2013-10-29 08:34:35 +00:00
|
|
|
if (verbose)
|
|
|
|
fprintf(stderr, "Add_Selected: %s\n", sel);
|
2000-01-17 08:06:03 +00:00
|
|
|
|
2013-09-09 06:26:42 +00:00
|
|
|
if ((locn = strchr(sel, '-')) == NULL) { /* No dash, so a single number? */
|
2013-10-29 08:34:35 +00:00
|
|
|
if (verbose)
|
|
|
|
fprintf(stderr, "Not inclusive ...");
|
2000-01-17 08:06:03 +00:00
|
|
|
|
2016-01-14 14:52:27 +00:00
|
|
|
selectfrm[max_selected].inclusive = FALSE;
|
2016-01-15 00:47:52 +00:00
|
|
|
selectfrm[max_selected].first = (guint)strtoul(sel, NULL, 10);
|
2016-01-14 14:52:27 +00:00
|
|
|
if (selectfrm[max_selected].first < *max_selection)
|
|
|
|
*max_selection = selectfrm[max_selected].first;
|
2000-01-17 08:06:03 +00:00
|
|
|
|
2013-10-29 08:34:35 +00:00
|
|
|
if (verbose)
|
|
|
|
fprintf(stderr, " %i\n", selectfrm[max_selected].first);
|
2013-09-09 06:26:42 +00:00
|
|
|
} else {
|
2013-10-29 08:34:35 +00:00
|
|
|
if (verbose)
|
|
|
|
fprintf(stderr, "Inclusive ...");
|
2000-01-17 08:06:03 +00:00
|
|
|
|
2013-09-09 06:26:42 +00:00
|
|
|
next = locn + 1;
|
2016-01-14 14:52:27 +00:00
|
|
|
selectfrm[max_selected].inclusive = TRUE;
|
2016-01-15 00:47:52 +00:00
|
|
|
selectfrm[max_selected].first = (guint)strtoul(sel, NULL, 10);
|
|
|
|
selectfrm[max_selected].second = (guint)strtoul(next, NULL, 10);
|
2016-01-14 14:52:27 +00:00
|
|
|
|
|
|
|
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;
|
2000-01-17 08:06:03 +00:00
|
|
|
|
2013-10-29 08:34:35 +00:00
|
|
|
if (verbose)
|
|
|
|
fprintf(stderr, " %i, %i\n", selectfrm[max_selected].first,
|
|
|
|
selectfrm[max_selected].second);
|
2013-09-09 06:26:42 +00:00
|
|
|
}
|
2000-01-17 08:06:03 +00:00
|
|
|
|
2016-01-14 14:52:27 +00:00
|
|
|
max_selected++;
|
2013-09-09 06:26:42 +00:00
|
|
|
return(TRUE);
|
2000-01-17 08:06:03 +00:00
|
|
|
}
|
|
|
|
|
2006-01-09 21:14:32 +00:00
|
|
|
/* Was the packet selected? */
|
1999-12-04 12:53:52 +00:00
|
|
|
|
2007-06-20 20:02:52 +00:00
|
|
|
static int
|
2016-01-14 14:52:27 +00:00
|
|
|
selected(guint recno)
|
1999-12-04 12:53:52 +00:00
|
|
|
{
|
2016-01-14 14:52:27 +00:00
|
|
|
guint i;
|
1999-12-04 12:53:52 +00:00
|
|
|
|
2016-01-14 14:52:27 +00:00
|
|
|
for (i = 0; i < max_selected; i++) {
|
2013-09-09 06:26:42 +00:00
|
|
|
if (selectfrm[i].inclusive) {
|
|
|
|
if (selectfrm[i].first <= recno && selectfrm[i].second >= recno)
|
|
|
|
return 1;
|
|
|
|
} else {
|
|
|
|
if (recno == selectfrm[i].first)
|
|
|
|
return 1;
|
|
|
|
}
|
2000-01-17 08:06:03 +00:00
|
|
|
}
|
1999-12-04 12:53:52 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2001-07-12 08:16:45 +00:00
|
|
|
static void
|
2010-01-29 16:09:25 +00:00
|
|
|
set_time_adjustment(char *optarg_str_p)
|
2001-07-12 08:16:45 +00:00
|
|
|
{
|
2014-01-03 14:30:09 +00:00
|
|
|
char *frac, *end;
|
|
|
|
long val;
|
|
|
|
size_t frac_digits;
|
2013-09-09 06:26:42 +00:00
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
2009-10-25 20:18:24 +00:00
|
|
|
}
|
2014-09-28 23:41:43 +00:00
|
|
|
time_adj.tv.secs = val;
|
2013-09-09 06:26:42 +00:00
|
|
|
|
|
|
|
/* now collect the partial seconds, if any */
|
|
|
|
if (*frac != '\0') { /* chars left, so get fractional part */
|
|
|
|
val = strtol(&(frac[1]), &end, 10);
|
2014-09-28 23:41:43 +00:00
|
|
|
/* if more than 9 fractional digits truncate to 9 */
|
|
|
|
if ((end - &(frac[1])) > 9) {
|
|
|
|
frac[10] = 't'; /* 't' for truncate */
|
2013-09-09 06:26:42 +00:00
|
|
|
val = strtol(&(frac[1]), &end, 10);
|
|
|
|
}
|
|
|
|
if (*frac != '.' || end == NULL || end == frac || val < 0
|
2014-09-28 23:41:43 +00:00
|
|
|
|| val > ONE_BILLION || val == LONG_MIN || val == LONG_MAX) {
|
2013-09-09 06:26:42 +00:00
|
|
|
fprintf(stderr, "editcap: \"%s\" isn't a valid time adjustment\n",
|
|
|
|
optarg_str_p);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
return; /* no fractional digits */
|
2001-07-12 08:16:45 +00:00
|
|
|
}
|
2013-09-09 06:26:42 +00:00
|
|
|
|
|
|
|
/* adjust fractional portion from fractional to numerator
|
2014-09-28 23:41:43 +00:00
|
|
|
* e.g., in "1.5" from 5 to 500000000 since .5*10^9 = 500000000 */
|
2013-09-09 06:26:42 +00:00
|
|
|
if (frac && end) { /* both are valid */
|
|
|
|
frac_digits = end - frac - 1; /* fractional digit count (remember '.') */
|
2014-09-28 23:41:43 +00:00
|
|
|
while(frac_digits < 9) { /* this is frac of 10^9 */
|
2013-09-09 06:26:42 +00:00
|
|
|
val *= 10;
|
|
|
|
frac_digits++;
|
|
|
|
}
|
2001-07-12 08:16:45 +00:00
|
|
|
}
|
2014-09-28 23:41:43 +00:00
|
|
|
time_adj.tv.nsecs = (int)val;
|
2001-07-12 08:16:45 +00:00
|
|
|
}
|
|
|
|
|
2010-06-02 00:30:25 +00:00
|
|
|
static void
|
2010-06-03 19:14:18 +00:00
|
|
|
set_strict_time_adj(char *optarg_str_p)
|
2010-06-02 00:30:25 +00:00
|
|
|
{
|
2014-01-03 14:30:09 +00:00
|
|
|
char *frac, *end;
|
|
|
|
long val;
|
|
|
|
size_t frac_digits;
|
2013-09-09 06:26:42 +00:00
|
|
|
|
|
|
|
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++;
|
|
|
|
}
|
2010-06-02 00:30:25 +00:00
|
|
|
|
2013-09-09 06:26:42 +00:00
|
|
|
/* 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);
|
|
|
|
}
|
|
|
|
}
|
2014-09-28 23:41:43 +00:00
|
|
|
strict_time_adj.tv.secs = val;
|
2010-06-02 00:30:25 +00:00
|
|
|
|
2013-09-09 06:26:42 +00:00
|
|
|
/* now collect the partial seconds, if any */
|
|
|
|
if (*frac != '\0') { /* chars left, so get fractional part */
|
2010-06-02 00:30:25 +00:00
|
|
|
val = strtol(&(frac[1]), &end, 10);
|
2014-09-28 23:41:43 +00:00
|
|
|
/* if more than 9 fractional digits truncate to 9 */
|
|
|
|
if ((end - &(frac[1])) > 9) {
|
|
|
|
frac[10] = 't'; /* 't' for truncate */
|
2013-09-09 06:26:42 +00:00
|
|
|
val = strtol(&(frac[1]), &end, 10);
|
|
|
|
}
|
|
|
|
if (*frac != '.' || end == NULL || end == frac || val < 0
|
2014-09-28 23:41:43 +00:00
|
|
|
|| val > ONE_BILLION || val == LONG_MIN || val == LONG_MAX) {
|
2013-09-09 06:26:42 +00:00
|
|
|
fprintf(stderr, "editcap: \"%s\" isn't a valid time adjustment\n",
|
|
|
|
optarg_str_p);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
return; /* no fractional digits */
|
2010-06-02 00:30:25 +00:00
|
|
|
}
|
2013-09-09 06:26:42 +00:00
|
|
|
|
|
|
|
/* adjust fractional portion from fractional to numerator
|
2014-09-28 23:41:43 +00:00
|
|
|
* e.g., in "1.5" from 5 to 500000000 since .5*10^9 = 500000000 */
|
2013-09-09 06:26:42 +00:00
|
|
|
if (frac && end) { /* both are valid */
|
|
|
|
frac_digits = end - frac - 1; /* fractional digit count (remember '.') */
|
2014-09-28 23:41:43 +00:00
|
|
|
while(frac_digits < 9) { /* this is frac of 10^9 */
|
2013-09-09 06:26:42 +00:00
|
|
|
val *= 10;
|
|
|
|
frac_digits++;
|
|
|
|
}
|
2010-06-02 00:30:25 +00:00
|
|
|
}
|
2014-09-28 23:41:43 +00:00
|
|
|
strict_time_adj.tv.nsecs = (int)val;
|
2010-06-02 00:30:25 +00:00
|
|
|
}
|
|
|
|
|
2009-04-17 15:21:46 +00:00
|
|
|
static void
|
2010-01-29 16:09:25 +00:00
|
|
|
set_rel_time(char *optarg_str_p)
|
2009-04-17 15:21:46 +00:00
|
|
|
{
|
2014-01-03 14:30:09 +00:00
|
|
|
char *frac, *end;
|
|
|
|
long val;
|
|
|
|
size_t frac_digits;
|
2013-09-09 06:26:42 +00:00
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
2009-10-25 20:18:24 +00:00
|
|
|
}
|
2013-09-09 06:26:42 +00:00
|
|
|
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 */
|
2009-04-17 15:21:46 +00:00
|
|
|
}
|
2013-09-09 06:26:42 +00:00
|
|
|
|
|
|
|
/* 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++;
|
|
|
|
}
|
2009-04-17 15:21:46 +00:00
|
|
|
}
|
2013-09-09 06:26:42 +00:00
|
|
|
relative_time_window.nsecs = (int)val;
|
2009-04-17 15:21:46 +00:00
|
|
|
}
|
|
|
|
|
2016-01-19 13:04:10 +00:00
|
|
|
#define LINUX_SLL_OFFSETP 14
|
|
|
|
#define VLAN_SIZE 4
|
|
|
|
static void
|
|
|
|
sll_remove_vlan_info(guint8* fd, guint32* len) {
|
2016-03-06 17:23:32 +00:00
|
|
|
if (pntoh16(fd + LINUX_SLL_OFFSETP) == ETHERTYPE_VLAN) {
|
2016-01-19 13:04:10 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-07-27 17:53:29 +00:00
|
|
|
static gboolean
|
|
|
|
is_duplicate(guint8* fd, guint32 len) {
|
2013-09-09 06:26:42 +00:00
|
|
|
int i;
|
|
|
|
md5_state_t ms;
|
2006-07-27 17:53:29 +00:00
|
|
|
|
2014-09-14 01:01:05 +00:00
|
|
|
/*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);
|
|
|
|
|
2013-09-09 06:26:42 +00:00
|
|
|
cur_dup_entry++;
|
|
|
|
if (cur_dup_entry >= dup_window)
|
|
|
|
cur_dup_entry = 0;
|
2006-07-27 17:53:29 +00:00
|
|
|
|
2013-09-09 06:26:42 +00:00
|
|
|
/* Calculate our digest */
|
|
|
|
md5_init(&ms);
|
2014-09-14 01:01:05 +00:00
|
|
|
md5_append(&ms, new_fd, new_len);
|
2013-09-09 06:26:42 +00:00
|
|
|
md5_finish(&ms, fd_hash[cur_dup_entry].digest);
|
2006-07-27 17:53:29 +00:00
|
|
|
|
2013-09-09 06:26:42 +00:00
|
|
|
fd_hash[cur_dup_entry].len = len;
|
2006-07-27 17:53:29 +00:00
|
|
|
|
2013-09-09 06:26:42 +00:00
|
|
|
/* Look for duplicates */
|
|
|
|
for (i = 0; i < dup_window; i++) {
|
|
|
|
if (i == cur_dup_entry)
|
|
|
|
continue;
|
2006-07-27 17:53:29 +00:00
|
|
|
|
2013-09-09 06:26:42 +00:00
|
|
|
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;
|
|
|
|
}
|
2009-04-17 15:21:46 +00:00
|
|
|
}
|
|
|
|
|
2013-09-09 06:26:42 +00:00
|
|
|
return FALSE;
|
2009-04-17 15:21:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
is_duplicate_rel_time(guint8* fd, guint32 len, const nstime_t *current) {
|
2013-09-09 06:26:42 +00:00
|
|
|
int i;
|
|
|
|
md5_state_t ms;
|
|
|
|
|
2014-09-14 01:01:05 +00:00
|
|
|
/*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);
|
|
|
|
|
2013-09-09 06:26:42 +00:00
|
|
|
cur_dup_entry++;
|
|
|
|
if (cur_dup_entry >= dup_window)
|
|
|
|
cur_dup_entry = 0;
|
|
|
|
|
|
|
|
/* Calculate our digest */
|
|
|
|
md5_init(&ms);
|
2014-09-14 01:01:05 +00:00
|
|
|
md5_append(&ms, new_fd, new_len);
|
2013-09-09 06:26:42 +00:00
|
|
|
md5_finish(&ms, fd_hash[cur_dup_entry].digest);
|
|
|
|
|
|
|
|
fd_hash[cur_dup_entry].len = len;
|
2015-09-28 13:11:44 +00:00
|
|
|
fd_hash[cur_dup_entry].frame_time.secs = current->secs;
|
|
|
|
fd_hash[cur_dup_entry].frame_time.nsecs = current->nsecs;
|
2013-09-09 06:26:42 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* 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!!).
|
|
|
|
*
|
2013-12-23 15:53:13 +00:00
|
|
|
* The fd_hash[] table was deliberately created large (1,000,000).
|
2013-09-09 06:26:42 +00:00
|
|
|
* 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;
|
|
|
|
}
|
2009-04-17 15:21:46 +00:00
|
|
|
|
2015-09-28 13:11:44 +00:00
|
|
|
if (nstime_is_unset(&(fd_hash[i].frame_time))) {
|
2013-09-09 06:26:42 +00:00
|
|
|
/*
|
|
|
|
* We've decremented to an unused fd_hash[] entry.
|
|
|
|
* Check no more!
|
|
|
|
*/
|
|
|
|
break;
|
|
|
|
}
|
2009-04-17 15:21:46 +00:00
|
|
|
|
2015-09-28 13:11:44 +00:00
|
|
|
nstime_delta(&delta, current, &fd_hash[i].frame_time);
|
2009-04-17 15:21:46 +00:00
|
|
|
|
2013-09-09 06:26:42 +00:00
|
|
|
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;
|
|
|
|
}
|
2009-04-17 15:21:46 +00:00
|
|
|
|
2013-09-09 06:26:42 +00:00
|
|
|
cmp = nstime_cmp(&delta, &relative_time_window);
|
2009-04-17 15:21:46 +00:00
|
|
|
|
2013-09-09 06:26:42 +00:00
|
|
|
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;
|
|
|
|
}
|
2006-07-27 17:53:29 +00:00
|
|
|
}
|
|
|
|
|
2013-09-09 06:26:42 +00:00
|
|
|
return FALSE;
|
2006-07-27 17:53:29 +00:00
|
|
|
}
|
|
|
|
|
2008-03-16 00:32:12 +00:00
|
|
|
static void
|
2014-07-03 08:45:32 +00:00
|
|
|
print_usage(FILE *output)
|
1999-12-04 12:53:52 +00:00
|
|
|
{
|
2013-09-09 06:26:42 +00:00
|
|
|
fprintf(output, "\n");
|
|
|
|
fprintf(output, "Usage: editcap [options] ... <infile> <outfile> [ <packet#>[-<packet#>] ... ]\n");
|
|
|
|
fprintf(output, "\n");
|
|
|
|
fprintf(output, "<infile> and <outfile> 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 <start time> 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 <stop time> 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");
|
2016-01-19 13:04:10 +00:00
|
|
|
fprintf(output, " --novlan remove vlan info from packets before checking for duplicates.\n");
|
2013-09-09 06:26:42 +00:00
|
|
|
fprintf(output, " -d remove packet if duplicate (window == %d).\n", DEFAULT_DUP_DEPTH);
|
|
|
|
fprintf(output, " -D <dup window> remove packet if duplicate; configurable <dup window>\n");
|
|
|
|
fprintf(output, " Valid <dup window> values are 0 to %d.\n", MAX_DUP_DEPTH);
|
|
|
|
fprintf(output, " NOTE: A <dup window> of 0 with -v (verbose option) is\n");
|
|
|
|
fprintf(output, " useful to print MD5 hashes.\n");
|
|
|
|
fprintf(output, " -w <dup time window> remove packet if duplicate packet is found EQUAL TO OR\n");
|
|
|
|
fprintf(output, " LESS THAN <dup time window> prior to current packet.\n");
|
|
|
|
fprintf(output, " A <dup time window> is specified in relative seconds\n");
|
|
|
|
fprintf(output, " (e.g. 0.000001).\n");
|
2015-06-25 22:36:54 +00:00
|
|
|
fprintf(output, " -a <framenum>:<comment> Add or replace comment for given frame number\n");
|
2013-09-09 06:26:42 +00:00
|
|
|
fprintf(output, "\n");
|
2014-09-14 01:01:05 +00:00
|
|
|
fprintf(output, " -I <bytes to ignore> 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(differents 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");
|
2013-09-09 06:26:42 +00:00
|
|
|
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 <snaplen> truncate each packet to max. <snaplen> bytes of data.\n");
|
|
|
|
fprintf(output, " -C [offset:]<choplen> chop each packet by <choplen> bytes. Positive values\n");
|
|
|
|
fprintf(output, " chop at the packet beginning, negative values at the\n");
|
|
|
|
fprintf(output, " packet end. If an optional offset precedes the length,\n");
|
|
|
|
fprintf(output, " then the bytes chopped will be offset from that value.\n");
|
|
|
|
fprintf(output, " Positive offsets are from the packet beginning,\n");
|
|
|
|
fprintf(output, " negative offsets are from the packet end. You can use\n");
|
2013-09-09 19:39:45 +00:00
|
|
|
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");
|
2015-06-21 12:17:33 +00:00
|
|
|
fprintf(output, " -L adjust the frame (i.e. reported) length when chopping\n");
|
|
|
|
fprintf(output, " and/or snapping\n");
|
2013-09-09 06:26:42 +00:00
|
|
|
fprintf(output, " -t <time adjustment> adjust the timestamp of each packet;\n");
|
|
|
|
fprintf(output, " <time adjustment> is in relative seconds (e.g. -0.5).\n");
|
|
|
|
fprintf(output, " -S <strict adjustment> adjust timestamp of packets if necessary to insure\n");
|
|
|
|
fprintf(output, " strict chronological increasing order. The <strict\n");
|
|
|
|
fprintf(output, " adjustment> is specified in relative seconds with\n");
|
|
|
|
fprintf(output, " values of 0 or 0.000001 being the most reasonable.\n");
|
|
|
|
fprintf(output, " A negative adjustment value will modify timestamps so\n");
|
|
|
|
fprintf(output, " that each packet's delta time is the absolute value\n");
|
|
|
|
fprintf(output, " of the adjustment specified. A value of -0 will set\n");
|
|
|
|
fprintf(output, " all packets to the timestamp of the first packet.\n");
|
|
|
|
fprintf(output, " -E <error probability> set the probability (between 0.0 and 1.0 incl.) that\n");
|
|
|
|
fprintf(output, " a particular packet byte will be randomly changed.\n");
|
2016-01-16 11:22:38 +00:00
|
|
|
fprintf(output, " -o <change offset> When used in conjunction with -E, skip some bytes from the\n");
|
|
|
|
fprintf(output, " beginning of the packet. This allows one to preserve some\n");
|
2015-08-11 21:58:54 +00:00
|
|
|
fprintf(output, " bytes, in order to have some headers untouched.\n");
|
2013-09-09 06:26:42 +00:00
|
|
|
fprintf(output, "\n");
|
|
|
|
fprintf(output, "Output File(s):\n");
|
|
|
|
fprintf(output, " -c <packets per file> split the packet output to different files based on\n");
|
|
|
|
fprintf(output, " uniform packet counts with a maximum of\n");
|
|
|
|
fprintf(output, " <packets per file> each.\n");
|
|
|
|
fprintf(output, " -i <seconds per file> split the packet output to different files based on\n");
|
|
|
|
fprintf(output, " uniform time intervals with a maximum of\n");
|
|
|
|
fprintf(output, " <seconds per file> each.\n");
|
|
|
|
fprintf(output, " -F <capture type> set the output file type; default is pcapng. An empty\n");
|
|
|
|
fprintf(output, " \"-F\" option will list the file types.\n");
|
|
|
|
fprintf(output, " -T <encap type> set the output file encapsulation type; default is the\n");
|
|
|
|
fprintf(output, " same as the input file. An empty \"-T\" option will\n");
|
|
|
|
fprintf(output, " list the encapsulation types.\n");
|
|
|
|
fprintf(output, "\n");
|
|
|
|
fprintf(output, "Miscellaneous:\n");
|
|
|
|
fprintf(output, " -h display this help and exit.\n");
|
|
|
|
fprintf(output, " -v verbose output.\n");
|
|
|
|
fprintf(output, " If -v is used with any of the 'Duplicate Packet\n");
|
|
|
|
fprintf(output, " Removal' options (-d, -D or -w) then Packet lengths\n");
|
2014-01-23 15:11:00 +00:00
|
|
|
fprintf(output, " and MD5 hashes are printed to standard-error.\n");
|
2013-09-09 06:26:42 +00:00
|
|
|
fprintf(output, "\n");
|
2006-01-10 21:37:36 +00:00
|
|
|
}
|
|
|
|
|
2010-11-24 16:24:44 +00:00
|
|
|
struct string_elem {
|
|
|
|
const char *sstr; /* The short string */
|
|
|
|
const char *lstr; /* The long string */
|
|
|
|
};
|
|
|
|
|
|
|
|
static gint
|
2010-11-24 17:10:48 +00:00
|
|
|
string_compare(gconstpointer a, gconstpointer b)
|
2010-11-24 16:24:44 +00:00
|
|
|
{
|
2011-06-15 19:23:58 +00:00
|
|
|
return strcmp(((const struct string_elem *)a)->sstr,
|
|
|
|
((const struct string_elem *)b)->sstr);
|
2011-05-24 00:07:56 +00:00
|
|
|
}
|
2010-11-24 16:24:44 +00:00
|
|
|
|
2013-07-10 16:18:37 +00:00
|
|
|
static gint
|
|
|
|
string_nat_compare(gconstpointer a, gconstpointer b)
|
|
|
|
{
|
2014-10-29 17:53:49 +00:00
|
|
|
return ws_ascii_strnatcmp(((const struct string_elem *)a)->sstr,
|
2013-07-10 16:18:37 +00:00
|
|
|
((const struct string_elem *)b)->sstr);
|
|
|
|
}
|
|
|
|
|
2010-11-24 16:24:44 +00:00
|
|
|
static void
|
2010-11-24 17:10:48 +00:00
|
|
|
string_elem_print(gpointer data, gpointer not_used _U_)
|
2011-05-24 00:07:56 +00:00
|
|
|
{
|
2012-02-24 05:17:46 +00:00
|
|
|
fprintf(stderr, " %s - %s\n",
|
2010-11-24 17:10:48 +00:00
|
|
|
((struct string_elem *)data)->sstr,
|
|
|
|
((struct string_elem *)data)->lstr);
|
2010-11-24 16:24:44 +00:00
|
|
|
}
|
|
|
|
|
2008-03-16 00:32:12 +00:00
|
|
|
static void
|
|
|
|
list_capture_types(void) {
|
2006-01-10 22:00:37 +00:00
|
|
|
int i;
|
2010-11-24 16:24:44 +00:00
|
|
|
struct string_elem *captypes;
|
|
|
|
GSList *list = NULL;
|
2006-01-10 21:37:36 +00:00
|
|
|
|
2013-11-08 09:53:01 +00:00
|
|
|
captypes = g_new(struct string_elem,WTAP_NUM_FILE_TYPES_SUBTYPES);
|
2012-02-24 05:17:46 +00:00
|
|
|
fprintf(stderr, "editcap: The available capture file types for the \"-F\" flag are:\n");
|
2013-11-08 09:53:01 +00:00
|
|
|
for (i = 0; i < WTAP_NUM_FILE_TYPES_SUBTYPES; i++) {
|
2013-09-09 06:26:42 +00:00
|
|
|
if (wtap_dump_can_open(i)) {
|
2013-11-08 09:53:01 +00:00
|
|
|
captypes[i].sstr = wtap_file_type_subtype_short_string(i);
|
|
|
|
captypes[i].lstr = wtap_file_type_subtype_string(i);
|
2013-09-09 06:26:42 +00:00
|
|
|
list = g_slist_insert_sorted(list, &captypes[i], string_compare);
|
|
|
|
}
|
2006-01-10 21:37:36 +00:00
|
|
|
}
|
2010-11-24 16:24:44 +00:00
|
|
|
g_slist_foreach(list, string_elem_print, NULL);
|
|
|
|
g_slist_free(list);
|
|
|
|
g_free(captypes);
|
2006-01-10 22:00:37 +00:00
|
|
|
}
|
|
|
|
|
2008-03-16 00:32:12 +00:00
|
|
|
static void
|
|
|
|
list_encap_types(void) {
|
2006-01-10 22:00:37 +00:00
|
|
|
int i;
|
2010-11-24 16:24:44 +00:00
|
|
|
struct string_elem *encaps;
|
|
|
|
GSList *list = NULL;
|
2006-01-10 22:00:37 +00:00
|
|
|
|
2013-03-20 01:18:10 +00:00
|
|
|
encaps = (struct string_elem *)g_malloc(sizeof(struct string_elem) * WTAP_NUM_ENCAP_TYPES);
|
2012-02-24 05:17:46 +00:00
|
|
|
fprintf(stderr, "editcap: The available encapsulation types for the \"-T\" flag are:\n");
|
2006-01-10 21:37:36 +00:00
|
|
|
for (i = 0; i < WTAP_NUM_ENCAP_TYPES; i++) {
|
2010-11-24 16:24:44 +00:00
|
|
|
encaps[i].sstr = wtap_encap_short_string(i);
|
|
|
|
if (encaps[i].sstr != NULL) {
|
|
|
|
encaps[i].lstr = wtap_encap_string(i);
|
2013-07-10 16:18:37 +00:00
|
|
|
list = g_slist_insert_sorted(list, &encaps[i], string_nat_compare);
|
2010-11-24 16:24:44 +00:00
|
|
|
}
|
2006-01-10 21:37:36 +00:00
|
|
|
}
|
2010-11-24 16:24:44 +00:00
|
|
|
g_slist_foreach(list, string_elem_print, NULL);
|
|
|
|
g_slist_free(list);
|
|
|
|
g_free(encaps);
|
1999-12-04 12:53:52 +00:00
|
|
|
}
|
|
|
|
|
2015-06-25 22:36:54 +00:00
|
|
|
static int
|
2016-01-14 04:37:53 +00:00
|
|
|
framenum_compare(gconstpointer a, gconstpointer b, gpointer user_data _U_)
|
2015-06-25 22:36:54 +00:00
|
|
|
{
|
2016-01-14 04:37:53 +00:00
|
|
|
if (GPOINTER_TO_UINT(a) < GPOINTER_TO_UINT(b))
|
|
|
|
return -1;
|
2015-06-25 22:36:54 +00:00
|
|
|
|
2016-01-14 04:37:53 +00:00
|
|
|
if (GPOINTER_TO_UINT(a) > GPOINTER_TO_UINT(b))
|
|
|
|
return 1;
|
2015-06-25 22:36:54 +00:00
|
|
|
|
2016-01-14 04:37:53 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2015-06-25 22:36:54 +00:00
|
|
|
|
2008-12-18 19:24:34 +00:00
|
|
|
#ifdef HAVE_PLUGINS
|
2008-03-16 00:58:15 +00:00
|
|
|
/*
|
|
|
|
* Don't report failures to load plugins because most (non-wiretap) plugins
|
|
|
|
* *should* fail to load (because we're not linked against libwireshark and
|
|
|
|
* dissector plugins need libwireshark).
|
|
|
|
*/
|
2007-05-25 17:22:32 +00:00
|
|
|
static void
|
2008-03-16 00:58:15 +00:00
|
|
|
failure_message(const char *msg_format _U_, va_list ap _U_)
|
2007-05-25 17:22:32 +00:00
|
|
|
{
|
|
|
|
}
|
2008-12-18 19:24:34 +00:00
|
|
|
#endif
|
2007-05-25 17:22:32 +00:00
|
|
|
|
2014-07-03 08:45:32 +00:00
|
|
|
static void
|
|
|
|
get_editcap_compiled_info(GString *str)
|
|
|
|
{
|
|
|
|
/* LIBZ */
|
|
|
|
g_string_append(str, ", ");
|
|
|
|
#ifdef HAVE_LIBZ
|
|
|
|
g_string_append(str, "with libz ");
|
|
|
|
#ifdef ZLIB_VERSION
|
|
|
|
g_string_append(str, ZLIB_VERSION);
|
|
|
|
#else /* ZLIB_VERSION */
|
|
|
|
g_string_append(str, "(version unknown)");
|
|
|
|
#endif /* ZLIB_VERSION */
|
|
|
|
#else /* HAVE_LIBZ */
|
|
|
|
g_string_append(str, "without libz");
|
|
|
|
#endif /* HAVE_LIBZ */
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
get_editcap_runtime_info(GString *str)
|
|
|
|
{
|
|
|
|
/* zlib */
|
|
|
|
#if defined(HAVE_LIBZ) && !defined(_WIN32)
|
|
|
|
g_string_append_printf(str, ", with libz %s", zlibVersion());
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2015-11-10 01:21:46 +00:00
|
|
|
static wtap_dumper *
|
|
|
|
editcap_dump_open(const char *filename, guint32 snaplen,
|
2016-01-26 01:17:21 +00:00
|
|
|
wtap_optionblock_t shb_hdr,
|
2015-11-10 01:21:46 +00:00
|
|
|
wtapng_iface_descriptions_t *idb_inf,
|
2016-01-26 01:17:21 +00:00
|
|
|
wtap_optionblock_t nrb_hdr, int *write_err)
|
2015-11-10 01:21:46 +00:00
|
|
|
{
|
|
|
|
wtap_dumper *pdh;
|
|
|
|
|
|
|
|
if (strcmp(filename, "-") == 0) {
|
|
|
|
/* Write to the standard output. */
|
2015-11-10 10:01:43 +00:00
|
|
|
pdh = wtap_dump_open_stdout_ng(out_file_type_subtype, out_frame_type,
|
|
|
|
snaplen, FALSE /* compressed */,
|
|
|
|
shb_hdr, idb_inf, nrb_hdr,
|
|
|
|
write_err);
|
2015-11-10 01:21:46 +00:00
|
|
|
} else {
|
|
|
|
pdh = wtap_dump_open_ng(filename, out_file_type_subtype, out_frame_type,
|
|
|
|
snaplen, FALSE /* compressed */,
|
|
|
|
shb_hdr, idb_inf, nrb_hdr,
|
|
|
|
write_err);
|
|
|
|
}
|
|
|
|
return pdh;
|
|
|
|
}
|
|
|
|
|
2008-03-16 00:32:12 +00:00
|
|
|
int
|
|
|
|
main(int argc, char *argv[])
|
1999-12-04 12:53:52 +00:00
|
|
|
{
|
2014-07-03 08:45:32 +00:00
|
|
|
GString *comp_info_str;
|
|
|
|
GString *runtime_info_str;
|
2014-05-09 05:18:49 +00:00
|
|
|
wtap *wth;
|
2015-08-28 22:54:53 +00:00
|
|
|
int i, j, read_err, write_err;
|
|
|
|
gchar *read_err_info, *write_err_info;
|
2014-01-03 14:30:09 +00:00
|
|
|
int opt;
|
2014-07-03 04:50:54 +00:00
|
|
|
static const struct option long_options[] = {
|
2016-01-19 13:04:10 +00:00
|
|
|
{"novlan", no_argument, NULL, 0x8100},
|
2015-11-21 23:48:27 +00:00
|
|
|
{"help", no_argument, NULL, 'h'},
|
|
|
|
{"version", no_argument, NULL, 'V'},
|
2014-07-03 04:50:54 +00:00
|
|
|
{0, 0, 0, 0 }
|
|
|
|
};
|
2014-05-23 10:50:02 +00:00
|
|
|
|
2014-01-03 14:30:09 +00:00
|
|
|
char *p;
|
|
|
|
guint32 snaplen = 0; /* No limit */
|
|
|
|
chop_t chop = {0, 0, 0, 0, 0, 0}; /* No chop */
|
|
|
|
gboolean adjlen = FALSE;
|
2014-05-09 05:18:49 +00:00
|
|
|
wtap_dumper *pdh = NULL;
|
2014-01-03 14:30:09 +00:00
|
|
|
unsigned int count = 1;
|
|
|
|
unsigned int duplicate_count = 0;
|
|
|
|
gint64 data_offset;
|
|
|
|
int err_type;
|
|
|
|
guint8 *buf;
|
|
|
|
guint32 read_count = 0;
|
|
|
|
int split_packet_count = 0;
|
|
|
|
int written_count = 0;
|
|
|
|
char *filename = NULL;
|
2014-05-23 18:53:08 +00:00
|
|
|
gboolean ts_okay;
|
2014-01-03 14:30:09 +00:00
|
|
|
int secs_per_block = 0;
|
|
|
|
int block_cnt = 0;
|
|
|
|
nstime_t block_start;
|
|
|
|
gchar *fprefix = NULL;
|
|
|
|
gchar *fsuffix = NULL;
|
2015-08-11 21:58:54 +00:00
|
|
|
guint32 change_offset = 0;
|
2016-01-14 14:52:27 +00:00
|
|
|
guint max_packet_number = G_MAXUINT;
|
2014-01-03 14:30:09 +00:00
|
|
|
const struct wtap_pkthdr *phdr;
|
2015-06-25 22:36:54 +00:00
|
|
|
struct wtap_pkthdr temp_phdr;
|
2015-07-20 14:35:06 +00:00
|
|
|
wtapng_iface_descriptions_t *idb_inf = NULL;
|
2016-01-26 01:17:21 +00:00
|
|
|
wtap_optionblock_t shb_hdr = NULL;
|
|
|
|
wtap_optionblock_t nrb_hdr = NULL;
|
|
|
|
char *shb_user_appl;
|
2008-06-21 09:45:21 +00:00
|
|
|
|
2007-06-17 04:58:16 +00:00
|
|
|
#ifdef HAVE_PLUGINS
|
2013-09-09 06:26:42 +00:00
|
|
|
char* init_progfile_dir_error;
|
2008-03-16 00:32:12 +00:00
|
|
|
#endif
|
|
|
|
|
2011-01-06 23:28:58 +00:00
|
|
|
#ifdef _WIN32
|
2013-09-09 06:26:42 +00:00
|
|
|
arg_list_utf_16to8(argc, argv);
|
|
|
|
create_app_running_mutex();
|
2011-01-06 23:28:58 +00:00
|
|
|
#endif /* _WIN32 */
|
|
|
|
|
2014-12-31 06:28:25 +00:00
|
|
|
/* Get the compile-time version information string */
|
|
|
|
comp_info_str = get_compiled_version_info(NULL, get_editcap_compiled_info);
|
2014-07-03 08:45:32 +00:00
|
|
|
|
2014-12-31 06:28:25 +00:00
|
|
|
/* Get the run-time version information string */
|
|
|
|
runtime_info_str = get_runtime_version_info(get_editcap_runtime_info);
|
2014-07-03 08:45:32 +00:00
|
|
|
|
|
|
|
/* Add it to the information to be reported on a crash. */
|
|
|
|
ws_add_crash_info("Editcap (Wireshark) %s\n"
|
|
|
|
"\n"
|
|
|
|
"%s"
|
|
|
|
"\n"
|
|
|
|
"%s",
|
|
|
|
get_ws_vcs_version_info(), comp_info_str->str, runtime_info_str->str);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Get credential information for later use.
|
|
|
|
*/
|
2013-09-09 06:26:42 +00:00
|
|
|
init_process_policies();
|
2014-01-18 14:20:02 +00:00
|
|
|
init_open_routines();
|
2007-11-09 20:05:44 +00:00
|
|
|
|
2008-03-16 00:32:12 +00:00
|
|
|
#ifdef HAVE_PLUGINS
|
2013-09-09 06:26:42 +00:00
|
|
|
/* Register wiretap plugins */
|
2015-12-12 02:34:47 +00:00
|
|
|
if ((init_progfile_dir_error = init_progfile_dir(argv[0], main))) {
|
2013-09-09 06:26:42 +00:00
|
|
|
g_warning("editcap: init_progfile_dir(): %s", init_progfile_dir_error);
|
|
|
|
g_free(init_progfile_dir_error);
|
|
|
|
} else {
|
2013-12-02 08:30:29 +00:00
|
|
|
/* Register all the plugin types we have. */
|
|
|
|
wtap_register_plugin_types(); /* Types known to libwiretap */
|
|
|
|
|
2013-09-09 06:26:42 +00:00
|
|
|
init_report_err(failure_message,NULL,NULL,NULL);
|
2013-12-02 08:30:29 +00:00
|
|
|
|
|
|
|
/* Scan for plugins. This does *not* call their registration routines;
|
|
|
|
that's done later. */
|
|
|
|
scan_plugins();
|
|
|
|
|
|
|
|
/* Register all libwiretap plugin modules. */
|
|
|
|
register_all_wiretap_modules();
|
2013-09-09 06:26:42 +00:00
|
|
|
}
|
2007-06-17 04:58:16 +00:00
|
|
|
#endif
|
2007-11-09 20:05:44 +00:00
|
|
|
|
2013-09-09 06:26:42 +00:00
|
|
|
/* Process the options */
|
2015-08-11 21:58:54 +00:00
|
|
|
while ((opt = getopt_long(argc, argv, "a:A:B:c:C:dD:E:F:hi:I:Lo:rs:S:t:T:vVw:", long_options, NULL)) != -1) {
|
2013-09-09 06:26:42 +00:00
|
|
|
switch (opt) {
|
2016-01-19 13:04:10 +00:00
|
|
|
case 0x8100:
|
|
|
|
{
|
|
|
|
rem_vlan = TRUE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2015-06-25 22:36:54 +00:00
|
|
|
case 'a':
|
|
|
|
{
|
|
|
|
guint frame_number;
|
|
|
|
gint string_start_index = 0;
|
|
|
|
|
|
|
|
if ((sscanf(optarg, "%u:%n", &frame_number, &string_start_index) < 1) || (string_start_index == 0)) {
|
|
|
|
fprintf(stderr, "editcap: \"%s\" isn't a valid <frame>:<comment>\n\n",
|
|
|
|
optarg);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Lazily create the table */
|
|
|
|
if (!frames_user_comments) {
|
2016-01-14 04:37:53 +00:00
|
|
|
frames_user_comments = g_tree_new_full(framenum_compare, NULL, NULL, g_free);
|
2015-06-25 22:36:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Insert this entry (framenum -> comment) */
|
|
|
|
g_tree_replace(frames_user_comments, GUINT_TO_POINTER(frame_number), g_strdup(optarg+string_start_index));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2013-09-09 06:26:42 +00:00
|
|
|
case 'A':
|
|
|
|
{
|
|
|
|
struct tm starttm;
|
1999-12-04 12:53:52 +00:00
|
|
|
|
2013-09-09 06:26:42 +00:00
|
|
|
memset(&starttm,0,sizeof(struct tm));
|
2013-07-10 20:02:45 +00:00
|
|
|
|
2013-09-09 06:26:42 +00:00
|
|
|
if (!strptime(optarg,"%Y-%m-%d %T", &starttm)) {
|
|
|
|
fprintf(stderr, "editcap: \"%s\" isn't a valid time format\n\n",
|
|
|
|
optarg);
|
|
|
|
exit(1);
|
|
|
|
}
|
2002-08-28 21:04:11 +00:00
|
|
|
|
2013-09-09 06:26:42 +00:00
|
|
|
check_startstop = TRUE;
|
|
|
|
starttm.tm_isdst = -1;
|
2013-07-10 20:02:45 +00:00
|
|
|
|
2013-09-09 06:26:42 +00:00
|
|
|
starttime = mktime(&starttm);
|
|
|
|
break;
|
|
|
|
}
|
2013-07-10 20:02:45 +00:00
|
|
|
|
2013-09-09 06:26:42 +00:00
|
|
|
case 'B':
|
|
|
|
{
|
|
|
|
struct tm stoptm;
|
1999-12-04 12:53:52 +00:00
|
|
|
|
2013-09-09 06:26:42 +00:00
|
|
|
memset(&stoptm,0,sizeof(struct tm));
|
2006-01-09 21:14:32 +00:00
|
|
|
|
2013-09-09 06:26:42 +00:00
|
|
|
if (!strptime(optarg,"%Y-%m-%d %T", &stoptm)) {
|
|
|
|
fprintf(stderr, "editcap: \"%s\" isn't a valid time format\n\n",
|
|
|
|
optarg);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
check_startstop = TRUE;
|
|
|
|
stoptm.tm_isdst = -1;
|
|
|
|
stoptime = mktime(&stoptm);
|
|
|
|
break;
|
2013-07-10 20:02:45 +00:00
|
|
|
}
|
1999-12-04 12:53:52 +00:00
|
|
|
|
2013-09-09 06:26:42 +00:00
|
|
|
case 'c':
|
|
|
|
split_packet_count = (int)strtol(optarg, &p, 10);
|
|
|
|
if (p == optarg || *p != '\0') {
|
|
|
|
fprintf(stderr, "editcap: \"%s\" isn't a valid packet count\n",
|
|
|
|
optarg);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
if (split_packet_count <= 0) {
|
|
|
|
fprintf(stderr, "editcap: \"%d\" packet count must be larger than zero\n",
|
|
|
|
split_packet_count);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
break;
|
2006-07-27 17:53:29 +00:00
|
|
|
|
2013-09-09 06:26:42 +00:00
|
|
|
case 'C':
|
|
|
|
{
|
|
|
|
int choplen = 0, chopoff = 0;
|
2013-09-09 19:46:02 +00:00
|
|
|
|
2013-09-09 06:26:42 +00:00
|
|
|
switch (sscanf(optarg, "%d:%d", &chopoff, &choplen)) {
|
|
|
|
case 1: /* only the chop length was specififed */
|
|
|
|
choplen = chopoff;
|
|
|
|
chopoff = 0;
|
|
|
|
break;
|
1999-12-04 12:53:52 +00:00
|
|
|
|
2013-09-09 06:26:42 +00:00
|
|
|
case 2: /* both an offset and chop length was specified */
|
|
|
|
break;
|
1999-12-04 12:53:52 +00:00
|
|
|
|
2013-09-09 06:26:42 +00:00
|
|
|
default:
|
|
|
|
fprintf(stderr, "editcap: \"%s\" isn't a valid chop length or offset:length\n",
|
|
|
|
optarg);
|
|
|
|
exit(1);
|
|
|
|
break;
|
|
|
|
}
|
1999-12-04 12:53:52 +00:00
|
|
|
|
2013-09-09 06:26:42 +00:00
|
|
|
if (choplen > 0) {
|
2013-09-09 19:39:45 +00:00
|
|
|
chop.len_begin += choplen;
|
2013-09-09 06:26:42 +00:00
|
|
|
if (chopoff > 0)
|
2013-09-09 19:39:45 +00:00
|
|
|
chop.off_begin_pos += chopoff;
|
2013-09-09 06:26:42 +00:00
|
|
|
else
|
2013-09-09 19:39:45 +00:00
|
|
|
chop.off_begin_neg += chopoff;
|
2013-09-09 06:26:42 +00:00
|
|
|
} else if (choplen < 0) {
|
2013-09-09 19:39:45 +00:00
|
|
|
chop.len_end += choplen;
|
2013-09-09 06:26:42 +00:00
|
|
|
if (chopoff > 0)
|
2013-09-09 19:39:45 +00:00
|
|
|
chop.off_end_pos += chopoff;
|
2013-09-09 06:26:42 +00:00
|
|
|
else
|
2013-09-09 19:39:45 +00:00
|
|
|
chop.off_end_neg += chopoff;
|
2013-09-09 06:26:42 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2007-09-30 22:13:38 +00:00
|
|
|
|
2013-09-09 06:26:42 +00:00
|
|
|
case 'd':
|
|
|
|
dup_detect = TRUE;
|
|
|
|
dup_detect_by_time = FALSE;
|
|
|
|
dup_window = DEFAULT_DUP_DEPTH;
|
|
|
|
break;
|
2006-07-27 17:53:29 +00:00
|
|
|
|
2013-09-09 06:26:42 +00:00
|
|
|
case 'D':
|
|
|
|
dup_detect = TRUE;
|
|
|
|
dup_detect_by_time = FALSE;
|
|
|
|
dup_window = (int)strtol(optarg, &p, 10);
|
|
|
|
if (p == optarg || *p != '\0') {
|
|
|
|
fprintf(stderr, "editcap: \"%s\" isn't a valid duplicate window value\n",
|
|
|
|
optarg);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
if (dup_window < 0 || dup_window > MAX_DUP_DEPTH) {
|
|
|
|
fprintf(stderr, "editcap: \"%d\" duplicate window value must be between 0 and %d inclusive.\n",
|
|
|
|
dup_window, MAX_DUP_DEPTH);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
break;
|
2009-05-23 07:59:23 +00:00
|
|
|
|
2013-09-09 06:26:42 +00:00
|
|
|
case 'E':
|
2015-02-20 00:05:49 +00:00
|
|
|
err_prob = g_ascii_strtod(optarg, &p);
|
2013-09-09 06:26:42 +00:00
|
|
|
if (p == optarg || err_prob < 0.0 || err_prob > 1.0) {
|
|
|
|
fprintf(stderr, "editcap: probability \"%s\" must be between 0.0 and 1.0\n",
|
|
|
|
optarg);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
srand( (unsigned int) (time(NULL) + getpid()) );
|
|
|
|
break;
|
2006-07-27 17:53:29 +00:00
|
|
|
|
2013-09-09 06:26:42 +00:00
|
|
|
case 'F':
|
2013-11-08 09:53:01 +00:00
|
|
|
out_file_type_subtype = wtap_short_string_to_file_type_subtype(optarg);
|
|
|
|
if (out_file_type_subtype < 0) {
|
2013-09-09 06:26:42 +00:00
|
|
|
fprintf(stderr, "editcap: \"%s\" isn't a valid capture file type\n\n",
|
|
|
|
optarg);
|
|
|
|
list_capture_types();
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
break;
|
2008-06-21 09:45:21 +00:00
|
|
|
|
2013-09-09 06:26:42 +00:00
|
|
|
case 'h':
|
2014-07-03 08:45:32 +00:00
|
|
|
printf("Editcap (Wireshark) %s\n"
|
|
|
|
"Edit and/or translate the format of capture files.\n"
|
2015-11-11 17:19:50 +00:00
|
|
|
"See https://www.wireshark.org for more information.\n",
|
2014-07-03 08:45:32 +00:00
|
|
|
get_ws_vcs_version_info());
|
|
|
|
print_usage(stdout);
|
2014-01-03 14:30:09 +00:00
|
|
|
exit(0);
|
2013-09-09 06:26:42 +00:00
|
|
|
break;
|
1999-12-04 12:53:52 +00:00
|
|
|
|
2013-09-09 06:26:42 +00:00
|
|
|
case 'i': /* break capture file based on time interval */
|
|
|
|
secs_per_block = atoi(optarg);
|
|
|
|
if (secs_per_block <= 0) {
|
|
|
|
fprintf(stderr, "editcap: \"%s\" isn't a valid time interval\n\n",
|
|
|
|
optarg);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
break;
|
Have the Wiretap open, read, and seek-and-read routines return, in
addition to an error code, an error info string, for
WTAP_ERR_UNSUPPORTED, WTAP_ERR_UNSUPPORTED_ENCAP, and
WTAP_ERR_BAD_RECORD errors. Replace the error messages logged with
"g_message()" for those errors with g_strdup()ed or g_strdup_printf()ed
strings returned as the error info string, and change the callers of
those routines to, for those errors, put the info string into the
printed message or alert box for the error.
Add messages for cases where those errors were returned without printing
an additional message.
Nobody uses the error code from "cf_read()" - "cf_read()" puts up the
alert box itself for failures; get rid of the error code, so it just
returns a success/failure indication.
Rename "file_read_error_message()" to "cf_read_error_message()", as it
handles read errors from Wiretap, and have it take an error info string
as an argument. (That handles a lot of the work of putting the info
string into the error message.)
Make some variables in "ascend-grammar.y" static.
Check the return value of "erf_read_header()" in "erf_seek_read()".
Get rid of an unused #define in "i4btrace.c".
svn path=/trunk/; revision=9852
2004-01-25 21:55:17 +00:00
|
|
|
|
2014-09-14 01:01:05 +00:00
|
|
|
case 'I': /* ignored_bytes at the beginning of the frame for duplications removal */
|
|
|
|
ignored_bytes = atoi(optarg);
|
|
|
|
if(ignored_bytes <= 0) {
|
|
|
|
fprintf(stderr, "editcap: \"%s\" isn't a valid number of bytes to ignore\n", optarg);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2013-09-09 06:26:42 +00:00
|
|
|
case 'L':
|
|
|
|
adjlen = TRUE;
|
|
|
|
break;
|
1999-12-04 12:53:52 +00:00
|
|
|
|
2015-08-11 21:58:54 +00:00
|
|
|
case 'o':
|
|
|
|
change_offset = (guint32)strtol(optarg, &p, 10);
|
|
|
|
break;
|
|
|
|
|
2013-09-09 06:26:42 +00:00
|
|
|
case 'r':
|
|
|
|
keep_em = !keep_em; /* Just invert */
|
|
|
|
break;
|
1999-12-04 12:53:52 +00:00
|
|
|
|
2013-09-09 06:26:42 +00:00
|
|
|
case 's':
|
|
|
|
snaplen = (guint32)strtol(optarg, &p, 10);
|
|
|
|
if (p == optarg || *p != '\0') {
|
|
|
|
fprintf(stderr, "editcap: \"%s\" isn't a valid snapshot length\n",
|
|
|
|
optarg);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
break;
|
1999-12-04 12:53:52 +00:00
|
|
|
|
2013-09-09 06:26:42 +00:00
|
|
|
case 'S':
|
|
|
|
set_strict_time_adj(optarg);
|
|
|
|
do_strict_time_adjustment = TRUE;
|
|
|
|
break;
|
2012-03-03 00:14:16 +00:00
|
|
|
|
2013-09-09 06:26:42 +00:00
|
|
|
case 't':
|
|
|
|
set_time_adjustment(optarg);
|
|
|
|
break;
|
1999-12-04 12:53:52 +00:00
|
|
|
|
2013-09-09 06:26:42 +00:00
|
|
|
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\n",
|
|
|
|
optarg);
|
|
|
|
list_encap_types();
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
break;
|
1999-12-04 12:53:52 +00:00
|
|
|
|
2013-09-09 06:26:42 +00:00
|
|
|
case 'v':
|
|
|
|
verbose = !verbose; /* Just invert */
|
|
|
|
break;
|
1999-12-04 12:53:52 +00:00
|
|
|
|
2014-06-20 18:48:27 +00:00
|
|
|
case 'V':
|
2014-12-23 21:58:38 +00:00
|
|
|
show_version("Editcap (Wireshark)", comp_info_str, runtime_info_str);
|
2014-07-03 08:45:32 +00:00
|
|
|
g_string_free(comp_info_str, TRUE);
|
|
|
|
g_string_free(runtime_info_str, TRUE);
|
2014-06-20 18:48:27 +00:00
|
|
|
exit(0);
|
|
|
|
break;
|
|
|
|
|
2013-09-09 06:26:42 +00:00
|
|
|
case 'w':
|
|
|
|
dup_detect = FALSE;
|
|
|
|
dup_detect_by_time = TRUE;
|
|
|
|
dup_window = MAX_DUP_DEPTH;
|
|
|
|
set_rel_time(optarg);
|
|
|
|
break;
|
1999-12-12 21:04:29 +00:00
|
|
|
|
2013-09-09 06:26:42 +00:00
|
|
|
case '?': /* Bad options if GNU getopt */
|
|
|
|
switch(optopt) {
|
|
|
|
case'F':
|
|
|
|
list_capture_types();
|
|
|
|
break;
|
|
|
|
case'T':
|
|
|
|
list_encap_types();
|
|
|
|
break;
|
|
|
|
default:
|
2014-07-03 08:45:32 +00:00
|
|
|
print_usage(stderr);
|
2013-09-09 06:26:42 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
exit(1);
|
|
|
|
break;
|
|
|
|
}
|
2015-06-25 22:36:54 +00:00
|
|
|
} /* processing commmand-line options */
|
2009-04-17 15:21:46 +00:00
|
|
|
|
2013-09-09 06:26:42 +00:00
|
|
|
#ifdef DEBUG
|
2013-10-29 08:34:35 +00:00
|
|
|
fprintf(stderr, "Optind = %i, argc = %i\n", optind, argc);
|
2013-09-09 06:26:42 +00:00
|
|
|
#endif
|
2005-04-03 11:00:49 +00:00
|
|
|
|
2013-09-09 06:26:42 +00:00
|
|
|
if ((argc - optind) < 1) {
|
2014-07-03 08:45:32 +00:00
|
|
|
print_usage(stderr);
|
2013-09-09 06:26:42 +00:00
|
|
|
exit(1);
|
|
|
|
}
|
2008-06-21 09:45:21 +00:00
|
|
|
|
2013-09-09 06:26:42 +00:00
|
|
|
if (check_startstop && !stoptime) {
|
|
|
|
struct tm stoptm;
|
2009-05-23 07:59:23 +00:00
|
|
|
|
2013-09-09 06:26:42 +00:00
|
|
|
/* XXX: will work until 2035 */
|
|
|
|
memset(&stoptm,0,sizeof(struct tm));
|
|
|
|
stoptm.tm_year = 135;
|
|
|
|
stoptm.tm_mday = 31;
|
|
|
|
stoptm.tm_mon = 11;
|
2008-06-21 09:45:21 +00:00
|
|
|
|
2013-09-09 06:26:42 +00:00
|
|
|
stoptime = mktime(&stoptm);
|
|
|
|
}
|
2012-03-13 09:13:27 +00:00
|
|
|
|
2013-09-09 06:26:42 +00:00
|
|
|
nstime_set_unset(&block_start);
|
2012-03-14 01:08:09 +00:00
|
|
|
|
2013-09-09 06:26:42 +00:00
|
|
|
if (starttime > stoptime) {
|
|
|
|
fprintf(stderr, "editcap: start time is after the stop time\n");
|
|
|
|
exit(1);
|
|
|
|
}
|
2009-05-23 07:59:23 +00:00
|
|
|
|
2013-09-09 06:26:42 +00:00
|
|
|
if (split_packet_count > 0 && secs_per_block > 0) {
|
|
|
|
fprintf(stderr, "editcap: can't split on both packet count and time interval\n");
|
|
|
|
fprintf(stderr, "editcap: at the same time\n");
|
|
|
|
exit(1);
|
|
|
|
}
|
2009-05-23 07:59:23 +00:00
|
|
|
|
2015-08-28 22:54:53 +00:00
|
|
|
wth = wtap_open_offline(argv[optind], WTAP_TYPE_AUTO, &read_err, &read_err_info, FALSE);
|
2008-06-21 09:45:21 +00:00
|
|
|
|
2013-09-09 06:26:42 +00:00
|
|
|
if (!wth) {
|
|
|
|
fprintf(stderr, "editcap: Can't open %s: %s\n", argv[optind],
|
2015-08-28 22:54:53 +00:00
|
|
|
wtap_strerror(read_err));
|
|
|
|
if (read_err_info != NULL) {
|
|
|
|
fprintf(stderr, "(%s)\n", read_err_info);
|
|
|
|
g_free(read_err_info);
|
2008-06-21 09:45:21 +00:00
|
|
|
}
|
2013-09-09 06:26:42 +00:00
|
|
|
exit(2);
|
|
|
|
}
|
2008-06-21 09:45:21 +00:00
|
|
|
|
2013-09-09 06:26:42 +00:00
|
|
|
if (verbose) {
|
|
|
|
fprintf(stderr, "File %s is a %s capture file.\n", argv[optind],
|
2014-05-09 05:18:49 +00:00
|
|
|
wtap_file_type_subtype_string(wtap_file_type_subtype(wth)));
|
2013-09-09 06:26:42 +00:00
|
|
|
}
|
2005-12-16 16:37:03 +00:00
|
|
|
|
2015-07-20 15:09:06 +00:00
|
|
|
shb_hdr = wtap_file_get_shb_for_new_file(wth);
|
2013-09-09 06:26:42 +00:00
|
|
|
idb_inf = wtap_file_get_idb_info(wth);
|
2015-07-20 14:35:06 +00:00
|
|
|
nrb_hdr = wtap_file_get_nrb_for_new_file(wth);
|
2005-12-16 16:37:03 +00:00
|
|
|
|
2013-09-09 06:26:42 +00:00
|
|
|
/*
|
|
|
|
* Now, process the rest, if any ... we only write if there is an extra
|
|
|
|
* argument or so ...
|
|
|
|
*/
|
2006-07-27 17:53:29 +00:00
|
|
|
|
2013-09-09 06:26:42 +00:00
|
|
|
if ((argc - optind) >= 2) {
|
|
|
|
if (out_frame_type == -2)
|
2014-05-09 05:18:49 +00:00
|
|
|
out_frame_type = wtap_file_encap(wth);
|
2006-07-27 17:53:29 +00:00
|
|
|
|
2013-09-09 06:26:42 +00:00
|
|
|
for (i = optind + 2; i < argc; i++)
|
2016-01-14 14:52:27 +00:00
|
|
|
if (add_selection(argv[i], &max_packet_number) == FALSE)
|
2013-09-09 06:26:42 +00:00
|
|
|
break;
|
2007-11-09 20:05:44 +00:00
|
|
|
|
2016-01-14 14:52:27 +00:00
|
|
|
if (keep_em == FALSE)
|
|
|
|
max_packet_number = G_MAXUINT;
|
|
|
|
|
2013-09-09 06:26:42 +00:00
|
|
|
if (dup_detect || dup_detect_by_time) {
|
|
|
|
for (i = 0; i < dup_window; i++) {
|
|
|
|
memset(&fd_hash[i].digest, 0, 16);
|
|
|
|
fd_hash[i].len = 0;
|
2015-09-28 13:11:44 +00:00
|
|
|
nstime_set_unset(&fd_hash[i].frame_time);
|
2013-09-09 06:26:42 +00:00
|
|
|
}
|
|
|
|
}
|
2007-11-09 20:05:44 +00:00
|
|
|
|
2015-06-25 22:36:54 +00:00
|
|
|
/* Read all of the packets in turn */
|
2015-08-28 22:54:53 +00:00
|
|
|
while (wtap_read(wth, &read_err, &read_err_info, &data_offset)) {
|
2016-01-14 14:52:27 +00:00
|
|
|
if (max_packet_number <= read_count)
|
|
|
|
break;
|
|
|
|
|
2014-05-23 10:50:02 +00:00
|
|
|
read_count++;
|
2011-02-04 21:09:55 +00:00
|
|
|
|
2014-05-23 21:03:42 +00:00
|
|
|
phdr = wtap_phdr(wth);
|
|
|
|
|
2015-06-25 22:36:54 +00:00
|
|
|
/* Extra actions for the first packet */
|
|
|
|
if (read_count == 1) {
|
2014-05-23 10:50:02 +00:00
|
|
|
if (split_packet_count > 0 || secs_per_block > 0) {
|
|
|
|
if (!fileset_extract_prefix_suffix(argv[optind+1], &fprefix, &fsuffix))
|
2015-07-20 15:09:06 +00:00
|
|
|
goto error_on_exit;
|
2013-09-09 06:26:42 +00:00
|
|
|
|
2014-05-23 21:03:42 +00:00
|
|
|
filename = fileset_get_filename_by_pattern(block_cnt++, phdr, fprefix, fsuffix);
|
2014-05-23 10:50:02 +00:00
|
|
|
} else {
|
|
|
|
filename = g_strdup(argv[optind+1]);
|
|
|
|
}
|
2014-05-23 18:53:08 +00:00
|
|
|
g_assert(filename);
|
2014-05-23 10:50:02 +00:00
|
|
|
|
|
|
|
/* If we don't have an application name add Editcap */
|
2016-01-26 01:17:21 +00:00
|
|
|
wtap_optionblock_get_option_string(shb_hdr, OPT_SHB_USERAPPL, &shb_user_appl);
|
|
|
|
if (shb_user_appl == NULL) {
|
|
|
|
shb_user_appl = g_strdup("Editcap " VERSION);
|
|
|
|
wtap_optionblock_set_option_string(shb_hdr, OPT_SHB_USERAPPL, shb_user_appl);
|
|
|
|
g_free(shb_user_appl);
|
2014-05-23 10:50:02 +00:00
|
|
|
}
|
2013-09-09 06:26:42 +00:00
|
|
|
|
2015-11-10 01:21:46 +00:00
|
|
|
pdh = editcap_dump_open(filename,
|
2014-05-23 10:50:02 +00:00
|
|
|
snaplen ? MIN(snaplen, wtap_snapshot_length(wth)) : wtap_snapshot_length(wth),
|
2015-11-10 01:21:46 +00:00
|
|
|
shb_hdr, idb_inf, nrb_hdr, &write_err);
|
2014-05-23 10:50:02 +00:00
|
|
|
|
|
|
|
if (pdh == NULL) {
|
|
|
|
fprintf(stderr, "editcap: Can't open or create %s: %s\n",
|
2015-08-28 22:54:53 +00:00
|
|
|
filename, wtap_strerror(write_err));
|
2015-07-20 15:09:06 +00:00
|
|
|
goto error_on_exit;
|
2014-05-23 10:50:02 +00:00
|
|
|
}
|
2015-06-25 22:36:54 +00:00
|
|
|
} /* first packet only handling */
|
|
|
|
|
2014-05-23 10:50:02 +00:00
|
|
|
|
2014-05-23 18:53:08 +00:00
|
|
|
buf = wtap_buf_ptr(wth);
|
2014-05-23 10:50:02 +00:00
|
|
|
|
2014-05-23 18:53:08 +00:00
|
|
|
/*
|
|
|
|
* Not all packets have time stamps. Only process the time
|
|
|
|
* stamp if we have one.
|
|
|
|
*/
|
|
|
|
if (phdr->presence_flags & WTAP_HAS_TS) {
|
|
|
|
if (nstime_is_unset(&block_start)) {
|
2016-01-23 08:05:01 +00:00
|
|
|
block_start = phdr->ts;
|
2014-05-23 18:53:08 +00:00
|
|
|
}
|
2013-09-09 06:26:42 +00:00
|
|
|
|
2014-05-23 18:53:08 +00:00
|
|
|
if (secs_per_block > 0) {
|
|
|
|
while ((phdr->ts.secs - block_start.secs > secs_per_block)
|
|
|
|
|| (phdr->ts.secs - block_start.secs == secs_per_block
|
|
|
|
&& phdr->ts.nsecs >= block_start.nsecs )) { /* time for the next file */
|
2013-09-09 06:26:42 +00:00
|
|
|
|
2015-08-28 22:54:53 +00:00
|
|
|
if (!wtap_dump_close(pdh, &write_err)) {
|
2014-05-23 18:53:08 +00:00
|
|
|
fprintf(stderr, "editcap: Error writing to %s: %s\n",
|
2015-08-28 22:54:53 +00:00
|
|
|
filename, wtap_strerror(write_err));
|
2015-07-20 15:09:06 +00:00
|
|
|
goto error_on_exit;
|
2014-05-23 18:53:08 +00:00
|
|
|
}
|
|
|
|
block_start.secs = block_start.secs + secs_per_block; /* reset for next interval */
|
|
|
|
g_free(filename);
|
2014-05-23 21:03:42 +00:00
|
|
|
filename = fileset_get_filename_by_pattern(block_cnt++, phdr, fprefix, fsuffix);
|
2014-05-23 18:53:08 +00:00
|
|
|
g_assert(filename);
|
|
|
|
|
|
|
|
if (verbose)
|
|
|
|
fprintf(stderr, "Continuing writing in file %s\n", filename);
|
|
|
|
|
2015-11-10 01:21:46 +00:00
|
|
|
pdh = editcap_dump_open(filename,
|
2014-05-23 18:53:08 +00:00
|
|
|
snaplen ? MIN(snaplen, wtap_snapshot_length(wth)) : wtap_snapshot_length(wth),
|
2015-11-10 01:21:46 +00:00
|
|
|
shb_hdr, idb_inf, nrb_hdr, &write_err);
|
2014-05-23 18:53:08 +00:00
|
|
|
|
|
|
|
if (pdh == NULL) {
|
|
|
|
fprintf(stderr, "editcap: Can't open or create %s: %s\n",
|
2015-08-28 22:54:53 +00:00
|
|
|
filename, wtap_strerror(write_err));
|
2015-07-20 15:09:06 +00:00
|
|
|
goto error_on_exit;
|
2014-05-23 18:53:08 +00:00
|
|
|
}
|
2013-09-09 06:26:42 +00:00
|
|
|
}
|
|
|
|
}
|
2015-06-25 22:36:54 +00:00
|
|
|
} /* time stamp handling */
|
2013-09-09 06:26:42 +00:00
|
|
|
|
2014-05-23 10:50:02 +00:00
|
|
|
if (split_packet_count > 0) {
|
|
|
|
/* time for the next file? */
|
|
|
|
if (written_count > 0 && written_count % split_packet_count == 0) {
|
2015-08-28 22:54:53 +00:00
|
|
|
if (!wtap_dump_close(pdh, &write_err)) {
|
2014-05-23 10:50:02 +00:00
|
|
|
fprintf(stderr, "editcap: Error writing to %s: %s\n",
|
2015-08-28 22:54:53 +00:00
|
|
|
filename, wtap_strerror(write_err));
|
2015-07-20 15:09:06 +00:00
|
|
|
goto error_on_exit;
|
2013-09-09 06:26:42 +00:00
|
|
|
}
|
2009-04-17 15:21:46 +00:00
|
|
|
|
2014-05-23 10:50:02 +00:00
|
|
|
g_free(filename);
|
2014-05-23 21:03:42 +00:00
|
|
|
filename = fileset_get_filename_by_pattern(block_cnt++, phdr, fprefix, fsuffix);
|
2014-05-23 10:50:02 +00:00
|
|
|
g_assert(filename);
|
2009-04-17 15:21:46 +00:00
|
|
|
|
2014-05-23 10:50:02 +00:00
|
|
|
if (verbose)
|
|
|
|
fprintf(stderr, "Continuing writing in file %s\n", filename);
|
2009-04-17 15:21:46 +00:00
|
|
|
|
2015-11-10 01:21:46 +00:00
|
|
|
pdh = editcap_dump_open(filename,
|
2014-05-23 10:50:02 +00:00
|
|
|
snaplen ? MIN(snaplen, wtap_snapshot_length(wth)) : wtap_snapshot_length(wth),
|
2015-11-10 01:21:46 +00:00
|
|
|
shb_hdr, idb_inf, nrb_hdr, &write_err);
|
2014-05-23 10:50:02 +00:00
|
|
|
if (pdh == NULL) {
|
|
|
|
fprintf(stderr, "editcap: Can't open or create %s: %s\n",
|
2015-08-28 22:54:53 +00:00
|
|
|
filename, wtap_strerror(write_err));
|
2015-07-20 15:09:06 +00:00
|
|
|
goto error_on_exit;
|
2013-09-09 06:26:42 +00:00
|
|
|
}
|
|
|
|
}
|
2015-06-25 22:36:54 +00:00
|
|
|
} /* split packet handling */
|
2006-07-27 17:53:29 +00:00
|
|
|
|
2014-05-23 18:53:08 +00:00
|
|
|
if (check_startstop) {
|
|
|
|
/*
|
|
|
|
* Is the packet in the selected timeframe?
|
|
|
|
* If the packet has no time stamp, the answer is "no".
|
|
|
|
*/
|
|
|
|
if (phdr->presence_flags & WTAP_HAS_TS)
|
|
|
|
ts_okay = (phdr->ts.secs >= starttime) && (phdr->ts.secs < stoptime);
|
|
|
|
else
|
|
|
|
ts_okay = FALSE;
|
2014-06-20 18:48:27 +00:00
|
|
|
} else {
|
|
|
|
/*
|
|
|
|
* No selected timeframe, so all packets are "in the
|
|
|
|
* selected timeframe".
|
|
|
|
*/
|
|
|
|
ts_okay = TRUE;
|
|
|
|
}
|
2014-05-23 03:01:31 +00:00
|
|
|
|
2014-05-23 10:50:02 +00:00
|
|
|
if (ts_okay && ((!selected(count) && !keep_em)
|
|
|
|
|| (selected(count) && keep_em))) {
|
2014-05-23 03:01:31 +00:00
|
|
|
|
2014-05-23 10:50:02 +00:00
|
|
|
if (verbose && !dup_detect && !dup_detect_by_time)
|
|
|
|
fprintf(stderr, "Packet: %u\n", count);
|
2014-05-23 03:01:31 +00:00
|
|
|
|
2014-05-23 10:50:02 +00:00
|
|
|
/* We simply write it, perhaps after truncating it; we could
|
|
|
|
* do other things, like modify it. */
|
2005-04-03 11:00:49 +00:00
|
|
|
|
2014-05-23 10:50:02 +00:00
|
|
|
phdr = wtap_phdr(wth);
|
2013-09-09 06:26:42 +00:00
|
|
|
|
2014-05-23 10:50:02 +00:00
|
|
|
if (snaplen != 0) {
|
2015-06-21 11:44:24 +00:00
|
|
|
/* Limit capture length to snaplen */
|
2014-05-23 10:50:02 +00:00
|
|
|
if (phdr->caplen > snaplen) {
|
2015-06-21 11:44:24 +00:00
|
|
|
/* Copy and change rather than modify returned phdr */
|
2015-06-25 22:36:54 +00:00
|
|
|
temp_phdr = *phdr;
|
|
|
|
temp_phdr.caplen = snaplen;
|
|
|
|
phdr = &temp_phdr;
|
2014-05-23 03:01:31 +00:00
|
|
|
}
|
2015-06-21 11:44:24 +00:00
|
|
|
/* If -L, also set reported length to snaplen */
|
2014-05-23 10:50:02 +00:00
|
|
|
if (adjlen && phdr->len > snaplen) {
|
2015-06-21 11:44:24 +00:00
|
|
|
/* Copy and change rather than modify returned phdr */
|
2015-06-25 22:36:54 +00:00
|
|
|
temp_phdr = *phdr;
|
|
|
|
temp_phdr.len = snaplen;
|
|
|
|
phdr = &temp_phdr;
|
2014-05-23 10:50:02 +00:00
|
|
|
}
|
|
|
|
}
|
2013-09-09 06:26:42 +00:00
|
|
|
|
2014-05-23 10:50:02 +00:00
|
|
|
/* CHOP */
|
2015-06-25 22:36:54 +00:00
|
|
|
temp_phdr = *phdr;
|
|
|
|
handle_chopping(chop, &temp_phdr, phdr, &buf, adjlen);
|
|
|
|
phdr = &temp_phdr;
|
2013-09-09 06:26:42 +00:00
|
|
|
|
2014-05-23 18:53:08 +00:00
|
|
|
if (phdr->presence_flags & WTAP_HAS_TS) {
|
|
|
|
/* Do we adjust timestamps to ensure strict chronological
|
|
|
|
* order? */
|
|
|
|
if (do_strict_time_adjustment) {
|
|
|
|
if (previous_time.secs || previous_time.nsecs) {
|
|
|
|
if (!strict_time_adj.is_negative) {
|
|
|
|
nstime_t current;
|
|
|
|
nstime_t delta;
|
|
|
|
|
2016-01-23 08:05:01 +00:00
|
|
|
current = phdr->ts;
|
2014-05-23 18:53:08 +00:00
|
|
|
|
|
|
|
nstime_delta(&delta, ¤t, &previous_time);
|
|
|
|
|
|
|
|
if (delta.secs < 0 || delta.nsecs < 0) {
|
|
|
|
/*
|
|
|
|
* A negative delta indicates that the current packet
|
|
|
|
* has an absolute timestamp less than the previous 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).
|
|
|
|
*/
|
|
|
|
/* fprintf(stderr, "++out of order, need to adjust this packet!\n"); */
|
2015-06-25 22:36:54 +00:00
|
|
|
temp_phdr = *phdr;
|
|
|
|
temp_phdr.ts.secs = previous_time.secs + strict_time_adj.tv.secs;
|
|
|
|
temp_phdr.ts.nsecs = previous_time.nsecs;
|
|
|
|
if (temp_phdr.ts.nsecs + strict_time_adj.tv.nsecs > ONE_BILLION) {
|
2014-05-23 18:53:08 +00:00
|
|
|
/* carry */
|
2015-06-25 22:36:54 +00:00
|
|
|
temp_phdr.ts.secs++;
|
|
|
|
temp_phdr.ts.nsecs += strict_time_adj.tv.nsecs - ONE_BILLION;
|
2014-05-23 18:53:08 +00:00
|
|
|
} else {
|
2015-06-25 22:36:54 +00:00
|
|
|
temp_phdr.ts.nsecs += strict_time_adj.tv.nsecs;
|
2014-05-23 18:53:08 +00:00
|
|
|
}
|
2015-06-25 22:36:54 +00:00
|
|
|
phdr = &temp_phdr;
|
2014-05-23 18:53:08 +00:00
|
|
|
}
|
|
|
|
} else {
|
2013-09-09 06:26:42 +00:00
|
|
|
/*
|
2014-05-23 18:53:08 +00:00
|
|
|
* A negative strict time adjustment is requested.
|
|
|
|
* Unconditionally set each timestamp to previous
|
|
|
|
* packet's timestamp plus delta.
|
2013-09-09 06:26:42 +00:00
|
|
|
*/
|
2015-06-25 22:36:54 +00:00
|
|
|
temp_phdr = *phdr;
|
|
|
|
temp_phdr.ts.secs = previous_time.secs + strict_time_adj.tv.secs;
|
|
|
|
temp_phdr.ts.nsecs = previous_time.nsecs;
|
|
|
|
if (temp_phdr.ts.nsecs + strict_time_adj.tv.nsecs > ONE_BILLION) {
|
2013-09-09 06:26:42 +00:00
|
|
|
/* carry */
|
2015-06-25 22:36:54 +00:00
|
|
|
temp_phdr.ts.secs++;
|
|
|
|
temp_phdr.ts.nsecs += strict_time_adj.tv.nsecs - ONE_BILLION;
|
2013-09-09 06:26:42 +00:00
|
|
|
} else {
|
2015-06-25 22:36:54 +00:00
|
|
|
temp_phdr.ts.nsecs += strict_time_adj.tv.nsecs;
|
2013-09-09 06:26:42 +00:00
|
|
|
}
|
2015-06-25 22:36:54 +00:00
|
|
|
phdr = &temp_phdr;
|
2013-09-09 06:26:42 +00:00
|
|
|
}
|
|
|
|
}
|
2016-01-23 08:05:01 +00:00
|
|
|
previous_time = phdr->ts;
|
2013-09-09 06:26:42 +00:00
|
|
|
}
|
2009-05-23 07:59:23 +00:00
|
|
|
|
2016-02-12 02:13:15 +00:00
|
|
|
if (time_adj.tv.secs != 0) {
|
2015-06-25 22:36:54 +00:00
|
|
|
temp_phdr = *phdr;
|
2014-05-23 18:53:08 +00:00
|
|
|
if (time_adj.is_negative)
|
2015-06-25 22:36:54 +00:00
|
|
|
temp_phdr.ts.secs -= time_adj.tv.secs;
|
2014-05-23 18:53:08 +00:00
|
|
|
else
|
2015-06-25 22:36:54 +00:00
|
|
|
temp_phdr.ts.secs += time_adj.tv.secs;
|
|
|
|
phdr = &temp_phdr;
|
2014-05-23 18:53:08 +00:00
|
|
|
}
|
2014-05-23 10:50:02 +00:00
|
|
|
|
2016-02-12 02:13:15 +00:00
|
|
|
if (time_adj.tv.nsecs != 0) {
|
2015-06-25 22:36:54 +00:00
|
|
|
temp_phdr = *phdr;
|
2014-05-23 18:53:08 +00:00
|
|
|
if (time_adj.is_negative) { /* subtract */
|
2015-06-25 22:36:54 +00:00
|
|
|
if (temp_phdr.ts.nsecs < time_adj.tv.nsecs) { /* borrow */
|
|
|
|
temp_phdr.ts.secs--;
|
|
|
|
temp_phdr.ts.nsecs += ONE_BILLION;
|
2014-05-23 18:53:08 +00:00
|
|
|
}
|
2015-06-25 22:36:54 +00:00
|
|
|
temp_phdr.ts.nsecs -= time_adj.tv.nsecs;
|
2014-05-23 18:53:08 +00:00
|
|
|
} else { /* add */
|
2015-06-25 22:36:54 +00:00
|
|
|
if (temp_phdr.ts.nsecs + time_adj.tv.nsecs > ONE_BILLION) {
|
2014-05-23 18:53:08 +00:00
|
|
|
/* carry */
|
2015-06-25 22:36:54 +00:00
|
|
|
temp_phdr.ts.secs++;
|
|
|
|
temp_phdr.ts.nsecs += time_adj.tv.nsecs - ONE_BILLION;
|
2014-05-23 18:53:08 +00:00
|
|
|
} else {
|
2015-06-25 22:36:54 +00:00
|
|
|
temp_phdr.ts.nsecs += time_adj.tv.nsecs;
|
2014-05-23 18:53:08 +00:00
|
|
|
}
|
2013-09-09 06:26:42 +00:00
|
|
|
}
|
2015-06-25 22:36:54 +00:00
|
|
|
phdr = &temp_phdr;
|
2013-09-09 06:26:42 +00:00
|
|
|
}
|
2015-06-25 22:36:54 +00:00
|
|
|
} /* time stamp adjustment */
|
1999-12-12 21:04:29 +00:00
|
|
|
|
2016-01-19 13:04:10 +00:00
|
|
|
/* remove vlan info */
|
|
|
|
if (rem_vlan) {
|
|
|
|
/* TODO: keep casting const like this? change pointer instead of value? */
|
|
|
|
remove_vlan_info(phdr, buf, (guint32 *) &phdr->caplen);
|
|
|
|
}
|
|
|
|
|
2014-05-23 10:50:02 +00:00
|
|
|
/* suppress duplicates by packet window */
|
|
|
|
if (dup_detect) {
|
|
|
|
if (is_duplicate(buf, phdr->caplen)) {
|
|
|
|
if (verbose) {
|
|
|
|
fprintf(stderr, "Skipped: %u, Len: %u, MD5 Hash: ",
|
|
|
|
count, phdr->caplen);
|
|
|
|
for (i = 0; i < 16; i++)
|
|
|
|
fprintf(stderr, "%02x",
|
|
|
|
(unsigned char)fd_hash[cur_dup_entry].digest[i]);
|
|
|
|
fprintf(stderr, "\n");
|
|
|
|
}
|
|
|
|
duplicate_count++;
|
|
|
|
count++;
|
|
|
|
continue;
|
|
|
|
} else {
|
|
|
|
if (verbose) {
|
|
|
|
fprintf(stderr, "Packet: %u, Len: %u, MD5 Hash: ",
|
|
|
|
count, phdr->caplen);
|
|
|
|
for (i = 0; i < 16; i++)
|
|
|
|
fprintf(stderr, "%02x",
|
|
|
|
(unsigned char)fd_hash[cur_dup_entry].digest[i]);
|
|
|
|
fprintf(stderr, "\n");
|
2013-09-09 06:26:42 +00:00
|
|
|
}
|
|
|
|
}
|
2015-06-25 22:36:54 +00:00
|
|
|
} /* suppression of duplicates */
|
2013-09-09 06:26:42 +00:00
|
|
|
|
2014-05-23 18:53:08 +00:00
|
|
|
if (phdr->presence_flags & WTAP_HAS_TS) {
|
|
|
|
/* suppress duplicates by time window */
|
|
|
|
if (dup_detect_by_time) {
|
|
|
|
nstime_t current;
|
|
|
|
|
|
|
|
current.secs = phdr->ts.secs;
|
|
|
|
current.nsecs = phdr->ts.nsecs;
|
|
|
|
|
|
|
|
if (is_duplicate_rel_time(buf, phdr->caplen, ¤t)) {
|
|
|
|
if (verbose) {
|
|
|
|
fprintf(stderr, "Skipped: %u, Len: %u, MD5 Hash: ",
|
|
|
|
count, phdr->caplen);
|
|
|
|
for (i = 0; i < 16; i++)
|
|
|
|
fprintf(stderr, "%02x",
|
|
|
|
(unsigned char)fd_hash[cur_dup_entry].digest[i]);
|
|
|
|
fprintf(stderr, "\n");
|
|
|
|
}
|
|
|
|
duplicate_count++;
|
|
|
|
count++;
|
|
|
|
continue;
|
|
|
|
} else {
|
|
|
|
if (verbose) {
|
|
|
|
fprintf(stderr, "Packet: %u, Len: %u, MD5 Hash: ",
|
|
|
|
count, phdr->caplen);
|
|
|
|
for (i = 0; i < 16; i++)
|
|
|
|
fprintf(stderr, "%02x",
|
|
|
|
(unsigned char)fd_hash[cur_dup_entry].digest[i]);
|
|
|
|
fprintf(stderr, "\n");
|
|
|
|
}
|
2014-05-23 10:50:02 +00:00
|
|
|
}
|
|
|
|
}
|
2015-06-25 22:36:54 +00:00
|
|
|
} /* suppress duplicates by time window */
|
2013-09-09 06:26:42 +00:00
|
|
|
|
2015-08-11 21:58:54 +00:00
|
|
|
if (change_offset > phdr->caplen) {
|
|
|
|
fprintf(stderr, "change offset %u is longer than caplen %u in packet %u\n",
|
|
|
|
change_offset, phdr->caplen, count);
|
|
|
|
}
|
|
|
|
|
2014-05-23 10:50:02 +00:00
|
|
|
/* Random error mutation */
|
2015-08-11 21:58:54 +00:00
|
|
|
if (err_prob > 0.0 && change_offset <= phdr->caplen) {
|
2014-05-23 10:50:02 +00:00
|
|
|
int real_data_start = 0;
|
2013-09-09 06:26:42 +00:00
|
|
|
|
2014-05-23 10:50:02 +00:00
|
|
|
/* Protect non-protocol data */
|
|
|
|
if (wtap_file_type_subtype(wth) == WTAP_FILE_TYPE_SUBTYPE_CATAPULT_DCT2000)
|
|
|
|
real_data_start = find_dct2000_real_data(buf);
|
2013-09-09 06:26:42 +00:00
|
|
|
|
2015-08-11 21:58:54 +00:00
|
|
|
real_data_start += change_offset;
|
|
|
|
|
2014-05-23 10:50:02 +00:00
|
|
|
for (i = real_data_start; i < (int) phdr->caplen; i++) {
|
|
|
|
if (rand() <= err_prob * RAND_MAX) {
|
|
|
|
err_type = rand() / (RAND_MAX / ERR_WT_TOTAL + 1);
|
2013-09-09 06:26:42 +00:00
|
|
|
|
2014-05-23 10:50:02 +00:00
|
|
|
if (err_type < ERR_WT_BIT) {
|
|
|
|
buf[i] ^= 1 << (rand() / (RAND_MAX / 8 + 1));
|
|
|
|
err_type = ERR_WT_TOTAL;
|
|
|
|
} else {
|
|
|
|
err_type -= ERR_WT_BYTE;
|
|
|
|
}
|
2013-09-09 06:26:42 +00:00
|
|
|
|
2014-05-23 10:50:02 +00:00
|
|
|
if (err_type < ERR_WT_BYTE) {
|
|
|
|
buf[i] = rand() / (RAND_MAX / 255 + 1);
|
|
|
|
err_type = ERR_WT_TOTAL;
|
|
|
|
} else {
|
|
|
|
err_type -= ERR_WT_BYTE;
|
|
|
|
}
|
2013-09-09 06:26:42 +00:00
|
|
|
|
2014-05-23 10:50:02 +00:00
|
|
|
if (err_type < ERR_WT_ALNUM) {
|
|
|
|
buf[i] = ALNUM_CHARS[rand() / (RAND_MAX / ALNUM_LEN + 1)];
|
|
|
|
err_type = ERR_WT_TOTAL;
|
|
|
|
} else {
|
|
|
|
err_type -= ERR_WT_ALNUM;
|
|
|
|
}
|
2013-09-09 06:26:42 +00:00
|
|
|
|
2014-05-23 10:50:02 +00:00
|
|
|
if (err_type < ERR_WT_FMT) {
|
|
|
|
if ((unsigned int)i < phdr->caplen - 2)
|
|
|
|
g_strlcpy((char*) &buf[i], "%s", 2);
|
|
|
|
err_type = ERR_WT_TOTAL;
|
|
|
|
} else {
|
|
|
|
err_type -= ERR_WT_FMT;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (err_type < ERR_WT_AA) {
|
|
|
|
for (j = i; j < (int) phdr->caplen; j++)
|
|
|
|
buf[j] = 0xAA;
|
|
|
|
i = phdr->caplen;
|
2013-09-09 06:26:42 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2015-06-25 22:36:54 +00:00
|
|
|
} /* random error mutation */
|
|
|
|
|
|
|
|
/* Find a packet comment we may need to write */
|
|
|
|
if (frames_user_comments) {
|
|
|
|
const char *comment =
|
|
|
|
(const char*)g_tree_lookup(frames_user_comments, GUINT_TO_POINTER(read_count));
|
|
|
|
if (comment != NULL) {
|
|
|
|
/* Copy and change rather than modify returned phdr */
|
|
|
|
temp_phdr = *phdr;
|
|
|
|
temp_phdr.opt_comment = g_strdup(comment);
|
|
|
|
phdr = &temp_phdr;
|
|
|
|
}
|
2014-05-23 10:50:02 +00:00
|
|
|
}
|
2013-09-09 06:26:42 +00:00
|
|
|
|
2015-06-25 22:36:54 +00:00
|
|
|
/* Attempt to dump out current frame to the output file */
|
2015-08-28 22:54:53 +00:00
|
|
|
if (!wtap_dump(pdh, phdr, buf, &write_err, &write_err_info)) {
|
|
|
|
switch (write_err) {
|
2014-12-17 06:40:45 +00:00
|
|
|
case WTAP_ERR_UNWRITABLE_ENCAP:
|
2014-05-23 10:50:02 +00:00
|
|
|
/*
|
|
|
|
* This is a problem with the particular frame we're
|
|
|
|
* writing and the file type and subtype we're
|
|
|
|
* writing; note that, and report the frame number
|
|
|
|
* and file type/subtype.
|
|
|
|
*/
|
|
|
|
fprintf(stderr,
|
2014-12-18 00:02:50 +00:00
|
|
|
"editcap: Frame %u of \"%s\" has a network type that can't be saved in a \"%s\" file.\n",
|
2014-05-23 10:50:02 +00:00
|
|
|
read_count, argv[optind],
|
|
|
|
wtap_file_type_subtype_string(out_file_type_subtype));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WTAP_ERR_PACKET_TOO_LARGE:
|
|
|
|
/*
|
|
|
|
* This is a problem with the particular frame we're
|
|
|
|
* writing and the file type and subtype we're
|
|
|
|
* writing; note that, and report the frame number
|
|
|
|
* and file type/subtype.
|
|
|
|
*/
|
|
|
|
fprintf(stderr,
|
2014-12-18 00:02:50 +00:00
|
|
|
"editcap: Frame %u of \"%s\" is too large for a \"%s\" file.\n",
|
2014-05-23 10:50:02 +00:00
|
|
|
read_count, argv[optind],
|
|
|
|
wtap_file_type_subtype_string(out_file_type_subtype));
|
|
|
|
break;
|
|
|
|
|
2014-12-18 00:31:49 +00:00
|
|
|
case WTAP_ERR_UNWRITABLE_REC_TYPE:
|
2014-12-18 00:02:50 +00:00
|
|
|
/*
|
|
|
|
* This is a problem with the particular record we're
|
|
|
|
* writing and the file type and subtype we're
|
|
|
|
* writing; note that, and report the record number
|
|
|
|
* and file type/subtype.
|
|
|
|
*/
|
|
|
|
fprintf(stderr,
|
|
|
|
"editcap: Record %u of \"%s\" has a record type that can't be saved in a \"%s\" file.\n",
|
|
|
|
read_count, argv[optind],
|
|
|
|
wtap_file_type_subtype_string(out_file_type_subtype));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WTAP_ERR_UNWRITABLE_REC_DATA:
|
|
|
|
/*
|
|
|
|
* This is a problem with the particular record we're
|
|
|
|
* writing and the file type and subtype we're
|
|
|
|
* writing; note that, and report the record number
|
|
|
|
* and file type/subtype.
|
|
|
|
*/
|
|
|
|
fprintf(stderr,
|
|
|
|
"editcap: Record %u of \"%s\" has data that can't be saved in a \"%s\" file.\n(%s)\n",
|
|
|
|
read_count, argv[optind],
|
|
|
|
wtap_file_type_subtype_string(out_file_type_subtype),
|
2015-08-28 22:54:53 +00:00
|
|
|
write_err_info != NULL ? write_err_info : "no information supplied");
|
|
|
|
g_free(write_err_info);
|
2014-12-18 00:02:50 +00:00
|
|
|
break;
|
|
|
|
|
2014-05-23 10:50:02 +00:00
|
|
|
default:
|
|
|
|
fprintf(stderr, "editcap: Error writing to %s: %s\n",
|
2015-08-28 22:54:53 +00:00
|
|
|
filename, wtap_strerror(write_err));
|
2014-05-23 10:50:02 +00:00
|
|
|
break;
|
2013-09-09 06:26:42 +00:00
|
|
|
}
|
2015-07-20 15:09:06 +00:00
|
|
|
goto error_on_exit;
|
2013-09-09 06:26:42 +00:00
|
|
|
}
|
2014-05-23 10:50:02 +00:00
|
|
|
written_count++;
|
2013-09-09 06:26:42 +00:00
|
|
|
}
|
2014-05-23 10:50:02 +00:00
|
|
|
count++;
|
2013-09-09 06:26:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
g_free(fprefix);
|
|
|
|
g_free(fsuffix);
|
|
|
|
|
2015-08-28 22:54:53 +00:00
|
|
|
if (read_err != 0) {
|
2013-09-09 06:26:42 +00:00
|
|
|
/* Print a message noting that the read failed somewhere along the
|
|
|
|
* line. */
|
|
|
|
fprintf(stderr,
|
|
|
|
"editcap: An error occurred while reading \"%s\": %s.\n",
|
2015-08-28 22:54:53 +00:00
|
|
|
argv[optind], wtap_strerror(read_err));
|
|
|
|
if (read_err_info != NULL) {
|
|
|
|
fprintf(stderr, "(%s)\n", read_err_info);
|
|
|
|
g_free(read_err_info);
|
2013-09-09 06:26:42 +00:00
|
|
|
}
|
|
|
|
}
|
1999-12-12 21:04:29 +00:00
|
|
|
|
2013-09-09 06:26:42 +00:00
|
|
|
if (!pdh) {
|
|
|
|
/* No valid packages found, open the outfile so we can write an
|
|
|
|
* empty header */
|
|
|
|
g_free (filename);
|
|
|
|
filename = g_strdup(argv[optind+1]);
|
|
|
|
|
2015-11-10 01:21:46 +00:00
|
|
|
pdh = editcap_dump_open(filename,
|
2014-05-09 05:18:49 +00:00
|
|
|
snaplen ? MIN(snaplen, wtap_snapshot_length(wth)): wtap_snapshot_length(wth),
|
2015-11-10 01:21:46 +00:00
|
|
|
shb_hdr, idb_inf, nrb_hdr, &write_err);
|
2013-09-09 06:26:42 +00:00
|
|
|
if (pdh == NULL) {
|
|
|
|
fprintf(stderr, "editcap: Can't open or create %s: %s\n",
|
2015-08-28 22:54:53 +00:00
|
|
|
filename, wtap_strerror(write_err));
|
2015-07-20 15:09:06 +00:00
|
|
|
goto error_on_exit;
|
2013-09-09 06:26:42 +00:00
|
|
|
}
|
|
|
|
}
|
2012-06-15 12:27:21 +00:00
|
|
|
|
2013-09-09 06:26:42 +00:00
|
|
|
g_free(idb_inf);
|
|
|
|
idb_inf = NULL;
|
2009-06-02 23:14:19 +00:00
|
|
|
|
2015-08-28 22:54:53 +00:00
|
|
|
if (!wtap_dump_close(pdh, &write_err)) {
|
2013-09-09 06:26:42 +00:00
|
|
|
fprintf(stderr, "editcap: Error writing to %s: %s\n", filename,
|
2015-08-28 22:54:53 +00:00
|
|
|
wtap_strerror(write_err));
|
2015-07-20 15:09:06 +00:00
|
|
|
goto error_on_exit;
|
2013-09-09 06:26:42 +00:00
|
|
|
}
|
2016-01-26 01:17:21 +00:00
|
|
|
wtap_optionblock_free(shb_hdr);
|
2015-07-20 14:35:06 +00:00
|
|
|
shb_hdr = NULL;
|
2016-01-26 01:17:21 +00:00
|
|
|
wtap_optionblock_free(nrb_hdr);
|
2015-07-20 14:35:06 +00:00
|
|
|
nrb_hdr = NULL;
|
2013-09-09 06:26:42 +00:00
|
|
|
g_free(filename);
|
2015-06-25 22:36:54 +00:00
|
|
|
|
|
|
|
if (frames_user_comments) {
|
|
|
|
g_tree_destroy(frames_user_comments);
|
|
|
|
}
|
2013-09-09 06:26:42 +00:00
|
|
|
}
|
1999-12-12 21:04:29 +00:00
|
|
|
|
2013-09-09 06:26:42 +00:00
|
|
|
if (dup_detect) {
|
2014-01-23 15:11:00 +00:00
|
|
|
fprintf(stderr, "%u packet%s seen, %u packet%s skipped with duplicate window of %i packets.\n",
|
2013-09-09 06:26:42 +00:00
|
|
|
count - 1, plurality(count - 1, "", "s"), duplicate_count,
|
|
|
|
plurality(duplicate_count, "", "s"), dup_window);
|
|
|
|
} else if (dup_detect_by_time) {
|
2014-01-23 15:11:00 +00:00
|
|
|
fprintf(stderr, "%u packet%s seen, %u packet%s skipped with duplicate time window equal to or less than %ld.%09ld seconds.\n",
|
2013-09-09 06:26:42 +00:00
|
|
|
count - 1, plurality(count - 1, "", "s"), duplicate_count,
|
|
|
|
plurality(duplicate_count, "", "s"),
|
|
|
|
(long)relative_time_window.secs,
|
|
|
|
(long int)relative_time_window.nsecs);
|
1999-12-12 21:04:29 +00:00
|
|
|
}
|
2009-04-17 15:21:46 +00:00
|
|
|
|
2013-09-09 06:26:42 +00:00
|
|
|
return 0;
|
2015-07-20 15:09:06 +00:00
|
|
|
|
|
|
|
error_on_exit:
|
2016-01-26 01:17:21 +00:00
|
|
|
wtap_optionblock_free(shb_hdr);
|
|
|
|
wtap_optionblock_free(nrb_hdr);
|
2015-07-20 15:09:06 +00:00
|
|
|
g_free(idb_inf);
|
|
|
|
exit(2);
|
1999-12-04 12:53:52 +00:00
|
|
|
}
|
2002-08-28 21:04:11 +00:00
|
|
|
|
2008-02-20 14:13:15 +00:00
|
|
|
/* Skip meta-information read from file to return offset of real
|
2013-09-09 06:26:42 +00:00
|
|
|
* protocol data */
|
|
|
|
static int
|
|
|
|
find_dct2000_real_data(guint8 *buf)
|
2008-02-20 14:13:15 +00:00
|
|
|
{
|
2013-09-09 06:26:42 +00:00
|
|
|
int n = 0;
|
|
|
|
|
|
|
|
for (n = 0; buf[n] != '\0'; n++); /* Context name */
|
|
|
|
n++;
|
|
|
|
n++; /* Context port number */
|
|
|
|
for (; buf[n] != '\0'; n++); /* Timestamp */
|
|
|
|
n++;
|
|
|
|
for (; buf[n] != '\0'; n++); /* Protocol name */
|
|
|
|
n++;
|
|
|
|
for (; buf[n] != '\0'; n++); /* Variant number (as string) */
|
|
|
|
n++;
|
|
|
|
for (; buf[n] != '\0'; n++); /* Outhdr (as string) */
|
|
|
|
n++;
|
|
|
|
n += 2; /* Direction & encap */
|
|
|
|
|
|
|
|
return n;
|
2008-02-20 14:13:15 +00:00
|
|
|
}
|
2013-09-09 06:26:42 +00:00
|
|
|
|
2013-09-09 19:39:45 +00:00
|
|
|
/*
|
2014-01-03 14:30:09 +00:00
|
|
|
* We support up to 2 chopping regions in a single pass: one specified by the
|
2013-09-09 19:39:45 +00:00
|
|
|
* positive chop length, and one by the negative chop length.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
handle_chopping(chop_t chop, struct wtap_pkthdr *out_phdr,
|
2013-11-15 22:31:11 +00:00
|
|
|
const struct wtap_pkthdr *in_phdr, guint8 **buf,
|
2013-09-09 19:39:45 +00:00
|
|
|
gboolean adjlen)
|
|
|
|
{
|
2014-05-24 18:28:30 +00:00
|
|
|
/* Only packets can be chopped. */
|
|
|
|
if (in_phdr->rec_type != REC_TYPE_PACKET)
|
|
|
|
return;
|
|
|
|
|
2013-09-09 19:39:45 +00:00
|
|
|
/* If we're not chopping anything from one side, then the offset for that
|
|
|
|
* side is meaningless. */
|
|
|
|
if (chop.len_begin == 0)
|
|
|
|
chop.off_begin_pos = chop.off_begin_neg = 0;
|
|
|
|
if (chop.len_end == 0)
|
|
|
|
chop.off_end_pos = chop.off_end_neg = 0;
|
|
|
|
|
|
|
|
if (chop.off_begin_neg < 0) {
|
|
|
|
chop.off_begin_pos += in_phdr->caplen + chop.off_begin_neg;
|
|
|
|
chop.off_begin_neg = 0;
|
|
|
|
}
|
|
|
|
if (chop.off_end_pos > 0) {
|
|
|
|
chop.off_end_neg += chop.off_end_pos - in_phdr->caplen;
|
|
|
|
chop.off_end_pos = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* If we've crossed chopping regions, swap them */
|
|
|
|
if (chop.len_begin && chop.len_end) {
|
|
|
|
if (chop.off_begin_pos > ((int)in_phdr->caplen + chop.off_end_neg)) {
|
|
|
|
int tmp_len, tmp_off;
|
|
|
|
|
|
|
|
tmp_off = in_phdr->caplen + chop.off_end_neg + chop.len_end;
|
|
|
|
tmp_len = -chop.len_end;
|
|
|
|
|
|
|
|
chop.off_end_neg = chop.len_begin + chop.off_begin_pos - in_phdr->caplen;
|
|
|
|
chop.len_end = -chop.len_begin;
|
|
|
|
|
|
|
|
chop.len_begin = tmp_len;
|
|
|
|
chop.off_begin_pos = tmp_off;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Make sure we don't chop off more than we have available */
|
|
|
|
if (in_phdr->caplen < (guint32)(chop.off_begin_pos - chop.off_end_neg)) {
|
|
|
|
chop.len_begin = 0;
|
|
|
|
chop.len_end = 0;
|
|
|
|
}
|
|
|
|
if ((guint32)(chop.len_begin - chop.len_end) >
|
|
|
|
(in_phdr->caplen - (guint32)(chop.off_begin_pos - chop.off_end_neg))) {
|
|
|
|
chop.len_begin = in_phdr->caplen - (chop.off_begin_pos - chop.off_end_neg);
|
|
|
|
chop.len_end = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Handle chopping from the beginning. Note that if a beginning offset
|
|
|
|
* was specified, we need to keep that piece */
|
|
|
|
if (chop.len_begin > 0) {
|
|
|
|
*out_phdr = *in_phdr;
|
|
|
|
|
|
|
|
if (chop.off_begin_pos > 0) {
|
2013-11-15 22:31:11 +00:00
|
|
|
memmove(*buf + chop.off_begin_pos,
|
|
|
|
*buf + chop.off_begin_pos + chop.len_begin,
|
2013-09-09 19:39:45 +00:00
|
|
|
out_phdr->caplen - chop.len_begin);
|
|
|
|
} else {
|
2013-11-15 22:31:11 +00:00
|
|
|
*buf += chop.len_begin;
|
2013-09-09 19:39:45 +00:00
|
|
|
}
|
|
|
|
out_phdr->caplen -= chop.len_begin;
|
|
|
|
|
|
|
|
if (adjlen) {
|
|
|
|
if (in_phdr->len > (guint32)chop.len_begin)
|
|
|
|
out_phdr->len -= chop.len_begin;
|
|
|
|
else
|
|
|
|
out_phdr->len = 0;
|
|
|
|
}
|
|
|
|
in_phdr = out_phdr;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Handle chopping from the end. Note that if an ending offset was
|
|
|
|
* specified, we need to keep that piece */
|
|
|
|
if (chop.len_end < 0) {
|
|
|
|
*out_phdr = *in_phdr;
|
|
|
|
|
|
|
|
if (chop.off_end_neg < 0) {
|
2013-11-15 22:31:11 +00:00
|
|
|
memmove(*buf + (gint)out_phdr->caplen + (chop.len_end + chop.off_end_neg),
|
|
|
|
*buf + (gint)out_phdr->caplen + chop.off_end_neg,
|
2013-09-09 19:39:45 +00:00
|
|
|
-chop.off_end_neg);
|
|
|
|
}
|
|
|
|
out_phdr->caplen += chop.len_end;
|
|
|
|
|
|
|
|
if (adjlen) {
|
|
|
|
if (((signed int) in_phdr->len + chop.len_end) > 0)
|
|
|
|
out_phdr->len += chop.len_end;
|
|
|
|
else
|
|
|
|
out_phdr->len = 0;
|
|
|
|
}
|
2013-09-16 07:56:04 +00:00
|
|
|
/*in_phdr = out_phdr;*/
|
2013-09-09 19:39:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-09-09 06:26:42 +00:00
|
|
|
/*
|
|
|
|
* Editor modelines - http://www.wireshark.org/tools/modelines.html
|
|
|
|
*
|
|
|
|
* Local variables:
|
|
|
|
* c-basic-offset: 4
|
2014-01-03 14:30:09 +00:00
|
|
|
* tab-width: 8
|
2013-09-09 06:26:42 +00:00
|
|
|
* indent-tabs-mode: nil
|
|
|
|
* End:
|
|
|
|
*
|
2014-01-03 14:30:09 +00:00
|
|
|
* vi: set shiftwidth=4 tabstop=8 expandtab:
|
|
|
|
* :indentSize=4:tabSize=8:noTabs=true:
|
2013-09-09 06:26:42 +00:00
|
|
|
*/
|
|
|
|
|