summaryrefslogtreecommitdiffstats
path: root/lib/libpcap
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libpcap')
-rw-r--r--lib/libpcap/Makefile148
-rw-r--r--lib/libpcap/config.h349
-rw-r--r--lib/libpcap/pcap-netmap.c283
3 files changed, 780 insertions, 0 deletions
diff --git a/lib/libpcap/Makefile b/lib/libpcap/Makefile
new file mode 100644
index 0000000..c36b3ef
--- /dev/null
+++ b/lib/libpcap/Makefile
@@ -0,0 +1,148 @@
+# Makefile for libpcap
+# $FreeBSD$
+
+SHLIBDIR?= /lib
+
+.include <src.opts.mk>
+
+LIB= pcap
+SRCS= grammar.y tokdefs.h version.h pcap-bpf.c \
+ pcap-netmap.c \
+ pcap.c pcap-common.c inet.c fad-getad.c gencode.c optimize.c nametoaddr.c \
+ etherent.c savefile.c bpf_filter.c bpf_image.c bpf_dump.c \
+ scanner.l sf-pcap.c sf-pcap-ng.c version.c
+
+# Old compatibility headers
+INCS= pcap.h pcap-int.h pcap-namedb.h pcap-bpf.h
+
+PCAPINCS= pcap/pcap.h pcap/namedb.h pcap/bpf.h
+PCAPINCSDIR= ${INCLUDEDIR}/pcap
+INCSGROUPS= INCS PCAPINCS
+
+MAN= pcap.3 \
+ pcap_activate.3 \
+ pcap_breakloop.3 \
+ pcap_can_set_rfmon.3 \
+ pcap_close.3 \
+ pcap_compile.3 \
+ pcap_create.3 \
+ pcap_datalink.3 \
+ pcap_datalink_name_to_val.3 \
+ pcap_datalink_val_to_name.3 \
+ pcap_dump.3 \
+ pcap_dump_close.3 \
+ pcap_dump_file.3 \
+ pcap_dump_flush.3 \
+ pcap_dump_ftell.3 \
+ pcap_dump_open.3 \
+ pcap_file.3 \
+ pcap_fileno.3 \
+ pcap_findalldevs.3 \
+ pcap_freecode.3 \
+ pcap_get_selectable_fd.3 \
+ pcap_get_tstamp_precision.3 \
+ pcap_geterr.3 \
+ pcap_inject.3 \
+ pcap_is_swapped.3 \
+ pcap_lib_version.3 \
+ pcap_list_datalinks.3 \
+ pcap_list_tstamp_types.3 \
+ pcap_lookupdev.3 \
+ pcap_lookupnet.3 \
+ pcap_loop.3 \
+ pcap_major_version.3 \
+ pcap_next_ex.3 \
+ pcap_offline_filter.3 \
+ pcap_open_dead.3 \
+ pcap_open_live.3 \
+ pcap_open_offline.3 \
+ pcap_set_buffer_size.3 \
+ pcap_set_datalink.3 \
+ pcap_set_immediate_mode.3 \
+ pcap_set_promisc.3 \
+ pcap_set_rfmon.3 \
+ pcap_set_snaplen.3 \
+ pcap_set_timeout.3 \
+ pcap_set_tstamp_precision.3 \
+ pcap_set_tstamp_type.3 \
+ pcap_setdirection.3 \
+ pcap_setfilter.3 \
+ pcap_setnonblock.3 \
+ pcap_snapshot.3 \
+ pcap_stats.3 \
+ pcap_statustostr.3 \
+ pcap_strerror.3 \
+ pcap-savefile.5 \
+ pcap_tstamp_type_name_to_val.3 \
+ pcap_tstamp_type_val_to_name.3 \
+ pcap-filter.7 \
+ pcap-linktype.7
+MLINKS= pcap_datalink_val_to_name.3 pcap_datalink_val_to_description.3 \
+ pcap_dump_open.3 pcap_dump_fopen.3 \
+ pcap_findalldevs.3 pcap_freealldevs.3 \
+ pcap_geterr.3 pcap_perror.3 \
+ pcap_inject.3 pcap_sendpacket.3 \
+ pcap_list_datalinks.3 pcap_free_datalinks.3 \
+ pcap_list_tstamp_types.3 pcap_free_tstamp_types.3 \
+ pcap_loop.3 pcap_dispatch.3 \
+ pcap_major_version.3 pcap_minor_version.3 \
+ pcap_next_ex.3 pcap_next.3 \
+ pcap_open_offline.3 pcap_fopen_offline.3 \
+ pcap_setnonblock.3 pcap_getnonblock.3
+
+# Our man pages are a special copy from the distdir. See below.
+CLEANFILES+=${MAN}
+CLEANFILES+=tokdefs.h version.h version.c
+
+YFLAGS+=-p pcapyy
+LFLAGS+=-Ppcapyy
+CFLAGS+=-DHAVE_CONFIG_H -Dyylval=pcapyylval -I${.CURDIR} -I.
+CFLAGS+=-D_U_="__attribute__((unused))"
+CFLAGS+=-DHAVE_SNPRINTF -DHAVE_VSNPRINTF
+.if ${MK_INET6_SUPPORT} != "no"
+CFLAGS+=-DINET6
+.endif
+.if ${MK_PF} != "no"
+CFLAGS+=-DHAVE_NET_PFVAR_H
+.endif
+
+WARNS?= 0
+
+SHLIB_MAJOR= 8
+
+#
+# Magic to grab sources out of src/contrib
+#
+PCAP_DISTDIR?=${.CURDIR}/../../contrib/libpcap
+CFLAGS+=-I${PCAP_DISTDIR}
+.PATH: ${PCAP_DISTDIR}
+.PATH: ${PCAP_DISTDIR}/bpf/net
+
+version.c: ${PCAP_DISTDIR}/VERSION
+ @rm -f $@
+ sed 's/.*/char pcap_version[] = "&";/' ${PCAP_DISTDIR}/VERSION > $@
+
+version.h: ${PCAP_DISTDIR}/VERSION
+ @rm -f $@
+ sed 's/.*/char pcap_version_string[] = "libpcap version &";/' ${PCAP_DISTDIR}/VERSION > $@
+
+tokdefs.h: grammar.h
+ ln -sf grammar.h tokdefs.h
+
+
+#
+# Magic to convert the man pages to something non Solarish
+#
+.for _page in ${MAN}
+${_page}:
+ if [ -f ${PCAP_DISTDIR}/${_page:S/3$/3pcap/} ]; then \
+ F=${_page:S/3$/3pcap/}; \
+ elif [ -f ${PCAP_DISTDIR}/${_page:S/5$/manfile/} ]; then \
+ F=${_page:S/5$/manfile/}; \
+ else \
+ F=${_page:S/7$/manmisc/}; \
+ fi; \
+ sed -e 's/3PCAP/3/g' ${PCAP_DISTDIR}/$$F > ${_page}
+.endfor
+
+.include <bsd.lib.mk>
diff --git a/lib/libpcap/config.h b/lib/libpcap/config.h
new file mode 100644
index 0000000..4033b27
--- /dev/null
+++ b/lib/libpcap/config.h
@@ -0,0 +1,349 @@
+/* $FreeBSD$ */
+/* This is an edited copy of the config.h generated by configure. */
+
+/* config.h. Generated from config.h.in by configure. */
+/* config.h.in. Generated from configure.in by autoheader. */
+
+/* Enable optimizer debugging */
+/* #undef BDEBUG */
+
+/* define if you have a cloning BPF device */
+#define HAVE_CLONING_BPF 1
+
+/* define if you have the DAG API */
+/* #undef HAVE_DAG_API */
+
+/* define if you have dag_get_erf_types() */
+/* #undef HAVE_DAG_GET_ERF_TYPES */
+
+/* define if you have dag_get_stream_erf_types() */
+/* #undef HAVE_DAG_GET_STREAM_ERF_TYPES */
+
+/* define if you have streams capable DAG API */
+/* #undef HAVE_DAG_STREAMS_API */
+
+/* define if you have vdag_set_device_info() */
+/* #undef HAVE_DAG_VDAG */
+
+/* Define to 1 if you have the declaration of `ether_hostton', and to 0 if you
+ don't. */
+#define HAVE_DECL_ETHER_HOSTTON 1
+
+/* define if you have a /dev/dlpi */
+/* #undef HAVE_DEV_DLPI */
+
+/* if passive_req_t primitive exists */
+/* #undef HAVE_DLPI_PASSIVE */
+
+/* Define to 1 if you have the `ether_hostton' function. */
+#define HAVE_ETHER_HOSTTON 1
+
+/* Define to 1 if fseeko (and presumably ftello) exists and is declared. */
+#define HAVE_FSEEKO 1
+
+/* on HP-UX 10.20 or later */
+/* #undef HAVE_HPUX10_20_OR_LATER */
+
+/* on HP-UX 9.x */
+/* #undef HAVE_HPUX9 */
+
+/* if ppa_info_t_dl_module_id exists */
+/* #undef HAVE_HP_PPA_INFO_T_DL_MODULE_ID_1 */
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* if libdlpi exists */
+/* #undef HAVE_LIBDLPI */
+
+/* if libnl exists */
+/* #undef HAVE_LIBNL */
+
+/* if libnl exists and is version 2.x */
+/* #undef HAVE_LIBNL_2_x */
+
+/* if libnl exists and is version 3.x */
+/* #undef HAVE_LIBNL_3_x */
+
+/* libnl has NLE_FAILURE */
+/* #undef HAVE_LIBNL_NLE */
+
+/* libnl has new-style socket api */
+/* #undef HAVE_LIBNL_SOCKETS */
+
+/* Define to 1 if you have the <limits.h> header file. */
+#define HAVE_LIMITS_H 1
+
+/* Define to 1 if you have the <linux/compiler.h> header file. */
+/* #undef HAVE_LINUX_COMPILER_H */
+
+/* Define to 1 if you have the <linux/ethtool.h> header file. */
+/* #undef HAVE_LINUX_ETHTOOL_H */
+
+/* Define to 1 if you have the <linux/if_packet.h> header file. */
+/* #undef HAVE_LINUX_IF_PACKET_H */
+
+/* Define to 1 if you have the <linux/net_tstamp.h> header file. */
+/* #undef HAVE_LINUX_NET_TSTAMP_H */
+
+/* if tp_vlan_tci exists */
+/* #undef HAVE_LINUX_TPACKET_AUXDATA_TP_VLAN_TCI */
+
+/* Define to 1 if you have the <linux/types.h> header file. */
+/* #undef HAVE_LINUX_TYPES_H */
+
+/* Define to 1 if you have the <linux/usbdevice_fs.h> header file. */
+/* #undef HAVE_LINUX_USBDEVICE_FS_H */
+
+/* Define to 1 if you have the <linux/wireless.h> header file. */
+/* #undef HAVE_LINUX_WIRELESS_H */
+
+/* Define to 1 if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the <netinet/ether.h> header file. */
+/* #undef HAVE_NETINET_ETHER_H */
+
+/* Define to 1 if you have the <netinet/if_ether.h> header file. */
+#define HAVE_NETINET_IF_ETHER_H 1
+
+/* Define to 1 if you have the <netpacket/if_packet.h> header file. */
+/* #undef HAVE_NETPACKET_IF_PACKET_H */
+
+/* Define to 1 if you have the <netpacket/packet.h> header file. */
+/* #undef HAVE_NETPACKET_PACKET_H */
+
+/* Define to 1 if you have the <net/if_media.h> header file. */
+#define HAVE_NET_IF_MEDIA_H 1
+
+/* Define to 1 if you have the <net/pfvar.h> header file. */
+/* See Makefile */
+/* #undef HAVE_NET_PFVAR_H */
+
+/* if there's an os_proto.h for this platform, to use additional prototypes */
+/* #undef HAVE_OS_PROTO_H */
+
+/* Define to 1 if you have the <paths.h> header file. */
+#define HAVE_PATHS_H 1
+
+/* define if net/pfvar.h defines PF_NAT through PF_NORDR */
+#define HAVE_PF_NAT_THROUGH_PF_NORDR 1
+
+/* define if you have a Septel API */
+/* #undef HAVE_SEPTEL_API */
+
+/* define if you have Myricom SNF API */
+/* #undef HAVE_SNF_API */
+
+/* Define to 1 if you have the `snprintf' function. */
+#define HAVE_SNPRINTF 1
+
+/* if struct sockaddr has the sa_len member */
+#define HAVE_SOCKADDR_SA_LEN 1
+
+/* if struct sockaddr_storage exists */
+#define HAVE_SOCKADDR_STORAGE 1
+
+/* define if socklen_t is defined */
+#define HAVE_SOCKLEN_T 1
+
+/* On solaris */
+/* #undef HAVE_SOLARIS */
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the `strerror' function. */
+#define HAVE_STRERROR 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the `strlcpy' function. */
+#define HAVE_STRLCPY 1
+
+/* Define to 1 if the system has the type `struct BPF_TIMEVAL'. */
+/* #undef HAVE_STRUCT_BPF_TIMEVAL */
+
+/* Define to 1 if the system has the type `struct ether_addr'. */
+/* #undef HAVE_STRUCT_ETHER_ADDR */
+
+/* Define to 1 if you have the <sys/bitypes.h> header file. */
+/* #undef HAVE_SYS_BITYPES_H */
+
+/* Define to 1 if you have the <sys/bufmod.h> header file. */
+/* #undef HAVE_SYS_BUFMOD_H */
+
+/* Define to 1 if you have the <sys/dlpi_ext.h> header file. */
+/* #undef HAVE_SYS_DLPI_EXT_H */
+
+/* Define to 1 if you have the <sys/ioccom.h> header file. */
+#define HAVE_SYS_IOCCOM_H 1
+
+/* Define to 1 if you have the <sys/sockio.h> header file. */
+#define HAVE_SYS_SOCKIO_H 1
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* if if_packet.h has tpacket_stats defined */
+/* #undef HAVE_TPACKET_STATS */
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* if struct usbdevfs_ctrltransfer has bRequestType */
+/* #undef HAVE_USBDEVFS_CTRLTRANSFER_BREQUESTTYPE */
+
+/* define if version.h is generated in the build procedure */
+#define HAVE_VERSION_H 1
+
+/* Define to 1 if you have the `vsnprintf' function. */
+#define HAVE_VSNPRINTF 1
+
+/* define if the system supports zerocopy BPF */
+#define HAVE_ZEROCOPY_BPF 1
+
+/* define if your compiler has __attribute__ */
+#define HAVE___ATTRIBUTE__ 1
+
+/* IPv6 */
+/* See Makefile */
+/* #undef INET6 */
+
+/* if unaligned access fails */
+/* #undef LBL_ALIGN */
+
+/* path for device for USB sniffing */
+/* #undef LINUX_USB_MON_DEV */
+
+/* if we need a pcap_parse wrapper around yyparse */
+#define NEED_YYPARSE_WRAPPER 1
+
+/* Define to 1 if netinet/ether.h declares `ether_hostton' */
+/* #undef NETINET_ETHER_H_DECLARES_ETHER_HOSTTON */
+
+/* Define to 1 if netinet/if_ether.h declares `ether_hostton' */
+#define NETINET_IF_ETHER_H_DECLARES_ETHER_HOSTTON /**/
+
+/* do not use protochain */
+/* #undef NO_PROTOCHAIN */
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT ""
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME ""
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING ""
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME ""
+
+/* Define to the home page for this package. */
+#define PACKAGE_URL ""
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION ""
+
+/* /dev/dlpi directory */
+/* #undef PCAP_DEV_PREFIX */
+
+/* target host supports Bluetooth sniffing */
+/* #undef PCAP_SUPPORT_BT */
+
+/* target host supports Bluetooth Monitor */
+/* #undef PCAP_SUPPORT_BT_MONITOR */
+
+/* target host supports CAN sniffing */
+/* #undef PCAP_SUPPORT_CAN */
+
+/* target host supports canusb */
+/* #undef PCAP_SUPPORT_CANUSB */
+
+/* support D-Bus sniffing */
+/* #undef PCAP_SUPPORT_DBUS */
+
+/* target host supports netfilter sniffing */
+/* #undef PCAP_SUPPORT_NETFILTER */
+
+/* target host supports USB sniffing */
+/* #undef PCAP_SUPPORT_USB */
+
+/* target host supports netmap */
+#define PCAP_SUPPORT_NETMAP 1
+
+/* include ACN support */
+/* #undef SITA */
+
+/* if struct sockaddr_hci has hci_channel member */
+/* #undef SOCKADDR_HCI_HAS_HCI_CHANNEL */
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Enable parser debugging */
+/* #undef YYDEBUG */
+
+/* Enable large inode numbers on Mac OS X 10.5. */
+#ifndef _DARWIN_USE_64_BIT_INODE
+# define _DARWIN_USE_64_BIT_INODE 1
+#endif
+
+/* Number of bits in a file offset, on hosts where this is settable. */
+/* #undef _FILE_OFFSET_BITS */
+
+/* Define to 1 to make fseeko visible on some hosts (e.g. glibc 2.2). */
+/* #undef _LARGEFILE_SOURCE */
+
+/* Define for large files, on AIX-style hosts. */
+/* #undef _LARGE_FILES */
+
+/* define on AIX to get certain functions */
+/* #undef _SUN */
+
+/* define if your compiler allows __attribute__((format)) without a warning */
+#define __ATTRIBUTE___FORMAT_OK 1
+
+/* to handle Ultrix compilers that don't support const in prototypes */
+/* #undef const */
+
+/* Define as token for inline if inlining supported */
+#define inline inline
+
+/* Define to `short' if int16_t not defined. */
+/* #undef int16_t */
+
+/* Define to `int' if int32_t not defined. */
+/* #undef int32_t */
+
+/* Define to `long long' if int64_t not defined. */
+/* #undef int64_t */
+
+/* Define to `signed char' if int8_t not defined. */
+/* #undef int8_t */
+
+/* on sinix */
+/* #undef sinix */
+
+/* Define to `unsigned short' if u_int16_t not defined. */
+/* #undef u_int16_t */
+
+/* Define to `unsigned int' if u_int32_t not defined. */
+/* #undef u_int32_t */
+
+/* Define to `unsigned long long' if u_int64_t not defined. */
+/* #undef u_int64_t */
+
+/* Define to `unsigned char' if u_int8_t not defined. */
+/* #undef u_int8_t */
diff --git a/lib/libpcap/pcap-netmap.c b/lib/libpcap/pcap-netmap.c
new file mode 100644
index 0000000..309cf63
--- /dev/null
+++ b/lib/libpcap/pcap-netmap.c
@@ -0,0 +1,283 @@
+/*
+ * Copyright (C) 2014 Luigi Rizzo. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS''AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <poll.h>
+#include <ctype.h>
+#include <errno.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#define NETMAP_WITH_LIBS
+#include <net/netmap_user.h>
+
+#include "pcap-int.h"
+
+/*
+ * $FreeBSD$
+ *
+ * This code is meant to build also on other versions of libpcap.
+ *
+ * older libpcap miss p->priv, use p->md.device instead (and allocate).
+ * Also opt.timeout was in md.timeout before.
+ * Use #define PCAP_IF_UP to discriminate
+ */
+#ifdef PCAP_IF_UP
+#define NM_PRIV(p) ((struct pcap_netmap *)(p->priv))
+#define the_timeout opt.timeout
+#else
+#define HAVE_NO_PRIV
+#define NM_PRIV(p) ((struct pcap_netmap *)(p->md.device))
+#define SET_PRIV(p, x) p->md.device = (void *)x
+#define the_timeout md.timeout
+#endif
+
+#if defined (linux)
+/* On FreeBSD we use IFF_PPROMISC which is in ifr_flagshigh.
+ * remap to IFF_PROMISC on linux
+ */
+#define IFF_PPROMISC IFF_PROMISC
+#endif /* linux */
+
+struct pcap_netmap {
+ struct nm_desc *d; /* pointer returned by nm_open() */
+ pcap_handler cb; /* callback and argument */
+ u_char *cb_arg;
+ int must_clear_promisc; /* flag */
+ uint64_t rx_pkts; /* # of pkts received before the filter */
+};
+
+
+static int
+pcap_netmap_stats(pcap_t *p, struct pcap_stat *ps)
+{
+ struct pcap_netmap *pn = NM_PRIV(p);
+
+ ps->ps_recv = pn->rx_pkts;
+ ps->ps_drop = 0;
+ ps->ps_ifdrop = 0;
+ return 0;
+}
+
+
+static void
+pcap_netmap_filter(u_char *arg, struct pcap_pkthdr *h, const u_char *buf)
+{
+ pcap_t *p = (pcap_t *)arg;
+ struct pcap_netmap *pn = NM_PRIV(p);
+ const struct bpf_insn *pc = p->fcode.bf_insns;
+
+ ++pn->rx_pkts;
+ if (pc == NULL || bpf_filter(pc, buf, h->len, h->caplen))
+ pn->cb(pn->cb_arg, h, buf);
+}
+
+
+static int
+pcap_netmap_dispatch(pcap_t *p, int cnt, pcap_handler cb, u_char *user)
+{
+ int ret;
+ struct pcap_netmap *pn = NM_PRIV(p);
+ struct nm_desc *d = pn->d;
+ struct pollfd pfd = { .fd = p->fd, .events = POLLIN, .revents = 0 };
+
+ pn->cb = cb;
+ pn->cb_arg = user;
+
+ for (;;) {
+ if (p->break_loop) {
+ p->break_loop = 0;
+ return PCAP_ERROR_BREAK;
+ }
+ /* nm_dispatch won't run forever */
+
+ ret = nm_dispatch((void *)d, cnt, (void *)pcap_netmap_filter, (void *)p);
+ if (ret != 0)
+ break;
+ errno = 0;
+ ret = poll(&pfd, 1, p->the_timeout);
+ }
+ return ret;
+}
+
+
+/* XXX need to check the NIOCTXSYNC/poll */
+static int
+pcap_netmap_inject(pcap_t *p, const void *buf, size_t size)
+{
+ struct nm_desc *d = NM_PRIV(p)->d;
+
+ return nm_inject(d, buf, size);
+}
+
+
+static int
+pcap_netmap_ioctl(pcap_t *p, u_long what, uint32_t *if_flags)
+{
+ struct pcap_netmap *pn = NM_PRIV(p);
+ struct nm_desc *d = pn->d;
+ struct ifreq ifr;
+ int error, fd = d->fd;
+
+#ifdef linux
+ fd = socket(AF_INET, SOCK_DGRAM, 0);
+ if (fd < 0) {
+ fprintf(stderr, "Error: cannot get device control socket.\n");
+ return -1;
+ }
+#endif /* linux */
+ bzero(&ifr, sizeof(ifr));
+ strncpy(ifr.ifr_name, d->req.nr_name, sizeof(ifr.ifr_name));
+ switch (what) {
+ case SIOCSIFFLAGS:
+ ifr.ifr_flags = *if_flags;
+#ifdef __FreeBSD__
+ ifr.ifr_flagshigh = *if_flags >> 16;
+#endif /* __FreeBSD__ */
+ break;
+ }
+ error = ioctl(fd, what, &ifr);
+ if (!error) {
+ switch (what) {
+ case SIOCGIFFLAGS:
+ *if_flags = ifr.ifr_flags;
+#ifdef __FreeBSD__
+ *if_flags |= (ifr.ifr_flagshigh << 16);
+#endif /* __FreeBSD__ */
+ }
+ }
+#ifdef linux
+ close(fd);
+#endif /* linux */
+ return error ? -1 : 0;
+}
+
+
+static void
+pcap_netmap_close(pcap_t *p)
+{
+ struct pcap_netmap *pn = NM_PRIV(p);
+ struct nm_desc *d = pn->d;
+ uint32_t if_flags = 0;
+
+ if (pn->must_clear_promisc) {
+ pcap_netmap_ioctl(p, SIOCGIFFLAGS, &if_flags); /* fetch flags */
+ if (if_flags & IFF_PPROMISC) {
+ if_flags &= ~IFF_PPROMISC;
+ pcap_netmap_ioctl(p, SIOCSIFFLAGS, &if_flags);
+ }
+ }
+ nm_close(d);
+#ifdef HAVE_NO_PRIV
+ free(pn);
+ SET_PRIV(p, NULL); // unnecessary
+#endif
+ pcap_cleanup_live_common(p);
+}
+
+
+static int
+pcap_netmap_activate(pcap_t *p)
+{
+ struct pcap_netmap *pn = NM_PRIV(p);
+ struct nm_desc *d = nm_open(p->opt.source, NULL, 0, NULL);
+ uint32_t if_flags = 0;
+
+ if (d == NULL) {
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "netmap open: cannot access %s: %s\n",
+ p->opt.source, pcap_strerror(errno));
+#ifdef HAVE_NO_PRIV
+ free(pn);
+ SET_PRIV(p, NULL); // unnecessary
+#endif
+ pcap_cleanup_live_common(p);
+ return (PCAP_ERROR);
+ }
+ if (0)
+ fprintf(stderr, "%s device %s priv %p fd %d ports %d..%d\n",
+ __FUNCTION__, p->opt.source, d, d->fd,
+ d->first_rx_ring, d->last_rx_ring);
+ pn->d = d;
+ p->fd = d->fd;
+ if (p->opt.promisc && !(d->req.nr_ringid & NETMAP_SW_RING)) {
+ pcap_netmap_ioctl(p, SIOCGIFFLAGS, &if_flags); /* fetch flags */
+ if (!(if_flags & IFF_PPROMISC)) {
+ pn->must_clear_promisc = 1;
+ if_flags |= IFF_PPROMISC;
+ pcap_netmap_ioctl(p, SIOCSIFFLAGS, &if_flags);
+ }
+ }
+ p->linktype = DLT_EN10MB;
+ p->selectable_fd = p->fd;
+ p->read_op = pcap_netmap_dispatch;
+ p->inject_op = pcap_netmap_inject,
+ p->setfilter_op = install_bpf_program;
+ p->setdirection_op = NULL;
+ p->set_datalink_op = NULL;
+ p->getnonblock_op = pcap_getnonblock_fd;
+ p->setnonblock_op = pcap_setnonblock_fd;
+ p->stats_op = pcap_netmap_stats;
+ p->cleanup_op = pcap_netmap_close;
+
+ return (0);
+}
+
+
+pcap_t *
+pcap_netmap_create(const char *device, char *ebuf, int *is_ours)
+{
+ pcap_t *p;
+
+ *is_ours = (!strncmp(device, "netmap:", 7) || !strncmp(device, "vale", 4));
+ if (! *is_ours)
+ return NULL;
+#ifdef HAVE_NO_PRIV
+ {
+ void *pn = calloc(1, sizeof(struct pcap_netmap));
+ if (pn == NULL)
+ return NULL;
+ p = pcap_create_common(device, ebuf);
+ if (p == NULL) {
+ free(pn);
+ return NULL;
+ }
+ SET_PRIV(p, pn);
+ }
+#else
+ p = pcap_create_common(device, ebuf, sizeof (struct pcap_netmap));
+ if (p == NULL)
+ return (NULL);
+#endif
+ p->activate_op = pcap_netmap_activate;
+ return (p);
+}
OpenPOWER on IntegriCloud