Juergen Lock d4e5177000 Finally bring qemu 0.12.1 into ports as the new emulators/qemu-devel,
release announcement is here:
	http://lists.gnu.org/archive/html/qemu-devel/2009-12/msg02151.html

Quoting from pkg-message:

- kqemu is no longer supported in qemu upstream after the 0.11 branch
was created, which means also not in this version.  (Linux has moved
on to kvm now for qemu(-like) virtualization needs, so if you want qemu
to go faster and don't want to switch to virtualbox or stick to the older
emulators/qemu port which is at 0.11.1 atm and as such still supports
kqemu you should help getting the FreeBSD kvm port updated and
completed:
	http://wiki.freebsd.org/FabioChecconi/PortingLinuxKVMToFreeBSD
)
2010-01-17 16:20:56 +00:00

355 lines
9.1 KiB
Plaintext

Index: configure
@@ -257,6 +257,9 @@ pkgversion=""
check_utests="no"
user_pie="no"
zero_malloc=""
+pcap="no"
+pcap_create="no"
+bpf="no"
# OS specific
if check_define __linux__ ; then
@@ -492,6 +495,8 @@ for opt do
;;
--enable-vnc-sasl) vnc_sasl="yes"
;;
+ --enable-pcap) pcap="yes"
+ ;;
--disable-slirp) slirp="no"
;;
--disable-uuid) uuid="no"
@@ -1041,6 +1046,49 @@ EOF
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
+ libs_softmmu="$libpcap $libs_softmmu"
+fi # test "$pcap"
+
+##########################################
# VNC TLS detection
if test "$vnc_tls" != "no" ; then
cat > $TMPC <<EOF
@@ -1976,6 +2024,15 @@ fi
if test $profiler = "yes" ; then
echo "CONFIG_PROFILER=y" >> $config_host_mak
fi
+if test "$pcap" = "yes" ; then
+ echo "CONFIG_PCAP=y" >> $config_host_mak
+ if test "$pcap_create" = "yes" ; then
+ echo "CONFIG_PCAP_CREATE=y" >> $config_host_mak
+ fi
+ if test "$bpf" = "yes" ; then
+ echo "CONFIG_BPF=y" >> $config_host_mak
+ fi
+fi
if test "$slirp" = "yes" ; then
echo "CONFIG_SLIRP=y" >> $config_host_mak
QEMU_CFLAGS="-I\$(SRC_PATH)/slirp $QEMU_CFLAGS"
Index: net.h
@@ -33,7 +33,8 @@ typedef enum {
NET_CLIENT_TYPE_TAP,
NET_CLIENT_TYPE_SOCKET,
NET_CLIENT_TYPE_VDE,
- NET_CLIENT_TYPE_DUMP
+ NET_CLIENT_TYPE_DUMP,
+ NET_CLIENT_TYPE_PCAP
} net_client_type;
typedef int (NetCanReceive)(VLANClientState *);
Index: net.c
@@ -36,6 +36,8 @@
#include "qemu-common.h"
#include "qemu_socket.h"
+#include <sys/ioctl.h>
+
static QTAILQ_HEAD(, VLANState) vlans;
static QTAILQ_HEAD(, VLANClientState) non_vlan_clients;
@@ -820,6 +822,212 @@ static int net_init_nic(QemuOpts *opts,
return idx;
}
+#if defined(CONFIG_PCAP)
+#if defined(CONFIG_BPF)
+#define PCAP_DONT_INCLUDE_PCAP_BPF_H
+#include <net/bpf.h>
+#endif
+#include <pcap.h>
+
+typedef struct PCAPState {
+ VLANClientState nc;
+ pcap_t *handle;
+} PCAPState;
+
+static ssize_t pcap_receive(VLANClientState *nc, const uint8_t *buf, size_t size)
+{
+ PCAPState *s = DO_UPCAST(PCAPState, nc, nc);
+
+ return pcap_inject(s->handle, (u_char*)buf, size);
+}
+
+#define MAX_ETH_FRAME_SIZE 1514
+
+static void pcap_callback(u_char *user, struct pcap_pkthdr *phdr, u_char *pdata)
+{
+ VLANClientState *vc = (VLANClientState *)user;
+ int len = phdr->len;
+
+ if (len > MAX_ETH_FRAME_SIZE) {
+ fprintf(stderr,
+ "pcap_send: packet size > %d (%d), truncating\n",
+ MAX_ETH_FRAME_SIZE, len);
+ len = MAX_ETH_FRAME_SIZE;
+ }
+ qemu_send_packet(vc, pdata, len);
+}
+
+static void pcap_send(void *opaque)
+{
+ PCAPState *s = (PCAPState *)opaque;
+
+ pcap_dispatch(s->handle, 1, (pcap_handler)&pcap_callback, (u_char *)&s->nc);
+}
+
+static void pcap_cleanup(VLANClientState *nc)
+{
+ PCAPState *s = DO_UPCAST(PCAPState, nc, nc);
+
+ pcap_close(s->handle);
+}
+
+static NetClientInfo net_pcap_info = {
+ .type = NET_CLIENT_TYPE_PCAP,
+ .size = sizeof(PCAPState),
+ .receive = pcap_receive,
+#if 0
+ .receive_raw = tap_receive_raw,
+ .receive_iov = tap_receive_iov,
+#endif
+ .cleanup = pcap_cleanup,
+};
+
+static int net_pcap_init(VLANState *vlan, const char *model, const char *name, const char *ifname)
+{
+ VLANClientState *nc;
+ PCAPState *s = NULL;
+ char errbuf[PCAP_ERRBUF_SIZE];
+#if defined(_WIN32)
+ HANDLE h;
+#endif
+ int i;
+
+ s = qemu_mallocz(sizeof(PCAPState));
+ nc = qemu_new_net_client(&net_pcap_info, vlan, NULL, model, name);
+#if 0
+ nc = qemu_new_vlan_client(NET_CLIENT_TYPE_PCAP,
+ vlan, NULL, model, name, NULL,
+ pcap_receive, NULL, NULL,
+ pcap_cleanup, s);
+#endif
+
+ s = DO_UPCAST(PCAPState, nc, nc);
+ if (!s)
+ return -1;
+
+ if (ifname == NULL && (ifname = pcap_lookupdev(errbuf)) == NULL) {
+ fprintf(stderr, "qemu: pcap_create: %s\n", errbuf);
+ goto fail;
+ }
+
+#if defined(CONFIG_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(CONFIG_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 /* CONFIG_BPF */
+#endif /* _WIN32 */
+
+ snprintf(s->nc.info_str, sizeof(s->nc.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;
+}
+
+static int net_init_pcap(QemuOpts *opts,
+ Monitor *mon,
+ const char *name,
+ VLANState *vlan)
+{
+ const char *ifname;
+
+ ifname = qemu_opt_get(opts, "ifname");
+
+ if (net_pcap_init(vlan, "pcap", name, ifname) == -1) {
+ return -1;
+ }
+
+ vlan->nb_host_devs++;
+
+ return 0;
+}
+#endif /* CONFIG_PCAP */
+
#define NET_COMMON_PARAMS_DESC \
{ \
.name = "type", \
@@ -980,6 +1188,20 @@ static struct {
#endif /* _WIN32 */
{ /* end of list */ }
},
+#ifdef CONFIG_PCAP
+ }, {
+ .type = "pcap",
+ .init = net_init_pcap,
+ .desc = {
+ NET_COMMON_PARAMS_DESC,
+ {
+ .name = "ifname",
+ .type = QEMU_OPT_STRING,
+ .help = "interface name",
+ },
+ { /* end of list */ }
+ },
+#endif
}, {
.type = "socket",
.init = net_init_socket,
--- qemu-options.hx.orig 2009-08-28 16:46:21.000000000 -0400
+++ qemu-options.hx 2009-09-02 16:20:14.000000000 -0400
@@ -783,6 +783,10 @@
DEF("net", HAS_ARG, QEMU_OPTION_net,
"-net nic[,vlan=n][,macaddr=mac][,model=type][,name=str][,addr=str][,vectors=v]\n"
" create a new Network Interface Card and connect it to VLAN 'n'\n"
+#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 CONFIG_SLIRP
"-net user[,vlan=n][,name=str][,net=addr[/mask]][,host=addr][,restrict=y|n]\n"
" [,hostname=host][,dhcpstart=addr][,dns=addr][,tftp=dir][,bootfile=f]\n"