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):