Mergecap utility for merging capture files, from Scott Renfro.

svn path=/trunk/; revision=3701
This commit is contained in:
Guy Harris 2001-07-12 19:59:41 +00:00
parent c5881bc7b9
commit e9d00f4a4f
12 changed files with 559 additions and 14 deletions

View File

@ -25,6 +25,8 @@ install-sh
libtool
ltconfig
ltmain.sh
mergecap
mergecap.1
missing
mkinstalldirs
packet-ncp2222.c

View File

@ -734,6 +734,7 @@ Pekka Savola <pekkas@netcore.fi> {
Scott Renfro <scott@renfro.org> {
SSL/TLS support
Mergecap utility for merging capture files
}
David Eisner <cradle@Glue.umd.edu> {

View File

@ -49,8 +49,8 @@ Installation Checklist
You won't be able to capture packets, but you can read traces
that have already been captured to disk by other programs.
You can build or not build ethereal, tethereal, and editcap
with the appropriate --enable-XXX or --disable-XXX flags.
You can build or not build ethereal, tethereal, editcap, and
mergecap with the appropriate --enable-XXX or --disable-XXX flags.
The default is to build everything. If GTK+ is not detected
on the system, then ethereal won't be built.

View File

@ -1,7 +1,7 @@
# Makefile.am
# Automake file for Ethereal
#
# $Id: Makefile.am,v 1.349 2001/07/11 18:19:15 guy Exp $
# $Id: Makefile.am,v 1.350 2001/07/12 19:59:38 guy Exp $
#
# Ethereal - Network traffic analyzer
# By Gerald Combs <gerald@ethereal.com>
@ -60,11 +60,11 @@ ACLOCAL_AMFLAGS = `./aclocal-flags`
# automake will arrange that the Makefile define it as the union of all
# the "man{section}_MANS" variables.
#
bin_PROGRAMS = @ethereal_bin@ @editcap_bin@ @tethereal_bin@ @dftest_bin@ @randpkt_bin@ @text2pcap_bin@
man1_MANS = @ethereal_man@ @editcap_man@ @tethereal_man@ @text2pcap_man@
bin_PROGRAMS = @ethereal_bin@ @editcap_bin@ @mergecap_bin@ @tethereal_bin@ @dftest_bin@ @randpkt_bin@ @text2pcap_bin@
man1_MANS = @ethereal_man@ @editcap_man@ @mergecap_man@ @tethereal_man@ @text2pcap_man@
man_MANS =
EXTRA_PROGRAMS = ethereal ethereal_static tethereal tethereal_static editcap dftest text2pcap
EXTRA_PROGRAMS = ethereal ethereal_static tethereal tethereal_static editcap mergecap dftest text2pcap
sysconf_DATA = manuf
@ -583,6 +583,9 @@ tethereal_static_LDFLAGS = -Wl,-static
text2pcap_SOURCES = text2pcap.c text2pcap-scanner.l
text2pcap_DEPENDENCIES = text2pcap.h
mergecap_SOURCES = mergecap.c
mergecap_DEPENDENCIES = wiretap/libwiretap.a
editcap_SOURCES = editcap.c
# This is the automake dependency variable for the executable
@ -590,6 +593,7 @@ editcap_DEPENDENCIES = wiretap/libwiretap.a
# This automake variable adds to the link-line for the executable
editcap_LDADD = wiretap/libwiretap.a @GLIB_LIBS@
mergecap_LDADD = wiretap/libwiretap.a @GLIB_LIBS@
#
# Build various header files for the X11 dissector.
@ -703,12 +707,14 @@ EXTRA_DIST = \
doc/dfilter2pod.pl \
doc/editcap.pod \
doc/ethereal.pod.template \
doc/mergecap.pod \
doc/randpkt.txt \
doc/tethereal.pod.template \
doc/text2pcap.pod \
editcap.c \
ethereal_be.py \
ethereal_gen.py \
mergecap.c \
text2pcap.c \
text2pcap.h \
text2pcap-scanner.l \
@ -790,6 +796,10 @@ editcap.1: doc/editcap.pod
(cd doc ; \
$(MAKE) ../editcap.1 )
mergecap.1: doc/mergecap.pod
(cd doc ; \
$(MAKE) ../mergecap.1 )
text2pcap.1: doc/text2pcap.pod
(cd doc ; \
$(MAKE) ../text2pcap.1 )

View File

@ -1,7 +1,7 @@
## Makefile for building ethereal.exe with Microsoft C and nmake
## Use: $(MAKE) /$(MAKEFLAGS) -f makefile.nmake
#
# $Id: Makefile.nmake,v 1.124 2001/07/11 18:19:15 guy Exp $
# $Id: Makefile.nmake,v 1.125 2001/07/12 19:59:38 guy Exp $
include config.nmake
include <win32.mak>
@ -286,15 +286,20 @@ editcap_LIBS= wiretap\wiretap-$(WTAP_VERSION).lib \
$(GLIB_DIR)\glib-$(GLIB_VERSION).lib \
$(GLIB_DIR)\gmodule\gmodule-$(GLIB_VERSION).lib
mergecap_LIBS= wiretap\wiretap-$(WTAP_VERSION).lib \
wsock32.lib user32.lib \
$(GLIB_DIR)\glib-$(GLIB_VERSION).lib \
$(GLIB_DIR)\gmodule\gmodule-$(GLIB_VERSION).lib
dftest_LIBS= epan\ethereal.lib \
epan\dfilter\dfilter.lib epan\ftypes\ftypes.lib \
wsock32.lib user32.lib \
$(GLIB_DIR)\glib-$(GLIB_VERSION).lib \
$(GLIB_DIR)\gmodule\gmodule-$(GLIB_VERSION).lib
EXECUTABLES=ethereal.exe tethereal.exe editcap.exe text2pcap.exe
EXECUTABLES=ethereal.exe tethereal.exe editcap.exe mergecap.exe text2pcap.exe
RESOURCES=image\ethereal.res image\tethereal.res image\editcap.res image\text2pcap.res
RESOURCES=image\ethereal.res image\tethereal.res image\editcap.res image\mergecap.res image\text2pcap.res
all: tools wiretap gtk epan image $(EXECUTABLES) $(RESOURCES)
@ -316,6 +321,12 @@ editcap.exe : config.h editcap.obj getopt.obj wiretap\wiretap-$(WTAP_VERSION).li
/OUT:editcap.exe $(conflags) $(conlibsdll) $(LDFLAGS) /SUBSYSTEM:console editcap.obj getopt.obj $(editcap_LIBS) image\editcap.res
<<
mergecap.exe : config.h mergecap.obj getopt.obj wiretap\wiretap-$(WTAP_VERSION).lib image\mergecap.res
@echo Linking $@
$(LINK) @<<
/OUT:mergecap.exe $(conflags) $(conlibsdll) $(LDFLAGS) /SUBSYSTEM:console mergecap.obj getopt.obj $(mergecap_LIBS) image\mergecap.res
<<
text2pcap.exe : config.h text2pcap.obj text2pcap-scanner.obj getopt.obj image\text2pcap.res
@echo Linking $@
$(LINK) @<<
@ -361,7 +372,7 @@ text2pcap-scanner.c : text2pcap-scanner.l
clean:
rm -f $(ethereal_OBJECTS) $(EXTRA_OBJECTS) $(EXECUTABLES) \
tethereal.obj editcap.obj text2pcap.obj \
tethereal.obj editcap.obj mergecap.obj text2pcap.obj \
text2pcap-scanner.c register.c rdps.obj config.h \
ps.c packet-ncp2222.c register.c
cd wiretap

View File

@ -1,4 +1,4 @@
# $Id: configure.in,v 1.130 2001/06/27 07:47:48 guy Exp $
# $Id: configure.in,v 1.131 2001/07/12 19:59:38 guy Exp $
dnl
dnl Process this file with autoconf 2.13 or later to produce a
dnl configure script; 2.12 doesn't generate a "configure" script that
@ -282,6 +282,22 @@ AC_SUBST(editcap_bin)
AC_SUBST(editcap_man)
# Enable/disable mergecap
AC_ARG_ENABLE(mergecap,
[ --enable-mergecap build mergecap. [default=yes]],,enable_mergecap=yes)
if test "x$enable_mergecap" = "xyes" ; then
mergecap_bin="mergecap"
mergecap_man="mergecap.1"
else
mergecap_bin=""
mergecap_man=""
fi
AC_SUBST(mergecap_bin)
AC_SUBST(mergecap_man)
# Enable/disable text2pcap
AC_ARG_ENABLE(text2pcap,
@ -638,6 +654,7 @@ echo "The Ethereal package has been configured with the following options."
echo " Build ethereal : $enable_ethereal"
echo " Build tethereal : $enable_tethereal"
echo " Build editcap : $enable_editcap"
echo " Build mergecap : $enable_mergecap"
echo " Build text2pcap : $enable_text2pcap"
echo " Build randpkt : $enable_randpkt"
echo " Build dftest : $enable_dftest"

View File

@ -1,7 +1,7 @@
# Makefile.am
# Automake file for Ethereal documentation
#
# $Id: Makefile.am,v 1.10 2001/05/16 21:32:05 ashokn Exp $
# $Id: Makefile.am,v 1.11 2001/07/12 19:59:40 guy Exp $
#
# Ethereal - Network traffic analyzer
# By Gerald Combs <gerald@zing.org>
@ -49,6 +49,12 @@ tethereal.pod: tethereal.pod.template ../tethereal
--release=$(VERSION) \
> ../editcap.1
../mergecap.1: mergecap.pod ../config.h
pod2man $(srcdir)/mergecap.pod \
--center="The Ethereal Network Analyzer" \
--release=$(VERSION) \
> ../mergecap.1
../text2pcap.1: text2pcap.pod ../config.h
pod2man $(srcdir)/text2pcap.pod \
--center="The Ethereal Network Analyzer" \

View File

@ -118,7 +118,7 @@ Prints the version and options and exits.
=head1 SEE ALSO
L<tcpdump(8)>, L<pcap(3)>, L<ethereal(1)>
L<tcpdump(8)>, L<pcap(3)>, L<ethereal(1)>, L<mergecap(1)>
=head1 NOTES

127
doc/mergecap.pod Normal file
View File

@ -0,0 +1,127 @@
=head1 NAME
mergecap - Merges two capture files into one
=head1 SYNOPSYS
B<mergecap>
S<[ B<-F> file format ]>
S<[ B<-T> encapsulation type ]>
S<[ B<-a> ]>
S<[ B<-v> ]>
S<[ B<-s> snaplen ]>
S<[ B<-h> ]>
I<infile1>
I<infile2>
I<outfile>
=head1 DESCRIPTION
B<Mergecap> is a program that reads two saved capture files and merges
all of the packets in those capture files into a third capture
file. B<Mergecap> knows how to read B<libpcap> capture files, including
those of B<tcpdump>. In addition, B<Mergecap> can read capture files
from B<snoop> (including B<Shomiti>) and B<atmsnoop>, B<LanAlyzer>,
B<Sniffer> (compressed or uncompressed), Microsoft B<Network Monitor>,
AIX's B<iptrace>, B<NetXray>, B<Sniffer Pro>, B<RADCOM>'s WAN/LAN
analyzer, B<Lucent/Ascend> router debug output, HP-UX's B<nettl>, and
the dump output from B<Toshiba's> ISDN routers. There is no need to
tell B<Mergecap> what type of file you are reading; it will determine the
file type by itself. B<Mergecap> is also capable of reading any of
these file formats if they are compressed using gzip. B<Mergecap>
recognizes this directly from the file; the '.gz' extension is not
required for this purpose.
By default, it writes the capture file in B<libpcap> format, and writes
all of the packets in both input capture files to the output file. The
B<-F> flag can be used to specify the format in which to write the
capture file; it can write the file in B<libpcap> format (standard
B<libpcap> format, a modified format used by some patched versions of
B<libpcap>, the format used by Red Hat Linux 6.1, or the format used by
SuSE Linux 6.3), B<snoop> format, uncompressed B<Sniffer> format,
Microsoft B<Network Monitor> 1.x format, and the format used by
Windows-based versions of the B<Sniffer> software.
By default, the packets in the input files are merged in chronological
order based on each frame's timestamp, unless the B<-a> flag is
specified. B<Mergecap> assumes that frames within a single capture file
are already stored in chronological order. When the B<-a> flag is
specified, all the packets from the first input capture file are output,
followed by all of the packets from the second input capture file.
If the B<-s> flag is used to specify a snapshot length, frames in the
input file with more captured data than the specified snapshot length
will have only the amount of data specified by the snapshot length
written to the output file. This may be useful if the program that is
to read the output file cannot handle packets larger than a certain size
(for example, the versions of snoop in Solaris 2.5.1 and Solaris 2.6
appear to reject Ethernet frames larger than the standard Ethernet MTU,
making them incapable of handling gigabit Ethernet captures if jumbo
frames were used).
If the B<-T> flag is used to specify an encapsulation type, the
encapsulation type of the output capture file will be forced to the
specified type, rather than being the type appropriate to the
encapsulation type of the input capture file. Note that this merely
forces the encapsulation type of the output file to be the specified
type; the packet headers of the packets will not be translated from the
encapsulation type of the input capture file to the specified
encapsulation type (for example, it will not translate an Ethernet
capture to an FDDI capture if an Ethernet capture is read and 'B<-T
fddi>' is specified).
=head1 OPTIONS
=over 4
=item -F
Sets the file format of the output capture file.
=item -T
Sets the packet encapsulation type of the output capture file.
=item -a
Causes the frame timestamps to be ignored, writing all packets from the
first input file followed by all packets from the second input file. By
default, when B<-a> is not specified, the contents of the input files
are merged in chronological order based on each frame's timestamp.
Note: when merging, B<mergecap> assumes that packets within a capture
file are already in chronological order.
=item -v
Causes B<mergecap> to print a number of messages while it's working.
=item -s
Sets the snapshot length to use when writing the data.
=item -h
Prints the version and options and exits.
=head1 SEE ALSO
L<tcpdump(8)>, L<pcap(3)>, L<ethereal(1)>, L<editcap(1)>
=head1 NOTES
B<Mergecap> is based heavily upon B<editcap> by Richard Sharpe
<sharpe@ns.aus.com> and Guy Harris <guy@alum.mit.edu>.
B<Mergecap> is part of the B<Ethereal> distribution. The latest version
of B<Ethereal> can be found at B<http://www.ethereal.com>.
=head1 AUTHORS
Original Author
-------- ------
Scott Renfro <scott@renfro.org>
Contributors
------------

View File

@ -1,5 +1,5 @@
#
# $Id: Makefile.nmake,v 1.2 2001/05/21 05:04:49 guy Exp $
# $Id: Makefile.nmake,v 1.3 2001/07/12 19:59:41 guy Exp $
#
include ..\config.nmake
@ -22,6 +22,11 @@ editcap.rc : editcap.rc.in
-e s/@RC_VERSION@/$(RC_VERSION)/ \
< editcap.rc.in > $@
mergecap.rc : mergecap.rc.in
sed -e s/@VERSION@/$(VERSION)/ \
-e s/@RC_VERSION@/$(RC_VERSION)/ \
< mergecap.rc.in > $@
text2pcap.rc : text2pcap.rc.in
sed -e s/@VERSION@/$(VERSION)/ \
-e s/@RC_VERSION@/$(RC_VERSION)/ \

36
image/mergecap.rc.in Normal file
View File

@ -0,0 +1,36 @@
#include "winver.h"
ETHEREAL_ICON ICON "ethereal.ico"
VS_VERSION_INFO VERSIONINFO
FILEVERSION @RC_VERSION@,0
PRODUCTVERSION @RC_VERSION@,0
FILEFLAGSMASK 0x0L
#ifdef _DEBUG
FILEFLAGS 0x3L
#else
FILEFLAGS 0x2L
#endif
FILEOS 0x4L
FILETYPE 0x1L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904b0"
BEGIN
VALUE "CompanyName", "The Ethereal developer community\0"
VALUE "FileDescription", "Mergecap\0"
VALUE "FileVersion", "@VERSION@\0"
VALUE "InternalName", "Mergecap @VERSION@\0"
VALUE "LegalCopyright", "Copyright © 2000 Gerald Combs <gerald@ethereal.com>, Gilbert Ramirez <gram@xiexie.org> and others\0"
VALUE "OriginalFilename", "Mergecap.exe\0"
VALUE "ProductName", "Mergecap\0"
VALUE "ProductVersion", "@VERSION@\0"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x409, 1200
END
END

330
mergecap.c Normal file
View File

@ -0,0 +1,330 @@
/* Combine two dump files, either by appending or by merging by timestamp
*
* $Id: mergecap.c,v 1.1 2001/07/12 19:59:39 guy Exp $
*
* Written by Scott Renfro <scott@renfro.org> based on
* editcap by Richard Sharpe and Guy Harris
*
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdio.h>
#include <stdlib.h>
#include <glib.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
#ifdef HAVE_WINSOCK_H
#include <winsock.h>
#endif
#include <string.h>
#include "wtap.h"
#ifdef NEED_GETOPT_H
#include "getopt.h"
#endif
#ifndef MAX
# define MAX(a,b) ((a)>(b))?(a):(b)
#endif
/*
* Some globals so we can pass things to various routines
*/
static int count = 1;
static int out_file_type = WTAP_FILE_PCAP; /* default to "libpcap" */
static int out_frame_type = -2; /* Leave frame type alone */
static int verbose = 0; /* Not so verbose */
static int do_append = 0; /* append, don't merge */
static unsigned int snaplen = 0; /* No limit */
/*
* Routine to write frame to output file
*/
static void
write_frame(u_char *user, const struct wtap_pkthdr *phdr, int offset,
union wtap_pseudo_header *pseudo_header, const u_char *buf)
{
wtap_dumper *pdh = (wtap_dumper*)user;
int err;
struct wtap_pkthdr snap_phdr;
if (verbose)
printf("Record: %u\n", count++);
/* We simply write it, perhaps after truncating it; we could do other
* things, like modify it. */
if (snaplen != 0 && phdr->caplen > snaplen) {
snap_phdr = *phdr;
snap_phdr.caplen = snaplen;
phdr = &snap_phdr;
}
if (!wtap_dump(pdh, phdr, pseudo_header, buf, &err)) {
fprintf(stderr, "editcap: Error writing to output: %s\n",
wtap_strerror(err));
exit(1);
}
}
/*
* routine to append file2 to file1
*/
static void
append(wtap *wth_1, wtap *wth_2, wtap_dumper *pdh)
{
int err;
if (!wtap_loop(wth_1, 0, write_frame, (u_char*)pdh, &err)) {
fprintf(stderr, "mergecap: Error appending: %s\n",
wtap_strerror(err));
}
if (!wtap_loop(wth_2, 0, write_frame, (u_char*)pdh, &err)) {
fprintf(stderr, "mergecap: Error appending: %s\n",
wtap_strerror(err));
}
}
/*
* judges whether the first argument has an earlier
* timestamp than the second
*/
static gboolean
is_earlier(struct wtap_pkthdr *one, struct wtap_pkthdr *two)
{
if (one->ts.tv_sec > two->ts.tv_sec) {
return FALSE;
} else if (one->ts.tv_sec < two->ts.tv_sec) {
return TRUE;
} else if (one->ts.tv_usec > two->ts.tv_usec) {
return FALSE;
}
/* either one < two or one == two
* either way, return one
*/
return TRUE;
}
/*
* actually merge the files
*/
static void
merge(wtap *wth_1, wtap *wth_2, wtap_dumper *pdh)
{
int err;
int data_offset_1, data_offset_2, loop = 0;
gboolean ok_1, ok_2;
ok_1 = wtap_read(wth_1, &err, &data_offset_1);
ok_2 = wtap_read(wth_2, &err, &data_offset_2);
while (ok_1 && ok_2) {
/* if wth_1 is earlier, then write it and fetch another
* otherwise, write wth_2 and increment it
*/
if (is_earlier(wtap_phdr(wth_1), wtap_phdr(wth_2))) {
write_frame((u_char*)pdh, wtap_phdr(wth_1), data_offset_1,
wtap_pseudoheader(wth_1), wtap_buf_ptr(wth_1));
ok_1 = wtap_read(wth_1, &err, &data_offset_1);
} else{
write_frame((u_char*)pdh, wtap_phdr(wth_2), data_offset_2,
wtap_pseudoheader(wth_2), wtap_buf_ptr(wth_2));
ok_2 = wtap_read(wth_2, &err, &data_offset_2);
}
}
while (ok_1) {
write_frame((u_char*)pdh, wtap_phdr(wth_1), data_offset_1,
wtap_pseudoheader(wth_1), wtap_buf_ptr(wth_1));
ok_1 = wtap_read(wth_1, &err, &data_offset_1);
}
while (ok_2) {
write_frame((u_char*)pdh, wtap_phdr(wth_2), data_offset_2,
wtap_pseudoheader(wth_2), wtap_buf_ptr(wth_2));
ok_2 = wtap_read(wth_2, &err, &data_offset_2);
}
}
/*
* routine to open the input and output files, then call the merge
*/
static void
merge_files(const char *from1, const char *from2, const char *into)
{
int err;
wtap *wth_1, *wth_2;
wtap_dumper *pdh;
/* open the input files */
wth_1 = wtap_open_offline(from1, &err, FALSE);
if (!wth_1) {
fprintf(stderr, "mergecap: Can't open %s: %s\n", from1,
wtap_strerror(err));
exit(1);
}
wth_2 = wtap_open_offline(from2, &err, FALSE);
if (!wth_2) {
fprintf(stderr, "mergecap: Can't open %s: %s\n", from2,
wtap_strerror(err));
wtap_close(wth_1);
exit(1);
}
if (verbose) {
fprintf(stderr, "File %s is a %s capture file.\n", from1,
wtap_file_type_string(wtap_file_type(wth_1)));
fprintf(stderr, "File %s is a %s capture file.\n", from2,
wtap_file_type_string(wtap_file_type(wth_2)));
}
/* open the output file */
if (out_frame_type == -2)
out_frame_type = wtap_file_encap(wth_1);
pdh = wtap_dump_open(into, out_file_type, out_frame_type,
MAX(wtap_snapshot_length(wth_1),
wtap_snapshot_length(wth_2)), &err);
if (!pdh) {
fprintf(stderr, "mergecap: Can't open/create %s: %s\n", into,
wtap_strerror(err));
wtap_close(wth_1);
wtap_close(wth_2);
exit(1);
}
if (do_append)
append(wth_1, wth_2, pdh);
else
merge(wth_1, wth_2, pdh);
wtap_close(wth_1);
wtap_close(wth_2);
if (!wtap_dump_close(pdh, &err)) {
fprintf(stderr, "mergecap: Error writing to %s: %s\n", into,
wtap_strerror(err));
exit(1);
}
}
void usage()
{
int i;
const char *string;
fprintf(stderr, "Usage: mergecap [-v] [-a] [-s <snaplen>]\n");
fprintf(stderr, " [-T <encap type>] [-F <capture type>]\n");
fprintf(stderr, " <infile1> <infile2> <outfile>\n\n");
fprintf(stderr, " where\t-a infile2 should be appended, not merged.\n");
fprintf(stderr, " \t Default merges based on frame timestamps.\n");
fprintf(stderr, " \t-s <snaplen> truncate packets to <snaplen>\n");
fprintf(stderr, " \t bytes of data\n");
fprintf(stderr, " \t-v verbose operation, default is silent\n");
fprintf(stderr, " \t-h produces this help listing.\n");
fprintf(stderr, " \t-T <encap type> encapsulation type to use:\n");
for (i = 0; i < WTAP_NUM_ENCAP_TYPES; i++) {
string = wtap_encap_short_string(i);
if (string != NULL)
fprintf(stderr, " \t %s - %s\n",
string, wtap_encap_string(i));
}
fprintf(stderr, " \t default is the same as the first input file\n");
fprintf(stderr, " \t-F <capture type> capture file type to write:\n");
for (i = 0; i < WTAP_NUM_FILE_TYPES; i++) {
if (wtap_dump_can_open(i))
fprintf(stderr, " \t %s - %s\n",
wtap_file_type_short_string(i), wtap_file_type_string(i));
}
fprintf(stderr, " \t default is libpcap\n");
}
int
main(int argc, char *argv[])
{
wtap *wth;
int i, err;
extern char *optarg;
extern int optind;
char opt;
char *p;
/* Process the options first */
while ((opt = getopt(argc, argv, "aT:F:vs:h")) != EOF) {
switch (opt) {
case 'a':
do_append = !do_append;
break;
case 'T':
out_frame_type = wtap_short_string_to_encap(optarg);
if (out_frame_type < 0) {
fprintf(stderr, "mergecap: \"%s\" is not a valid encapsulation type\n",
optarg);
exit(1);
}
break;
case 'F':
out_file_type = wtap_short_string_to_file_type(optarg);
if (out_file_type < 0) {
fprintf(stderr, "editcap: \"%s\" is not a valid capture file type\n",
optarg);
exit(1);
}
break;
case 'v':
verbose = !verbose; /* Just invert */
break;
case 's':
snaplen = strtol(optarg, &p, 10);
if (p == optarg || *p != '\0') {
fprintf(stderr, "editcap: \"%s\" is not a valid snapshot length\n",
optarg);
exit(1);
}
break;
case 'h':
fprintf(stderr, "mergecap version %s\n", VERSION);
usage();
exit(1);
break;
case '?': /* Bad options if GNU getopt */
usage();
exit(1);
break;
}
}
/* should now have three arguments left: infile1, infile2, outfile */
#ifdef DEBUG
printf("Optind = %i, argc = %i\n", optind, argc);
#endif
if ((argc - optind) < 3) {
usage();
exit(1);
}
merge_files(argv[optind], argv[optind+1], argv[optind+2]);
return 0;
}