Add a new console wiretap program to reorder the frames within a capture

file.  This version has been tested with pcap and IxCatapult files.

Haven't got config/makefile changes quite right yet, will commit later.

svn path=/trunk/; revision=45023
This commit is contained in:
Martin Mathieson 2012-09-20 10:28:05 +00:00
parent 32ed74e83d
commit f4edf2fa41
1 changed files with 353 additions and 0 deletions

353
reordercap.c Normal file
View File

@ -0,0 +1,353 @@
/* Reorder the frames from an input dump file, and write to output dump file.
* Martin Mathieson
*
* $Id$
*
* 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.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include "wtap.h"
/* Show command-line usage */
/* TODO: add reoder list length as an optional param? */
static void usage(void)
{
printf("usage: reorder <infile> <outfile>\n");
}
/* Remember where this frame was in the file */
typedef struct FrameRecord_t {
gint64 offset;
guint32 length;
struct wtap_nstime time;
/* List item pointers */
struct FrameRecord_t *prev;
struct FrameRecord_t *next;
} FrameRecord_t;
/* This is pretty big, but I don't mind waiting a few seconds */
#define MAX_REORDER_LIST_LENGTH 3000
static int g_FrameRecordCount;
/* This is the list of frames, sorted by time. Later frames at the front, earlier
ones at the end */
static FrameRecord_t *g_FrameListHead;
static FrameRecord_t *g_FrameListTail;
/**************************************************/
/* Debugging only */
/* Enable this symbol to see debug output */
#define REORDER_DEBUG
#ifdef REORDER_DEBUG
static void ReorderListDebugPrint(void)
{
int count=0;
FrameRecord_t *tmp = g_FrameListHead;
printf("\n");
while (tmp != NULL) {
printf("%6d: offset=%6llu, length=%6u, time=%lu:%u",
++count, tmp->offset, tmp->length, tmp->time.secs, tmp->time.nsecs);
if (tmp == g_FrameListHead) {
printf(" (head)");
}
if (tmp == g_FrameListTail) {
printf(" (tail)\n");
}
printf("\n");
tmp = tmp->next;
}
printf("\n");
}
#else
#define ReorderListDebugPrint()
#endif
#ifdef REORDER_DEBUG
#define DEBUG_PRINT printf
#else
#define DEBUG_PRINT(...)
#endif
/**************************************************/
/* Counting frames that weren't in order */
static int g_OutOfOrder = 0;
/* Is time1 later than time2? */
static gboolean isLaterTime(struct wtap_nstime time1,
struct wtap_nstime time2)
{
if (time1.secs > time2.secs) {
return TRUE;
}
if (time1.secs == time2.secs) {
return (time1.nsecs > time2.nsecs);
}
else {
return FALSE;
}
}
/* Is the reorder list empty? */
static gboolean ReorderListEmpty(void)
{
return (g_FrameRecordCount == 0);
}
/* Is the reorder list full? */
static gboolean ReorderListFull(void)
{
return (g_FrameRecordCount >= MAX_REORDER_LIST_LENGTH);
}
/* Add a new frame to the reorder list */
/* Adding later ones to the front */
static void ReorderListAdd(gint64 offset, guint32 length,
struct wtap_nstime time)
{
FrameRecord_t *tmp;
FrameRecord_t *newFrameRecord = g_malloc(sizeof(FrameRecord_t));
/* Populate fields */
DEBUG_PRINT("\nAdded with offset=%06llu, length=%05u, secs=%lu, nsecs=%d\n",
offset, length, time.secs, time.nsecs);
newFrameRecord->offset = offset;
newFrameRecord->length = length;
newFrameRecord->time = time;
/* We will definitely add it below, so inc counter */
g_FrameRecordCount++;
/* First time, this will be the head */
if (g_FrameListHead == NULL) {
DEBUG_PRINT("this item will be head - only item\n");
g_FrameListHead = newFrameRecord;
newFrameRecord->prev = NULL;
newFrameRecord->next = NULL;
g_FrameListTail = newFrameRecord;
return;
}
/* Look for the place in the list where this item fits */
tmp = g_FrameListHead;
while (tmp != NULL) {
if (isLaterTime(time, tmp->time)) {
DEBUG_PRINT("Time was Later, writing before element\n");
/* Insert newFrameRecord *before* tmp */
/* Fix up prev item */
if (tmp == g_FrameListHead) {
/* Inserting before existing head */
g_FrameListHead = newFrameRecord;
}
else {
/* Our prev is tmps old prev */
newFrameRecord->prev = tmp->prev;
/* Its next points to us */
newFrameRecord->prev->next = newFrameRecord;
}
/* Fix up next item */
newFrameRecord->next = tmp;
tmp->prev = newFrameRecord;
g_OutOfOrder++;
return;
}
/* Didn't find an item to insert in front of */
if (tmp->next == NULL) {
DEBUG_PRINT("Reached the end of the list, so insert here\n");
/* We are the new last item */
tmp->next = newFrameRecord;
newFrameRecord->prev = tmp;
newFrameRecord->next = NULL;
g_FrameListTail = newFrameRecord;
return;
}
else {
/* Move onto the next item */
DEBUG_PRINT("Time was earlier, move to next position\n");
tmp = tmp->next;
}
}
}
/* Dump the earliest item in the reorder list to the output file, and pop it */
static void ReorderListDumpEarliest(wtap *wth, wtap_dumper *pdh)
{
union wtap_pseudo_header pseudo_header;
int err;
gchar *errinfo;
const struct wtap_pkthdr *phdr;
guint8 buf[16000];
struct wtap_pkthdr new_phdr;
FrameRecord_t *prev_tail = g_FrameListTail;
DEBUG_PRINT("\nDumping frame (offset=%llu, length=%u) (%u items in list)\n",
g_FrameListHead->offset, g_FrameListHead->length,
g_FrameRecordCount);
/* Re-read the first frame from the stored location */
wtap_seek_read(wth,
g_FrameListTail->offset,
&pseudo_header,
buf,
g_FrameListTail->length,
&err,
&errinfo);
DEBUG_PRINT("re-read: err is %u, buf is (%s)\n", err, buf);
/* Get packet header */
phdr = wtap_phdr(wth);
/* Copy, and set length and timestamp from item. */
memcpy((void*)&new_phdr, phdr, sizeof(struct wtap_pkthdr));
new_phdr.len = g_FrameListTail->length;
new_phdr.ts.secs = g_FrameListTail->time.secs;
new_phdr.ts.nsecs = g_FrameListTail->time.nsecs;
/* Dump frame to outfile */
if (!wtap_dump(pdh, &new_phdr, &pseudo_header, buf, &err)) {
printf("Error (%s) writing frame to outfile\n", wtap_strerror(err));
exit(1);
}
/* Now remove this (the last/earliest) item from the list */
if (g_FrameListTail->prev == NULL) {
g_FrameListTail = NULL;
g_FrameListHead = NULL;
}
else {
/* 2nd last item is now last */
g_FrameListTail->prev->next = NULL;
g_FrameListTail = g_FrameListTail->prev;
}
/* And free the struct */
g_free(prev_tail);
g_FrameRecordCount--;
DEBUG_PRINT("Frame written, %u remaining\n", g_FrameRecordCount);
}
/********************************************************************/
/* Main function. */
/********************************************************************/
int main(int argc, char *argv[])
{
wtap *wth = NULL;
wtap_dumper *pdh = NULL;
int err;
gchar *err_info;
gint64 data_offset;
const struct wtap_pkthdr *phdr;
guint32 read_count = 0;
/* 1st arg is infile, 2nd arg is outfile */
char *infile;
char *outfile;
if (argc == 3) {
infile = argv[1];
outfile = argv[2];
}
else {
usage();
exit(1);
}
/* Open infile */
wth = wtap_open_offline(infile, &err, &err_info, TRUE);
if (wth == NULL) {
printf("reorder: Can't open %s: %s\n", infile, wtap_strerror(err));
exit(1);
}
DEBUG_PRINT("file_type is %u\n", wtap_file_type(wth));
/* Open outfile (same filetype/encap as input file) */
pdh = wtap_dump_open(outfile, wtap_file_type(wth), wtap_file_encap(wth), 65535, FALSE, &err);
if (pdh == NULL) {
printf("Failed to open output file: (%s) - error %s\n", outfile, wtap_strerror(err));
exit(1);
}
/* Read each frame from infile */
while (wtap_read(wth, &err, &err_info, &data_offset)) {
read_count++;
phdr = wtap_phdr(wth);
/* Add it to the reordering list */
ReorderListAdd(data_offset, phdr->len, phdr->ts);
ReorderListDebugPrint();
/* If/when the list gets full, dump the earliest item out */
if (ReorderListFull()) {
DEBUG_PRINT("List is full, dumping earliest!\n");
/* Write out the earliest one */
ReorderListDumpEarliest(wth, pdh);
ReorderListDebugPrint();
}
}
/* Flush out the remaining (ordered) frames */
while (!ReorderListEmpty()) {
ReorderListDumpEarliest(wth, pdh);
ReorderListDebugPrint();
}
/* Close outfile */
if (!wtap_dump_close(pdh, &err)) {
printf("reorder: Error closing %s: %s\n", outfile, wtap_strerror(err));
exit(1);
}
/* Write how many frames, and how many were out of order */
printf("%u frames, %u out of order\n", read_count, g_OutOfOrder);
/* Finally, close infile */
wtap_fdclose(wth);
return 0;
}