qemu with native networking!

Started by neozeed, May 29, 2006, 07:03:11 AM

Previous topic - Next topic

neozeed

Ok, this patch lets you use qemu with no nat!  I was able to do the remote framebuffer from the i386 to my next, and in addition I installed novell netware 4 with this patch, and was able to map drives using my next..   Note that you may need to fanagle the i386-softmmu/Makefile to include -lpcap, or -lpthreads depending on your platform.  At the least I can say this works fine under OSX 10.4, although I think I may have installed a newer pcap for use from simh.  Credit should go to simh, since that is where I 'liberated' the pcap networking.



--- configure   2006-05-28 10:21:31.000000000 -0400
+++ ../qemu-0.8.1/configure     2006-05-03 16:32:58.000000000 -0400
@@ -656,9 +656,7 @@
fi
if test "$slirp" = "yes" ; then
  echo "CONFIG_SLIRP=yes" >> $config_mak
-  echo "CONFIG_PCAP=yes" >> $config_mak
  echo "#define CONFIG_SLIRP 1" >> $config_h
-  echo "#define CONFIG_PCAP 1" >> $config_h
fi
if test "$adlib" = "yes" ; then
  echo "CONFIG_ADLIB=yes" >> $config_mak







--- ../qemu-0.8.1/vl.c   2006-05-03 16:32:58.000000000 -0400
+++ vl.c   2006-05-28 15:50:13.000000000 -0400
@@ -2505,6 +2505,257 @@

#endif /* CONFIG_SLIRP */

+/////////////////////////////////////////////////////////////////////////////////////////////////////////////
+#ifdef CONFIG_PCAP
+#include <pcap.h>
+#include <string.h>
+char pcap_devicename[32];
+
+#if defined(_WIN32)
+#include <winreg.h>
+#endif
+
+#include <pthread.h>
+
+static VLANClientState *pcap_vc;
+pcap_t* pcaphandle;
+static void pcap_receive(void *opaque, const uint8_t *buf, int size);
+char* eth_getname_bydesc(char* desc, char* name);
+char* eth_getname(int number, char* name);
+void eth_callback(u_char *user, struct pcap_pkthdr *phdr, u_char *pdata);
+void *pcap_send(void *threadid);
+int eth_open(char* name);
+
+static int net_pcap_init(VLANState *vlan)
+{
+pcap_vc = qemu_new_vlan_client(vlan,pcap_receive,NULL,NULL);
+snprintf(pcap_vc->info_str,sizeof(pcap_vc->info_str),"pcap redirector");
+//LAN
+eth_open(pcap_devicename);
+
+pthread_attr_t attr;
+pthread_t threads;
+int rc;
+//ethq_init (&dev->read_queue, 200); /* initialize FIFO queue */
+//pthread_mutex_init (&dev->lock, NULL);
+//pthread_attr_init(&attr);
+//pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
+//pthread_create (&dev->reader_thread, &attr, _eth_reader, (void *)dev);
+//pthread_create (NULL, &attr, pcap_send, NULL);
+rc=pthread_create (&threads,NULL,pcap_send,NULL);
+pthread_attr_destroy(&attr);
+
+
+return 0;
+}
+
+//cheesy hack to not 'read' my own packets.
+//makes netware happy
+unsigned char mymac[8];
+int wtf=0;
+static void pcap_receive(void *opaque, const uint8_t *buf, int size)
+{
+//printf("pcap input:\n");
+//hex_dump(stdout,buf,size);
+//status = pcap_sendpacket((pcap_t*)dev->handle, (u_char*)packet->msg, packet->len);
+
+//use wtf to drop the 1st packet.
+if(wtf==0)
+{
+   memset(mymac,0x0,8);
+   memcpy(mymac,(u_char*)buf+6,6);
+   //printf("\nThis is my mac:\n");
+   //hex_dump(stdout,(u_char*)buf,15);
+   //hex_dump(stdout,mymac,6);
+   //printf("\n");
+   wtf++;
+   }
+else{
+   pcap_sendpacket((pcap_t*)pcaphandle, (u_char*)buf, size);
+   }
+}
+
+void *pcap_send(void *threadid)
+{
+int sel_ret;
+struct timeval timeout;
+timeout.tv_sec = 0;
+timeout.tv_usec = 200*1000;
+int status;
+
+while(pcaphandle)
+{
+fd_set setl;
+//sleep(1);
+//printf("t");
+FD_ZERO(&setl);
+//FD_SET(pcap_get_selectable_fd((pcap_t *)pcaphandle), &setl);
+//sel_ret = select(pcap_get_selectable_fd((pcap_t *)pcaphandle), &setl, NULL, NULL, &timeout);
+//if (sel_ret < 0 && errno != EINTR) break;
+//if (sel_ret > 0) {
+/* dispatch read request queue available packets */
+//printf("D");
+//status = pcap_dispatch((pcap_t*)pcaphandle, -1, &eth_callback, "");
+//printf("d");
+// }
+status = pcap_dispatch((pcap_t*)pcaphandle, 1, &eth_callback, NULL);
+//printf("d");
+}
+}
+
+void eth_callback(u_char *user, struct pcap_pkthdr *phdr, u_char *pdata)
+{
+//printf("eth_callback:\n");
+//printf("%d\t\t\r",phdr->len);
+//fflush(stdout);
+//hex_dump(stdout,pdata,phdr->len);
+if(phdr->len<1501)
+   {
+   //Its ugly but netware complains if it sees its own packets.
+   //So this is how i strip out its self originated packets
+   if(memcmp(mymac,(u_char*)pdata+6,6))
+      {
+      //hex_dump(stdout,(u_char*)pdata,6);
+      //hex_dump(stdout,(u_char*)pdata,12);
+      qemu_send_packet(pcap_vc, pdata, phdr->len);
+      }
+   }
+}
+
+#define ETH_PROMISC 1
+#define PCAP_READ_TIMEOUT 15
+
+int eth_open(char* name)
+{
+const int bufsz = (BUFSIZ < 1520) ? 1520 : BUFSIZ;
+char errbuf[PCAP_ERRBUF_SIZE];
+char temp[1024];
+char* savname = name;
+int num;
+char* msg;
+
+/* translate name of type "ethX" to real device name */
+if ((strlen(name) == 4)
+&& (tolower(name[0]) == 'e')
+&& (tolower(name[1]) == 't')
+&& (tolower(name[2]) == 'h')
+&& isdigit(name[3])
+) {
+num = atoi(&name[3]);
+savname = eth_getname(num, temp);
+if (savname == 0) /* didn't translate */
+return -1;
+} else {
+/* are they trying to use device description? */
+//savname = eth_getname_bydesc(name, temp);
+if (savname == 0) /* didn't translate */
+return -1;
+}
+
+/* attempt to connect device */
+memset(errbuf, 0, sizeof(errbuf));
+pcaphandle = (void*) pcap_open_live(savname, bufsz, ETH_PROMISC, PCAP_READ_TIMEOUT, errbuf);
+if (!pcaphandle) { /* can't open device */
+msg = "Eth: pcap_open_live error - %s\r\n";
+printf (msg, errbuf);
+return -1;
+} else {
+msg = "Eth: opened %s\r\n";
+printf (msg, savname);
+}
+
+/* save name of device */
+//dev->name = malloc(strlen(savname)+1);
+//strcpy(dev->name, savname);
+
+/* save debugging information */
+//dev->dptr = dptr;
+//dev->dbit = dbit;
+
+#if !defined(HAS_PCAP_SENDPACKET) && defined (xBSD) && !defined (__APPLE__)
+/* Tell the kernel that the header is fully-formed when it gets it.
+This is required in order to fake the src address. */
+{
+int one = 1;
+ioctl(pcap_fileno(dev->pcaphandle), BIOCSHDRCMPLT, &one);
+}
+#endif /* xBSD */
+
+#if defined (USE_READER_THREAD)
+{
+pthread_attr_t attr;
+
+ethq_init (&dev->read_queue, 200); /* initialize FIFO queue */
+pthread_mutex_init (&dev->lock, NULL);
+pthread_attr_init(&attr);
+pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
+pthread_create (&dev->reader_thread, &attr, _pcap_send, (void *)dev);
+pthread_attr_destroy(&attr);
+}
+#else /* !defined (USE_READER_THREAD */
+#ifdef USE_SETNONBLOCK
+/* set ethernet device non-blocking so pcap_dispatch() doesn't hang */
+if (pcap_setnonblock (dev->pcaphandle, 1, errbuf) == -1) {
+msg = "Eth: Failed to set non-blocking: %s\r\n";
+printf (msg, errbuf);
+if (sim_log) fprintf (sim_log, msg, errbuf);
+}
+#endif
+#endif /* !defined (USE_READER_THREAD */
+return 0;
+}
+
+#define ETH_MAX_DEVICE 10
+char* eth_getname_bydesc(char* desc, char* name)
+{
+// ETH_LIST list[ETH_MAX_DEVICE];
+struct slist {
+int num;
+char name[50];
+char desc[50];
+}list[10];
+int count = 1;//eth_devices(ETH_MAX_DEVICE, list);
+int i;
+int j=strlen(desc);
+
+for (i=0; i<count; i++) {
+int found = 1;
+int k = strlen(list.desc);
+
+if (j != k) continue;
+for (k=0; k<j; k++)
+if (tolower(list.desc[k]) != tolower(desc[k]))
+found = 0;
+if (found == 0) continue;
+
+/* found a case-insensitive description match */
+strcpy(name, list.name);
+return name;
+}
+/* not found */
+return 0;
+}
+
+char* eth_getname(int number, char* name)
+{
+//ETH_LIST list[ETH_MAX_DEVICE];
+struct slist {
+int num;
+char name[50];
+char desc[50];
+}list[10];
+int count =1;// eth_devices(ETH_MAX_DEVICE, list);
+
+if (count < number) return 0;
+strcpy(name, list[number].name);
+return name;
+}
+
+
+#endif //CONFIG_PCAP
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
#if !defined(_WIN32)

typedef struct TAPState {
@@ -3176,6 +3427,14 @@
        ret = net_slirp_init(vlan);
    } else
#endif
+#ifdef CONFIG_PCAP
+if (!strcmp(device, "pcap")) {
+   if (get_param_value(buf, sizeof(buf),"devicename",p)){
+      pstrcpy(pcap_devicename,sizeof(pcap_devicename),buf);
+   }
+ret = net_pcap_init(vlan);
+} else
+#endif
#ifdef _WIN32
    if (!strcmp(device, "tap")) {
        char ifname[64];
@@ -4632,6 +4891,9 @@
           "                connect the user mode network stack to VLAN 'n' and send\n"
           "                hostname 'host' to DHCP clients\n"
#endif
+#ifdef CONFIG_PCAP
+      "-net pcap,devicename=name\n"
+#endif
#ifdef _WIN32
           "-net tap[,vlan=n],ifname=name\n"
           "                connect the host TAP network interface to VLAN 'n'\n"
# include <wittycomment.h>