ports/emulators/qemu/files/pcap-patch
Juergen Lock b987bd37c9 - Update to 0.11.1 - from the official announcement:
- fix I2C slave addressing (Juha Riihimaki)
  - Revert "vga: do not resize the screen on hw_invalidate" (Aurelien Jarno)
  - slirp: fix use-after-free (Mark McLoughlin)
  - Fix sparc.ld (Blue Swirl)
  - ELF codedump build failures (Laurent Desnogues)
  - kvm: Move KVM mp_state accessors to i386-specific code (Hollis Blanchard)
  - fix configure script with armv4l cpu (Laurent Desnogues)
  - net: disable draining tap queue in one go (Mark McLoughlin)
  - pcnet: Restart poll timer on pcnet_start (Jan Kiszka)
  - Sparc32: Fix lance (Blue Swirl)
  - mac99: fix segmentation fault on startup (Aurelien Jarno)
  - usb-linux.c: fix buffer overflow (Jim Paris)
  - ARM host: fix generated blocks linking (Laurent Desnogues)
  - qemu serial: lost tx irqs (affecting FreeBSD's new uart(4) driver)
    (Juergen Lock)
  - exec-all.h: increase MAX_OP_PER_INSTR to 96 from 64 (Aurelien Jarno)

- Added a cherry picked commit from stable branch that fixes qcow2.
2009-12-06 19:37:46 +00:00

307 lines
7.6 KiB
Text

--- Makefile.target.orig 2008-07-18 15:18:11.000000000 -0400
+++ Makefile.target 2008-07-18 15:23:11.000000000 -0400
@@ -619,6 +619,13 @@
COCOA_LIBS+=-framework CoreAudio
endif
endif
+ifdef CONFIG_PCAP
+ifdef CONFIG_WIN32
+LIBS+=-lwpcap
+else
+LIBS+=-lpcap
+endif
+endif
ifdef CONFIG_SLIRP
CPPFLAGS+=-I$(SRC_PATH)/slirp
endif
Index: configure
@@ -203,6 +203,9 @@
sdl_x11="no"
xen="yes"
pkgversion=""
+pcap="no"
+pcap_create="no"
+bpf="no"
# OS specific
if check_define __linux__ ; then
@@ -428,6 +431,8 @@
;;
--disable-vnc-sasl) vnc_sasl="no"
;;
+ --enable-pcap) pcap="yes"
+ ;;
--disable-slirp) slirp="no"
;;
--disable-vde) vde="no"
@@ -925,6 +930,48 @@
fi
##########################################
+# pcap probe
+
+if test "$pcap" = "yes" ; then
+ cat > $TMPC << EOF
+#include <pcap.h>
+int main(void) { return (pcap_lib_version() == (char *)0 ? 1 : 0); }
+EOF
+ if test "$mingw32" = "no" ; then
+ libpcap=-lpcap
+ else
+ libpcap=-lwpcap
+ fi
+ if ! $cc $ARCH_CFLAGS -o $TMPE $libpcap $TMPC 2> /dev/null ; then
+ echo
+ echo "Error: Could not find pcap"
+ echo "Make sure to have the pcap libs and headers installed."
+ echo
+ exit 1
+ fi
+ cat > $TMPC << EOF
+#include <pcap.h>
+int main(void)
+{
+ char errbuf[PCAP_ERRBUF_SIZE];
+ return (pcap_create("foo", errbuf) == (pcap_t *)0 ? 1 : 0);
+}
+EOF
+ if $cc $ARCH_CFLAGS -o $TMPE $libpcap $TMPC 2> /dev/null ; then
+ pcap_create="yes"
+ fi
+ cat > $TMPC << EOF
+#define PCAP_DONT_INCLUDE_PCAP_BPF_H
+#include <pcap.h>
+#include <net/bpf.h>
+int main(void) { return (BPF_MAJOR_VERSION); }
+EOF
+ if $cc $ARCH_CFLAGS -o $TMPE $TMPC 2> /dev/null ; then
+ bpf="yes"
+ fi
+fi # test "$pcap"
+
+##########################################
# VNC TLS detection
if test "$vnc_tls" = "yes" ; then
cat > $TMPC <<EOF
@@ -1436,6 +1484,7 @@
echo " SASL CFLAGS $vnc_sasl_cflags"
echo " SASL LIBS $vnc_sasl_libs"
fi
+echo "pcap support $pcap"
if test -n "$sparc_cpu"; then
echo "Target Sparc Arch $sparc_cpu"
fi
@@ -1589,6 +1638,16 @@
if test $profiler = "yes" ; then
echo "#define CONFIG_PROFILER 1" >> $config_host_h
fi
+if test "$pcap" = "yes" ; then
+ echo "CONFIG_PCAP=yes" >> $config_host_mak
+ echo "#define CONFIG_PCAP 1" >> $config_host_h
+ if test "$pcap_create" = "yes" ; then
+ echo "#define HAVE_PCAP_CREATE 1" >> $config_host_h
+ fi
+ if test "$bpf" = "yes" ; then
+ echo "#define HAVE_BPF 1" >> $config_host_h
+ fi
+fi
if test "$slirp" = "yes" ; then
echo "CONFIG_SLIRP=y" >> $config_host_mak
echo "#define CONFIG_SLIRP 1" >> $config_host_h
Index: net.c
@@ -688,6 +688,166 @@
va_end(ap);
}
+#if defined(CONFIG_PCAP)
+#if defined(HAVE_BPF)
+#define PCAP_DONT_INCLUDE_PCAP_BPF_H
+#include <net/bpf.h>
+#endif
+#include <pcap.h>
+
+typedef struct PCAPState {
+ VLANClientState *vc;
+ pcap_t *handle;
+} PCAPState;
+
+static ssize_t pcap_receive(VLANClientState *vc, const uint8_t *buf, size_t size)
+{
+ PCAPState *s = (PCAPState *)vc->opaque;
+
+ return pcap_inject(s->handle, (u_char*)buf, size);
+}
+
+static void pcap_callback(u_char *user, struct pcap_pkthdr *phdr, u_char *pdata)
+{
+ VLANClientState *vc = (VLANClientState *)user;
+
+ qemu_send_packet(vc, pdata, phdr->len);
+}
+
+static void pcap_send(void *opaque)
+{
+ PCAPState *s = (PCAPState *)opaque;
+
+ pcap_dispatch(s->handle, 1, (pcap_handler)&pcap_callback, (u_char *)s->vc);
+}
+
+static void pcap_cleanup(VLANClientState *vc)
+{
+ PCAPState *s = vc->opaque;
+
+ pcap_close(s->handle);
+ qemu_free(s);
+}
+
+static int net_pcap_init(VLANState *vlan, const char *model, const char *name, char *ifname)
+{
+ PCAPState *s = NULL;
+ char errbuf[PCAP_ERRBUF_SIZE];
+#if defined(_WIN32)
+ HANDLE h;
+#endif
+ int i;
+
+ s = qemu_mallocz(sizeof(PCAPState));
+ if (!s)
+ return -1;
+
+ if (ifname == NULL && (ifname = pcap_lookupdev(errbuf)) == NULL) {
+ fprintf(stderr, "qemu: pcap_lookupdev: %s\n", errbuf);
+ goto fail;
+ }
+
+#if defined(HAVE_PCAP_CREATE) || defined(_WIN32)
+ /*
+ * Create pcap handle for the device, set promiscuous mode and activate.
+ */
+ s->handle = (void *)pcap_create(ifname, errbuf);
+ if (!s->handle) {
+ fprintf(stderr, "qemu: pcap_create: %s\n", errbuf);
+ goto fail;
+ }
+ if (pcap_set_promisc(s->handle, 1) != 0) {
+ pcap_perror(s->handle, "qemu: pcap_set_promisc:");
+ goto fail;
+ }
+ if (pcap_activate(s->handle) != 0) {
+ pcap_perror(s->handle, "qemu: pcap_activate:");
+ goto fail;
+ }
+#else
+ /* Attempt to connect device. */
+ s->handle = (void *)pcap_open_live(ifname, 65535, 1, 0, errbuf);
+ if (!s->handle) {
+ fprintf(stderr, "qemu: pcap_open_live: %s\n", errbuf);
+ goto fail;
+ }
+#endif
+
+ /* Set non-blocking mode. */
+ if (pcap_setnonblock(s->handle, 1, errbuf) < 0) {
+ fprintf(stderr, "qemu: pcap_setnonblock: %s\n", errbuf);
+ goto fail;
+ }
+
+#if defined(_WIN32)
+ /*
+ * Tell the kernel that the packet has to be seen immediately.
+ */
+ if (pcap_setmintocopy(s->handle, 0) < 0) {
+ fprintf(stderr, "qemu: pcap failed to set immediate mode\n");
+ goto fail;
+ }
+#else /* !_WIN32 */
+#if defined(HAVE_BPF)
+#if defined(BIOCIMMEDIATE)
+ /*
+ * Tell the kernel that the packet has to be seen immediately.
+ */
+ {
+ unsigned int one = 1;
+ if (ioctl(pcap_fileno(s->handle), BIOCIMMEDIATE, &one) < 0) {
+ fprintf(stderr, "qemu: pcap failed to set immediate mode\n");
+ goto fail;
+ }
+ }
+#endif /* BIOCIMMEDIATE */
+
+#if defined(BIOCFEEDBACK)
+ /*
+ * Tell the kernel that the sent packet has to be fed back.
+ * This is necessary to connect host and guest.
+ */
+ {
+ unsigned int one = 1;
+ if (ioctl(pcap_fileno(s->handle), BIOCFEEDBACK, &one) < 0) {
+ fprintf(stderr, "qemu: pcap failed to set feedback mode\n");
+ goto fail;
+ }
+ }
+#endif /* BIOCFEEDBACK */
+#endif /* HAVE_BPF */
+#endif /* _WIN32 */
+
+ s->vc = qemu_new_vlan_client(vlan, model, name, NULL, pcap_receive, NULL, pcap_cleanup, s);
+ snprintf(s->vc->info_str, sizeof(s->vc->info_str), "pcap redirector");
+
+#if defined(_WIN32)
+ if ((h = pcap_getevent(s->handle)) == NULL) {
+ fprintf(stderr, "qemu: pcap_getevent failed\n");
+ goto fail;
+ }
+ qemu_add_wait_object(h, pcap_send, s);
+#else /* !_WIN32 */
+ if ((i = pcap_get_selectable_fd(s->handle)) < 0) {
+ fprintf(stderr, "qemu: pcap_get_selectable_fd failed\n");
+ goto fail;
+ }
+ qemu_set_fd_handler(i, pcap_send, NULL, s);
+#endif /* _WIN32 */
+
+ return 0;
+
+fail:
+ if (s) {
+ if (s->handle)
+ pcap_close(s->handle);
+ qemu_free(s);
+ }
+
+ return -1;
+}
+#endif /* CONFIG_PCAP */
+
#if defined(CONFIG_SLIRP)
/* slirp network adapter */
@@ -2598,6 +2758,16 @@
are wanted */
ret = 0;
} else
+#ifdef CONFIG_PCAP
+ if (!strcmp(device, "pcap")) {
+ char ifname[64];
+ vlan->nb_host_devs++;
+ if (get_param_value(ifname, sizeof(ifname), "ifname", p) <= 0)
+ ret = net_pcap_init(vlan, device, name, NULL);
+ else
+ ret = net_pcap_init(vlan, device, name, ifname);
+ } else
+#endif
#ifdef CONFIG_SLIRP
if (!strcmp(device, "user")) {
static const char * const slirp_params[] = {
Index: qemu-options.hx
@@ -782,6 +782,10 @@
" connect the user mode network stack to VLAN 'n', configure its\n"
" DHCP server and enabled optional services\n"
#endif
+#ifdef CONFIG_PCAP
+ "-net pcap[,vlan=n][,name=str][,ifname=name]\n"
+ " connect the host network interface using PCAP to VLAN 'n'\n"
+#endif
#ifdef _WIN32
"-net tap[,vlan=n][,name=str],ifname=name\n"
" connect the host TAP network interface to VLAN 'n'\n"