#include <zlib.h> /* to get the libz version number */
#endif
-#include "wtap.h"
+#include <wiretap/wtap.h>
+
+#include "epan/etypes.h"
#ifndef HAVE_GETOPT_LONG
#include "wsutil/wsgetopt.h"
#include <wsutil/str_util.h>
#include <wsutil/ws_diag_control.h>
#include <wsutil/ws_version_info.h>
+#include <wsutil/pint.h>
+#include <wiretap/wtap_opttypes.h>
+#include <wiretap/pcapng.h>
#include "ringbuffer.h" /* For RINGBUFFER_MAX_NUM_FILES */
*/
struct select_item {
- int inclusive;
- int first, second;
+ gboolean inclusive;
+ guint first, second;
};
/*
#define MAX_SELECTIONS 512
static struct select_item selectfrm[MAX_SELECTIONS];
-static int max_selected = -1;
+static guint max_selected = 0;
static int keep_em = 0;
#ifdef PCAP_NG_DEFAULT
static int out_file_type_subtype = WTAP_FILE_TYPE_SUBTYPE_PCAPNG; /* default to pcapng */
static time_t starttime = 0;
static time_t stoptime = 0;
static gboolean check_startstop = FALSE;
+static gboolean rem_vlan = FALSE;
static gboolean dup_detect = FALSE;
static gboolean dup_detect_by_time = FALSE;
/* Add a selection item, a simple parser for now */
static gboolean
-add_selection(char *sel)
+add_selection(char *sel, guint* max_selection)
{
char *locn;
char *next;
- if (++max_selected >= MAX_SELECTIONS) {
+ if (max_selected >= MAX_SELECTIONS) {
/* Let the user know we stopped selecting */
fprintf(stderr, "Out of room for packet selections!\n");
return(FALSE);
if (verbose)
fprintf(stderr, "Not inclusive ...");
- selectfrm[max_selected].inclusive = 0;
- selectfrm[max_selected].first = atoi(sel);
+ selectfrm[max_selected].inclusive = FALSE;
+ selectfrm[max_selected].first = (guint)strtoul(sel, NULL, 10);
+ if (selectfrm[max_selected].first < *max_selection)
+ *max_selection = selectfrm[max_selected].first;
if (verbose)
fprintf(stderr, " %i\n", selectfrm[max_selected].first);
fprintf(stderr, "Inclusive ...");
next = locn + 1;
- selectfrm[max_selected].inclusive = 1;
- selectfrm[max_selected].first = atoi(sel);
- selectfrm[max_selected].second = atoi(next);
+ selectfrm[max_selected].inclusive = TRUE;
+ selectfrm[max_selected].first = (guint)strtoul(sel, NULL, 10);
+ selectfrm[max_selected].second = (guint)strtoul(next, NULL, 10);
+
+ if (selectfrm[max_selected].second == 0)
+ {
+ /* Not a valid number, presume all */
+ selectfrm[max_selected].second = *max_selection = G_MAXUINT;
+ }
+ else if (selectfrm[max_selected].second < *max_selection)
+ *max_selection = selectfrm[max_selected].second;
if (verbose)
fprintf(stderr, " %i, %i\n", selectfrm[max_selected].first,
selectfrm[max_selected].second);
}
+ max_selected++;
return(TRUE);
}
/* Was the packet selected? */
static int
-selected(int recno)
+selected(guint recno)
{
- int i;
+ guint i;
- for (i = 0; i <= max_selected; i++) {
+ for (i = 0; i < max_selected; i++) {
if (selectfrm[i].inclusive) {
if (selectfrm[i].first <= recno && selectfrm[i].second >= recno)
return 1;
/* adjust fractional portion from fractional to numerator
* e.g., in "1.5" from 5 to 500000000 since .5*10^9 = 500000000 */
- if (frac && end) { /* both are valid */
- frac_digits = end - frac - 1; /* fractional digit count (remember '.') */
- while(frac_digits < 9) { /* this is frac of 10^9 */
- val *= 10;
- frac_digits++;
- }
+ frac_digits = end - frac - 1; /* fractional digit count (remember '.') */
+ while(frac_digits < 9) { /* this is frac of 10^9 */
+ val *= 10;
+ frac_digits++;
}
+
time_adj.tv.nsecs = (int)val;
}
/* adjust fractional portion from fractional to numerator
* e.g., in "1.5" from 5 to 500000000 since .5*10^9 = 500000000 */
- if (frac && end) { /* both are valid */
- frac_digits = end - frac - 1; /* fractional digit count (remember '.') */
- while(frac_digits < 9) { /* this is frac of 10^9 */
- val *= 10;
- frac_digits++;
- }
+ frac_digits = end - frac - 1; /* fractional digit count (remember '.') */
+ while(frac_digits < 9) { /* this is frac of 10^9 */
+ val *= 10;
+ frac_digits++;
}
+
strict_time_adj.tv.nsecs = (int)val;
}
/* adjust fractional portion from fractional to numerator
* e.g., in "1.5" from 5 to 500000000 since .5*10^9 = 500000000 */
- if (frac && end) { /* both are valid */
- frac_digits = end - frac - 1; /* fractional digit count (remember '.') */
- while(frac_digits < 9) { /* this is frac of 10^9 */
- val *= 10;
- frac_digits++;
- }
+ frac_digits = end - frac - 1; /* fractional digit count (remember '.') */
+ while(frac_digits < 9) { /* this is frac of 10^9 */
+ val *= 10;
+ frac_digits++;
}
+
relative_time_window.nsecs = (int)val;
}
+#define LINUX_SLL_OFFSETP 14
+#define VLAN_SIZE 4
+static void
+sll_remove_vlan_info(guint8* fd, guint32* len) {
+ if (pntoh16(fd + LINUX_SLL_OFFSETP) == ETHERTYPE_VLAN) {
+ int rest_len;
+ /* point to start of vlan */
+ fd = fd + LINUX_SLL_OFFSETP;
+ /* bytes to read after vlan info */
+ rest_len = *len - (LINUX_SLL_OFFSETP + VLAN_SIZE);
+ /* remove vlan info from packet */
+ memmove(fd, fd + VLAN_SIZE, rest_len);
+ *len -= 4;
+ }
+}
+
+static void
+remove_vlan_info(const struct wtap_pkthdr *phdr, guint8* fd, guint32* len) {
+ switch (phdr->pkt_encap) {
+ case WTAP_ENCAP_SLL:
+ sll_remove_vlan_info(fd, len);
+ break;
+ default:
+ /* no support for current pkt_encap */
+ break;
+ }
+}
+
static gboolean
is_duplicate(guint8* fd, guint32 len) {
int i;
fprintf(output, " given time (format as YYYY-MM-DD hh:mm:ss).\n");
fprintf(output, "\n");
fprintf(output, "Duplicate packet removal:\n");
+ fprintf(output, " --novlan remove vlan info from packets before checking for duplicates.\n");
fprintf(output, " -d remove packet if duplicate (window == %d).\n", DEFAULT_DUP_DEPTH);
fprintf(output, " -D <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, " 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");
- fprintf(output, " -o <change offset> When used in conjuction with -E, skip some bytes from the\n");
- fprintf(output, " beginning of the packet. This allows to preserve some\n");
+ 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");
fprintf(output, " bytes, in order to have some headers untouched.\n");
fprintf(output, "\n");
fprintf(output, "Output File(s):\n");
g_free(encaps);
}
-/* TODO: is there the equivalent of g_direct_equal? */
static int
-framenum_equal(gconstpointer a, gconstpointer b, gpointer user_data _U_)
+framenum_compare(gconstpointer a, gconstpointer b, gpointer user_data _U_)
{
- return (a != b);
-}
+ if (GPOINTER_TO_UINT(a) < GPOINTER_TO_UINT(b))
+ return -1;
+ if (GPOINTER_TO_UINT(a) > GPOINTER_TO_UINT(b))
+ return 1;
+ return 0;
+}
#ifdef HAVE_PLUGINS
/*
}
static void
-get_editcap_runtime_info(GString *str)
+get_editcap_runtime_info(GString *str _U_)
{
/* zlib */
#if defined(HAVE_LIBZ) && !defined(_WIN32)
static wtap_dumper *
editcap_dump_open(const char *filename, guint32 snaplen,
- wtapng_section_t *shb_hdr,
+ wtap_optionblock_t shb_hdr,
wtapng_iface_descriptions_t *idb_inf,
- wtapng_name_res_t *nrb_hdr, int *write_err)
+ wtap_optionblock_t nrb_hdr, int *write_err)
{
wtap_dumper *pdh;
gchar *read_err_info, *write_err_info;
int opt;
static const struct option long_options[] = {
+ {"novlan", no_argument, NULL, 0x8100},
{"help", no_argument, NULL, 'h'},
{"version", no_argument, NULL, 'V'},
{0, 0, 0, 0 }
gchar *fprefix = NULL;
gchar *fsuffix = NULL;
guint32 change_offset = 0;
-
+ guint max_packet_number = G_MAXUINT;
const struct wtap_pkthdr *phdr;
struct wtap_pkthdr temp_phdr;
wtapng_iface_descriptions_t *idb_inf = NULL;
- wtapng_section_t *shb_hdr = NULL;
- wtapng_name_res_t *nrb_hdr = NULL;
+ wtap_optionblock_t shb_hdr = NULL;
+ wtap_optionblock_t nrb_hdr = NULL;
+ char *shb_user_appl;
#ifdef HAVE_PLUGINS
char* init_progfile_dir_error;
/* Process the options */
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) {
switch (opt) {
+ case 0x8100:
+ {
+ rem_vlan = TRUE;
+ break;
+ }
+
case 'a':
{
guint frame_number;
/* Lazily create the table */
if (!frames_user_comments) {
- frames_user_comments = g_tree_new_full(framenum_equal, NULL, NULL, g_free);
+ frames_user_comments = g_tree_new_full(framenum_compare, NULL, NULL, g_free);
}
/* Insert this entry (framenum -> comment) */
out_frame_type = wtap_file_encap(wth);
for (i = optind + 2; i < argc; i++)
- if (add_selection(argv[i]) == FALSE)
+ if (add_selection(argv[i], &max_packet_number) == FALSE)
break;
+ if (keep_em == FALSE)
+ max_packet_number = G_MAXUINT;
+
if (dup_detect || dup_detect_by_time) {
for (i = 0; i < dup_window; i++) {
memset(&fd_hash[i].digest, 0, 16);
/* Read all of the packets in turn */
while (wtap_read(wth, &read_err, &read_err_info, &data_offset)) {
+ if (max_packet_number <= read_count)
+ break;
+
read_count++;
phdr = wtap_phdr(wth);
g_assert(filename);
/* If we don't have an application name add Editcap */
- if (shb_hdr->shb_user_appl == NULL) {
- shb_hdr->shb_user_appl = g_strdup("Editcap " VERSION);
+ 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);
}
pdh = editcap_dump_open(filename,
*/
if (phdr->presence_flags & WTAP_HAS_TS) {
if (nstime_is_unset(&block_start)) {
- block_start.secs = phdr->ts.secs;
- block_start.nsecs = phdr->ts.nsecs;
+ block_start = phdr->ts;
}
if (secs_per_block > 0) {
nstime_t current;
nstime_t delta;
- current.secs = phdr->ts.secs;
- current.nsecs = phdr->ts.nsecs;
+ current = phdr->ts;
nstime_delta(&delta, ¤t, &previous_time);
phdr = &temp_phdr;
}
}
- previous_time.secs = phdr->ts.secs;
- previous_time.nsecs = phdr->ts.nsecs;
+ previous_time = phdr->ts;
}
- /* assume that if the frame's tv_sec is 0, then
- * the timestamp isn't supported */
- if (phdr->ts.secs > 0 && time_adj.tv.secs != 0) {
+ if (time_adj.tv.secs != 0) {
temp_phdr = *phdr;
if (time_adj.is_negative)
temp_phdr.ts.secs -= time_adj.tv.secs;
phdr = &temp_phdr;
}
- /* assume that if the frame's tv_sec is 0, then
- * the timestamp isn't supported */
- if (phdr->ts.secs > 0 && time_adj.tv.nsecs != 0) {
+ if (time_adj.tv.nsecs != 0) {
temp_phdr = *phdr;
if (time_adj.is_negative) { /* subtract */
if (temp_phdr.ts.nsecs < time_adj.tv.nsecs) { /* borrow */
}
} /* time stamp adjustment */
+ /* 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);
+ }
+
/* suppress duplicates by packet window */
if (dup_detect) {
if (is_duplicate(buf, phdr->caplen)) {
wtap_strerror(write_err));
goto error_on_exit;
}
- wtap_free_shb(shb_hdr);
+ wtap_optionblock_free(shb_hdr);
shb_hdr = NULL;
- wtap_free_nrb(nrb_hdr);
+ wtap_optionblock_free(nrb_hdr);
nrb_hdr = NULL;
g_free(filename);
return 0;
error_on_exit:
- wtap_free_shb(shb_hdr);
- wtap_free_nrb(nrb_hdr);
+ wtap_optionblock_free(shb_hdr);
+ wtap_optionblock_free(nrb_hdr);
g_free(idb_inf);
exit(2);
}