[dpdk-dev] [PATCH v2 4/6] net/pcap: add libpcap wrappers
From: Dmitry Kozlyuk <hidden>
Date: 2021-02-14 02:17:02
Subsystem:
networking drivers, the rest · Maintainers:
Andrew Lunn, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Linus Torvalds
libpcap headers can expose OS headers. On Windows, system networking headers are incompatible with DPDK ones, causing multiple name clashes. API of libpcap itself involves a non-standard u_char type. Add a limited set of trivial libpcap wrappers, so that libpcap headers are not included directly by OS-independent PMD code. Use EAL types and functions for time instead of POSIX ones. Signed-off-by: Dmitry Kozlyuk <redacted> --- drivers/net/pcap/meson.build | 1 + drivers/net/pcap/pcap_ethdev.c | 157 +++++++++++++++++---------------- drivers/net/pcap/pcap_osdep.c | 122 +++++++++++++++++++++++++ drivers/net/pcap/pcap_osdep.h | 50 +++++++++++ 4 files changed, 252 insertions(+), 78 deletions(-) create mode 100644 drivers/net/pcap/pcap_osdep.c
diff --git a/drivers/net/pcap/meson.build b/drivers/net/pcap/meson.build
index 26b606699..9ab95ec3e 100644
--- a/drivers/net/pcap/meson.build
+++ b/drivers/net/pcap/meson.build@@ -13,6 +13,7 @@ if not dpdk_conf.has('RTE_PORT_PCAP') endif sources = files( 'pcap_ethdev.c', + 'pcap_osdep.c', 'pcap_osdep_@0@.c'.format(exec_env), ) ext_deps += pcap_dep
diff --git a/drivers/net/pcap/pcap_ethdev.c b/drivers/net/pcap/pcap_ethdev.c
index a102897e9..6461213e0 100644
--- a/drivers/net/pcap/pcap_ethdev.c
+++ b/drivers/net/pcap/pcap_ethdev.c@@ -4,17 +4,13 @@ * All rights reserved. */ -#include <time.h> - -#include <pcap.h> - -#include <rte_cycles.h> #include <ethdev_driver.h> #include <ethdev_vdev.h> +#include <rte_bus_vdev.h> +#include <rte_cycles.h> #include <rte_kvargs.h> #include <rte_malloc.h> #include <rte_mbuf.h> -#include <rte_bus_vdev.h> #include "pcap_osdep.h"
@@ -36,8 +32,8 @@ #define RTE_PMD_PCAP_MAX_QUEUES 16 -static char errbuf[PCAP_ERRBUF_SIZE]; -static struct timeval start_time; +static char errbuf[OSDEP_PCAP_ERRBUF_SIZE]; +static struct rte_time_us start_time; static uint64_t start_cycles; static uint64_t hz; static uint8_t iface_idx;
@@ -83,16 +79,16 @@ struct pmd_internals { }; struct pmd_process_private { - pcap_t *rx_pcap[RTE_PMD_PCAP_MAX_QUEUES]; - pcap_t *tx_pcap[RTE_PMD_PCAP_MAX_QUEUES]; - pcap_dumper_t *tx_dumper[RTE_PMD_PCAP_MAX_QUEUES]; + osdep_pcap * rx_pcap[RTE_PMD_PCAP_MAX_QUEUES]; + osdep_pcap * tx_pcap[RTE_PMD_PCAP_MAX_QUEUES]; + osdep_pcap_dumper * tx_dumper[RTE_PMD_PCAP_MAX_QUEUES]; }; struct pmd_devargs { unsigned int num_of_queue; struct devargs_queue { - pcap_dumper_t *dumper; - pcap_t *pcap; + osdep_pcap_dumper *dumper; + osdep_pcap *pcap; const char *name; const char *type; } queue[RTE_PMD_PCAP_MAX_QUEUES];
@@ -137,7 +133,7 @@ RTE_LOG_REGISTER(eth_pcap_logtype, pmd.net.pcap, NOTICE); static int eth_pcap_rx_jumbo(struct rte_mempool *mb_pool, struct rte_mbuf *mbuf, - const u_char *data, uint16_t data_len) + const uint8_t *data, uint16_t data_len) { /* Copy the first segment. */ uint16_t len = rte_pktmbuf_tailroom(mbuf);
@@ -214,14 +210,14 @@ static uint16_t eth_pcap_rx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts) { unsigned int i; - struct pcap_pkthdr header; + struct osdep_pcap_pkthdr header; struct pmd_process_private *pp; - const u_char *packet; + const uint8_t *packet; struct rte_mbuf *mbuf; struct pcap_rx_queue *pcap_q = queue; uint16_t num_rx = 0; uint32_t rx_bytes = 0; - pcap_t *pcap; + osdep_pcap *pcap; pp = rte_eth_devices[pcap_q->port_id].process_private; pcap = pp->rx_pcap[pcap_q->queue_id];
@@ -234,7 +230,7 @@ eth_pcap_rx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts) */ for (i = 0; i < nb_pkts; i++) { /* Get the next PCAP packet */ - packet = pcap_next(pcap, &header); + packet = osdep_pcap_next(pcap, &header); if (unlikely(packet == NULL)) break;
@@ -261,8 +257,8 @@ eth_pcap_rx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts) mbuf->pkt_len = (uint16_t)header.caplen; *RTE_MBUF_DYNFIELD(mbuf, timestamp_dynfield_offset, rte_mbuf_timestamp_t *) = - (uint64_t)header.ts.tv_sec * 1000000 + - header.ts.tv_usec; + (uint64_t)header.ts.sec * 1000000 + + header.ts.usec; mbuf->ol_flags |= timestamp_rx_dynflag; mbuf->port = pcap_q->port_id; bufs[num_rx] = mbuf;
@@ -285,20 +281,24 @@ eth_null_rx(void *queue __rte_unused, #define NSEC_PER_SEC 1000000000L +/* + * This function stores nanoseconds in "usec" field of struct rte_time_us, + * because "ts" goes directly to nanosecond-precision dump. + */ static inline void -calculate_timestamp(struct timeval *ts) { +calculate_timestamp(struct rte_time_us *ts) { uint64_t cycles; - struct timeval cur_time; + struct rte_time_us cur_time; cycles = rte_get_timer_cycles() - start_cycles; - cur_time.tv_sec = cycles / hz; - cur_time.tv_usec = (cycles % hz) * NSEC_PER_SEC / hz; - - ts->tv_sec = start_time.tv_sec + cur_time.tv_sec; - ts->tv_usec = start_time.tv_usec + cur_time.tv_usec; - if (ts->tv_usec >= NSEC_PER_SEC) { - ts->tv_usec -= NSEC_PER_SEC; - ts->tv_sec += 1; + cur_time.sec = cycles / hz; + cur_time.usec = (cycles % hz) * NSEC_PER_SEC / hz; + + ts->sec = start_time.sec + cur_time.sec; + ts->usec = start_time.usec + cur_time.usec; + if (ts->usec >= NSEC_PER_SEC) { + ts->usec -= NSEC_PER_SEC; + ts->sec += 1; } }
@@ -314,8 +314,8 @@ eth_pcap_tx_dumper(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts) struct pcap_tx_queue *dumper_q = queue; uint16_t num_tx = 0; uint32_t tx_bytes = 0; - struct pcap_pkthdr header; - pcap_dumper_t *dumper; + struct osdep_pcap_pkthdr header; + osdep_pcap_dumper *dumper; unsigned char temp_data[RTE_ETH_PCAP_SNAPLEN]; size_t len, caplen;
@@ -342,7 +342,7 @@ eth_pcap_tx_dumper(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts) * in the mbuf (when the mbuf is contiguous) or, otherwise, * a pointer to temp_data after copying into it. */ - pcap_dump((u_char *)dumper, &header, + osdep_pcap_dump((uint8_t *)dumper, &header, rte_pktmbuf_read(mbuf, 0, caplen, temp_data)); num_tx++;
@@ -355,7 +355,7 @@ eth_pcap_tx_dumper(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts) * process stops and to make sure the pcap file is actually written, * we flush the pcap dumper within each burst. */ - pcap_dump_flush(dumper); + osdep_pcap_dump_flush(dumper); dumper_q->tx_stat.pkts += num_tx; dumper_q->tx_stat.bytes += tx_bytes; dumper_q->tx_stat.err_pkts += nb_pkts - num_tx;
@@ -400,7 +400,7 @@ eth_pcap_tx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts) struct pcap_tx_queue *tx_queue = queue; uint16_t num_tx = 0; uint32_t tx_bytes = 0; - pcap_t *pcap; + osdep_pcap *pcap; unsigned char temp_data[RTE_ETH_PCAP_SNAPLEN]; size_t len;
@@ -426,7 +426,7 @@ eth_pcap_tx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts) * in the mbuf (when the mbuf is contiguous) or, otherwise, * a pointer to temp_data after copying into it. */ - ret = pcap_sendpacket(pcap, + ret = osdep_pcap_sendpacket(pcap, rte_pktmbuf_read(mbuf, 0, len, temp_data), len); if (unlikely(ret != 0)) break;
@@ -443,11 +443,11 @@ eth_pcap_tx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts) } /* - * pcap_open_live wrapper function + * osdep_pcap_open_live wrapper function */ static inline int -open_iface_live(const char *iface, pcap_t **pcap) { - *pcap = pcap_open_live(iface, RTE_ETH_PCAP_SNAPLEN, +open_iface_live(const char *iface, osdep_pcap **pcap) { + *pcap = osdep_pcap_open_live(iface, RTE_ETH_PCAP_SNAPLEN, RTE_ETH_PCAP_PROMISC, RTE_ETH_PCAP_TIMEOUT, errbuf); if (*pcap == NULL) {
@@ -459,7 +459,7 @@ open_iface_live(const char *iface, pcap_t **pcap) { } static int -open_single_iface(const char *iface, pcap_t **pcap) +open_single_iface(const char *iface, osdep_pcap **pcap) { if (open_iface_live(iface, pcap) < 0) { PMD_LOG(ERR, "Couldn't open interface %s", iface);
@@ -470,39 +470,39 @@ open_single_iface(const char *iface, pcap_t **pcap) } static int -open_single_tx_pcap(const char *pcap_filename, pcap_dumper_t **dumper) +open_single_tx_pcap(const char *pcap_filename, osdep_pcap_dumper **dumper) { - pcap_t *tx_pcap; + osdep_pcap *tx_pcap; /* - * We need to create a dummy empty pcap_t to use it - * with pcap_dump_open(). We create big enough an Ethernet + * We need to create a dummy empty osdep_pcap to use it + * with osdep_pcap_dump_open(). We create big enough an Ethernet * pcap holder. */ - tx_pcap = pcap_open_dead_with_tstamp_precision(DLT_EN10MB, - RTE_ETH_PCAP_SNAPSHOT_LEN, PCAP_TSTAMP_PRECISION_NANO); + tx_pcap = osdep_pcap_open_dead_with_tstamp_precision(OSDEP_DLT_EN10MB, + RTE_ETH_PCAP_SNAPSHOT_LEN, OSDEP_PCAP_TSTAMP_PRECISION_NANO); if (tx_pcap == NULL) { PMD_LOG(ERR, "Couldn't create dead pcap"); return -1; } - /* The dumper is created using the previous pcap_t reference */ - *dumper = pcap_dump_open(tx_pcap, pcap_filename); + /* The dumper is created using the previous osdep_pcap reference */ + *dumper = osdep_pcap_dump_open(tx_pcap, pcap_filename); if (*dumper == NULL) { - pcap_close(tx_pcap); + osdep_pcap_close(tx_pcap); PMD_LOG(ERR, "Couldn't open %s for writing.", pcap_filename); return -1; } - pcap_close(tx_pcap); + osdep_pcap_close(tx_pcap); return 0; } static int -open_single_rx_pcap(const char *pcap_filename, pcap_t **pcap) +open_single_rx_pcap(const char *pcap_filename, osdep_pcap **pcap) { - *pcap = pcap_open_offline(pcap_filename, errbuf); + *pcap = osdep_pcap_open_offline(pcap_filename, errbuf); if (*pcap == NULL) { PMD_LOG(ERR, "Couldn't open %s: %s", pcap_filename, errbuf);
@@ -513,17 +513,17 @@ open_single_rx_pcap(const char *pcap_filename, pcap_t **pcap) } static uint64_t -count_packets_in_pcap(pcap_t **pcap, struct pcap_rx_queue *pcap_q) +count_packets_in_pcap(osdep_pcap **pcap, struct pcap_rx_queue *pcap_q) { - const u_char *packet; - struct pcap_pkthdr header; + const uint8_t *packet; + struct osdep_pcap_pkthdr header; uint64_t pcap_pkt_count = 0; - while ((packet = pcap_next(*pcap, &header))) + while ((packet = osdep_pcap_next(*pcap, &header))) pcap_pkt_count++; /* The pcap is reopened so it can be used as normal later. */ - pcap_close(*pcap); + osdep_pcap_close(*pcap); *pcap = NULL; open_single_rx_pcap(pcap_q->name, pcap);
@@ -612,7 +612,7 @@ eth_dev_stop(struct rte_eth_dev *dev) /* Special iface case. Single pcap is open and shared between tx/rx. */ if (internals->single_iface) { - pcap_close(pp->tx_pcap[0]); + osdep_pcap_close(pp->tx_pcap[0]); pp->tx_pcap[0] = NULL; pp->rx_pcap[0] = NULL; goto status_down;
@@ -620,19 +620,19 @@ eth_dev_stop(struct rte_eth_dev *dev) for (i = 0; i < dev->data->nb_tx_queues; i++) { if (pp->tx_dumper[i] != NULL) { - pcap_dump_close(pp->tx_dumper[i]); + osdep_pcap_dump_close(pp->tx_dumper[i]); pp->tx_dumper[i] = NULL; } if (pp->tx_pcap[i] != NULL) { - pcap_close(pp->tx_pcap[i]); + osdep_pcap_close(pp->tx_pcap[i]); pp->tx_pcap[i] = NULL; } } for (i = 0; i < dev->data->nb_rx_queues; i++) { if (pp->rx_pcap[i] != NULL) { - pcap_close(pp->rx_pcap[i]); + osdep_pcap_close(pp->rx_pcap[i]); pp->rx_pcap[i] = NULL; } }
@@ -804,11 +804,11 @@ eth_rx_queue_setup(struct rte_eth_dev *dev, if (internals->infinite_rx) { struct pmd_process_private *pp; - char ring_name[NAME_MAX]; + char ring_name[RTE_RING_NAMESIZE]; static uint32_t ring_number; uint64_t pcap_pkt_count = 0; struct rte_mbuf *bufs[1]; - pcap_t **pcap; + osdep_pcap **pcap; pp = rte_eth_devices[pcap_q->port_id].process_private; pcap = &pp->rx_pcap[pcap_q->queue_id];
@@ -932,7 +932,7 @@ static const struct eth_dev_ops ops = { static int add_queue(struct pmd_devargs *pmd, const char *name, const char *type, - pcap_t *pcap, pcap_dumper_t *dumper) + osdep_pcap *pcap, osdep_pcap_dumper *dumper) { if (pmd->num_of_queue >= RTE_PMD_PCAP_MAX_QUEUES) return -1;
@@ -955,13 +955,13 @@ open_rx_pcap(const char *key, const char *value, void *extra_args) { const char *pcap_filename = value; struct pmd_devargs *rx = extra_args; - pcap_t *pcap = NULL; + osdep_pcap *pcap = NULL; if (open_single_rx_pcap(pcap_filename, &pcap) < 0) return -1; if (add_queue(rx, pcap_filename, key, pcap, NULL) < 0) { - pcap_close(pcap); + osdep_pcap_close(pcap); return -1; }
@@ -977,13 +977,13 @@ open_tx_pcap(const char *key, const char *value, void *extra_args) { const char *pcap_filename = value; struct pmd_devargs *dumpers = extra_args; - pcap_dumper_t *dumper; + osdep_pcap_dumper *dumper; if (open_single_tx_pcap(pcap_filename, &dumper) < 0) return -1; if (add_queue(dumpers, pcap_filename, key, NULL, dumper) < 0) { - pcap_dump_close(dumper); + osdep_pcap_dump_close(dumper); return -1; }
@@ -998,7 +998,7 @@ open_rx_tx_iface(const char *key, const char *value, void *extra_args) { const char *iface = value; struct pmd_devargs *tx = extra_args; - pcap_t *pcap = NULL; + osdep_pcap *pcap = NULL; if (open_single_iface(iface, &pcap) < 0) return -1;
@@ -1011,13 +1011,14 @@ open_rx_tx_iface(const char *key, const char *value, void *extra_args) } static inline int -set_iface_direction(const char *iface, pcap_t *pcap, - pcap_direction_t direction) +set_iface_direction(const char *iface, osdep_pcap *pcap, + enum osdep_pcap_direction direction) { - const char *direction_str = (direction == PCAP_D_IN) ? "IN" : "OUT"; - if (pcap_setdirection(pcap, direction) < 0) { + const char *direction_str = + (direction == OSDEP_PCAP_D_IN) ? "IN" : "OUT"; + if (osdep_pcap_setdirection(pcap, direction) < 0) { PMD_LOG(ERR, "Setting %s pcap direction %s failed - %s\n", - iface, direction_str, pcap_geterr(pcap)); + iface, direction_str, osdep_pcap_geterr(pcap)); return -1; } PMD_LOG(INFO, "Setting %s pcap direction %s\n",
@@ -1030,12 +1031,12 @@ open_iface(const char *key, const char *value, void *extra_args) { const char *iface = value; struct pmd_devargs *pmd = extra_args; - pcap_t *pcap = NULL; + osdep_pcap *pcap = NULL; if (open_single_iface(iface, &pcap) < 0) return -1; if (add_queue(pmd, iface, key, pcap, NULL) < 0) { - pcap_close(pcap); + osdep_pcap_close(pcap); return -1; }
@@ -1057,7 +1058,7 @@ open_rx_iface(const char *key, const char *value, void *extra_args) set_iface_direction(pmd->queue[qid].name, pmd->queue[qid].pcap, - PCAP_D_IN); + OSDEP_PCAP_D_IN); } return 0;
@@ -1311,7 +1312,7 @@ pmd_pcap_probe(struct rte_vdev_device *dev) name = rte_vdev_device_name(dev); PMD_LOG(INFO, "Initializing pmd_pcap for %s", name); - gettimeofday(&start_time, NULL); + rte_time_get_us(&start_time); start_cycles = rte_get_timer_cycles(); hz = rte_get_timer_hz();
diff --git a/drivers/net/pcap/pcap_osdep.c b/drivers/net/pcap/pcap_osdep.c
new file mode 100644
index 000000000..5cac9bb89
--- /dev/null
+++ b/drivers/net/pcap/pcap_osdep.c@@ -0,0 +1,122 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright (c) 2021 Dmitry Kozlyuk + */ + +#include <pcap.h> + +#include <rte_common.h> + +#include "pcap_osdep.h" + +static inline void +to_osdep_header(const struct pcap_pkthdr *in, struct osdep_pcap_pkthdr *out) +{ + out->ts.sec = in->ts.tv_sec; + out->ts.usec = in->ts.tv_usec; + out->caplen = in->caplen; + out->len = in->len; +} + +static inline void +to_pcap_header(const struct osdep_pcap_pkthdr *in, struct pcap_pkthdr *out) +{ + out->ts.tv_sec = in->ts.sec; + out->ts.tv_usec = in->ts.usec; + out->caplen = in->caplen; + out->len = in->len; +} + +osdep_pcap * +osdep_pcap_open_live(const char *device, int snaplen, + int promisc, int to_ms, char *errbuf) +{ + RTE_BUILD_BUG_ON(OSDEP_PCAP_ERRBUF_SIZE != PCAP_ERRBUF_SIZE); + + return (osdep_pcap *)pcap_open_live(device, snaplen, promisc, to_ms, + errbuf); +} + +osdep_pcap * +osdep_pcap_open_offline(const char *fname, char *errbuf) +{ + return (osdep_pcap *)pcap_open_offline(fname, errbuf); +} + +osdep_pcap * +osdep_pcap_open_dead_with_tstamp_precision(int linktype, int snaplen, + unsigned int precision) +{ + RTE_BUILD_BUG_ON(OSDEP_DLT_EN10MB != DLT_EN10MB); + RTE_BUILD_BUG_ON(OSDEP_PCAP_TSTAMP_PRECISION_NANO != + PCAP_TSTAMP_PRECISION_NANO); + + return (osdep_pcap *)pcap_open_dead_with_tstamp_precision(linktype, + snaplen, precision); +} + +const uint8_t * +osdep_pcap_next(osdep_pcap *pcap, struct osdep_pcap_pkthdr *header) +{ + const uint8_t *data; + struct pcap_pkthdr pkthdr; + + data = pcap_next((pcap_t *)pcap, &pkthdr); + to_osdep_header(&pkthdr, header); + return data; +} + +int +osdep_pcap_sendpacket(osdep_pcap *pcap, const uint8_t *buf, int size) +{ + return pcap_sendpacket((pcap_t *)pcap, buf, size); +} + +void +osdep_pcap_close(osdep_pcap *pcap) +{ + pcap_close((pcap_t *)pcap); +} + +osdep_pcap_dumper * +osdep_pcap_dump_open(osdep_pcap *pcap, const char *fname) +{ + return (osdep_pcap_dumper *)pcap_dump_open((pcap_t *)pcap, fname); +} + +void +osdep_pcap_dump(uint8_t *user, const struct osdep_pcap_pkthdr *header, + const uint8_t *sp) +{ + struct pcap_pkthdr pkthdr; + + to_pcap_header(header, &pkthdr); + pcap_dump(user, &pkthdr, sp); +} + +int +osdep_pcap_dump_flush(osdep_pcap_dumper *p) +{ + return pcap_dump_flush((pcap_dumper_t *)p); +} + +void +osdep_pcap_dump_close(osdep_pcap_dumper *p) +{ + pcap_dump_close((pcap_dumper_t *)p); +} + +int +osdep_pcap_setdirection(osdep_pcap *pcap, enum osdep_pcap_direction dir) +{ + RTE_BUILD_BUG_ON((int)OSDEP_PCAP_D_INOUT != (int)PCAP_D_INOUT); + RTE_BUILD_BUG_ON((int)OSDEP_PCAP_D_IN != (int)PCAP_D_IN); + RTE_BUILD_BUG_ON((int)OSDEP_PCAP_D_OUT != (int)PCAP_D_OUT); + + return pcap_setdirection((pcap_t *)pcap, (pcap_direction_t)dir); +} + +const char * +osdep_pcap_geterr(osdep_pcap *pcap) +{ + return pcap_geterr((pcap_t *)pcap); +}
diff --git a/drivers/net/pcap/pcap_osdep.h b/drivers/net/pcap/pcap_osdep.h
index 46810d86f..bd00b728a 100644
--- a/drivers/net/pcap/pcap_osdep.h
+++ b/drivers/net/pcap/pcap_osdep.h@@ -6,6 +6,7 @@ #define _RTE_PCAP_OSDEP_ #include <rte_ether.h> +#include <rte_time.h> /* * Interface manipulation is always OS-specific.
@@ -14,4 +15,53 @@ int osdep_iface_index_get(const char *name); int osdep_iface_mac_get(const char *name, struct rte_ether_addr *mac); +/* + * On Windows, libpcap (npcap or WinPcap) exposes Win32 API which clashes + * with some DPDK constructs. Trivial libpcap wrappers with "osdep_" prefix + * are provided to isolate PMD code from Win32 API. + */ + +#define OSDEP_DLT_EN10MB 1 + +#define OSDEP_PCAP_ERRBUF_SIZE 256 + +#define OSDEP_PCAP_TSTAMP_PRECISION_NANO 1 + +/** Handle for an open packet capture. */ +typedef struct osdep_pcap_type osdep_pcap; + +/** Handle for an open packet dump. */ +typedef struct osdep_pcap_dumper_type osdep_pcap_dumper; + +struct osdep_pcap_pkthdr { + struct rte_time_us ts; + uint32_t caplen; + uint32_t len; +}; + +enum osdep_pcap_direction { + OSDEP_PCAP_D_INOUT = 0, + OSDEP_PCAP_D_IN, + OSDEP_PCAP_D_OUT +}; + +osdep_pcap *osdep_pcap_open_live(const char *device, int snaplen, + int promisc, int to_ms, char *errbuf); +osdep_pcap *osdep_pcap_open_offline(const char *fname, char *errbuf); +osdep_pcap *osdep_pcap_open_dead_with_tstamp_precision(int linktype, + int snaplen, unsigned int precision); +const uint8_t *osdep_pcap_next(osdep_pcap *pcap, + struct osdep_pcap_pkthdr *header); +int osdep_pcap_sendpacket(osdep_pcap *pcap, const uint8_t *buf, int size); +void osdep_pcap_close(osdep_pcap *pcap); + +osdep_pcap_dumper *osdep_pcap_dump_open(osdep_pcap *pcap, const char *fname); +void osdep_pcap_dump(uint8_t *user, const struct osdep_pcap_pkthdr *header, + const uint8_t *sp); +int osdep_pcap_dump_flush(osdep_pcap_dumper *p); +void osdep_pcap_dump_close(osdep_pcap_dumper *p); + +int osdep_pcap_setdirection(osdep_pcap *pcap, enum osdep_pcap_direction dir); +const char *osdep_pcap_geterr(osdep_pcap *pcap); + #endif
--
2.29.2