Package: libpcap0.8 Version: 1.5.3-2 Severity: important Tags: patch Hello,
Here is a patch to include support in libpcap for Debian GNU/Hurd. Note that the changes in this patch expect Debian specific changes in the Hurd packages (most notably, userspace netdde drivers) and shouldn't be forwarded upstream yet. Thanks. -- System Information: Debian Release: jessie/sid APT prefers unreleased APT policy: (500, 'unreleased'), (500, 'unstable') Architecture: hurd-i386 (i686-AT386) Kernel: GNU-Mach 1.4-486-dbg/Hurd-0.5 Locale: LANG=en_US.UTF-8, LC_CTYPE=en_US.UTF-8 (charmap=UTF-8) Shell: /bin/sh linked to /bin/dash Versions of packages libpcap0.8 depends on: ii libc0.3 2.18-3 ii multiarch-support 2.18-3 libpcap0.8 recommends no packages. libpcap0.8 suggests no packages. -- no debconf information
>From 0345076badd69b840777fbd3fdf2e0bdd77954db Mon Sep 17 00:00:00 2001 From: Richard Braun <[email protected]> Date: Thu, 10 Apr 2014 01:26:01 +0200 Subject: [PATCH] Debian GNU/Hurd (with NETDDE) support --- configure.in | 6 ++ pcap-hurd.c | 255 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 261 insertions(+) create mode 100644 pcap-hurd.c diff --git a/configure.in b/configure.in index e53f106..a4433bc 100644 --- a/configure.in +++ b/configure.in @@ -324,6 +324,8 @@ elif test -r /usr/include/linux/socket.h ; then V_PCAP=linux elif test -r /usr/include/net/raw.h ; then V_PCAP=snoop +elif test -r /usr/include/hurd.h ; then + V_PCAP=hurd elif test -r /usr/include/odmi.h ; then # # On AIX, the BPF devices might not yet be present - they're @@ -552,6 +554,10 @@ bpf) LIBS="$LIBS -lrt" ;; +hurd) + LIBS="$LIBS -lrt" + ;; + dag) V_DEFS="$V_DEFS -DDAG_ONLY" ;; diff --git a/pcap-hurd.c b/pcap-hurd.c new file mode 100644 index 0000000..c657388 --- /dev/null +++ b/pcap-hurd.c @@ -0,0 +1,255 @@ +#define _GNU_SOURCE + +/* XXX Hack not to include the Mach BPF interface */ +#define _DEVICE_BPF_H_ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <fcntl.h> +#include <hurd.h> +#include <mach.h> +#include <time.h> +#include <errno.h> +#include <stdio.h> +#include <stddef.h> +#include <stdlib.h> +#include <string.h> +#include <device/device.h> +#include <device/device_types.h> +#include <device/net_status.h> +#include <net/if_ether.h> + +#include "pcap-int.h" + +struct pcap_hurd { + struct pcap_stat stat; + device_t mach_dev; + mach_port_t rcv_port; +}; + +static struct bpf_insn filter[] = { + { NETF_IN | NETF_OUT | NETF_BPF, 0, 0, 0 }, + { BPF_RET | BPF_K, 0, 0, 1500 }, +}; + +#define FILTER_COUNT (sizeof(filter) / sizeof(short)) + +static int +pcap_read_hurd(pcap_t *p, int cnt, pcap_handler callback, u_char *user) +{ + struct net_rcv_msg *msg; + struct pcap_hurd *ph; + struct pcap_pkthdr h; + struct timespec ts; + int ret, wirelen, caplen; + u_char *pkt; + kern_return_t kr; + + ph = p->priv; + msg = (struct net_rcv_msg *)p->buffer; + +retry: + if (p->break_loop) { + p->break_loop = 0; + return PCAP_ERROR_BREAK; + } + + kr = mach_msg(&msg->msg_hdr, MACH_RCV_MSG | MACH_RCV_INTERRUPT, 0, + p->bufsize, ph->rcv_port, MACH_MSG_TIMEOUT_NONE, + MACH_PORT_NULL); + + if (kr) { + if (kr == MACH_RCV_INTERRUPTED) + goto retry; + + snprintf(p->errbuf, sizeof(p->errbuf), "mach_msg: %s", + pcap_strerror(kr)); + return PCAP_ERROR; + } + + ph->stat.ps_recv++; + + /* XXX Ethernet support only */ + wirelen = ETH_HLEN + msg->net_rcv_msg_packet_count + - sizeof(struct packet_header); + pkt = p->buffer + offsetof(struct net_rcv_msg, packet) + + sizeof(struct packet_header) - ETH_HLEN; + memmove(pkt, p->buffer + offsetof(struct net_rcv_msg, header), + ETH_HLEN); + + caplen = (wirelen > p->snapshot) ? p->snapshot : wirelen; + ret = bpf_filter(p->fcode.bf_insns, pkt, wirelen, caplen); + + if (!ret) + goto out; + + clock_gettime(CLOCK_REALTIME, &ts); + h.ts.tv_sec = ts.tv_sec; + h.ts.tv_usec = ts.tv_nsec / 1000; + h.len = wirelen; + h.caplen = caplen; + callback(user, &h, pkt); + +out: + return 1; +} + +static int +pcap_inject_hurd(pcap_t *p, const void *buf, size_t size) +{ + struct pcap_hurd *ph; + kern_return_t kr; + int count; + + ph = p->priv; + kr = device_write(ph->mach_dev, D_NOWAIT, 0, + (io_buf_ptr_t)buf, size, &count); + + if (kr) { + snprintf(p->errbuf, sizeof(p->errbuf), "device_write: %s", + pcap_strerror(kr)); + return -1; + } + + return count; +} + +static int +pcap_stats_hurd(pcap_t *p, struct pcap_stat *ps) +{ + struct pcap_hurd *ph; + + ph = p->priv; + *ps = ph->stat; + return 0; +} + +static void +pcap_cleanup_hurd(pcap_t *p) +{ + struct pcap_hurd *ph; + + ph = p->priv; + + if (ph->rcv_port != MACH_PORT_NULL) { + mach_port_deallocate(mach_task_self(), ph->rcv_port); + ph->rcv_port = MACH_PORT_NULL; + } + + if (ph->mach_dev != MACH_PORT_NULL) { + device_close(ph->mach_dev); + ph->mach_dev = MACH_PORT_NULL; + } + + pcap_cleanup_live_common(p); +} + +static int +pcap_activate_hurd(pcap_t *p) +{ + struct pcap_hurd *ph; + mach_port_t master; + kern_return_t kr; + + ph = p->priv; + + /* Try devnode first */ + master = file_name_lookup(p->opt.source, O_READ | O_WRITE, 0); + + if (master != MACH_PORT_NULL) + kr = device_open(master, D_WRITE | D_READ, "eth", &ph->mach_dev); + else { + /* If unsuccessful, try Mach device */ + kr = get_privileged_ports(NULL, &master); + + if (kr) { + snprintf(p->errbuf, sizeof(p->errbuf), + "get_privileged_ports: %s", pcap_strerror(kr)); + goto error; + } + + kr = device_open(master, D_READ | D_WRITE, p->opt.source, + &ph->mach_dev); + } + + mach_port_deallocate(mach_task_self(), master); + + if (kr) { + snprintf(p->errbuf, sizeof(p->errbuf), "device_open: %s", + pcap_strerror(kr)); + goto error; + } + + kr = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, + &ph->rcv_port); + + if (kr) { + snprintf(p->errbuf, sizeof(p->errbuf), "mach_port_allocate: %s", + pcap_strerror(kr)); + goto error; + } + + kr = device_set_filter(ph->mach_dev, ph->rcv_port, + MACH_MSG_TYPE_MAKE_SEND, 0, + (filter_array_t)filter, FILTER_COUNT); + + if (kr) { + snprintf(p->errbuf, sizeof(p->errbuf), "device_set_filter: %s", + pcap_strerror(kr)); + goto error; + } + + /* XXX Ethernet only currently */ + p->linktype = DLT_EN10MB; + + p->bufsize = sizeof(struct net_rcv_msg); + p->buffer = malloc(p->bufsize); + + if (p->buffer == NULL) { + snprintf(p->errbuf, sizeof(p->errbuf), "malloc: %s", + pcap_strerror(errno)); + goto error; + } + + p->dlt_list = malloc(sizeof(*p->dlt_list)); + + if (p->dlt_list != NULL) + *p->dlt_list = DLT_EN10MB; + + p->read_op = pcap_read_hurd; + p->inject_op = pcap_inject_hurd; + p->setfilter_op = install_bpf_program; + p->stats_op = pcap_stats_hurd; + + return 0; + +error: + pcap_cleanup_hurd(p); + return PCAP_ERROR; +} + +pcap_t * +pcap_create_interface(const char *device, char *ebuf) +{ + struct pcap_hurd *ph; + pcap_t *p; + + p = pcap_create_common(device, ebuf, sizeof (struct pcap_hurd)); + + if (p == NULL) + return NULL; + + ph = p->priv; + ph->mach_dev = MACH_PORT_NULL; + ph->rcv_port = MACH_PORT_NULL; + p->activate_op = pcap_activate_hurd; + return p; +} + +int +pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf) +{ + return 0; +} -- 1.9.1

