Wireshark-dev: [Wireshark-dev] Adding support for pcap-ng to dumpcap or reading from pipes
From: Richard Sharpe <realrichardsharpe@xxxxxxxxx>
Date: Mon, 7 May 2012 08:24:10 -0700
Hi folks,
I am looking at adding support for pcap-ng to dumpcap.c so it can be
read directly from pipes.
Is anyone else working on this?
In any event, I have an initial patch that moves the relevant pcap
stuff into a separate structure, and it currently works, but it is a
bit ugly and does not yet handle pcap-ng. That is, I can still load a
multi-record pcap file via a pipe.
Does anyone have any feedback on the approach or concerns?
Index: dumpcap.c
===================================================================
--- dumpcap.c (revision 42332)
+++ dumpcap.c (working copy)
@@ -84,6 +84,7 @@
#endif /* _WIN32 */
#include "pcapio.h"
+#include "wtap.h"
#ifdef _WIN32
#include "capture-wpcap.h"
@@ -215,6 +216,29 @@
INITFILTER_OTHER_ERROR
} initfilter_status_t;
+/*
+ * Allow us to handle both pcap and pcapng records through a pipe
+ */
+typedef struct _pcap_pipe_info {
+ struct pcap_hdr cap_pipe_hdr;
+ struct pcaprec_modified_hdr cap_pipe_rechdr;
+ gboolean cap_pipe_modified;
+ enum {
+ PCAP_STATE_EXPECT_REC_HDR,
+ PCAP_STATE_READ_REC_HDR,
+ PCAP_STATE_EXPECT_DATA,
+ PCAP_STATE_READ_DATA
+ } cap_pipe_state;
+} pcap_pipe_info;
+
+typedef struct _pcapng_pipe_info {
+ struct wtap_pkthdr capng_pipe_hdr;
+ enum {
+ PCAPNG_STATE_EXPECT_SHB_REC,
+ PCAPNG_STATE_READ_SHB_REC
+ } capng_pipe_state;
+} pcapng_pipe_info;
+
typedef struct _pcap_options {
guint32 received;
guint32 dropped;
@@ -230,26 +254,21 @@
gboolean ts_nsec; /* TRUE if we're using
nanosecond precision. */
/* capture pipe (unix only "input file") */
gboolean from_cap_pipe; /* TRUE if we are capturing
data from a capture pipe */
- struct pcap_hdr cap_pipe_hdr; /* Pcap header when
capturing from a pipe */
- struct pcaprec_modified_hdr cap_pipe_rechdr; /* Pcap record
header when capturing from a pipe */
+ union {
+ pcap_pipe_info pcap;
+ pcapng_pipe_info pcapng;
+ } u;
#ifdef _WIN32
HANDLE cap_pipe_h; /* The handle of the capture pipe */
#else
int cap_pipe_fd; /* the file descriptor of
the capture pipe */
#endif
- gboolean cap_pipe_modified; /* TRUE if data in the pipe
uses modified pcap headers */
gboolean cap_pipe_byte_swapped; /* TRUE if data in the pipe
is byte swapped */
#if defined(_WIN32)
char * cap_pipe_buf; /* Pointer to the data
buffer we read into */
#endif
int cap_pipe_bytes_to_read;/* Used by cap_pipe_dispatch */
int cap_pipe_bytes_read; /* Used by cap_pipe_dispatch */
- enum {
- STATE_EXPECT_REC_HDR,
- STATE_READ_REC_HDR,
- STATE_EXPECT_DATA,
- STATE_READ_DATA
- } cap_pipe_state;
enum { PIPOK, PIPEOF, PIPERR, PIPNEXIST } cap_pipe_err;
#if defined(_WIN32)
GMutex *cap_pipe_read_mtx;
@@ -1998,14 +2017,14 @@
/* Host that wrote it has our byte order, and was running
a program using either standard or ss990417 libpcap. */
pcap_opts->cap_pipe_byte_swapped = FALSE;
- pcap_opts->cap_pipe_modified = FALSE;
+ pcap_opts->u.pcap.cap_pipe_modified = FALSE;
pcap_opts->ts_nsec = magic == PCAP_NSEC_MAGIC;
break;
case PCAP_MODIFIED_MAGIC:
/* Host that wrote it has our byte order, but was running
a program using either ss990915 or ss991029 libpcap. */
pcap_opts->cap_pipe_byte_swapped = FALSE;
- pcap_opts->cap_pipe_modified = TRUE;
+ pcap_opts->u.pcap.cap_pipe_modified = TRUE;
break;
case PCAP_SWAPPED_MAGIC:
case PCAP_SWAPPED_NSEC_MAGIC:
@@ -2013,7 +2032,7 @@
and was running a program using either standard or
ss990417 libpcap. */
pcap_opts->cap_pipe_byte_swapped = TRUE;
- pcap_opts->cap_pipe_modified = FALSE;
+ pcap_opts->u.pcap.cap_pipe_modified = FALSE;
pcap_opts->ts_nsec = magic == PCAP_SWAPPED_NSEC_MAGIC;
break;
case PCAP_SWAPPED_MODIFIED_MAGIC:
@@ -2021,7 +2040,7 @@
ours, and was running a program using either ss990915
or ss991029 libpcap. */
pcap_opts->cap_pipe_byte_swapped = TRUE;
- pcap_opts->cap_pipe_modified = TRUE;
+ pcap_opts->u.pcap.cap_pipe_modified = TRUE;
break;
default:
/* Not a "libpcap" type we know about. */
@@ -2082,7 +2101,7 @@
goto error;
}
- pcap_opts->cap_pipe_state = STATE_EXPECT_REC_HDR;
+ pcap_opts->u.pcap.cap_pipe_state = PCAP_STATE_EXPECT_REC_HDR;
pcap_opts->cap_pipe_err = PIPOK;
#ifndef _WIN32
pcap_opts->cap_pipe_fd = fd;
@@ -2125,15 +2144,15 @@
g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "cap_pipe_dispatch");
#endif
- switch (pcap_opts->cap_pipe_state) {
+ switch (pcap_opts->u.pcap.cap_pipe_state) {
- case STATE_EXPECT_REC_HDR:
+ case PCAP_STATE_EXPECT_REC_HDR:
#ifdef _WIN32
if (g_mutex_trylock(pcap_opts->cap_pipe_read_mtx)) {
#endif
- pcap_opts->cap_pipe_state = STATE_READ_REC_HDR;
- pcap_opts->cap_pipe_bytes_to_read = pcap_opts->cap_pipe_modified ?
+ pcap_opts->u.pcap.cap_pipe_state = PCAP_STATE_READ_REC_HDR;
+ pcap_opts->cap_pipe_bytes_to_read =
pcap_opts->u.pcap.cap_pipe_modified ?
sizeof(struct pcaprec_modified_hdr) : sizeof(struct
pcaprec_hdr);
pcap_opts->cap_pipe_bytes_read = 0;
@@ -2145,9 +2164,9 @@
#endif
/* Fall through */
- case STATE_READ_REC_HDR:
+ case PCAP_STATE_READ_REC_HDR:
#ifndef _WIN32
- b = read(pcap_opts->cap_pipe_fd, ((char
*)&pcap_opts->cap_pipe_rechdr)+pcap_opts->cap_pipe_bytes_read,
+ b = read(pcap_opts->cap_pipe_fd, ((char
*)&pcap_opts->u.pcap.cap_pipe_rechdr)+pcap_opts->cap_pipe_bytes_read,
pcap_opts->cap_pipe_bytes_to_read -
pcap_opts->cap_pipe_bytes_read);
if (b <= 0) {
if (b == 0)
@@ -2181,13 +2200,13 @@
result = PD_REC_HDR_READ;
break;
- case STATE_EXPECT_DATA:
+ case PCAP_STATE_EXPECT_DATA:
#ifdef _WIN32
if (g_mutex_trylock(pcap_opts->cap_pipe_read_mtx)) {
#endif
- pcap_opts->cap_pipe_state = STATE_READ_DATA;
- pcap_opts->cap_pipe_bytes_to_read =
pcap_opts->cap_pipe_rechdr.hdr.incl_len;
+ pcap_opts->u.pcap.cap_pipe_state = PCAP_STATE_READ_DATA;
+ pcap_opts->cap_pipe_bytes_to_read =
pcap_opts->u.pcap.cap_pipe_rechdr.hdr.incl_len;
pcap_opts->cap_pipe_bytes_read = 0;
#ifdef _WIN32
@@ -2198,7 +2217,7 @@
#endif
/* Fall through */
- case STATE_READ_DATA:
+ case PCAP_STATE_READ_DATA:
#ifndef _WIN32
b = read(pcap_opts->cap_pipe_fd, data+pcap_opts->cap_pipe_bytes_read,
pcap_opts->cap_pipe_bytes_to_read -
pcap_opts->cap_pipe_bytes_read);
@@ -2247,33 +2266,33 @@
case PD_REC_HDR_READ:
/* We've read the header. Take care of byte order. */
- cap_pipe_adjust_header(pcap_opts->cap_pipe_byte_swapped,
&pcap_opts->cap_pipe_hdr,
- &pcap_opts->cap_pipe_rechdr.hdr);
- if (pcap_opts->cap_pipe_rechdr.hdr.incl_len > WTAP_MAX_PACKET_SIZE) {
+ cap_pipe_adjust_header(pcap_opts->cap_pipe_byte_swapped,
&pcap_opts->u.pcap.cap_pipe_hdr,
+ &pcap_opts->u.pcap.cap_pipe_rechdr.hdr);
+ if (pcap_opts->u.pcap.cap_pipe_rechdr.hdr.incl_len >
WTAP_MAX_PACKET_SIZE) {
g_snprintf(errmsg, errmsgl, "Frame %u too long (%d bytes)",
- ld->packet_count+1,
pcap_opts->cap_pipe_rechdr.hdr.incl_len);
+ ld->packet_count+1,
pcap_opts->u.pcap.cap_pipe_rechdr.hdr.incl_len);
break;
}
- if (pcap_opts->cap_pipe_rechdr.hdr.incl_len) {
- pcap_opts->cap_pipe_state = STATE_EXPECT_DATA;
+ if (pcap_opts->u.pcap.cap_pipe_rechdr.hdr.incl_len) {
+ pcap_opts->u.pcap.cap_pipe_state = PCAP_STATE_EXPECT_DATA;
return 0;
}
/* no data to read? fall through */
case PD_DATA_READ:
/* Fill in a "struct pcap_pkthdr", and process the packet. */
- phdr.ts.tv_sec = pcap_opts->cap_pipe_rechdr.hdr.ts_sec;
- phdr.ts.tv_usec = pcap_opts->cap_pipe_rechdr.hdr.ts_usec;
- phdr.caplen = pcap_opts->cap_pipe_rechdr.hdr.incl_len;
- phdr.len = pcap_opts->cap_pipe_rechdr.hdr.orig_len;
+ phdr.ts.tv_sec = pcap_opts->u.pcap.cap_pipe_rechdr.hdr.ts_sec;
+ phdr.ts.tv_usec = pcap_opts->u.pcap.cap_pipe_rechdr.hdr.ts_usec;
+ phdr.caplen = pcap_opts->u.pcap.cap_pipe_rechdr.hdr.incl_len;
+ phdr.len = pcap_opts->u.pcap.cap_pipe_rechdr.hdr.orig_len;
if (use_threads) {
capture_loop_queue_packet_cb((u_char *)pcap_opts, &phdr, data);
} else {
capture_loop_write_packet_cb((u_char *)pcap_opts, &phdr, data);
}
- pcap_opts->cap_pipe_state = STATE_EXPECT_REC_HDR;
+ pcap_opts->u.pcap.cap_pipe_state = PCAP_STATE_EXPECT_REC_HDR;
return 1;
case PD_PIPE_EOF:
@@ -2397,21 +2416,21 @@
pcap_opts->linktype = -1;
pcap_opts->ts_nsec = FALSE;
pcap_opts->from_cap_pipe = FALSE;
- memset(&pcap_opts->cap_pipe_hdr, 0, sizeof(struct pcap_hdr));
- memset(&pcap_opts->cap_pipe_rechdr, 0, sizeof(struct
pcaprec_modified_hdr));
+ memset(&pcap_opts->u.pcap.cap_pipe_hdr, 0, sizeof(struct pcap_hdr));
+ memset(&pcap_opts->u.pcap.cap_pipe_rechdr, 0, sizeof(struct
pcaprec_modified_hdr));
#ifdef _WIN32
pcap_opts->cap_pipe_h = INVALID_HANDLE_VALUE;
#else
pcap_opts->cap_pipe_fd = -1;
#endif
- pcap_opts->cap_pipe_modified = FALSE;
+ pcap_opts->u.pcap.cap_pipe_modified = FALSE;
pcap_opts->cap_pipe_byte_swapped = FALSE;
#ifdef _WIN32
pcap_opts->cap_pipe_buf = NULL;
#endif
pcap_opts->cap_pipe_bytes_to_read = 0;
pcap_opts->cap_pipe_bytes_read = 0;
- pcap_opts->cap_pipe_state = 0;
+ pcap_opts->u.pcap.cap_pipe_state = 0;
pcap_opts->cap_pipe_err = PIPOK;
#ifdef _WIN32
#if GLIB_CHECK_VERSION(2,31,0)
@@ -2487,7 +2506,7 @@
} else {
/* We couldn't open "iface" as a network device. */
/* Try to open it as a pipe */
- cap_pipe_open_live(interface_opts.name, pcap_opts,
&pcap_opts->cap_pipe_hdr, errmsg, (int) errmsg_len);
+ cap_pipe_open_live(interface_opts.name, pcap_opts,
&pcap_opts->u.pcap.cap_pipe_hdr, errmsg, (int) errmsg_len);
#ifndef _WIN32
if (pcap_opts->cap_pipe_fd == -1) {
@@ -2670,7 +2689,7 @@
interface_opts = g_array_index(capture_opts->ifaces,
interface_options, i);
pcap_opts = g_array_index(ld->pcaps, pcap_options *, i);
if (pcap_opts->from_cap_pipe) {
- pcap_opts->snaplen = pcap_opts->cap_pipe_hdr.snaplen;
+ pcap_opts->snaplen =
pcap_opts->u.pcap.cap_pipe_hdr.snaplen;
} else {
pcap_opts->snaplen = pcap_snapshot(pcap_opts->pcap_h);
}
@@ -2693,7 +2712,7 @@
} else {
pcap_opts = g_array_index(ld->pcaps, pcap_options *, 0);
if (pcap_opts->from_cap_pipe) {
- pcap_opts->snaplen = pcap_opts->cap_pipe_hdr.snaplen;
+ pcap_opts->snaplen = pcap_opts->u.pcap.cap_pipe_hdr.snaplen;
} else {
pcap_opts->snaplen = pcap_snapshot(pcap_opts->pcap_h);
}
--
Regards,
Richard Sharpe
(何以解憂?唯有杜康。--曹操)
- Follow-Ups:
- Re: [Wireshark-dev] Adding support for pcap-ng to dumpcap or reading from pipes
- From: Jakub Zawadzki
- Re: [Wireshark-dev] Adding support for pcap-ng to dumpcap or reading from pipes
- Prev by Date: Re: [Wireshark-dev] Filtering on eth.type if vlan is used
- Next by Date: Re: [Wireshark-dev] [Wireshark-commits] rev 42468: /trunk/epan/dissectors/ /trunk/epan/dissectors/: packet-rlc-lte.c
- Previous by thread: Re: [Wireshark-dev] Filtering on eth.type if vlan is used
- Next by thread: Re: [Wireshark-dev] Adding support for pcap-ng to dumpcap or reading from pipes
- Index(es):