--- qemu/Makefile.target Tue Feb 6 15:30:47 2007 +++ qemu/Makefile.target Tue Feb 6 15:32:40 2007 @@ -421,12 +421,17 @@ COCOA_LIBS+=-framework CoreAudio endif endif + ifdef CONFIG_SLIRP CPPFLAGS+=-I$(SRC_PATH)/slirp SLIRP_OBJS=cksum.o if.o ip_icmp.o ip_input.o ip_output.o \ slirp.o mbuf.o misc.o sbuf.o socket.o tcp_input.o tcp_output.o \ tcp_subr.o tcp_timer.o udp.o bootp.o debug.o tftp.o VL_OBJS+=$(addprefix slirp/, $(SLIRP_OBJS)) +endif + +ifdef CONFIG_PCAP +LIBS+=-lpcap endif VL_LDFLAGS= --- qemu/configure Tue Feb 6 15:30:47 2007 +++ qemu/configure Tue Feb 6 15:33:43 2007 @@ -78,6 +78,7 @@ EXESUF="" gdbstub="yes" slirp="yes" +pcap="yes" adlib="no" oss="no" dsound="no" @@ -230,6 +231,8 @@ ;; --disable-slirp) slirp="no" ;; + --disable-pcap) pcap="no" + ;; --enable-adlib) adlib="yes" ;; --disable-kqemu) kqemu="no" @@ -740,6 +743,10 @@ if test "$slirp" = "yes" ; then 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 if test "$adlib" = "yes" ; then echo "CONFIG_ADLIB=yes" >> $config_mak --- qemu/vl.c Tue Feb 6 15:30:47 2007 +++ qemu/vl.c Tue Feb 6 19:36:07 2007 @@ -64,6 +64,10 @@ #endif #endif +#if defined(CONFIG_PCAP) +#include +#endif + #if defined(CONFIG_SLIRP) #include "libslirp.h" #endif @@ -3275,6 +3279,104 @@ } #endif +#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 { @@ -3991,6 +4093,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]; @@ -6208,6 +6319,10 @@ "-net user[,vlan=n][,hostname=host]\n" " 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"