diff options
Diffstat (limited to 'lib/libpcap')
-rw-r--r-- | lib/libpcap/Makefile | 148 | ||||
-rw-r--r-- | lib/libpcap/config.h | 349 | ||||
-rw-r--r-- | lib/libpcap/pcap-netmap.c | 283 |
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); +} |