qemu/qemu-svn-pcap.patch

184 lines
4.7 KiB
Diff

Index: Makefile.target
================================================================================
--- Makefile.target
+++ Makefile.target
@@ -690,6 +690,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
--- configure
+++ configure
@@ -160,6 +160,7 @@
gdbstub="yes"
slirp="yes"
vde="yes"
+pcap="yes"
fmod_lib=""
fmod_inc=""
oss_lib=""
@@ -392,6 +393,8 @@
;;
--disable-vde) vde="no"
;;
+ --disable-pcap) pcap="no"
+ ;;
--disable-kqemu) kqemu="no"
;;
--disable-brlapi) brlapi="no"
@@ -1353,6 +1356,10 @@
echo "#define CONFIG_VDE 1" >> $config_h
echo "VDE_LIBS=-lvdeplug" >> $config_mak
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
--- net.c
+++ net.c
@@ -689,6 +689,104 @@
#endif /* CONFIG_SLIRP */
+#if defined(CONFIG_PCAP)
+#include <pcap.h>
+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, const char *model, const char *name, 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, model, name, 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 {
@@ -1656,7 +1754,17 @@
}
vlan->nb_host_devs++;
ret = net_slirp_init(vlan, device, name);
- } else if (!strcmp(device, "channel")) {
+ } else
+#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, device, name, NULL);
+ else
+ ret = net_pcap_init(vlan, device, name, ifname);
+ } else
+#endif
+ if (!strcmp(device, "channel")) {
long port;
char name[20], *devname;
struct VMChannel *vmc;
--- vl.c
+++ vl.c
@@ -3990,6 +3994,10 @@
" use '[down]script=no' to disable script execution;\n"
" use 'fd=h' to connect to an already opened TAP interface\n"
#endif
+#ifdef CONFIG_PCAP
+ "-net pcap[,vlan=n][,ifname=name]\n"
+ " connect the host network interface using PCAP to VLAN 'n'\n"
+#endif
"-net socket[,vlan=n][,name=str][,fd=h][,listen=[host]:port][,connect=host:port]\n"
" connect the vlan 'n' to another VLAN using a socket connection\n"
"-net socket[,vlan=n][,name=str][,fd=h][,mcast=maddr:port]\n"