mirror of
https://github.com/yann64/haikuports.git
synced 2026-04-22 19:50:05 +02:00
libpcap: added a recipe for version 1.7.3
* reused pcap-haiku.cpp from Haiku tree. * cannot be sent to upstream as is, had to hack Makefile.in for instance.
This commit is contained in:
82
net-libs/libpcap/libpcap-1.7.3.recipe
Normal file
82
net-libs/libpcap/libpcap-1.7.3.recipe
Normal file
@@ -0,0 +1,82 @@
|
||||
SUMMARY="A system-independent interface for user-level packet capture"
|
||||
HOMEPAGE="http://www.tcpdump.org"
|
||||
COPYRIGHT="1996-2014, Daniel Stenberg, <daniel@haxx.se>. All rights reserved."
|
||||
LICENSE="BSD (3-clause)"
|
||||
SRC_URI="http://www.tcpdump.org/release/libpcap-$portVersion.tar.gz"
|
||||
CHECKSUM_SHA256="dd9f85213dc8e948068405b55dd20f8b32e3083e9e0e186f833bd0372e559e2f"
|
||||
REVISION="1"
|
||||
ARCHITECTURES="x86_gcc2 x86 x86_64 arm"
|
||||
SECONDARY_ARCHITECTURES="x86_gcc2 x86"
|
||||
|
||||
PATCHES="libpcap-$portVersion.patchset"
|
||||
|
||||
PROVIDES="
|
||||
libpcap$secondaryArchSuffix = $portVersion
|
||||
lib:libpcap$secondaryArchSuffix = $portVersion compat >= 1
|
||||
"
|
||||
|
||||
REQUIRES="
|
||||
haiku$secondaryArchSuffix
|
||||
"
|
||||
BUILD_REQUIRES="
|
||||
haiku${secondaryArchSuffix}_devel
|
||||
"
|
||||
BUILD_PREREQUIRES="
|
||||
cmd:autoconf
|
||||
cmd:gcc$secondaryArchSuffix
|
||||
cmd:ld$secondaryArchSuffix
|
||||
cmd:libtoolize
|
||||
cmd:make
|
||||
cmd:bison
|
||||
cmd:flex
|
||||
cmd:pkg_config$secondaryArchSuffix
|
||||
"
|
||||
|
||||
BUILD()
|
||||
{
|
||||
autoreconf -fi
|
||||
CFLAGS="-D_BSD_SOURCE" runConfigure ./configure \
|
||||
--enable-shared
|
||||
make $jobArgs
|
||||
}
|
||||
|
||||
INSTALL()
|
||||
{
|
||||
make install
|
||||
|
||||
# prepare develop/lib
|
||||
prepareInstalledDevelLibs libpcap
|
||||
fixPkgconfig
|
||||
|
||||
# devel package
|
||||
packageEntries devel \
|
||||
$developDir \
|
||||
$binDir/pcap-config
|
||||
|
||||
}
|
||||
|
||||
TEST()
|
||||
{
|
||||
make check
|
||||
}
|
||||
|
||||
DESCRIPTION="
|
||||
libpcap provides a portable \
|
||||
framework for low-level network monitoring. Applications include \
|
||||
network statistics collection, security monitoring, network debugging, \
|
||||
etc. Since almost every system vendor provides a different interface \
|
||||
for packet capture, and since we''ve developed several tools that \
|
||||
require this functionality, we''ve created this system-independent API \
|
||||
to ease in porting and to alleviate the need for several \
|
||||
system-dependent packet capture modules in each application."
|
||||
|
||||
# ----- devel package -------------------------------------------------------
|
||||
|
||||
PROVIDES_devel="
|
||||
libpcap${secondaryArchSuffix}_devel = $portVersion
|
||||
cmd:pcap_config$secondaryArchSuffix
|
||||
devel:libpcap$secondaryArchSuffix = $portVersion compat >= 1
|
||||
"
|
||||
REQUIRES_devel="
|
||||
libpcap$secondaryArchSuffix == $portVersion base
|
||||
"
|
||||
425
net-libs/libpcap/patches/libpcap-1.7.3.patchset
Normal file
425
net-libs/libpcap/patches/libpcap-1.7.3.patchset
Normal file
@@ -0,0 +1,425 @@
|
||||
From bd45ddf62df401e0de9ae034b3b66306e52d0c86 Mon Sep 17 00:00:00 2001
|
||||
From: Jerome Duval <jerome.duval@gmail.com>
|
||||
Date: Tue, 28 Apr 2015 18:39:03 +0000
|
||||
Subject: Haiku patch
|
||||
|
||||
|
||||
diff --git a/Makefile.in b/Makefile.in
|
||||
index f317973..a3d89ae 100644
|
||||
--- a/Makefile.in
|
||||
+++ b/Makefile.in
|
||||
@@ -63,6 +63,7 @@ PROG=libpcap
|
||||
|
||||
# Standard CFLAGS
|
||||
FULL_CFLAGS = $(CCOPT) $(INCLS) $(DEFS) $(CFLAGS)
|
||||
+CXXFLAGS = $(CCOPT) $(INCLS) $(DEFS) $(CFLAGS)
|
||||
|
||||
INSTALL = @INSTALL@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
@@ -84,7 +85,7 @@ YACC = @V_YACC@
|
||||
@rm -f $@
|
||||
$(CC) $(FULL_CFLAGS) -c $(srcdir)/$*.c
|
||||
|
||||
-PSRC = pcap-@V_PCAP@.c @USB_SRC@ @BT_SRC@ @BT_MONITOR_SRC@ @CAN_SRC@ @NETFILTER_SRC@ @CANUSB_SRC@ @DBUS_SRC@
|
||||
+PSRC = pcap-@V_PCAP@.cpp @USB_SRC@ @BT_SRC@ @BT_MONITOR_SRC@ @CAN_SRC@ @NETFILTER_SRC@ @CANUSB_SRC@ @DBUS_SRC@
|
||||
FSRC = fad-@V_FINDALLDEVS@.c
|
||||
SSRC = @SSRC@
|
||||
CSRC = pcap.c inet.c gencode.c optimize.c nametoaddr.c etherent.c \
|
||||
@@ -97,7 +98,7 @@ SRC = $(PSRC) $(FSRC) $(CSRC) $(SSRC) $(GENSRC)
|
||||
|
||||
# We would like to say "OBJ = $(SRC:.c=.o)" but Ultrix's make cannot
|
||||
# hack the extra indirection
|
||||
-OBJ = $(PSRC:.c=.o) $(FSRC:.c=.o) $(CSRC:.c=.o) $(SSRC:.c=.o) $(GENSRC:.c=.o) $(LIBOBJS)
|
||||
+OBJ = $(PSRC:.cpp=.o) $(FSRC:.c=.o) $(CSRC:.c=.o) $(SSRC:.c=.o) $(GENSRC:.c=.o) $(LIBOBJS)
|
||||
PUBHDR = \
|
||||
pcap.h \
|
||||
pcap-bpf.h \
|
||||
diff --git a/aclocal.m4 b/aclocal.m4
|
||||
index 02502b2..56f1422 100644
|
||||
--- a/aclocal.m4
|
||||
+++ b/aclocal.m4
|
||||
@@ -1105,7 +1105,7 @@ AC_DEFUN(AC_LBL_LIBRARY_NET, [
|
||||
AC_CHECK_LIB(socket, gethostbyname,
|
||||
LIBS="-lsocket -lnsl $LIBS", , -lnsl)
|
||||
fi
|
||||
- AC_SEARCH_LIBS(socket, socket, ,
|
||||
+ AC_SEARCH_LIBS(socket, socket network, ,
|
||||
AC_CHECK_LIB(socket, socket, LIBS="-lsocket -lnsl $LIBS", , -lnsl))
|
||||
# DLPI needs putmsg under HPUX so test for -lstr while we're at it
|
||||
AC_SEARCH_LIBS(putmsg, str)
|
||||
diff --git a/configure.in b/configure.in
|
||||
index be4b29e..7b80c0b 100644
|
||||
--- a/configure.in
|
||||
+++ b/configure.in
|
||||
@@ -347,6 +347,8 @@ elif test -c /dev/enet ; then # check again in case not readable
|
||||
V_PCAP=enet
|
||||
elif test -c /dev/nit ; then # check again in case not readable
|
||||
V_PCAP=snit
|
||||
+elif test -r /boot/system ; then
|
||||
+ V_PCAP=haiku
|
||||
else
|
||||
V_PCAP=null
|
||||
fi
|
||||
diff --git a/pcap-haiku.cpp b/pcap-haiku.cpp
|
||||
new file mode 100644
|
||||
index 0000000..9b2b598
|
||||
--- /dev/null
|
||||
+++ b/pcap-haiku.cpp
|
||||
@@ -0,0 +1,354 @@
|
||||
+/*
|
||||
+ * Copyright 2006-2010, Haiku, Inc. All Rights Reserved.
|
||||
+ * Distributed under the terms of the MIT License.
|
||||
+ *
|
||||
+ * Authors:
|
||||
+ * Axel Dörfler, axeld@pinc-software.de
|
||||
+ * James Woodcock
|
||||
+ */
|
||||
+
|
||||
+
|
||||
+#include "config.h"
|
||||
+#include "pcap-int.h"
|
||||
+
|
||||
+#include <OS.h>
|
||||
+
|
||||
+#include <sys/socket.h>
|
||||
+#include <sys/sockio.h>
|
||||
+
|
||||
+#include <net/if.h>
|
||||
+#include <net/if_dl.h>
|
||||
+#include <net/if_types.h>
|
||||
+
|
||||
+#include <errno.h>
|
||||
+#include <stdio.h>
|
||||
+#include <stdlib.h>
|
||||
+#include <string.h>
|
||||
+
|
||||
+
|
||||
+/*
|
||||
+ * Private data for capturing on Haiku sockets.
|
||||
+ */
|
||||
+struct pcap_haiku {
|
||||
+ struct pcap_stat stat;
|
||||
+ char *device; /* device name */
|
||||
+};
|
||||
+
|
||||
+
|
||||
+bool
|
||||
+prepare_request(struct ifreq& request, const char* name)
|
||||
+{
|
||||
+ if (strlen(name) >= IF_NAMESIZE)
|
||||
+ return false;
|
||||
+
|
||||
+ strcpy(request.ifr_name, name);
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+static int
|
||||
+pcap_read_haiku(pcap_t* handle, int maxPackets, pcap_handler callback,
|
||||
+ u_char* userdata)
|
||||
+{
|
||||
+ // Receive a single packet
|
||||
+
|
||||
+ struct pcap_haiku* handlep = (struct pcap_haiku*)handle->priv;
|
||||
+ u_char* buffer = handle->buffer + handle->offset;
|
||||
+ struct sockaddr_dl from;
|
||||
+ ssize_t bytesReceived;
|
||||
+ do {
|
||||
+ if (handle->break_loop) {
|
||||
+ // Clear the break loop flag, and return -2 to indicate our
|
||||
+ // reasoning
|
||||
+ handle->break_loop = 0;
|
||||
+ return -2;
|
||||
+ }
|
||||
+
|
||||
+ socklen_t fromLength = sizeof(from);
|
||||
+ bytesReceived = recvfrom(handle->fd, buffer, handle->bufsize, MSG_TRUNC,
|
||||
+ (struct sockaddr*)&from, &fromLength);
|
||||
+ } while (bytesReceived < 0 && errno == B_INTERRUPTED);
|
||||
+
|
||||
+ if (bytesReceived < 0) {
|
||||
+ if (errno == B_WOULD_BLOCK) {
|
||||
+ // there is no packet for us
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ snprintf(handle->errbuf, sizeof(handle->errbuf),
|
||||
+ "recvfrom: %s", strerror(errno));
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ int32 captureLength = bytesReceived;
|
||||
+ if (captureLength > handle->snapshot)
|
||||
+ captureLength = handle->snapshot;
|
||||
+
|
||||
+/*
|
||||
+ // run the packet filter
|
||||
+ if (!handle->md.use_bpf && handle->fcode.bf_insns) {
|
||||
+ if (bpf_filter(handle->fcode.bf_insns, buffer, bytesReceived,
|
||||
+ captureLength) == 0) {
|
||||
+ // packet got rejected
|
||||
+ return 0;
|
||||
+ }
|
||||
+ }
|
||||
+*/
|
||||
+
|
||||
+ // fill in pcap_header
|
||||
+
|
||||
+ pcap_pkthdr header;
|
||||
+ header.caplen = captureLength;
|
||||
+ header.len = bytesReceived;
|
||||
+ header.ts.tv_usec = system_time() % 1000000;
|
||||
+ header.ts.tv_sec = system_time() / 1000000;
|
||||
+ // TODO: get timing from packet!!!
|
||||
+
|
||||
+ /* Call the user supplied callback function */
|
||||
+ callback(userdata, &header, buffer);
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+static int
|
||||
+pcap_inject_haiku(pcap_t *handle, const void *buffer, size_t size)
|
||||
+{
|
||||
+ // we don't support injecting packets yet
|
||||
+ // TODO: use the AF_LINK protocol (we need another socket for this) to
|
||||
+ // inject the packets
|
||||
+ strlcpy(handle->errbuf, "Sending packets isn't supported yet",
|
||||
+ PCAP_ERRBUF_SIZE);
|
||||
+ return -1;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+static int
|
||||
+pcap_setfilter_haiku(pcap_t *handle, struct bpf_program *filter)
|
||||
+{
|
||||
+ // Make our private copy of the filter
|
||||
+ if (install_bpf_program(handle, filter) < 0) {
|
||||
+ // install_bpf_program() filled in errbuf
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ // we don't support kernel filters at all
|
||||
+ //handle->md.use_bpf = 0;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+static int
|
||||
+pcap_stats_haiku(pcap_t *handle, struct pcap_stat *stats)
|
||||
+{
|
||||
+ struct pcap_haiku* handlep = (struct pcap_haiku*)handle->priv;
|
||||
+ ifreq request;
|
||||
+ prepare_request(request, handlep->device);
|
||||
+
|
||||
+ if (ioctl(handle->fd, SIOCGIFSTATS, &request, sizeof(struct ifreq)) < 0) {
|
||||
+ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "pcap_stats: %s",
|
||||
+ strerror(errno));
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ handlep->stat.ps_recv += request.ifr_stats.receive.packets;
|
||||
+ handlep->stat.ps_drop += request.ifr_stats.receive.dropped;
|
||||
+ *stats = handlep->stat;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+static int
|
||||
+pcap_activate_haiku(pcap_t *handle)
|
||||
+{
|
||||
+ struct pcap_haiku* handlep = (struct pcap_haiku*)handle->priv;
|
||||
+
|
||||
+ const char* device = handle->opt.source;
|
||||
+
|
||||
+ handle->read_op = pcap_read_haiku;
|
||||
+ handle->setfilter_op = pcap_setfilter_haiku;
|
||||
+ handle->inject_op = pcap_inject_haiku;
|
||||
+ handle->stats_op = pcap_stats_haiku;
|
||||
+
|
||||
+ // use default hooks where possible
|
||||
+ handle->getnonblock_op = pcap_getnonblock_fd;
|
||||
+ handle->setnonblock_op = pcap_setnonblock_fd;
|
||||
+ //handle->close_op = pcap_close_common;
|
||||
+
|
||||
+ handlep->device = strdup(device);
|
||||
+ if (handlep->device == NULL) {
|
||||
+ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "strdup: %s",
|
||||
+ pcap_strerror(errno) );
|
||||
+ return PCAP_ERROR;
|
||||
+ }
|
||||
+
|
||||
+ handle->bufsize = 65536;
|
||||
+ // TODO: should be determined by interface MTU
|
||||
+
|
||||
+ // allocate buffer for monitoring the device
|
||||
+ handle->buffer = (u_char*)malloc(handle->bufsize);
|
||||
+ if (handle->buffer == NULL) {
|
||||
+ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "buffer malloc: %s",
|
||||
+ strerror(errno));
|
||||
+ return PCAP_ERROR;
|
||||
+ }
|
||||
+
|
||||
+ handle->offset = 0;
|
||||
+ handle->linktype = DLT_EN10MB;
|
||||
+ // TODO: check interface type!
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+// #pragma mark - pcap API
|
||||
+
|
||||
+
|
||||
+extern "C" pcap_t *
|
||||
+pcap_create_interface(const char *device, char *errorBuffer)
|
||||
+{
|
||||
+ // TODO: handle promiscous mode!
|
||||
+
|
||||
+ // we need a socket to talk to the networking stack
|
||||
+ int socket = ::socket(AF_INET, SOCK_DGRAM, 0);
|
||||
+ if (socket < 0) {
|
||||
+ snprintf(errorBuffer, PCAP_ERRBUF_SIZE,
|
||||
+ "The networking stack doesn't seem to be available.\n");
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ struct ifreq request;
|
||||
+ if (!prepare_request(request, device)) {
|
||||
+ snprintf(errorBuffer, PCAP_ERRBUF_SIZE,
|
||||
+ "Interface name \"%s\" is too long.", device);
|
||||
+ close(socket);
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ // check if the interface exist
|
||||
+ if (ioctl(socket, SIOCGIFINDEX, &request, sizeof(request)) < 0) {
|
||||
+ snprintf(errorBuffer, PCAP_ERRBUF_SIZE,
|
||||
+ "Interface \"%s\" does not exist.\n", device);
|
||||
+ close(socket);
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ close(socket);
|
||||
+ // no longer needed after this point
|
||||
+
|
||||
+ // get link level interface for this interface
|
||||
+
|
||||
+ socket = ::socket(AF_LINK, SOCK_DGRAM, 0);
|
||||
+ if (socket < 0) {
|
||||
+ snprintf(errorBuffer, PCAP_ERRBUF_SIZE, "No link level: %s\n",
|
||||
+ strerror(errno));
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ // start monitoring
|
||||
+ if (ioctl(socket, SIOCSPACKETCAP, &request, sizeof(struct ifreq)) < 0) {
|
||||
+ snprintf(errorBuffer, PCAP_ERRBUF_SIZE, "Cannot start monitoring: %s\n",
|
||||
+ strerror(errno));
|
||||
+ close(socket);
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ pcap_t* handle = pcap_create_common(device, errorBuffer,
|
||||
+ sizeof (struct pcap_haiku));
|
||||
+ if (handle == NULL) {
|
||||
+ snprintf(errorBuffer, PCAP_ERRBUF_SIZE, "malloc: %s", strerror(errno));
|
||||
+ close(socket);
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ handle->selectable_fd = socket;
|
||||
+ handle->fd = socket;
|
||||
+
|
||||
+ handle->activate_op = pcap_activate_haiku;
|
||||
+ //handle->can_set_rfmon_op = pcap_can_set_rfmon_linux;
|
||||
+
|
||||
+ return handle;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+extern "C" int
|
||||
+pcap_platform_finddevs(pcap_if_t** _allDevices, char* errorBuffer)
|
||||
+{
|
||||
+ // we need a socket to talk to the networking stack
|
||||
+ int socket = ::socket(AF_INET, SOCK_DGRAM, 0);
|
||||
+ if (socket < 0) {
|
||||
+ snprintf(errorBuffer, PCAP_ERRBUF_SIZE,
|
||||
+ "The networking stack doesn't seem to be available.\n");
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ // get a list of all interfaces
|
||||
+
|
||||
+ ifconf config;
|
||||
+ config.ifc_len = sizeof(config.ifc_value);
|
||||
+ if (ioctl(socket, SIOCGIFCOUNT, &config, sizeof(struct ifconf)) < 0) {
|
||||
+ close(socket);
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ uint32 count = (uint32)config.ifc_value;
|
||||
+ if (count == 0) {
|
||||
+ snprintf(errorBuffer, PCAP_ERRBUF_SIZE,
|
||||
+ "There are no interfaces defined!\n");
|
||||
+ close(socket);
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ void* buffer = malloc(count * sizeof(struct ifreq));
|
||||
+ if (buffer == NULL) {
|
||||
+ snprintf(errorBuffer, PCAP_ERRBUF_SIZE, "Out of memory.\n");
|
||||
+ close(socket);
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ config.ifc_len = count * sizeof(struct ifreq);
|
||||
+ config.ifc_buf = buffer;
|
||||
+ if (ioctl(socket, SIOCGIFCONF, &config, sizeof(struct ifconf)) < 0) {
|
||||
+ close(socket);
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ ifreq* interface = (ifreq*)buffer;
|
||||
+
|
||||
+ for (uint32 i = 0; i < count; i++) {
|
||||
+ int flags = 0;
|
||||
+
|
||||
+ // get interface type
|
||||
+
|
||||
+ int linkSocket = ::socket(AF_LINK, SOCK_DGRAM, 0);
|
||||
+ if (linkSocket < 0) {
|
||||
+ fprintf(stderr, "No link level: %s\n", strerror(errno));
|
||||
+ } else {
|
||||
+ struct ifreq request;
|
||||
+ if (!prepare_request(request, interface->ifr_name)) {
|
||||
+ snprintf(errorBuffer, PCAP_ERRBUF_SIZE,
|
||||
+ "Interface name \"%s\" is too long.", interface->ifr_name);
|
||||
+ close(linkSocket);
|
||||
+ close(socket);
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ if (ioctl(linkSocket, SIOCGIFADDR, &request, sizeof(struct ifreq))
|
||||
+ == 0) {
|
||||
+ sockaddr_dl &link = *(sockaddr_dl*)&request.ifr_addr;
|
||||
+
|
||||
+ if (link.sdl_type == IFT_LOOP)
|
||||
+ flags = IFF_LOOPBACK;
|
||||
+ }
|
||||
+ close(linkSocket);
|
||||
+ }
|
||||
+
|
||||
+ pcap_add_if(_allDevices, interface->ifr_name, flags, NULL, errorBuffer);
|
||||
+
|
||||
+ interface = (ifreq*)((uint8*)interface
|
||||
+ + _SIZEOF_ADDR_IFREQ(interface[0]));
|
||||
+ }
|
||||
+
|
||||
+ free(buffer);
|
||||
+ close(socket);
|
||||
+ return 0;
|
||||
+}
|
||||
--
|
||||
1.8.3.4
|
||||
|
||||
Reference in New Issue
Block a user