Skip to contentSkip to conversation

networking using libpcap

PATCH In review Ulrich Hecht 4 participants 6 messages Jul 2, 2008 Kbuild

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 networking using libpcap

Hi!

I just discovered this patch

http://lists.freebsd.org/pipermail/freebsd-emulation/2007-February/003107.html

that implements network access using libpcap. Works perfect for me and allows access to the local Ethernet right out of the box, very much unlike tap and bridging. The attached version applies to trunk.

CU
Uli

Makefile.target +3 -0
Index: Makefile.target
===================================================================
@@ -619,6 +619,9 @@
 ifdef CONFIG_SLIRP
 CPPFLAGS+=-I$(SRC_PATH)/slirp
 endif
+ifdef CONFIG_PCAP
+LIBS+=-lpcap
+endif
 
 LIBS+=$(AIOLIBS)
 # specific flags are needed for non soft mmu emulator
vl.c +19 -0
Index: vl.c
===================================================================
@@ -102,6 +102,10 @@
 int inet_aton(const char *cp, struct in_addr *ia);
 #endif
 
+#if defined(CONFIG_PCAP)
+#include <pcap.h>
+#endif
+
 #if defined(CONFIG_SLIRP)
 #include "libslirp.h"
 #endif
@@ -4094,6 +4098,104 @@
 
 #endif /* CONFIG_SLIRP */
 
+#if defined(CONFIG_PCAP)
+
+typedef struct PCAPState {
+    VLANClientState *vc;
+    pcap_t *handle;
+} PCAPState;
+
+static void pcap_receive(void *opaque, const uint8_t *buf, int size)
+{
+    PCAPState *s = (PCAPState *)opaque;
+
+    pcap_sendpacket(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 int net_pcap_init(VLANState *vlan, char *ifname) +{

+    PCAPState *s;
+    char errbuf[PCAP_ERRBUF_SIZE];
+    int fd;

+
+ 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;
+ }
+

+    /* 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;
+ }
+
+ /* Check non-blocking mode. */
+ if (pcap_setnonblock(s->handle, 1, errbuf) < 0) {
+ fprintf(stderr, "qemu: pcap_setnonblock: %s\n", errbuf);
+ goto fail;
+ }
+
+#if defined(BIOCSHDRCMPLT)
+ /*

+     * Tell the kernel that the header is fully-formed when it gets it.
+     * This is required in order to fake the src address.
+     */

+ {
+ unsigned int one = 1;
+ ioctl(pcap_fileno(s->handle), BIOCSHDRCMPLT, &one);
+ }
+#endif /* BIOCSHDRCMPLT */
+
+#if defined(BIOCIMMEDIATE)
+ /*
+ * Tell the kernel that the packet has to be processed immediately.
+ */
+ {
+ unsigned int one = 1;
+ ioctl(pcap_fileno(s->handle), BIOCIMMEDIATE, &one);
+ }
+#endif /* BIOCIMMEDIATE */
+
+ s->vc = qemu_new_vlan_client(vlan, pcap_receive, NULL, s);
+ snprintf(s->vc->info_str, sizeof(s->vc->info_str), "pcap
redirector");
+ if ((fd = pcap_get_selectable_fd(s->handle)) < 0) {
+ fprintf(stderr, "qemu: pcap_get_selectable_fd failed\n");
+ goto fail;
+ }
+ qemu_set_fd_handler(fd, pcap_send, NULL, s);
+
+ return 0;
+
+fail:
+ if (s) {
+ if (s->handle)
+ pcap_close(s->handle);
+ qemu_free(s);
+ }
+
+ return -1;
+}
+#endif /* CONFIG_PCAP */
+
#if !defined(_WIN32)

typedef struct TAPState {
@@ -4978,6 +5080,15 @@

         ret = net_slirp_init(vlan);
     } else

#endif
+#ifdef CONFIG_PCAP
+ if (!strcmp(device, "pcap")) {
+ char ifname[64];
+ if (get_param_value(ifname, sizeof(ifname), "ifname", p) <= 0)
+ ret = net_pcap_init(vlan, NULL);
+ else
+ ret = net_pcap_init(vlan, ifname);
+ } else
+#endif

 #ifdef _WIN32
     if (!strcmp(device, "tap")) {
         char ifname[64];

@@ -7381,6 +7492,10 @@
" connect the user mode network stack to
VLAN 'n' and send\n"
" hostname 'host' to DHCP clients\n"
#endif
+#ifdef CONFIG_PCAP
+ "-net pcap[,vlan=n][,ifname=name]\n"
+ " connect the host network interface using
PCAP to VLAN 'n'\n"
+#endif
#ifdef _WIN32
"-net tap[,vlan=n],ifname=name\n"
" connect the host TAP network interface to
VLAN 'n'\n"

configure +7 -0
Index: configure
===================================================================
@@ -89,6 +89,7 @@
 EXESUF=""
 gdbstub="yes"
 slirp="yes"
+pcap="yes"
 fmod_lib=""
 fmod_inc=""
 vnc_tls="yes"
@@ -280,6 +281,8 @@
   ;;
   --disable-slirp) slirp="no"
   ;;
+  --disable-pcap) pcap="no"
+  ;;
   --disable-kqemu) kqemu="no"
   ;;
   --disable-brlapi) brlapi="no"
@@ -1032,6 +1035,10 @@
   echo "CONFIG_SLIRP=yes" >> $config_mak
   echo "#define CONFIG_SLIRP 1" >> $config_h
 fi
+if test "$pcap" = "yes" ; then
+  echo "CONFIG_PCAP=yes" >> $config_mak
+  echo "#define CONFIG_PCAP 1" >> $config_h
+fi
 for card in $audio_card_list; do
     def=CONFIG_`echo $card | tr '[:lower:]' '[:upper:]'`
     echo "$def=yes" >> $config_mak
Signature · 1 line
SUSE LINUX Products GmbH, GF: Markus Rex, HRB 16746 (AG Nürnberg)
Makefile.target +3 -0
Index: Makefile.target
===================================================================
@@ -619,6 +619,9 @@
 ifdef CONFIG_SLIRP
 CPPFLAGS+=-I$(SRC_PATH)/slirp
 endif
+ifdef CONFIG_PCAP
+LIBS+=-lpcap
+endif
 
 LIBS+=$(AIOLIBS)
 # specific flags are needed for non soft mmu emulator
vl.c +115 -0

139 lines not on this page · raw message

configure +7 -0
Index: configure
===================================================================
@@ -89,6 +89,7 @@
 EXESUF=""
 gdbstub="yes"
 slirp="yes"
+pcap="yes"
 fmod_lib=""
 fmod_inc=""
 vnc_tls="yes"
@@ -280,6 +281,8 @@
   ;;
   --disable-slirp) slirp="no"
   ;;
+  --disable-pcap) pcap="no"
+  ;;
   --disable-kqemu) kqemu="no"
   ;;
   --disable-brlapi) brlapi="no"
@@ -1032,6 +1035,10 @@
   echo "CONFIG_SLIRP=yes" >> $config_mak
   echo "#define CONFIG_SLIRP 1" >> $config_h
 fi
+if test "$pcap" = "yes" ; then
+  echo "CONFIG_PCAP=yes" >> $config_mak
+  echo "#define CONFIG_PCAP 1" >> $config_h
+fi
 for card in $audio_card_list; do
     def=CONFIG_`echo $card | tr '[:lower:]' '[:upper:]'`
     echo "$def=yes" >> $config_mak
#1 lore raw
Quoted 8 lines · Ulrich Hecht

Hi!

I just discovered this patch

http://lists.freebsd.org/pipermail/freebsd-emulation/2007-February/003107.html

that implements network access using libpcap. Works perfect for me and allows access to the local Ethernet right out of the box, very much unlike tap and bridging. The attached version applies to trunk.

You could also just use slirp? The difference being that pcap requires root (as would raw sockets, which could also work).

Regards,

Anthony Liguori

Quoted 205 lines

CU
Uli

Index: Makefile.target
===================================================================

Makefile.target +3 -0
@@ -619,6 +619,9 @@
 ifdef CONFIG_SLIRP
 CPPFLAGS+=-I$(SRC_PATH)/slirp
 endif
+ifdef CONFIG_PCAP
+LIBS+=-lpcap
+endif
 
 LIBS+=$(AIOLIBS)
 # specific flags are needed for non soft mmu emulator

Index: vl.c
===================================================================

vl.c +102 -0
@@ -102,6 +102,10 @@
 int inet_aton(const char *cp, struct in_addr *ia);
 #endif
 
+#if defined(CONFIG_PCAP)
+#include <pcap.h>
+#endif
+
 #if defined(CONFIG_SLIRP)
 #include "libslirp.h"
 #endif
@@ -4094,6 +4098,104 @@
 
 #endif /* CONFIG_SLIRP */
 
+#if defined(CONFIG_PCAP)
+
+typedef struct PCAPState {
+    VLANClientState *vc;
+    pcap_t *handle;
+} PCAPState;
+
+static void pcap_receive(void *opaque, const uint8_t *buf, int size)
+{
+    PCAPState *s = (PCAPState *)opaque;
+
+    pcap_sendpacket(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 int net_pcap_init(VLANState *vlan, char *ifname)
+{
+    PCAPState *s;
+    char errbuf[PCAP_ERRBUF_SIZE];
+    int fd;
+
+    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;
+    }
+
+    /* 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;
+    }
+
+    /* Check non-blocking mode. */
+    if (pcap_setnonblock(s->handle, 1, errbuf) < 0) {
+	fprintf(stderr, "qemu: pcap_setnonblock: %s\n", errbuf);
+	goto fail;
+    }
+
+#if defined(BIOCSHDRCMPLT)
+    /*
+     * Tell the kernel that the header is fully-formed when it gets it.
+     * This is required in order to fake the src address.
+     */
+    {
+	unsigned int one = 1;
+	ioctl(pcap_fileno(s->handle), BIOCSHDRCMPLT, &one);
+    }
+#endif /* BIOCSHDRCMPLT */
+
+#if defined(BIOCIMMEDIATE)
+    /*
+     * Tell the kernel that the packet has to be processed immediately.
+     */
+    {
+	unsigned int one = 1;
+	ioctl(pcap_fileno(s->handle), BIOCIMMEDIATE, &one);
+    }
+#endif /* BIOCIMMEDIATE */
+
+    s->vc = qemu_new_vlan_client(vlan, pcap_receive, NULL, s);
+    snprintf(s->vc->info_str, sizeof(s->vc->info_str), "pcap 
 redirector");
+    if ((fd = pcap_get_selectable_fd(s->handle)) < 0) {
+	fprintf(stderr, "qemu: pcap_get_selectable_fd failed\n");
+	goto fail;
+    }
+    qemu_set_fd_handler(fd, pcap_send, NULL, s);
+
+    return 0;
+
+fail:
+    if (s) {
+	if (s->handle)
+	    pcap_close(s->handle);
+	qemu_free(s);
+    }
+
+    return -1;
+}
+#endif /* CONFIG_PCAP */
+

#if !defined(_WIN32)

typedef struct TAPState {

vl.c +9 -0
@@ -4978,6 +5080,15 @@
         ret = net_slirp_init(vlan);
     } else
 #endif
+#ifdef CONFIG_PCAP
+    if (!strcmp(device, "pcap")) {
+	char ifname[64];
+	if (get_param_value(ifname, sizeof(ifname), "ifname", p) <= 0)
+	    ret = net_pcap_init(vlan, NULL);
+	else
+	    ret = net_pcap_init(vlan, ifname);
+    } else
+#endif
 #ifdef _WIN32
     if (!strcmp(device, "tap")) {
         char ifname[64];
@@ -7381,6 +7492,10 @@
            "                connect the user mode network stack to 

VLAN 'n' and send\n"
" hostname 'host' to DHCP clients\n"
#endif

vl.c +3 -0
+#ifdef CONFIG_PCAP
+           "-net pcap[,vlan=n][,ifname=name]\n"
+           "                connect the host network interface using 

PCAP to VLAN 'n'\n"
+#endif
#ifdef _WIN32
"-net tap[,vlan=n],ifname=name\n"
" connect the host TAP network interface to
VLAN 'n'\n"
Index: configure
===================================================================

configure +7 -0
@@ -89,6 +89,7 @@
 EXESUF=""
 gdbstub="yes"
 slirp="yes"
+pcap="yes"
 fmod_lib=""
 fmod_inc=""
 vnc_tls="yes"
@@ -280,6 +281,8 @@
   ;;
   --disable-slirp) slirp="no"
   ;;
+  --disable-pcap) pcap="no"
+  ;;
   --disable-kqemu) kqemu="no"
   ;;
   --disable-brlapi) brlapi="no"
@@ -1032,6 +1035,10 @@
   echo "CONFIG_SLIRP=yes" >> $config_mak
   echo "#define CONFIG_SLIRP 1" >> $config_h
 fi
+if test "$pcap" = "yes" ; then
+  echo "CONFIG_PCAP=yes" >> $config_mak
+  echo "#define CONFIG_PCAP 1" >> $config_h
+fi
 for card in $audio_card_list; do
     def=CONFIG_`echo $card | tr '[:lower:]' '[:upper:]'`
     echo "$def=yes" >> $config_mak
#2 lore raw
Quoted 2 lines · Anthony Liguori

You could also just use slirp? The difference being that pcap requires root (as would raw sockets, which could also work).

Ever tried doing IPv6 with that?

CU
Uli

Signature · 1 line
SUSE LINUX Products GmbH, GF: Markus Rex, HRB 16746 (AG Nürnberg)
#3 lore raw
In reply to Ulrich Hecht

I think the patch is broken by your mailer agent.

Laurent

Quoted 52 lines · Ulrich Hecht

Hi!

I just discovered this patch

http://lists.freebsd.org/pipermail/freebsd-emulation/2007-February/003107.html

that implements network access using libpcap. Works perfect for me and allows access to the local Ethernet right out of the box, very much unlike tap and bridging. The attached version applies to trunk.

CU
Uli

Index: Makefile.target
===================================================================

Makefile.target +3 -0
@@ -619,6 +619,9 @@
 ifdef CONFIG_SLIRP
 CPPFLAGS+=-I$(SRC_PATH)/slirp
 endif
+ifdef CONFIG_PCAP
+LIBS+=-lpcap
+endif
 
 LIBS+=$(AIOLIBS)
 # specific flags are needed for non soft mmu emulator

Index: vl.c
===================================================================

vl.c +10 -0
@@ -102,6 +102,10 @@
 int inet_aton(const char *cp, struct in_addr *ia);
 #endif
 
+#if defined(CONFIG_PCAP)
+#include <pcap.h>
+#endif
+
 #if defined(CONFIG_SLIRP)
 #include "libslirp.h"
 #endif
@@ -4094,6 +4098,104 @@
 
 #endif /* CONFIG_SLIRP */
 
+#if defined(CONFIG_PCAP)
+
+typedef struct PCAPState {
+    VLANClientState *vc;
+    pcap_t *handle;
+} PCAPState;

vl.c line 4116

Quoted 10 lines
vl.c +9 -0
+
+static void pcap_receive(void *opaque, const uint8_t *buf, int size)
+{
+    PCAPState *s = (PCAPState *)opaque;
+
+    pcap_sendpacket(s->handle, (u_char*)buf, size);
+}
+
+static void pcap_callback(u_char *user, struct pcap_pkthdr *phdr, u_char 
 *pdata)

^ Here

vl.c

Quoted 12 lines
vl.c +11 -0
+{
+    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);

^Here

Quoted 140 lines
vl.c +72 -0
+}
+
+static int net_pcap_init(VLANState *vlan, char *ifname)
+{
+    PCAPState *s;
+    char errbuf[PCAP_ERRBUF_SIZE];
+    int fd;
+
+    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;
+    }
+
+    /* 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;
+    }
+
+    /* Check non-blocking mode. */
+    if (pcap_setnonblock(s->handle, 1, errbuf) < 0) {
+	fprintf(stderr, "qemu: pcap_setnonblock: %s\n", errbuf);
+	goto fail;
+    }
+
+#if defined(BIOCSHDRCMPLT)
+    /*
+     * Tell the kernel that the header is fully-formed when it gets it.
+     * This is required in order to fake the src address.
+     */
+    {
+	unsigned int one = 1;
+	ioctl(pcap_fileno(s->handle), BIOCSHDRCMPLT, &one);
+    }
+#endif /* BIOCSHDRCMPLT */
+
+#if defined(BIOCIMMEDIATE)
+    /*
+     * Tell the kernel that the packet has to be processed immediately.
+     */
+    {
+	unsigned int one = 1;
+	ioctl(pcap_fileno(s->handle), BIOCIMMEDIATE, &one);
+    }
+#endif /* BIOCIMMEDIATE */
+
+    s->vc = qemu_new_vlan_client(vlan, pcap_receive, NULL, s);
+    snprintf(s->vc->info_str, sizeof(s->vc->info_str), "pcap 
 redirector");
+    if ((fd = pcap_get_selectable_fd(s->handle)) < 0) {
+	fprintf(stderr, "qemu: pcap_get_selectable_fd failed\n");
+	goto fail;
+    }
+    qemu_set_fd_handler(fd, pcap_send, NULL, s);
+
+    return 0;
+
+fail:
+    if (s) {
+	if (s->handle)
+	    pcap_close(s->handle);
+	qemu_free(s);
+    }
+
+    return -1;
+}
+#endif /* CONFIG_PCAP */
+

#if !defined(_WIN32)

typedef struct TAPState {

vl.c +9 -0
@@ -4978,6 +5080,15 @@
         ret = net_slirp_init(vlan);
     } else
 #endif
+#ifdef CONFIG_PCAP
+    if (!strcmp(device, "pcap")) {
+	char ifname[64];
+	if (get_param_value(ifname, sizeof(ifname), "ifname", p) <= 0)
+	    ret = net_pcap_init(vlan, NULL);
+	else
+	    ret = net_pcap_init(vlan, ifname);
+    } else
+#endif
 #ifdef _WIN32
     if (!strcmp(device, "tap")) {
         char ifname[64];
@@ -7381,6 +7492,10 @@
            "                connect the user mode network stack to 

VLAN 'n' and send\n"
" hostname 'host' to DHCP clients\n"
#endif

vl.c +3 -0
+#ifdef CONFIG_PCAP
+           "-net pcap[,vlan=n][,ifname=name]\n"
+           "                connect the host network interface using 

PCAP to VLAN 'n'\n"
+#endif
#ifdef _WIN32
"-net tap[,vlan=n],ifname=name\n"
" connect the host TAP network interface to
VLAN 'n'\n"
Index: configure
===================================================================

configure +7 -0
@@ -89,6 +89,7 @@
 EXESUF=""
 gdbstub="yes"
 slirp="yes"
+pcap="yes"
 fmod_lib=""
 fmod_inc=""
 vnc_tls="yes"
@@ -280,6 +281,8 @@
   ;;
   --disable-slirp) slirp="no"
   ;;
+  --disable-pcap) pcap="no"
+  ;;
   --disable-kqemu) kqemu="no"
   ;;
   --disable-brlapi) brlapi="no"
@@ -1032,6 +1035,10 @@
   echo "CONFIG_SLIRP=yes" >> $config_mak
   echo "#define CONFIG_SLIRP 1" >> $config_h
 fi
+if test "$pcap" = "yes" ; then
+  echo "CONFIG_PCAP=yes" >> $config_mak
+  echo "#define CONFIG_PCAP 1" >> $config_h
+fi
 for card in $audio_card_list; do
     def=CONFIG_`echo $card | tr '[:lower:]' '[:upper:]'`
     echo "$def=yes" >> $config_mak
Signature · 3 lines
------------- [email protected] ---------------
"The best way to predict the future is to invent it."
- Alan Kay
#4 lore raw
Quoted 1 line · Laurent Vivier

I think the patch is broken by your mailer agent.

In fact, the inlined one is broken but the attached one is good...

Quoted 223 lines

Laurent

Quoted 52 lines · Ulrich Hecht

Hi!

I just discovered this patch

http://lists.freebsd.org/pipermail/freebsd-emulation/2007-February/003107.html

that implements network access using libpcap. Works perfect for me and allows access to the local Ethernet right out of the box, very much unlike tap and bridging. The attached version applies to trunk.

CU
Uli

Index: Makefile.target
===================================================================

Makefile.target +3 -0
@@ -619,6 +619,9 @@
 ifdef CONFIG_SLIRP
 CPPFLAGS+=-I$(SRC_PATH)/slirp
 endif
+ifdef CONFIG_PCAP
+LIBS+=-lpcap
+endif
 
 LIBS+=$(AIOLIBS)
 # specific flags are needed for non soft mmu emulator

Index: vl.c
===================================================================

vl.c +10 -0
@@ -102,6 +102,10 @@
 int inet_aton(const char *cp, struct in_addr *ia);
 #endif
 
+#if defined(CONFIG_PCAP)
+#include <pcap.h>
+#endif
+
 #if defined(CONFIG_SLIRP)
 #include "libslirp.h"
 #endif
@@ -4094,6 +4098,104 @@
 
 #endif /* CONFIG_SLIRP */
 
+#if defined(CONFIG_PCAP)
+
+typedef struct PCAPState {
+    VLANClientState *vc;
+    pcap_t *handle;
+} PCAPState;

vl.c line 4116

Quoted 10 lines
vl.c +9 -0
+
+static void pcap_receive(void *opaque, const uint8_t *buf, int size)
+{
+    PCAPState *s = (PCAPState *)opaque;
+
+    pcap_sendpacket(s->handle, (u_char*)buf, size);
+}
+
+static void pcap_callback(u_char *user, struct pcap_pkthdr *phdr, u_char 
 *pdata)

^ Here

vl.c

Quoted 12 lines
vl.c +11 -0
+{
+    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);

^Here

Quoted 140 lines
vl.c +72 -0
+}
+
+static int net_pcap_init(VLANState *vlan, char *ifname)
+{
+    PCAPState *s;
+    char errbuf[PCAP_ERRBUF_SIZE];
+    int fd;
+
+    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;
+    }
+
+    /* 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;
+    }
+
+    /* Check non-blocking mode. */
+    if (pcap_setnonblock(s->handle, 1, errbuf) < 0) {
+	fprintf(stderr, "qemu: pcap_setnonblock: %s\n", errbuf);
+	goto fail;
+    }
+
+#if defined(BIOCSHDRCMPLT)
+    /*
+     * Tell the kernel that the header is fully-formed when it gets it.
+     * This is required in order to fake the src address.
+     */
+    {
+	unsigned int one = 1;
+	ioctl(pcap_fileno(s->handle), BIOCSHDRCMPLT, &one);
+    }
+#endif /* BIOCSHDRCMPLT */
+
+#if defined(BIOCIMMEDIATE)
+    /*
+     * Tell the kernel that the packet has to be processed immediately.
+     */
+    {
+	unsigned int one = 1;
+	ioctl(pcap_fileno(s->handle), BIOCIMMEDIATE, &one);
+    }
+#endif /* BIOCIMMEDIATE */
+
+    s->vc = qemu_new_vlan_client(vlan, pcap_receive, NULL, s);
+    snprintf(s->vc->info_str, sizeof(s->vc->info_str), "pcap 
 redirector");
+    if ((fd = pcap_get_selectable_fd(s->handle)) < 0) {
+	fprintf(stderr, "qemu: pcap_get_selectable_fd failed\n");
+	goto fail;
+    }
+    qemu_set_fd_handler(fd, pcap_send, NULL, s);
+
+    return 0;
+
+fail:
+    if (s) {
+	if (s->handle)
+	    pcap_close(s->handle);
+	qemu_free(s);
+    }
+
+    return -1;
+}
+#endif /* CONFIG_PCAP */
+

#if !defined(_WIN32)

typedef struct TAPState {

vl.c +9 -0
@@ -4978,6 +5080,15 @@
         ret = net_slirp_init(vlan);
     } else
 #endif
+#ifdef CONFIG_PCAP
+    if (!strcmp(device, "pcap")) {
+	char ifname[64];
+	if (get_param_value(ifname, sizeof(ifname), "ifname", p) <= 0)
+	    ret = net_pcap_init(vlan, NULL);
+	else
+	    ret = net_pcap_init(vlan, ifname);
+    } else
+#endif
 #ifdef _WIN32
     if (!strcmp(device, "tap")) {
         char ifname[64];
@@ -7381,6 +7492,10 @@
            "                connect the user mode network stack to 

VLAN 'n' and send\n"
" hostname 'host' to DHCP clients\n"
#endif

vl.c +3 -0
+#ifdef CONFIG_PCAP
+           "-net pcap[,vlan=n][,ifname=name]\n"
+           "                connect the host network interface using 

PCAP to VLAN 'n'\n"
+#endif
#ifdef _WIN32
"-net tap[,vlan=n],ifname=name\n"
" connect the host TAP network interface to
VLAN 'n'\n"
Index: configure
===================================================================

configure +7 -0
@@ -89,6 +89,7 @@
 EXESUF=""
 gdbstub="yes"
 slirp="yes"
+pcap="yes"
 fmod_lib=""
 fmod_inc=""
 vnc_tls="yes"
@@ -280,6 +281,8 @@
   ;;
   --disable-slirp) slirp="no"
   ;;
+  --disable-pcap) pcap="no"
+  ;;
   --disable-kqemu) kqemu="no"
   ;;
   --disable-brlapi) brlapi="no"
@@ -1032,6 +1035,10 @@
   echo "CONFIG_SLIRP=yes" >> $config_mak
   echo "#define CONFIG_SLIRP 1" >> $config_h
 fi
+if test "$pcap" = "yes" ; then
+  echo "CONFIG_PCAP=yes" >> $config_mak
+  echo "#define CONFIG_PCAP 1" >> $config_h
+fi
 for card in $audio_card_list; do
     def=CONFIG_`echo $card | tr '[:lower:]' '[:upper:]'`
     echo "$def=yes" >> $config_mak
Signature · 3 lines
------------- [email protected] ---------------
"The best way to predict the future is to invent it."
- Alan Kay
#5 lore raw
In reply to Ulrich Hecht
Quoted 5 lines

I just discovered this patch

http://lists.freebsd.org/pipermail/freebsd-emulation/2007-February/003107.html

that implements network access using libpcap. Works perfect for me and allows access to the local Ethernet right out of the box, very much unlike tap and bridging. The attached version applies to trunk.

I have modified (e.g. got rid of threads) the original patch from the forum and am using it here on Windows. It works fine but performance is pretty low.

Makefile.target line 624

Quoted 3 lines
Makefile.target +3 -0
+ifdef CONFIG_PCAP
+LIBS+=-lpcap
+endif

On Windows it should be -lwpcap.

+ if ((fd = pcap_get_selectable_fd(s->handle)) < 0) {
+ fprintf(stderr, "qemu: pcap_get_selectable_fd failed\n");
+ goto fail;
+ }
+ qemu_set_fd_handler(fd, pcap_send, NULL, s);

pcap_get_selectable_fd() is not available on Windows. I just put pcap_send() in main_loop_wait().

- Sebastian