diff options
author | Jeff Morriss <jeff.morriss.ws@gmail.com> | 2013-07-16 02:35:33 +0000 |
---|---|---|
committer | Jeff Morriss <jeff.morriss.ws@gmail.com> | 2013-07-16 02:35:33 +0000 |
commit | 0a669967fa719111db64437f7dd3b2869091f9e8 (patch) | |
tree | 35aa1a3589fe2927087c1482683afaccb0183c89 /wiretap | |
parent | d331c33b4ff4f5ce6c001a040db5ba1a0ded1c60 (diff) |
Move merge.{h,c} into wiretap: these modules use wiretap to merge files.
svn path=/trunk/; revision=50656
Diffstat (limited to 'wiretap')
-rw-r--r-- | wiretap/CMakeLists.txt | 1 | ||||
-rw-r--r-- | wiretap/Makefile.common | 2 | ||||
-rw-r--r-- | wiretap/merge.c | 286 | ||||
-rw-r--r-- | wiretap/merge.h | 130 |
4 files changed, 419 insertions, 0 deletions
diff --git a/wiretap/CMakeLists.txt b/wiretap/CMakeLists.txt index 1ddbcfdbf1..4dcacdbd46 100644 --- a/wiretap/CMakeLists.txt +++ b/wiretap/CMakeLists.txt @@ -50,6 +50,7 @@ set(WIRETAP_FILES k12.c lanalyzer.c libpcap.c + merge.c mpeg.c mime_file.c mp2t.c diff --git a/wiretap/Makefile.common b/wiretap/Makefile.common index 8726adbb2e..eb54501c61 100644 --- a/wiretap/Makefile.common +++ b/wiretap/Makefile.common @@ -57,6 +57,7 @@ NONGENERATED_C_FILES = \ k12.c \ lanalyzer.c \ libpcap.c \ + merge.c \ mpeg.c \ mp2t.c \ netmon.c \ @@ -113,6 +114,7 @@ NONGENERATED_HEADER_FILES = \ lanalyzer.h \ libpcap.h \ mpeg.h \ + mpeg.h \ mp2t.h \ netmon.h \ netscreen.h \ diff --git a/wiretap/merge.c b/wiretap/merge.c new file mode 100644 index 0000000000..264f66c3ed --- /dev/null +++ b/wiretap/merge.c @@ -0,0 +1,286 @@ +/* Combine multiple dump files, either by appending or by merging by timestamp + * + * Written by Scott Renfro <scott@renfro.org> based on + * editcap by Richard Sharpe and Guy Harris + * + * Copyright 2013, Scott Renfro <scott[AT]renfro.org> + * + * $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 "config.h" + +#include <stdio.h> +#include <stdlib.h> +#include <glib.h> +#include <errno.h> + +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif + +#ifdef HAVE_SYS_TIME_H +#include <sys/time.h> +#endif + +#include <string.h> +#include "merge.h" + +/* + * Scan through the arguments and open the input files + */ +gboolean +merge_open_in_files(int in_file_count, char *const *in_file_names, + merge_in_file_t **in_files, int *err, gchar **err_info, + int *err_fileno) +{ + int i, j; + size_t files_size = in_file_count * sizeof(merge_in_file_t); + merge_in_file_t *files; + gint64 size; + + files = (merge_in_file_t *)g_malloc(files_size); + *in_files = files; + + for (i = 0; i < in_file_count; i++) { + files[i].filename = in_file_names[i]; + files[i].wth = wtap_open_offline(in_file_names[i], err, err_info, FALSE); + files[i].data_offset = 0; + files[i].state = PACKET_NOT_PRESENT; + files[i].packet_num = 0; + if (!files[i].wth) { + /* Close the files we've already opened. */ + for (j = 0; j < i; j++) + wtap_close(files[j].wth); + *err_fileno = i; + return FALSE; + } + size = wtap_file_size(files[i].wth, err); + if (size == -1) { + for (j = 0; j <= i; j++) + wtap_close(files[j].wth); + *err_fileno = i; + return FALSE; + } + files[i].size = size; + } + return TRUE; +} + +/* + * Scan through and close each input file + */ +void +merge_close_in_files(int count, merge_in_file_t in_files[]) +{ + int i; + for (i = 0; i < count; i++) { + wtap_close(in_files[i].wth); + } +} + +/* + * Select an output frame type based on the input files + * From Guy: If all files have the same frame type, then use that. + * Otherwise select WTAP_ENCAP_PER_PACKET. If the selected + * output file type doesn't support per packet frame types, + * then the wtap_dump_open call will fail with a reasonable + * error condition. + */ +int +merge_select_frame_type(int count, merge_in_file_t files[]) +{ + int i; + int selected_frame_type; + + selected_frame_type = wtap_file_encap(files[0].wth); + + for (i = 1; i < count; i++) { + int this_frame_type = wtap_file_encap(files[i].wth); + if (selected_frame_type != this_frame_type) { + selected_frame_type = WTAP_ENCAP_PER_PACKET; + break; + } + } + + return selected_frame_type; +} + +/* + * Scan through input files and find maximum snapshot length + */ +int +merge_max_snapshot_length(int count, merge_in_file_t in_files[]) +{ + int i; + int max_snapshot = 0; + int snapshot_length; + + for (i = 0; i < count; i++) { + snapshot_length = wtap_snapshot_length(in_files[i].wth); + if (snapshot_length == 0) { + /* Snapshot length of input file not known. */ + snapshot_length = WTAP_MAX_PACKET_SIZE; + } + if (snapshot_length > max_snapshot) + max_snapshot = snapshot_length; + } + return max_snapshot; +} + +/* + * returns TRUE if first argument is earlier than second + */ +static gboolean +is_earlier(struct wtap_nstime *l, struct wtap_nstime *r) { + if (l->secs > r->secs) { /* left is later */ + return FALSE; + } else if (l->secs < r->secs) { /* left is earlier */ + return TRUE; + } else if (l->nsecs > r->nsecs) { /* tv_sec equal, l.usec later */ + return FALSE; + } + /* either one < two or one == two + * either way, return one + */ + return TRUE; +} + +/* + * Read the next packet, in chronological order, from the set of files + * to be merged. + * + * On success, set *err to 0 and return a pointer to the merge_in_file_t + * for the file from which the packet was read. + * + * On a read error, set *err to the error and return a pointer to the + * merge_in_file_t for the file on which we got an error. + * + * On an EOF (meaning all the files are at EOF), set *err to 0 and return + * NULL. + */ +merge_in_file_t * +merge_read_packet(int in_file_count, merge_in_file_t in_files[], + int *err, gchar **err_info) +{ + int i; + int ei = -1; + struct wtap_nstime tv = { sizeof(time_t) > sizeof(int) ? LONG_MAX : INT_MAX, INT_MAX }; + struct wtap_pkthdr *phdr; + + /* + * Make sure we have a packet available from each file, if there are any + * packets left in the file in question, and search for the packet + * with the earliest time stamp. + */ + for (i = 0; i < in_file_count; i++) { + if (in_files[i].state == PACKET_NOT_PRESENT) { + /* + * No packet available, and we haven't seen an error or EOF yet, + * so try to read the next packet. + */ + if (!wtap_read(in_files[i].wth, err, err_info, &in_files[i].data_offset)) { + if (*err != 0) { + in_files[i].state = GOT_ERROR; + return &in_files[i]; + } + in_files[i].state = AT_EOF; + } else + in_files[i].state = PACKET_PRESENT; + } + + if (in_files[i].state == PACKET_PRESENT) { + phdr = wtap_phdr(in_files[i].wth); + if (is_earlier(&phdr->ts, &tv)) { + tv = phdr->ts; + ei = i; + } + } + } + + if (ei == -1) { + /* All the streams are at EOF. Return an EOF indication. */ + *err = 0; + return NULL; + } + + /* We'll need to read another packet from this file. */ + in_files[ei].state = PACKET_NOT_PRESENT; + + /* Count this packet. */ + in_files[ei].packet_num++; + + /* + * Return a pointer to the merge_in_file_t of the file from which the + * packet was read. + */ + *err = 0; + return &in_files[ei]; +} + +/* + * Read the next packet, in file sequence order, from the set of files + * to be merged. + * + * On success, set *err to 0 and return a pointer to the merge_in_file_t + * for the file from which the packet was read. + * + * On a read error, set *err to the error and return a pointer to the + * merge_in_file_t for the file on which we got an error. + * + * On an EOF (meaning all the files are at EOF), set *err to 0 and return + * NULL. + */ +merge_in_file_t * +merge_append_read_packet(int in_file_count, merge_in_file_t in_files[], + int *err, gchar **err_info) +{ + int i; + + /* + * Find the first file not at EOF, and read the next packet from it. + */ + for (i = 0; i < in_file_count; i++) { + if (in_files[i].state == AT_EOF) + continue; /* This file is already at EOF */ + if (wtap_read(in_files[i].wth, err, err_info, &in_files[i].data_offset)) + break; /* We have a packet */ + if (*err != 0) { + /* Read error - quit immediately. */ + in_files[i].state = GOT_ERROR; + return &in_files[i]; + } + /* EOF - flag this file as being at EOF, and try the next one. */ + in_files[i].state = AT_EOF; + } + if (i == in_file_count) { + /* All the streams are at EOF. Return an EOF indication. */ + *err = 0; + return NULL; + } + + /* + * Return a pointer to the merge_in_file_t of the file from which the + * packet was read. + */ + *err = 0; + return &in_files[i]; +} diff --git a/wiretap/merge.h b/wiretap/merge.h new file mode 100644 index 0000000000..12be91bc12 --- /dev/null +++ b/wiretap/merge.h @@ -0,0 +1,130 @@ +/* merge.h + * Definitions for routines for merging files. + * + * $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. + */ + +#ifndef __MERGE_H__ +#define __MERGE_H__ + +#include "wiretap/wtap.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +typedef enum { + PACKET_PRESENT, + PACKET_NOT_PRESENT, + AT_EOF, + GOT_ERROR +} in_file_state_e; + +/** + * Structures to manage our input files. + */ +typedef struct merge_in_file_s { + const char *filename; + wtap *wth; + gint64 data_offset; + in_file_state_e state; + guint32 packet_num; /* current packet number */ + gint64 size; /* file size */ + guint32 interface_id; /* identifier of the interface. + * Used for fake interfaces when writing WTAP_ENCAP_PER_PACKET */ +} merge_in_file_t; + +/** Open a number of input files to merge. + * + * @param in_file_count number of entries in in_file_names and in_files + * @param in_file_names filenames of the input files + * @param in_files input file array to be filled (>= sizeof(merge_in_file_t) * in_file_count) + * @param err wiretap error, if failed + * @param err_info wiretap error string, if failed + * @param err_fileno file on which open failed, if failed + * @return TRUE if all files could be opened, FALSE otherwise + */ +WS_DLL_PUBLIC gboolean +merge_open_in_files(int in_file_count, char *const *in_file_names, + merge_in_file_t **in_files, int *err, gchar **err_info, + int *err_fileno); + +/** Close the input files again. + * + * @param in_file_count number of entries in in_files + * @param in_files input file array to be closed + */ +WS_DLL_PUBLIC void +merge_close_in_files(int in_file_count, merge_in_file_t in_files[]); + +/** Try to get the frame type from the input files. + * + * @param in_file_count number of entries in in_files + * @param in_files input file array + * @return the frame type + */ +WS_DLL_PUBLIC int +merge_select_frame_type(int in_file_count, merge_in_file_t in_files[]); + +/** Try to get the snapshot length from the input files. + * + * @param in_file_count number of entries in in_files + * @param in_files input file array + * @return the snapshot length + */ +WS_DLL_PUBLIC int +merge_max_snapshot_length(int in_file_count, merge_in_file_t in_files[]); + +/** Read the next packet, in chronological order, from the set of files to + * be merged. + * + * @param in_file_count number of entries in in_files + * @param in_files input file array + * @param err wiretap error, if failed + * @param err_info wiretap error string, if failed + * @return pointer to merge_in_file_t for file from which that packet + * came, or NULL on error or EOF + */ +WS_DLL_PUBLIC merge_in_file_t * +merge_read_packet(int in_file_count, merge_in_file_t in_files[], int *err, + gchar **err_info); + + +/** Read the next packet, in file sequence order, from the set of files + * to be merged. + * + * @param in_file_count number of entries in in_files + * @param in_files input file array + * @param err wiretap error, if failed + * @param err_info wiretap error string, if failed + * @return pointer to merge_in_file_t for file from which that packet + * came, or NULL on error or EOF + */ +WS_DLL_PUBLIC merge_in_file_t * +merge_append_read_packet(int in_file_count, merge_in_file_t in_files[], + int *err, gchar **err_info); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __MERGE_H__ */ + |