From a7ead691803de7e0f099aeda9ca7e2be437ea8ff Mon Sep 17 00:00:00 2001 From: Jerome Duval Date: Tue, 28 Apr 2015 18:39:03 +0000 Subject: Haiku patch diff --git a/Makefile.in b/Makefile.in index e71d973..9be5f3a 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@ @@ -79,7 +80,12 @@ YACC = @YACC@ @rm -f $@ $(CC) $(FULL_CFLAGS) -c $(srcdir)/$*.c -PSRC = pcap-@V_PCAP@.c @USB_SRC@ @BT_SRC@ @BT_MONITOR_SRC@ @NETFILTER_SRC@ @DBUS_SRC@ +ifeq (@V_PCAP@,haiku) +PCAPSRC = pcap-@V_PCAP@.cpp +else +PCAPSRC = pcap-@V_PCAP@.c +endif +PSRC = $(PCAPSRC) @USB_SRC@ @BT_SRC@ @BT_MONITOR_SRC@ @NETFILTER_SRC@ @DBUS_SRC@ FSRC = @V_FINDALLDEVS@ SSRC = @SSRC@ CSRC = pcap.c inet.c fad-helpers.c gencode.c optimize.c nametoaddr.c \ @@ -92,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 = $(patsubst %.cpp,%.o,$(PSRC:.c=.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 83f5761..5da7783 100644 --- a/aclocal.m4 +++ b/aclocal.m4 @@ -447,7 +447,7 @@ AC_DEFUN(AC_LBL_SHLIBS_INIT, aix*) ;; - freebsd*|netbsd*|openbsd*|dragonfly*|linux*|osf*) + freebsd*|netbsd*|openbsd*|dragonfly*|linux*|osf*|haiku*) # # Platforms where the linker is the GNU linker # or accepts command-line arguments like @@ -1065,7 +1065,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.ac b/configure.ac index da2f940..ccdf999 100644 --- a/configure.ac +++ b/configure.ac @@ -381,6 +381,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 @@ -1384,7 +1386,7 @@ irix*) MAN_MISC_INFO=5 ;; -linux*|freebsd*|netbsd*|openbsd*|dragonfly*|kfreebsd*|gnu*) +linux*|freebsd*|netbsd*|openbsd*|dragonfly*|kfreebsd*|gnu*|haiku*) DYEXT="so" # diff --git a/pcap-haiku.cpp b/pcap-haiku.cpp new file mode 100644 index 0000000..983a7dc --- /dev/null +++ b/pcap-haiku.cpp @@ -0,0 +1,287 @@ +/* + * 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 + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + + +/* + * 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 = (u_char*)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; + int socket = ::socket(AF_INET, SOCK_DGRAM, 0); + if (socket < 0) { + return -1; + } + prepare_request(request, handlep->device); + if (ioctl(socket, SIOCGIFSTATS, &request, sizeof(struct ifreq)) < 0) { + snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "pcap_stats: %s", + strerror(errno)); + close(socket); + return -1; + } + + close(socket); + 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.device; + + 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(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; +} + +static int +canBeBound(const char *name) +{ + return 1; +} + +extern "C" int +pcap_platform_finddevs(pcap_if_t** _allDevices, char* errorBuffer) +{ + return pcap_findalldevs_interfaces(_allDevices, errorBuffer, canBeBound); +} -- 2.26.0 From 96ccd9be2fd19e5dc644463cbd81940cfa0b1612 Mon Sep 17 00:00:00 2001 From: Adrien Destugues Date: Tue, 26 Feb 2019 20:07:07 +0100 Subject: libpcap: fix 32bit x86 build Confusion around the definition of int32... diff --git a/bpf/net/bpf_filter.c b/bpf/net/bpf_filter.c index 01a1b64..3503839 100644 --- a/bpf/net/bpf_filter.c +++ b/bpf/net/bpf_filter.c @@ -81,7 +81,9 @@ #include #endif +#ifndef __HAIKU__ #define int32 bpf_int32 +#endif #define u_int32 bpf_u_int32 #ifndef LBL_ALIGN diff --git a/pcap/bpf.h b/pcap/bpf.h index 78ad890..fc05d7c 100644 --- a/pcap/bpf.h +++ b/pcap/bpf.h @@ -81,7 +81,7 @@ extern "C" { /* BSD style release date */ #define BPF_RELEASE 199606 -#ifdef MSDOS /* must be 32-bit */ +#if defined(MSDOS) || (defined(__HAIKU__) && defined(__X86__)) /* must be 32-bit */ typedef long bpf_int32; typedef unsigned long bpf_u_int32; #else -- 2.26.0