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 \
|
||||
print.c \
|
||||
ps.c \
|
||||
pcapio.c \
|
||||
ringbuffer.c \
|
||||
timestats.c \
|
||||
util.c \
|
||||
|
@ -81,6 +82,7 @@ ETHEREAL_COMMON_INCLUDES = \
|
|||
fileset.h \
|
||||
isprint.h \
|
||||
packet-range.h \
|
||||
pcapio.h \
|
||||
print.h \
|
||||
ps.h \
|
||||
register.h \
|
||||
|
@ -221,6 +223,7 @@ dumpcap_SOURCES = \
|
|||
clopts_common.c \
|
||||
conditions.c \
|
||||
dumpcap.c \
|
||||
pcapio.c \
|
||||
ringbuffer.c \
|
||||
tempfile.c \
|
||||
version_info.c
|
||||
|
|
|
@ -68,8 +68,7 @@
|
|||
|
||||
#include <pcap.h>
|
||||
|
||||
#include "wiretap/wtap.h"
|
||||
#include "wiretap/wtap-capture.h"
|
||||
#include "pcapio.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) {
|
||||
|
||||
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 */
|
||||
gboolean capture_loop_init_wiretap_output(capture_options *capture_opts, int save_file_fd, loop_data *ld, char *errmsg, int errmsg_len) {
|
||||
/* set up to write to the already-opened capture output file/files */
|
||||
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 file_snaplen;
|
||||
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 */
|
||||
#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. */
|
||||
ld->wtap_linktype = wtap_pcap_encap_to_wtap_encap(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;
|
||||
}
|
||||
ld->linktype = pcap_encap;
|
||||
if (capture_opts->multi_files_on) {
|
||||
ld->wtap_pdh = ringbuf_init_wtap_dump_fdopen(WTAP_FILE_PCAP, ld->wtap_linktype,
|
||||
file_snaplen, &err);
|
||||
ld->pdh = ringbuf_init_libpcap_fdopen(ld->linktype, file_snaplen, &err);
|
||||
} else {
|
||||
ld->wtap_pdh = wtap_dump_fdopen(save_file_fd, WTAP_FILE_PCAP,
|
||||
ld->wtap_linktype, file_snaplen, FALSE /* compressed */, &err);
|
||||
ld->pdh = libpcap_fdopen(save_file_fd, ld->linktype, file_snaplen,
|
||||
&ld->bytes_written, &err);
|
||||
}
|
||||
|
||||
if (ld->wtap_pdh == NULL) {
|
||||
if (ld->pdh == NULL) {
|
||||
/* We couldn't set up to write to the capture file. */
|
||||
/* XXX - use cf_open_error_message from tethereal instead? */
|
||||
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");
|
||||
|
||||
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 {
|
||||
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.pcap_err = FALSE;
|
||||
ld.from_cap_pipe = FALSE;
|
||||
ld.wtap_pdh = NULL;
|
||||
ld.pdh = NULL;
|
||||
#ifndef _WIN32
|
||||
ld.cap_pipe_fd = -1;
|
||||
#endif
|
||||
|
@ -1168,8 +1160,8 @@ capture_loop_start(capture_options *capture_opts, gboolean *stats_known, struct
|
|||
goto error;
|
||||
}
|
||||
|
||||
/* open the wiretap part of the output file (the output file is already open) */
|
||||
if (!capture_loop_init_wiretap_output(capture_opts, save_file_fd, &ld, errmsg, sizeof(errmsg))) {
|
||||
/* set up to write to the already-opened capture output file/files */
|
||||
if (!capture_loop_init_output(capture_opts, save_file_fd, &ld, errmsg, sizeof(errmsg))) {
|
||||
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
|
||||
update its windows to indicate that we have a live capture in
|
||||
progress. */
|
||||
wtap_dump_flush(ld.wtap_pdh);
|
||||
libpcap_dump_flush(ld.pdh, NULL);
|
||||
sync_pipe_filename_to_parent(capture_opts->save_file);
|
||||
|
||||
/* 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 */
|
||||
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? */
|
||||
if (capture_opts->multi_files_on) {
|
||||
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 */
|
||||
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 */
|
||||
cnd_reset(cnd_autostop_size);
|
||||
if (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);
|
||||
inpkts_to_sync_pipe = 0;
|
||||
inpkts_to_sync_pipe = 0;
|
||||
sync_pipe_filename_to_parent(capture_opts->save_file);
|
||||
} else {
|
||||
/* File switch failed: stop here */
|
||||
|
@ -1265,7 +1257,7 @@ capture_loop_start(capture_options *capture_opts, gboolean *stats_known, struct
|
|||
}
|
||||
} /* cnd_autostop_size */
|
||||
if (capture_opts->output_to_pipe) {
|
||||
wtap_dump_flush(ld.wtap_pdh);
|
||||
libpcap_dump_flush(ld.pdh, NULL);
|
||||
}
|
||||
} /* inpkts */
|
||||
|
||||
|
@ -1285,10 +1277,10 @@ capture_loop_start(capture_options *capture_opts, gboolean *stats_known, struct
|
|||
/* Let the parent process know. */
|
||||
if (inpkts_to_sync_pipe) {
|
||||
/* 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"
|
||||
packets to the capture file. */
|
||||
/* Send our parent a message saying we've written out "inpkts_to_sync_pipe"
|
||||
packets to the capture file. */
|
||||
sync_pipe_packet_count_to_parent(inpkts_to_sync_pipe);
|
||||
|
||||
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 */
|
||||
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 */
|
||||
cnd_reset(cnd_file_duration);
|
||||
if(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);
|
||||
inpkts_to_sync_pipe = 0;
|
||||
inpkts_to_sync_pipe = 0;
|
||||
sync_pipe_filename_to_parent(capture_opts->save_file);
|
||||
} else {
|
||||
/* File switch failed: stop here */
|
||||
|
@ -1517,8 +1509,6 @@ static void
|
|||
capture_loop_packet_cb(u_char *user, const struct pcap_pkthdr *phdr,
|
||||
const u_char *pd)
|
||||
{
|
||||
struct wtap_pkthdr whdr;
|
||||
union wtap_pseudo_header pseudo_header;
|
||||
loop_data *ld = (loop_data *) user;
|
||||
int err;
|
||||
|
||||
|
@ -1529,22 +1519,11 @@ capture_loop_packet_cb(u_char *user, const struct pcap_pkthdr *phdr,
|
|||
ld->go = FALSE;
|
||||
}
|
||||
|
||||
/* Convert from libpcap to Wiretap format.
|
||||
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) {
|
||||
if (ld->pdh) {
|
||||
/* 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
|
||||
"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->err = err;
|
||||
}
|
||||
|
|
|
@ -118,9 +118,11 @@ typedef struct _loop_data {
|
|||
enum { PIPOK, PIPEOF, PIPERR, PIPNEXIST } cap_pipe_err;
|
||||
#endif
|
||||
|
||||
/* wiretap (output file) */
|
||||
wtap_dumper *wtap_pdh;
|
||||
/* output file */
|
||||
FILE *pdh;
|
||||
int linktype;
|
||||
gint wtap_linktype;
|
||||
long bytes_written;
|
||||
|
||||
} 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);
|
||||
|
||||
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
|
||||
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 <errno.h>
|
||||
|
||||
#include <wiretap/wtap.h>
|
||||
#include <pcap.h>
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
#include "pcapio.h"
|
||||
#include "ringbuffer.h"
|
||||
#include "file_util.h"
|
||||
|
||||
|
@ -79,12 +83,12 @@ typedef struct _ringbuf_data {
|
|||
gchar *fprefix; /* Filename prefix */
|
||||
gchar *fsuffix; /* Filename suffix */
|
||||
gboolean unlimited; /* TRUE if unlimited number of files */
|
||||
int filetype;
|
||||
int linktype;
|
||||
int snaplen;
|
||||
|
||||
int fd; /* Current ringbuffer file descriptor */
|
||||
wtap_dumper *pdh;
|
||||
FILE *pdh;
|
||||
long bytes_written; /* Bytes written to the current file */
|
||||
} ringbuf_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*
|
||||
ringbuf_init_wtap_dump_fdopen(int filetype, int linktype, int snaplen, int *err)
|
||||
FILE *
|
||||
ringbuf_init_libpcap_fdopen(int linktype, int snaplen, int *err)
|
||||
{
|
||||
|
||||
rb_data.filetype = filetype;
|
||||
rb_data.linktype = linktype;
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -243,14 +246,14 @@ ringbuf_init_wtap_dump_fdopen(int filetype, int linktype, int snaplen, int *err)
|
|||
* Switches to the next ringbuffer file
|
||||
*/
|
||||
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;
|
||||
rb_file *next_rfile = NULL;
|
||||
|
||||
/* 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 */
|
||||
rb_data.pdh = NULL; /* it's still closed, we just got an error while closing */
|
||||
rb_data.fd = -1;
|
||||
|
@ -270,8 +273,8 @@ ringbuf_switch_file(wtap_dumper **pdh, gchar **save_file, int *save_file_fd, int
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
if (ringbuf_init_wtap_dump_fdopen(rb_data.filetype, rb_data.linktype,
|
||||
rb_data.snaplen, err) == NULL) {
|
||||
if (ringbuf_init_libpcap_fdopen(rb_data.linktype, rb_data.snaplen,
|
||||
err) == NULL) {
|
||||
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
|
||||
ringbuf_wtap_dump_close(gchar **save_file, int *err)
|
||||
ringbuf_libpcap_dump_close(gchar **save_file, int *err)
|
||||
{
|
||||
gboolean ret_val = TRUE;
|
||||
|
||||
/* close current file, if it's open */
|
||||
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);
|
||||
ret_val = FALSE;
|
||||
}
|
||||
|
@ -345,14 +348,14 @@ ringbuf_error_cleanup(void)
|
|||
|
||||
/* try to close via wtap */
|
||||
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.pdh = NULL;
|
||||
}
|
||||
|
||||
/* 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 */
|
||||
if (rb_data.fd != -1) {
|
||||
eth_close(rb_data.fd);
|
||||
|
|
|
@ -40,10 +40,9 @@
|
|||
|
||||
int ringbuf_init(const char *capture_name, guint num_files);
|
||||
const gchar *ringbuf_current_filename(void);
|
||||
wtap_dumper* ringbuf_init_wtap_dump_fdopen(int filetype, int linktype,
|
||||
int snaplen, int *err);
|
||||
gboolean ringbuf_switch_file(wtap_dumper **pdh, gchar **save_file, int *save_file_fd, int *err);
|
||||
gboolean ringbuf_wtap_dump_close(gchar **save_file, int *err);
|
||||
FILE *ringbuf_init_libpcap_fdopen(int linktype, int snaplen, int *err);
|
||||
gboolean ringbuf_switch_file(FILE **pdh, gchar **save_file, int *save_file_fd, int *err);
|
||||
gboolean ringbuf_libpcap_dump_close(gchar **save_file, int *err);
|
||||
void ringbuf_free(void);
|
||||
void ringbuf_error_cleanup(void);
|
||||
|
||||
|
|
148
tethereal.c
148
tethereal.c
|
@ -95,6 +95,7 @@
|
|||
#include <pcap.h>
|
||||
#include <setjmp.h>
|
||||
#include "capture-pcap-util.h"
|
||||
#include "pcapio.h"
|
||||
#include <wiretap/wtap-capture.h>
|
||||
#ifdef _WIN32
|
||||
#include "capture-wpcap.h"
|
||||
|
@ -170,9 +171,9 @@ static void report_counts_siginfo(int);
|
|||
#endif /* HAVE_LIBPCAP */
|
||||
|
||||
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 guchar *pd, int *err);
|
||||
const guchar *pd);
|
||||
static void show_capture_file_io_error(const char *, int, gboolean);
|
||||
static void show_print_file_io_error(int err);
|
||||
static gboolean write_preamble(capture_file *cf);
|
||||
|
@ -1449,10 +1450,16 @@ main(int argc, char *argv[])
|
|||
exit(status);
|
||||
}
|
||||
|
||||
if (!quiet) {
|
||||
if (!print_packet_info && !quiet) {
|
||||
/*
|
||||
* The user didn't ask us not to print a count of packets as
|
||||
* they arrive, so do so.
|
||||
* We're not printing information for each packet, and the user
|
||||
* 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;
|
||||
}
|
||||
|
@ -1509,7 +1516,7 @@ capture(void)
|
|||
init_dissection();
|
||||
|
||||
ld.wtap_linktype = WTAP_ENCAP_UNKNOWN;
|
||||
ld.wtap_pdh = NULL;
|
||||
ld.pdh = NULL;
|
||||
ld.packet_cb = capture_pcap_cb;
|
||||
|
||||
|
||||
|
@ -1545,12 +1552,14 @@ capture(void)
|
|||
goto error;
|
||||
}
|
||||
|
||||
/* open the wiretap part of the output file (the output file is already open) */
|
||||
if(!capture_loop_init_wiretap_output(&capture_opts, save_file_fd, &ld, errmsg, sizeof errmsg))
|
||||
/* set up to write to the already-opened capture output file/files */
|
||||
if(!capture_loop_init_output(&capture_opts, save_file_fd, &ld, errmsg, sizeof errmsg))
|
||||
{
|
||||
goto error;
|
||||
}
|
||||
|
||||
ld.wtap_linktype = wtap_pcap_encap_to_wtap_encap(ld.linktype);
|
||||
|
||||
/* Save the capture file name. */
|
||||
ld.save_file = capture_opts.save_file;
|
||||
|
||||
|
@ -1679,13 +1688,12 @@ capture(void)
|
|||
in effect. */
|
||||
ld.go = FALSE;
|
||||
} else if (cnd_autostop_size != NULL &&
|
||||
cnd_eval(cnd_autostop_size,
|
||||
(guint32)wtap_get_bytes_dumped(ld.wtap_pdh))) {
|
||||
cnd_eval(cnd_autostop_size, (guint32)ld.bytes_written)) {
|
||||
/* We're saving the capture to a file, and the capture file reached
|
||||
its maximum size. */
|
||||
if (capture_opts.multi_files_on) {
|
||||
/* 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 */
|
||||
cnd_reset(cnd_autostop_size);
|
||||
if (cnd_file_duration) {
|
||||
|
@ -1703,7 +1711,7 @@ capture(void)
|
|||
}
|
||||
if (capture_opts.output_to_pipe) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -1806,18 +1814,12 @@ capture_pcap_cb(u_char *user, const struct pcap_pkthdr *phdr,
|
|||
{
|
||||
struct wtap_pkthdr whdr;
|
||||
union wtap_pseudo_header pseudo_header;
|
||||
const guchar *wtap_pd;
|
||||
loop_data *ld = (loop_data *) user;
|
||||
int loop_err;
|
||||
int err;
|
||||
int save_file_fd;
|
||||
|
||||
/* 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;
|
||||
gboolean packet_accepted;
|
||||
|
||||
#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)) {
|
||||
/* 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 */
|
||||
cnd_reset(cnd_file_duration);
|
||||
} 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)) {
|
||||
/* 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");
|
||||
if (do_dissection) {
|
||||
/* We're goint to print packet information, run a read filter, or
|
||||
process taps. Use process_packet() to handle that; in order
|
||||
to do that, we need to convert from libpcap to Wiretap format.
|
||||
If that fails, ignore the packet (wtap_process_pcap_packet has
|
||||
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
|
||||
|
@ -2017,13 +2053,21 @@ load_cap_file(capture_file *cf, char *save_file, int out_file_type)
|
|||
pdh = NULL;
|
||||
}
|
||||
while (wtap_read(cf->wth, &err, &err_info, &data_offset)) {
|
||||
if (!process_packet(cf, pdh, data_offset, 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 (process_packet(cf, data_offset, wtap_phdr(cf->wth),
|
||||
wtap_pseudoheader(cf->wth), wtap_buf_ptr(cf->wth))) {
|
||||
/* Either there's no read filtering or this packet passed the
|
||||
filter, so, if we're writing to a capture file, write
|
||||
this packet out. */
|
||||
if (pdh != NULL) {
|
||||
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) {
|
||||
|
@ -2148,10 +2192,8 @@ clear_fdata(frame_data *fdata)
|
|||
}
|
||||
|
||||
static gboolean
|
||||
process_packet(capture_file *cf, wtap_dumper *pdh, long offset,
|
||||
const struct wtap_pkthdr *whdr,
|
||||
union wtap_pseudo_header *pseudo_header, const guchar *pd,
|
||||
int *err)
|
||||
process_packet(capture_file *cf, long offset, const struct wtap_pkthdr *whdr,
|
||||
union wtap_pseudo_header *pseudo_header, const guchar *pd)
|
||||
{
|
||||
frame_data fdata;
|
||||
gboolean create_proto_tree;
|
||||
|
@ -2215,27 +2257,7 @@ process_packet(capture_file *cf, wtap_dumper *pdh, long offset,
|
|||
}
|
||||
|
||||
if (passed) {
|
||||
/* Count this packet. */
|
||||
#ifdef HAVE_LIBPCAP
|
||||
ld.packet_count++;
|
||||
#endif
|
||||
|
||||
/* 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) {
|
||||
/* We're printing packet information; print the information for
|
||||
this packet. */
|
||||
|
@ -2275,7 +2297,7 @@ process_packet(capture_file *cf, wtap_dumper *pdh, long offset,
|
|||
epan_dissect_free(edt);
|
||||
clear_fdata(&fdata);
|
||||
}
|
||||
return TRUE;
|
||||
return passed;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
Loading…
Reference in New Issue