When capturing, we only support writing to libpcap files. Given that,
bypass Wiretap; that means we don't have to run the packet through wtap_process_pcap_packet() and then undo that conversion in Wiretap if we're just going to write it out, shortening the code path. svn path=/trunk/; revision=17461
This commit is contained in:
parent
a8b8b3d9ff
commit
e6886d90ce
|
@ -58,6 +58,7 @@ ETHEREAL_COMMON_SRC = \
|
||||||
packet-range.c \
|
packet-range.c \
|
||||||
print.c \
|
print.c \
|
||||||
ps.c \
|
ps.c \
|
||||||
|
pcapio.c \
|
||||||
ringbuffer.c \
|
ringbuffer.c \
|
||||||
timestats.c \
|
timestats.c \
|
||||||
util.c \
|
util.c \
|
||||||
|
@ -81,6 +82,7 @@ ETHEREAL_COMMON_INCLUDES = \
|
||||||
fileset.h \
|
fileset.h \
|
||||||
isprint.h \
|
isprint.h \
|
||||||
packet-range.h \
|
packet-range.h \
|
||||||
|
pcapio.h \
|
||||||
print.h \
|
print.h \
|
||||||
ps.h \
|
ps.h \
|
||||||
register.h \
|
register.h \
|
||||||
|
@ -221,6 +223,7 @@ dumpcap_SOURCES = \
|
||||||
clopts_common.c \
|
clopts_common.c \
|
||||||
conditions.c \
|
conditions.c \
|
||||||
dumpcap.c \
|
dumpcap.c \
|
||||||
|
pcapio.c \
|
||||||
ringbuffer.c \
|
ringbuffer.c \
|
||||||
tempfile.c \
|
tempfile.c \
|
||||||
version_info.c
|
version_info.c
|
||||||
|
|
|
@ -68,8 +68,7 @@
|
||||||
|
|
||||||
#include <pcap.h>
|
#include <pcap.h>
|
||||||
|
|
||||||
#include "wiretap/wtap.h"
|
#include "pcapio.h"
|
||||||
#include "wiretap/wtap-capture.h"
|
|
||||||
|
|
||||||
#include "capture-pcap-util.h"
|
#include "capture-pcap-util.h"
|
||||||
|
|
||||||
|
@ -640,7 +639,7 @@ gboolean capture_loop_open_input(capture_options *capture_opts, loop_data *ld, c
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* open the capture input file (pcap or capture pipe) */
|
/* close the capture input file (pcap or capture pipe) */
|
||||||
static void capture_loop_close_input(loop_data *ld) {
|
static void capture_loop_close_input(loop_data *ld) {
|
||||||
|
|
||||||
g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "capture_loop_close_input");
|
g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "capture_loop_close_input");
|
||||||
|
@ -746,14 +745,14 @@ gboolean capture_loop_init_filter(pcap_t *pcap_h, gboolean from_cap_pipe, const
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* open the wiretap part of the capture output file */
|
/* set up to write to the already-opened capture output file/files */
|
||||||
gboolean capture_loop_init_wiretap_output(capture_options *capture_opts, int save_file_fd, loop_data *ld, char *errmsg, int errmsg_len) {
|
gboolean capture_loop_init_output(capture_options *capture_opts, int save_file_fd, loop_data *ld, char *errmsg, int errmsg_len) {
|
||||||
int pcap_encap;
|
int pcap_encap;
|
||||||
int file_snaplen;
|
int file_snaplen;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
|
|
||||||
g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "capture_loop_init_wiretap_output");
|
g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "capture_loop_init_output");
|
||||||
|
|
||||||
/* get packet encapsulation type and snaplen */
|
/* get packet encapsulation type and snaplen */
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
|
@ -768,22 +767,15 @@ gboolean capture_loop_init_wiretap_output(capture_options *capture_opts, int sav
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set up to write to the capture file. */
|
/* Set up to write to the capture file. */
|
||||||
ld->wtap_linktype = wtap_pcap_encap_to_wtap_encap(pcap_encap);
|
ld->linktype = pcap_encap;
|
||||||
if (ld->wtap_linktype == WTAP_ENCAP_UNKNOWN) {
|
|
||||||
g_snprintf(errmsg, errmsg_len,
|
|
||||||
"The network you're capturing from is of a type"
|
|
||||||
" that (T)Ethereal doesn't support (data link type %d).", pcap_encap);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
if (capture_opts->multi_files_on) {
|
if (capture_opts->multi_files_on) {
|
||||||
ld->wtap_pdh = ringbuf_init_wtap_dump_fdopen(WTAP_FILE_PCAP, ld->wtap_linktype,
|
ld->pdh = ringbuf_init_libpcap_fdopen(ld->linktype, file_snaplen, &err);
|
||||||
file_snaplen, &err);
|
|
||||||
} else {
|
} else {
|
||||||
ld->wtap_pdh = wtap_dump_fdopen(save_file_fd, WTAP_FILE_PCAP,
|
ld->pdh = libpcap_fdopen(save_file_fd, ld->linktype, file_snaplen,
|
||||||
ld->wtap_linktype, file_snaplen, FALSE /* compressed */, &err);
|
&ld->bytes_written, &err);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ld->wtap_pdh == NULL) {
|
if (ld->pdh == NULL) {
|
||||||
/* We couldn't set up to write to the capture file. */
|
/* We couldn't set up to write to the capture file. */
|
||||||
/* XXX - use cf_open_error_message from tethereal instead? */
|
/* XXX - use cf_open_error_message from tethereal instead? */
|
||||||
switch (err) {
|
switch (err) {
|
||||||
|
@ -824,9 +816,9 @@ gboolean capture_loop_close_output(capture_options *capture_opts, loop_data *ld,
|
||||||
g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "capture_loop_close_output");
|
g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "capture_loop_close_output");
|
||||||
|
|
||||||
if (capture_opts->multi_files_on) {
|
if (capture_opts->multi_files_on) {
|
||||||
return ringbuf_wtap_dump_close(&capture_opts->save_file, err_close);
|
return ringbuf_libpcap_dump_close(&capture_opts->save_file, err_close);
|
||||||
} else {
|
} else {
|
||||||
return wtap_dump_close(ld->wtap_pdh, err_close);
|
return libpcap_dump_close(ld->pdh, err_close);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1129,7 +1121,7 @@ capture_loop_start(capture_options *capture_opts, gboolean *stats_known, struct
|
||||||
ld.wtap_linktype = WTAP_ENCAP_UNKNOWN;
|
ld.wtap_linktype = WTAP_ENCAP_UNKNOWN;
|
||||||
ld.pcap_err = FALSE;
|
ld.pcap_err = FALSE;
|
||||||
ld.from_cap_pipe = FALSE;
|
ld.from_cap_pipe = FALSE;
|
||||||
ld.wtap_pdh = NULL;
|
ld.pdh = NULL;
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
ld.cap_pipe_fd = -1;
|
ld.cap_pipe_fd = -1;
|
||||||
#endif
|
#endif
|
||||||
|
@ -1168,8 +1160,8 @@ capture_loop_start(capture_options *capture_opts, gboolean *stats_known, struct
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* open the wiretap part of the output file (the output file is already open) */
|
/* set up to write to the already-opened capture output file/files */
|
||||||
if (!capture_loop_init_wiretap_output(capture_opts, save_file_fd, &ld, errmsg, sizeof(errmsg))) {
|
if (!capture_loop_init_output(capture_opts, save_file_fd, &ld, errmsg, sizeof(errmsg))) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1186,7 +1178,7 @@ capture_loop_start(capture_options *capture_opts, gboolean *stats_known, struct
|
||||||
message to our parent so that they'll open the capture file and
|
message to our parent so that they'll open the capture file and
|
||||||
update its windows to indicate that we have a live capture in
|
update its windows to indicate that we have a live capture in
|
||||||
progress. */
|
progress. */
|
||||||
wtap_dump_flush(ld.wtap_pdh);
|
libpcap_dump_flush(ld.pdh, NULL);
|
||||||
sync_pipe_filename_to_parent(capture_opts->save_file);
|
sync_pipe_filename_to_parent(capture_opts->save_file);
|
||||||
|
|
||||||
/* initialize capture stop (and alike) conditions */
|
/* initialize capture stop (and alike) conditions */
|
||||||
|
@ -1233,7 +1225,7 @@ capture_loop_start(capture_options *capture_opts, gboolean *stats_known, struct
|
||||||
|
|
||||||
/* check capture size condition */
|
/* check capture size condition */
|
||||||
if (cnd_autostop_size != NULL && cnd_eval(cnd_autostop_size,
|
if (cnd_autostop_size != NULL && cnd_eval(cnd_autostop_size,
|
||||||
(guint32)wtap_get_bytes_dumped(ld.wtap_pdh))){
|
(guint32)ld.bytes_written)){
|
||||||
/* Capture size limit reached, do we have another file? */
|
/* Capture size limit reached, do we have another file? */
|
||||||
if (capture_opts->multi_files_on) {
|
if (capture_opts->multi_files_on) {
|
||||||
if (cnd_autostop_files != NULL && cnd_eval(cnd_autostop_files, ++autostop_files)) {
|
if (cnd_autostop_files != NULL && cnd_eval(cnd_autostop_files, ++autostop_files)) {
|
||||||
|
@ -1243,15 +1235,15 @@ capture_loop_start(capture_options *capture_opts, gboolean *stats_known, struct
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Switch to the next ringbuffer file */
|
/* Switch to the next ringbuffer file */
|
||||||
if (ringbuf_switch_file(&ld.wtap_pdh, &capture_opts->save_file, &save_file_fd, &ld.err)) {
|
if (ringbuf_switch_file(&ld.pdh, &capture_opts->save_file, &save_file_fd, &ld.err)) {
|
||||||
/* File switch succeeded: reset the conditions */
|
/* File switch succeeded: reset the conditions */
|
||||||
cnd_reset(cnd_autostop_size);
|
cnd_reset(cnd_autostop_size);
|
||||||
if (cnd_file_duration) {
|
if (cnd_file_duration) {
|
||||||
cnd_reset(cnd_file_duration);
|
cnd_reset(cnd_file_duration);
|
||||||
}
|
}
|
||||||
wtap_dump_flush(ld.wtap_pdh);
|
libpcap_dump_flush(ld.pdh, NULL);
|
||||||
sync_pipe_packet_count_to_parent(inpkts_to_sync_pipe);
|
sync_pipe_packet_count_to_parent(inpkts_to_sync_pipe);
|
||||||
inpkts_to_sync_pipe = 0;
|
inpkts_to_sync_pipe = 0;
|
||||||
sync_pipe_filename_to_parent(capture_opts->save_file);
|
sync_pipe_filename_to_parent(capture_opts->save_file);
|
||||||
} else {
|
} else {
|
||||||
/* File switch failed: stop here */
|
/* File switch failed: stop here */
|
||||||
|
@ -1265,7 +1257,7 @@ capture_loop_start(capture_options *capture_opts, gboolean *stats_known, struct
|
||||||
}
|
}
|
||||||
} /* cnd_autostop_size */
|
} /* cnd_autostop_size */
|
||||||
if (capture_opts->output_to_pipe) {
|
if (capture_opts->output_to_pipe) {
|
||||||
wtap_dump_flush(ld.wtap_pdh);
|
libpcap_dump_flush(ld.pdh, NULL);
|
||||||
}
|
}
|
||||||
} /* inpkts */
|
} /* inpkts */
|
||||||
|
|
||||||
|
@ -1285,10 +1277,10 @@ capture_loop_start(capture_options *capture_opts, gboolean *stats_known, struct
|
||||||
/* Let the parent process know. */
|
/* Let the parent process know. */
|
||||||
if (inpkts_to_sync_pipe) {
|
if (inpkts_to_sync_pipe) {
|
||||||
/* do sync here */
|
/* do sync here */
|
||||||
wtap_dump_flush(ld.wtap_pdh);
|
libpcap_dump_flush(ld.pdh, NULL);
|
||||||
|
|
||||||
/* Send our parent a message saying we've written out "inpkts_to_sync_pipe"
|
/* Send our parent a message saying we've written out "inpkts_to_sync_pipe"
|
||||||
packets to the capture file. */
|
packets to the capture file. */
|
||||||
sync_pipe_packet_count_to_parent(inpkts_to_sync_pipe);
|
sync_pipe_packet_count_to_parent(inpkts_to_sync_pipe);
|
||||||
|
|
||||||
inpkts_to_sync_pipe = 0;
|
inpkts_to_sync_pipe = 0;
|
||||||
|
@ -1312,14 +1304,14 @@ capture_loop_start(capture_options *capture_opts, gboolean *stats_known, struct
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Switch to the next ringbuffer file */
|
/* Switch to the next ringbuffer file */
|
||||||
if (ringbuf_switch_file(&ld.wtap_pdh, &capture_opts->save_file, &save_file_fd, &ld.err)) {
|
if (ringbuf_switch_file(&ld.pdh, &capture_opts->save_file, &save_file_fd, &ld.err)) {
|
||||||
/* file switch succeeded: reset the conditions */
|
/* file switch succeeded: reset the conditions */
|
||||||
cnd_reset(cnd_file_duration);
|
cnd_reset(cnd_file_duration);
|
||||||
if(cnd_autostop_size)
|
if(cnd_autostop_size)
|
||||||
cnd_reset(cnd_autostop_size);
|
cnd_reset(cnd_autostop_size);
|
||||||
wtap_dump_flush(ld.wtap_pdh);
|
libpcap_dump_flush(ld.pdh, NULL);
|
||||||
sync_pipe_packet_count_to_parent(inpkts_to_sync_pipe);
|
sync_pipe_packet_count_to_parent(inpkts_to_sync_pipe);
|
||||||
inpkts_to_sync_pipe = 0;
|
inpkts_to_sync_pipe = 0;
|
||||||
sync_pipe_filename_to_parent(capture_opts->save_file);
|
sync_pipe_filename_to_parent(capture_opts->save_file);
|
||||||
} else {
|
} else {
|
||||||
/* File switch failed: stop here */
|
/* File switch failed: stop here */
|
||||||
|
@ -1517,8 +1509,6 @@ static void
|
||||||
capture_loop_packet_cb(u_char *user, const struct pcap_pkthdr *phdr,
|
capture_loop_packet_cb(u_char *user, const struct pcap_pkthdr *phdr,
|
||||||
const u_char *pd)
|
const u_char *pd)
|
||||||
{
|
{
|
||||||
struct wtap_pkthdr whdr;
|
|
||||||
union wtap_pseudo_header pseudo_header;
|
|
||||||
loop_data *ld = (loop_data *) user;
|
loop_data *ld = (loop_data *) user;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
|
@ -1529,22 +1519,11 @@ capture_loop_packet_cb(u_char *user, const struct pcap_pkthdr *phdr,
|
||||||
ld->go = FALSE;
|
ld->go = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Convert from libpcap to Wiretap format.
|
if (ld->pdh) {
|
||||||
If that fails, set "ld->go" to FALSE, to stop the capture, and set
|
|
||||||
"ld->err" to the error. */
|
|
||||||
pd = wtap_process_pcap_packet(ld->wtap_linktype, phdr, pd, &pseudo_header,
|
|
||||||
&whdr, &err);
|
|
||||||
if (pd == NULL) {
|
|
||||||
ld->go = FALSE;
|
|
||||||
ld->err = err;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ld->wtap_pdh) {
|
|
||||||
/* We're supposed to write the packet to a file; do so.
|
/* We're supposed to write the packet to a file; do so.
|
||||||
If this fails, set "ld->go" to FALSE, to stop the capture, and set
|
If this fails, set "ld->go" to FALSE, to stop the capture, and set
|
||||||
"ld->err" to the error. */
|
"ld->err" to the error. */
|
||||||
if (!wtap_dump(ld->wtap_pdh, &whdr, &pseudo_header, pd, &err)) {
|
if (!libpcap_write_packet(ld->pdh, phdr, pd, &ld->bytes_written, &err)) {
|
||||||
ld->go = FALSE;
|
ld->go = FALSE;
|
||||||
ld->err = err;
|
ld->err = err;
|
||||||
}
|
}
|
||||||
|
|
|
@ -118,9 +118,11 @@ typedef struct _loop_data {
|
||||||
enum { PIPOK, PIPEOF, PIPERR, PIPNEXIST } cap_pipe_err;
|
enum { PIPOK, PIPEOF, PIPERR, PIPNEXIST } cap_pipe_err;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* wiretap (output file) */
|
/* output file */
|
||||||
wtap_dumper *wtap_pdh;
|
FILE *pdh;
|
||||||
|
int linktype;
|
||||||
gint wtap_linktype;
|
gint wtap_linktype;
|
||||||
|
long bytes_written;
|
||||||
|
|
||||||
} loop_data;
|
} loop_data;
|
||||||
|
|
||||||
|
@ -152,7 +154,7 @@ extern gboolean
|
||||||
capture_loop_open_output(capture_options *capture_opts, int *save_file_fd, char *errmsg, int errmsg_len);
|
capture_loop_open_output(capture_options *capture_opts, int *save_file_fd, char *errmsg, int errmsg_len);
|
||||||
|
|
||||||
extern gboolean
|
extern gboolean
|
||||||
capture_loop_init_wiretap_output(capture_options *capture_opts, int save_file_fd, loop_data *ld, char *errmsg, int errmsg_len);
|
capture_loop_init_output(capture_options *capture_opts, int save_file_fd, loop_data *ld, char *errmsg, int errmsg_len);
|
||||||
|
|
||||||
extern gboolean
|
extern gboolean
|
||||||
capture_loop_close_output(capture_options *capture_opts, loop_data *ld, int *err_close);
|
capture_loop_close_output(capture_options *capture_opts, loop_data *ld, int *err_close);
|
||||||
|
|
|
@ -0,0 +1,186 @@
|
||||||
|
/* pcapio.c
|
||||||
|
* Our own private code for writing libpcap files when capturing.
|
||||||
|
*
|
||||||
|
* We have these because we want a way to open a stream for output given
|
||||||
|
* only a file descriptor. libpcap 0.9[.x] has "pcap_dump_fopen()", which
|
||||||
|
* provides that, but
|
||||||
|
*
|
||||||
|
* 1) earlier versions of libpcap doesn't have it
|
||||||
|
*
|
||||||
|
* and
|
||||||
|
*
|
||||||
|
* 2) WinPcap doesn't have it, because a file descriptor opened
|
||||||
|
* by code built for one version of the MSVC++ C library
|
||||||
|
* can't be used by library routines built for another version
|
||||||
|
* (e.g., threaded vs. unthreaded).
|
||||||
|
*
|
||||||
|
* Libpcap's pcap_dump() also doesn't return any error indications.
|
||||||
|
*
|
||||||
|
* $Id$
|
||||||
|
*
|
||||||
|
* Ethereal - Network traffic analyzer
|
||||||
|
* By Gerald Combs <gerald@ethereal.com>
|
||||||
|
* Copyright 1998 Gerald Combs
|
||||||
|
*
|
||||||
|
* Derived from code in the Wiretap Library
|
||||||
|
* Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>
|
||||||
|
*
|
||||||
|
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include <pcap.h>
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
|
||||||
|
#include "pcapio.h"
|
||||||
|
|
||||||
|
/* Magic numbers in "libpcap" files.
|
||||||
|
|
||||||
|
"libpcap" file records are written in the byte order of the host that
|
||||||
|
writes them, and the reader is expected to fix this up.
|
||||||
|
|
||||||
|
PCAP_MAGIC is the magic number, in host byte order; PCAP_SWAPPED_MAGIC
|
||||||
|
is a byte-swapped version of that.
|
||||||
|
|
||||||
|
PCAP_NSEC_MAGIC is for Ulf Lamping's modified "libpcap" format,
|
||||||
|
which uses the same common file format as PCAP_MAGIC, but the
|
||||||
|
timestamps are saved in nanosecond resolution instead of microseconds.
|
||||||
|
PCAP_SWAPPED_NSEC_MAGIC is a byte-swapped version of that. */
|
||||||
|
#define PCAP_MAGIC 0xa1b2c3d4
|
||||||
|
#define PCAP_SWAPPED_MAGIC 0xd4c3b2a1
|
||||||
|
#define PCAP_NSEC_MAGIC 0xa1b23c4d
|
||||||
|
#define PCAP_SWAPPED_NSEC_MAGIC 0x4d3cb2a1
|
||||||
|
|
||||||
|
/* "libpcap" file header. */
|
||||||
|
struct pcap_hdr {
|
||||||
|
guint32 magic; /* magic number */
|
||||||
|
guint16 version_major; /* major version number */
|
||||||
|
guint16 version_minor; /* minor version number */
|
||||||
|
gint32 thiszone; /* GMT to local correction */
|
||||||
|
guint32 sigfigs; /* accuracy of timestamps */
|
||||||
|
guint32 snaplen; /* max length of captured packets, in octets */
|
||||||
|
guint32 network; /* data link type */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* "libpcap" record header. */
|
||||||
|
struct pcaprec_hdr {
|
||||||
|
guint32 ts_sec; /* timestamp seconds */
|
||||||
|
guint32 ts_usec; /* timestamp microseconds (nsecs for PCAP_NSEC_MAGIC) */
|
||||||
|
guint32 incl_len; /* number of octets of packet saved in file */
|
||||||
|
guint32 orig_len; /* actual length of packet */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Returns a FILE * to write to on success, NULL on failure; sets "*err" to
|
||||||
|
an error code, or 0 for a short write, on failure */
|
||||||
|
FILE *
|
||||||
|
libpcap_fdopen(int fd, int linktype, int snaplen, long *bytes_written,
|
||||||
|
int *err)
|
||||||
|
{
|
||||||
|
FILE *fp;
|
||||||
|
struct pcap_hdr file_hdr;
|
||||||
|
size_t nwritten;
|
||||||
|
|
||||||
|
fp = fdopen(fd, "wb");
|
||||||
|
if (fp == NULL) {
|
||||||
|
*err = errno;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
file_hdr.magic = PCAP_MAGIC;
|
||||||
|
/* current "libpcap" format is 2.4 */
|
||||||
|
file_hdr.version_major = 2;
|
||||||
|
file_hdr.version_minor = 4;
|
||||||
|
file_hdr.thiszone = 0; /* XXX - current offset? */
|
||||||
|
file_hdr.sigfigs = 0; /* unknown, but also apparently unused */
|
||||||
|
file_hdr.snaplen = snaplen;
|
||||||
|
file_hdr.network = linktype;
|
||||||
|
nwritten = fwrite(&file_hdr, 1, sizeof file_hdr, fp);
|
||||||
|
if (nwritten != sizeof file_hdr) {
|
||||||
|
if (nwritten == 0 && ferror(fp))
|
||||||
|
*err = errno;
|
||||||
|
else
|
||||||
|
*err = 0; /* short write */
|
||||||
|
fclose(fp);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
*bytes_written = sizeof file_hdr;
|
||||||
|
|
||||||
|
return fp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write a record for a packet to a dump file.
|
||||||
|
Returns TRUE on success, FALSE on failure. */
|
||||||
|
gboolean
|
||||||
|
libpcap_write_packet(FILE *fp, const struct pcap_pkthdr *phdr, const u_char *pd,
|
||||||
|
long *bytes_written, int *err)
|
||||||
|
{
|
||||||
|
struct pcaprec_hdr rec_hdr;
|
||||||
|
size_t nwritten;
|
||||||
|
|
||||||
|
rec_hdr.ts_sec = phdr->ts.tv_sec;
|
||||||
|
rec_hdr.ts_usec = phdr->ts.tv_usec;
|
||||||
|
rec_hdr.incl_len = phdr->caplen;
|
||||||
|
rec_hdr.orig_len = phdr->len;
|
||||||
|
nwritten = fwrite(&rec_hdr, 1, sizeof rec_hdr, fp);
|
||||||
|
if (nwritten != sizeof rec_hdr) {
|
||||||
|
if (nwritten == 0 && ferror(fp))
|
||||||
|
*err = errno;
|
||||||
|
else
|
||||||
|
*err = 0; /* short write */
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
*bytes_written += sizeof rec_hdr;
|
||||||
|
|
||||||
|
nwritten = fwrite(pd, 1, phdr->caplen, fp);
|
||||||
|
if (nwritten != phdr->caplen) {
|
||||||
|
if (nwritten == 0 && ferror(fp))
|
||||||
|
*err = errno;
|
||||||
|
else
|
||||||
|
*err = 0; /* short write */
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
*bytes_written += phdr->caplen;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
libpcap_dump_flush(FILE *pd, int *err)
|
||||||
|
{
|
||||||
|
if (fflush(pd) == EOF) {
|
||||||
|
if (err != NULL)
|
||||||
|
*err = errno;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
libpcap_dump_close(FILE *pd, int *err)
|
||||||
|
{
|
||||||
|
if (fclose(pd) == EOF) {
|
||||||
|
if (err != NULL)
|
||||||
|
*err = errno;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
/* pcapio.h
|
||||||
|
* Declarations of our own routins for writing libpcap files.
|
||||||
|
*
|
||||||
|
* $Id$
|
||||||
|
*
|
||||||
|
* Ethereal - Network traffic analyzer
|
||||||
|
* By Gerald Combs <gerald@ethereal.com>
|
||||||
|
* Copyright 1998 Gerald Combs
|
||||||
|
*
|
||||||
|
* Derived from code in the Wiretap Library
|
||||||
|
* Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>
|
||||||
|
*
|
||||||
|
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Returns a FILE * to write to on success, NULL on failure; sets "*err" to
|
||||||
|
an error code, or 0 for a short write, on failure */
|
||||||
|
extern FILE *
|
||||||
|
libpcap_fdopen(int fd, int linktype, int snaplen, long *bytes_written,
|
||||||
|
int *err);
|
||||||
|
|
||||||
|
/* Write a record for a packet to a dump file.
|
||||||
|
Returns TRUE on success, FALSE on failure. */
|
||||||
|
extern gboolean
|
||||||
|
libpcap_write_packet(FILE *fp, const struct pcap_pkthdr *phdr, const u_char *pd,
|
||||||
|
long *bytes_written, int *err);
|
||||||
|
|
||||||
|
extern gboolean
|
||||||
|
libpcap_dump_flush(FILE *pd, int *err);
|
||||||
|
|
||||||
|
extern gboolean
|
||||||
|
libpcap_dump_close(FILE *pd, int *err);
|
39
ringbuffer.c
39
ringbuffer.c
|
@ -61,7 +61,11 @@
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
#include <wiretap/wtap.h>
|
#include <pcap.h>
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
|
||||||
|
#include "pcapio.h"
|
||||||
#include "ringbuffer.h"
|
#include "ringbuffer.h"
|
||||||
#include "file_util.h"
|
#include "file_util.h"
|
||||||
|
|
||||||
|
@ -79,12 +83,12 @@ typedef struct _ringbuf_data {
|
||||||
gchar *fprefix; /* Filename prefix */
|
gchar *fprefix; /* Filename prefix */
|
||||||
gchar *fsuffix; /* Filename suffix */
|
gchar *fsuffix; /* Filename suffix */
|
||||||
gboolean unlimited; /* TRUE if unlimited number of files */
|
gboolean unlimited; /* TRUE if unlimited number of files */
|
||||||
int filetype;
|
|
||||||
int linktype;
|
int linktype;
|
||||||
int snaplen;
|
int snaplen;
|
||||||
|
|
||||||
int fd; /* Current ringbuffer file descriptor */
|
int fd; /* Current ringbuffer file descriptor */
|
||||||
wtap_dumper *pdh;
|
FILE *pdh;
|
||||||
|
long bytes_written; /* Bytes written to the current file */
|
||||||
} ringbuf_data;
|
} ringbuf_data;
|
||||||
|
|
||||||
static ringbuf_data rb_data;
|
static ringbuf_data rb_data;
|
||||||
|
@ -224,18 +228,17 @@ const gchar *ringbuf_current_filename(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Calls wtap_dump_fdopen() for the current ringbuffer file
|
* Calls libpcap_fdopen() for the current ringbuffer file
|
||||||
*/
|
*/
|
||||||
wtap_dumper*
|
FILE *
|
||||||
ringbuf_init_wtap_dump_fdopen(int filetype, int linktype, int snaplen, int *err)
|
ringbuf_init_libpcap_fdopen(int linktype, int snaplen, int *err)
|
||||||
{
|
{
|
||||||
|
|
||||||
rb_data.filetype = filetype;
|
|
||||||
rb_data.linktype = linktype;
|
rb_data.linktype = linktype;
|
||||||
rb_data.snaplen = snaplen;
|
rb_data.snaplen = snaplen;
|
||||||
|
|
||||||
rb_data.pdh = wtap_dump_fdopen(rb_data.fd, filetype, linktype, snaplen, FALSE /* compressed */, err);
|
rb_data.pdh = libpcap_fdopen(rb_data.fd, linktype, snaplen,
|
||||||
|
&rb_data.bytes_written, err);
|
||||||
return rb_data.pdh;
|
return rb_data.pdh;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -243,14 +246,14 @@ ringbuf_init_wtap_dump_fdopen(int filetype, int linktype, int snaplen, int *err)
|
||||||
* Switches to the next ringbuffer file
|
* Switches to the next ringbuffer file
|
||||||
*/
|
*/
|
||||||
gboolean
|
gboolean
|
||||||
ringbuf_switch_file(wtap_dumper **pdh, gchar **save_file, int *save_file_fd, int *err)
|
ringbuf_switch_file(FILE **pdh, gchar **save_file, int *save_file_fd, int *err)
|
||||||
{
|
{
|
||||||
int next_file_num;
|
int next_file_num;
|
||||||
rb_file *next_rfile = NULL;
|
rb_file *next_rfile = NULL;
|
||||||
|
|
||||||
/* close current file */
|
/* close current file */
|
||||||
|
|
||||||
if (!wtap_dump_close(rb_data.pdh, err)) {
|
if (!libpcap_dump_close(rb_data.pdh, err)) {
|
||||||
eth_close(rb_data.fd); /* XXX - the above should have closed this already */
|
eth_close(rb_data.fd); /* XXX - the above should have closed this already */
|
||||||
rb_data.pdh = NULL; /* it's still closed, we just got an error while closing */
|
rb_data.pdh = NULL; /* it's still closed, we just got an error while closing */
|
||||||
rb_data.fd = -1;
|
rb_data.fd = -1;
|
||||||
|
@ -270,8 +273,8 @@ ringbuf_switch_file(wtap_dumper **pdh, gchar **save_file, int *save_file_fd, int
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ringbuf_init_wtap_dump_fdopen(rb_data.filetype, rb_data.linktype,
|
if (ringbuf_init_libpcap_fdopen(rb_data.linktype, rb_data.snaplen,
|
||||||
rb_data.snaplen, err) == NULL) {
|
err) == NULL) {
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -284,16 +287,16 @@ ringbuf_switch_file(wtap_dumper **pdh, gchar **save_file, int *save_file_fd, int
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Calls wtap_dump_close() for the current ringbuffer file
|
* Calls libpcap_dump_close() for the current ringbuffer file
|
||||||
*/
|
*/
|
||||||
gboolean
|
gboolean
|
||||||
ringbuf_wtap_dump_close(gchar **save_file, int *err)
|
ringbuf_libpcap_dump_close(gchar **save_file, int *err)
|
||||||
{
|
{
|
||||||
gboolean ret_val = TRUE;
|
gboolean ret_val = TRUE;
|
||||||
|
|
||||||
/* close current file, if it's open */
|
/* close current file, if it's open */
|
||||||
if (rb_data.pdh != NULL) {
|
if (rb_data.pdh != NULL) {
|
||||||
if (!wtap_dump_close(rb_data.pdh, err)) {
|
if (!libpcap_dump_close(rb_data.pdh, err)) {
|
||||||
eth_close(rb_data.fd);
|
eth_close(rb_data.fd);
|
||||||
ret_val = FALSE;
|
ret_val = FALSE;
|
||||||
}
|
}
|
||||||
|
@ -345,14 +348,14 @@ ringbuf_error_cleanup(void)
|
||||||
|
|
||||||
/* try to close via wtap */
|
/* try to close via wtap */
|
||||||
if (rb_data.pdh != NULL) {
|
if (rb_data.pdh != NULL) {
|
||||||
if (wtap_dump_close(rb_data.pdh, NULL)) {
|
if (libpcap_dump_close(rb_data.pdh, NULL)) {
|
||||||
rb_data.fd = -1;
|
rb_data.fd = -1;
|
||||||
}
|
}
|
||||||
rb_data.pdh = NULL;
|
rb_data.pdh = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* close directly if still open */
|
/* close directly if still open */
|
||||||
/* XXX - it shouldn't still be open; "wtap_dump_close()" should leave the
|
/* XXX - it shouldn't still be open; "libpcap_dump_close()" should leave the
|
||||||
file closed even if it fails */
|
file closed even if it fails */
|
||||||
if (rb_data.fd != -1) {
|
if (rb_data.fd != -1) {
|
||||||
eth_close(rb_data.fd);
|
eth_close(rb_data.fd);
|
||||||
|
|
|
@ -40,10 +40,9 @@
|
||||||
|
|
||||||
int ringbuf_init(const char *capture_name, guint num_files);
|
int ringbuf_init(const char *capture_name, guint num_files);
|
||||||
const gchar *ringbuf_current_filename(void);
|
const gchar *ringbuf_current_filename(void);
|
||||||
wtap_dumper* ringbuf_init_wtap_dump_fdopen(int filetype, int linktype,
|
FILE *ringbuf_init_libpcap_fdopen(int linktype, int snaplen, int *err);
|
||||||
int snaplen, int *err);
|
gboolean ringbuf_switch_file(FILE **pdh, gchar **save_file, int *save_file_fd, int *err);
|
||||||
gboolean ringbuf_switch_file(wtap_dumper **pdh, gchar **save_file, int *save_file_fd, int *err);
|
gboolean ringbuf_libpcap_dump_close(gchar **save_file, int *err);
|
||||||
gboolean ringbuf_wtap_dump_close(gchar **save_file, int *err);
|
|
||||||
void ringbuf_free(void);
|
void ringbuf_free(void);
|
||||||
void ringbuf_error_cleanup(void);
|
void ringbuf_error_cleanup(void);
|
||||||
|
|
||||||
|
|
148
tethereal.c
148
tethereal.c
|
@ -95,6 +95,7 @@
|
||||||
#include <pcap.h>
|
#include <pcap.h>
|
||||||
#include <setjmp.h>
|
#include <setjmp.h>
|
||||||
#include "capture-pcap-util.h"
|
#include "capture-pcap-util.h"
|
||||||
|
#include "pcapio.h"
|
||||||
#include <wiretap/wtap-capture.h>
|
#include <wiretap/wtap-capture.h>
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#include "capture-wpcap.h"
|
#include "capture-wpcap.h"
|
||||||
|
@ -170,9 +171,9 @@ static void report_counts_siginfo(int);
|
||||||
#endif /* HAVE_LIBPCAP */
|
#endif /* HAVE_LIBPCAP */
|
||||||
|
|
||||||
static int load_cap_file(capture_file *, char *, int);
|
static int load_cap_file(capture_file *, char *, int);
|
||||||
static gboolean process_packet(capture_file *cf, wtap_dumper *pdh, long offset,
|
static gboolean process_packet(capture_file *cf, long offset,
|
||||||
const struct wtap_pkthdr *whdr, union wtap_pseudo_header *pseudo_header,
|
const struct wtap_pkthdr *whdr, union wtap_pseudo_header *pseudo_header,
|
||||||
const guchar *pd, int *err);
|
const guchar *pd);
|
||||||
static void show_capture_file_io_error(const char *, int, gboolean);
|
static void show_capture_file_io_error(const char *, int, gboolean);
|
||||||
static void show_print_file_io_error(int err);
|
static void show_print_file_io_error(int err);
|
||||||
static gboolean write_preamble(capture_file *cf);
|
static gboolean write_preamble(capture_file *cf);
|
||||||
|
@ -1449,10 +1450,16 @@ main(int argc, char *argv[])
|
||||||
exit(status);
|
exit(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!quiet) {
|
if (!print_packet_info && !quiet) {
|
||||||
/*
|
/*
|
||||||
* The user didn't ask us not to print a count of packets as
|
* We're not printing information for each packet, and the user
|
||||||
* they arrive, so do so.
|
* didn't ask us not to print a count of packets as they arrive,
|
||||||
|
* so print that count so the user knows that packets are arriving.
|
||||||
|
*
|
||||||
|
* XXX - what if the user wants to do a live capture, doesn't want
|
||||||
|
* to save it to a file, doesn't want information printed for each
|
||||||
|
* packet, does want some "-z" statistic, and wants packet counts
|
||||||
|
* so they know whether they're seeing any packets?
|
||||||
*/
|
*/
|
||||||
print_packet_counts = TRUE;
|
print_packet_counts = TRUE;
|
||||||
}
|
}
|
||||||
|
@ -1509,7 +1516,7 @@ capture(void)
|
||||||
init_dissection();
|
init_dissection();
|
||||||
|
|
||||||
ld.wtap_linktype = WTAP_ENCAP_UNKNOWN;
|
ld.wtap_linktype = WTAP_ENCAP_UNKNOWN;
|
||||||
ld.wtap_pdh = NULL;
|
ld.pdh = NULL;
|
||||||
ld.packet_cb = capture_pcap_cb;
|
ld.packet_cb = capture_pcap_cb;
|
||||||
|
|
||||||
|
|
||||||
|
@ -1545,12 +1552,14 @@ capture(void)
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* open the wiretap part of the output file (the output file is already open) */
|
/* set up to write to the already-opened capture output file/files */
|
||||||
if(!capture_loop_init_wiretap_output(&capture_opts, save_file_fd, &ld, errmsg, sizeof errmsg))
|
if(!capture_loop_init_output(&capture_opts, save_file_fd, &ld, errmsg, sizeof errmsg))
|
||||||
{
|
{
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ld.wtap_linktype = wtap_pcap_encap_to_wtap_encap(ld.linktype);
|
||||||
|
|
||||||
/* Save the capture file name. */
|
/* Save the capture file name. */
|
||||||
ld.save_file = capture_opts.save_file;
|
ld.save_file = capture_opts.save_file;
|
||||||
|
|
||||||
|
@ -1679,13 +1688,12 @@ capture(void)
|
||||||
in effect. */
|
in effect. */
|
||||||
ld.go = FALSE;
|
ld.go = FALSE;
|
||||||
} else if (cnd_autostop_size != NULL &&
|
} else if (cnd_autostop_size != NULL &&
|
||||||
cnd_eval(cnd_autostop_size,
|
cnd_eval(cnd_autostop_size, (guint32)ld.bytes_written)) {
|
||||||
(guint32)wtap_get_bytes_dumped(ld.wtap_pdh))) {
|
|
||||||
/* We're saving the capture to a file, and the capture file reached
|
/* We're saving the capture to a file, and the capture file reached
|
||||||
its maximum size. */
|
its maximum size. */
|
||||||
if (capture_opts.multi_files_on) {
|
if (capture_opts.multi_files_on) {
|
||||||
/* Switch to the next ringbuffer file */
|
/* Switch to the next ringbuffer file */
|
||||||
if (ringbuf_switch_file(&ld.wtap_pdh, &capture_opts.save_file, &save_file_fd, &loop_err)) {
|
if (ringbuf_switch_file(&ld.pdh, &capture_opts.save_file, &save_file_fd, &loop_err)) {
|
||||||
/* File switch succeeded: reset the condition */
|
/* File switch succeeded: reset the condition */
|
||||||
cnd_reset(cnd_autostop_size);
|
cnd_reset(cnd_autostop_size);
|
||||||
if (cnd_file_duration) {
|
if (cnd_file_duration) {
|
||||||
|
@ -1703,7 +1711,7 @@ capture(void)
|
||||||
}
|
}
|
||||||
if (capture_opts.output_to_pipe) {
|
if (capture_opts.output_to_pipe) {
|
||||||
if (ld.packet_count > packet_count_prev) {
|
if (ld.packet_count > packet_count_prev) {
|
||||||
wtap_dump_flush(ld.wtap_pdh);
|
libpcap_dump_flush(ld.pdh, NULL);
|
||||||
packet_count_prev = ld.packet_count;
|
packet_count_prev = ld.packet_count;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1806,18 +1814,12 @@ capture_pcap_cb(u_char *user, const struct pcap_pkthdr *phdr,
|
||||||
{
|
{
|
||||||
struct wtap_pkthdr whdr;
|
struct wtap_pkthdr whdr;
|
||||||
union wtap_pseudo_header pseudo_header;
|
union wtap_pseudo_header pseudo_header;
|
||||||
|
const guchar *wtap_pd;
|
||||||
loop_data *ld = (loop_data *) user;
|
loop_data *ld = (loop_data *) user;
|
||||||
int loop_err;
|
int loop_err;
|
||||||
int err;
|
int err;
|
||||||
int save_file_fd;
|
int save_file_fd;
|
||||||
|
gboolean packet_accepted;
|
||||||
/* Convert from libpcap to Wiretap format.
|
|
||||||
If that fails, ignore the packet (wtap_process_pcap_packet has
|
|
||||||
written an error message). */
|
|
||||||
pd = wtap_process_pcap_packet(ld->wtap_linktype, phdr, pd, &pseudo_header,
|
|
||||||
&whdr, &err);
|
|
||||||
if (pd == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
#ifdef SIGINFO
|
#ifdef SIGINFO
|
||||||
/*
|
/*
|
||||||
|
@ -1835,7 +1837,7 @@ capture_pcap_cb(u_char *user, const struct pcap_pkthdr *phdr,
|
||||||
*/
|
*/
|
||||||
if (cnd_file_duration != NULL && cnd_eval(cnd_file_duration)) {
|
if (cnd_file_duration != NULL && cnd_eval(cnd_file_duration)) {
|
||||||
/* time elapsed for this ring file, switch to the next */
|
/* time elapsed for this ring file, switch to the next */
|
||||||
if (ringbuf_switch_file(&ld->wtap_pdh, &ld->save_file, &save_file_fd, &loop_err)) {
|
if (ringbuf_switch_file(&ld->pdh, &ld->save_file, &save_file_fd, &loop_err)) {
|
||||||
/* File switch succeeded: reset the condition */
|
/* File switch succeeded: reset the condition */
|
||||||
cnd_reset(cnd_file_duration);
|
cnd_reset(cnd_file_duration);
|
||||||
} else {
|
} else {
|
||||||
|
@ -1845,17 +1847,51 @@ capture_pcap_cb(u_char *user, const struct pcap_pkthdr *phdr,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!process_packet(&cfile, ld->wtap_pdh, 0, &whdr, &pseudo_header, pd, &err)) {
|
if (do_dissection) {
|
||||||
/* Error writing to a capture file */
|
/* We're goint to print packet information, run a read filter, or
|
||||||
if (print_packet_counts) {
|
process taps. Use process_packet() to handle that; in order
|
||||||
/* We're printing counts of packets captured; move to the line after
|
to do that, we need to convert from libpcap to Wiretap format.
|
||||||
the count. */
|
If that fails, ignore the packet (wtap_process_pcap_packet has
|
||||||
fprintf(stderr, "\n");
|
written an error message). */
|
||||||
|
wtap_pd = wtap_process_pcap_packet(ld->wtap_linktype, phdr, pd,
|
||||||
|
&pseudo_header, &whdr, &err);
|
||||||
|
if (wtap_pd == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
packet_accepted = process_packet(&cfile, 0, &whdr, &pseudo_header, wtap_pd);
|
||||||
|
} else {
|
||||||
|
/* We're just writing out packets. */
|
||||||
|
packet_accepted = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (packet_accepted) {
|
||||||
|
/* Count this packet. */
|
||||||
|
#ifdef HAVE_LIBPCAP
|
||||||
|
ld->packet_count++;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (ld->pdh != NULL) {
|
||||||
|
if (!libpcap_write_packet(ld->pdh, phdr, pd, &ld->bytes_written, &err)) {
|
||||||
|
/* Error writing to a capture file */
|
||||||
|
if (print_packet_counts) {
|
||||||
|
/* We're printing counts of packets captured; move to the line after
|
||||||
|
the count. */
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
}
|
||||||
|
show_capture_file_io_error(ld->save_file, err, FALSE);
|
||||||
|
pcap_close(ld->pcap_h);
|
||||||
|
libpcap_dump_close(ld->pdh, &err);
|
||||||
|
exit(2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (print_packet_counts) {
|
||||||
|
/* We're printing packet counts. */
|
||||||
|
if (ld->packet_count != 0) {
|
||||||
|
fprintf(stderr, "\r%u ", ld->packet_count);
|
||||||
|
/* stderr could be line buffered */
|
||||||
|
fflush(stderr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
show_capture_file_io_error(ld->save_file, err, FALSE);
|
|
||||||
pcap_close(ld->pcap_h);
|
|
||||||
wtap_dump_close(ld->wtap_pdh, &err);
|
|
||||||
exit(2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef SIGINFO
|
#ifdef SIGINFO
|
||||||
|
@ -2017,13 +2053,21 @@ load_cap_file(capture_file *cf, char *save_file, int out_file_type)
|
||||||
pdh = NULL;
|
pdh = NULL;
|
||||||
}
|
}
|
||||||
while (wtap_read(cf->wth, &err, &err_info, &data_offset)) {
|
while (wtap_read(cf->wth, &err, &err_info, &data_offset)) {
|
||||||
if (!process_packet(cf, pdh, data_offset, wtap_phdr(cf->wth),
|
if (process_packet(cf, data_offset, wtap_phdr(cf->wth),
|
||||||
wtap_pseudoheader(cf->wth), wtap_buf_ptr(cf->wth),
|
wtap_pseudoheader(cf->wth), wtap_buf_ptr(cf->wth))) {
|
||||||
&err)) {
|
/* Either there's no read filtering or this packet passed the
|
||||||
/* Error writing to a capture file */
|
filter, so, if we're writing to a capture file, write
|
||||||
show_capture_file_io_error(save_file, err, FALSE);
|
this packet out. */
|
||||||
wtap_dump_close(pdh, &err);
|
if (pdh != NULL) {
|
||||||
exit(2);
|
if (!wtap_dump(pdh, wtap_phdr(cf->wth),
|
||||||
|
wtap_pseudoheader(cf->wth), wtap_buf_ptr(cf->wth),
|
||||||
|
&err)) {
|
||||||
|
/* Error writing to a capture file */
|
||||||
|
show_capture_file_io_error(save_file, err, FALSE);
|
||||||
|
wtap_dump_close(pdh, &err);
|
||||||
|
exit(2);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (err != 0) {
|
if (err != 0) {
|
||||||
|
@ -2148,10 +2192,8 @@ clear_fdata(frame_data *fdata)
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
process_packet(capture_file *cf, wtap_dumper *pdh, long offset,
|
process_packet(capture_file *cf, long offset, const struct wtap_pkthdr *whdr,
|
||||||
const struct wtap_pkthdr *whdr,
|
union wtap_pseudo_header *pseudo_header, const guchar *pd)
|
||||||
union wtap_pseudo_header *pseudo_header, const guchar *pd,
|
|
||||||
int *err)
|
|
||||||
{
|
{
|
||||||
frame_data fdata;
|
frame_data fdata;
|
||||||
gboolean create_proto_tree;
|
gboolean create_proto_tree;
|
||||||
|
@ -2215,27 +2257,7 @@ process_packet(capture_file *cf, wtap_dumper *pdh, long offset,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (passed) {
|
if (passed) {
|
||||||
/* Count this packet. */
|
|
||||||
#ifdef HAVE_LIBPCAP
|
|
||||||
ld.packet_count++;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Process this packet. */
|
/* Process this packet. */
|
||||||
if (pdh != NULL) {
|
|
||||||
/* We're writing to a capture file; write this packet. */
|
|
||||||
if (!wtap_dump(pdh, whdr, pseudo_header, pd, err))
|
|
||||||
return FALSE;
|
|
||||||
#ifdef HAVE_LIBPCAP
|
|
||||||
if (print_packet_counts) {
|
|
||||||
/* We're printing packet counts. */
|
|
||||||
if (ld.packet_count != 0) {
|
|
||||||
fprintf(stderr, "\r%u ", ld.packet_count);
|
|
||||||
/* stderr could be line buffered */
|
|
||||||
fflush(stderr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
if (print_packet_info) {
|
if (print_packet_info) {
|
||||||
/* We're printing packet information; print the information for
|
/* We're printing packet information; print the information for
|
||||||
this packet. */
|
this packet. */
|
||||||
|
@ -2275,7 +2297,7 @@ process_packet(capture_file *cf, wtap_dumper *pdh, long offset,
|
||||||
epan_dissect_free(edt);
|
epan_dissect_free(edt);
|
||||||
clear_fdata(&fdata);
|
clear_fdata(&fdata);
|
||||||
}
|
}
|
||||||
return TRUE;
|
return passed;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
Loading…
Reference in New Issue