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 +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"