From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1HFrSl-0008P5-Fy for qemu-devel@nongnu.org; Sat, 10 Feb 2007 07:36:19 -0500 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1HFrSk-0008OR-PD for qemu-devel@nongnu.org; Sat, 10 Feb 2007 07:36:19 -0500 Received: from [199.232.76.173] (helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1HFrSk-0008O2-JA for qemu-devel@nongnu.org; Sat, 10 Feb 2007 07:36:18 -0500 Received: from centrmmtao03.cox.net ([70.168.83.81]) by monty-python.gnu.org with esmtp (Exim 4.52) id 1HFrSk-0001EQ-3o for qemu-devel@nongnu.org; Sat, 10 Feb 2007 07:36:18 -0500 Received: from eastrmimpo02.cox.net ([68.1.16.120]) by centrmmtao03.cox.net (InterMail vM.6.01.06.03 201-2131-130-104-20060516) with ESMTP id <20070210123617.CKLK13993.centrmmtao03.cox.net@eastrmimpo02.cox.net> for ; Sat, 10 Feb 2007 07:36:17 -0500 Message-ID: <24999020.1171110977264.JavaMail.root@eastrmwml08.mgt.cox.net> Date: Sat, 10 Feb 2007 7:36:17 -0500 From: Ben Taylor MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="----=_Part_11632_8961580.1171110977219" Subject: [Qemu-devel] Patch: solaris TAP patch Reply-To: sol10x86@cox.net, qemu-devel@nongnu.org List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: Qemu-devel@nongnu.org ------=_Part_11632_8961580.1171110977219 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 7bit This patch is to allow solaris to create a tap device in qemu, using the modified tun/tap driver at http://www.whiteboard.ne.jp/~admin2/tuntap. I'm also including qemu_tap.c which is a setuid wrapper which sets up the tap, uses /etc/qemu-ifup (included - modify for your environment) and a start script (dsl.sh, minimal, but shows what needs done). To build qemu_tap, it's very simple. gcc -o qemu_tap qemu_tap.c sudo chown root qemu_tap sudo chmod 4755 qemu_tap The bridge code at http://www.whiteboard.ne.jp/~admin2/tuntap should also work, and should only require /etc/qemu-ifup to contain the commands to add the bridge, ie, no ifconfig should be needed. ------=_Part_11632_8961580.1171110977219 Content-Type: application/octet-stream; name=qemu-solaris-tap-patch Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename=qemu-solaris-tap-patch diff -ruN qemu-ORIG/vl.c qemu/vl.c --- qemu-ORIG/vl.c 2007-02-08 18:09:59.000000000 -0500 +++ qemu/vl.c 2007-02-10 07:20:48.696807000 -0500 @@ -55,6 +55,21 @@ #include #include #include +#else +#include +#include +#include +#include +#include +#include +#include +#include +#include // must come after ip.h +#include +#include +#include +#include +#include #endif #endif #endif @@ -3239,10 +3254,138 @@ return fd; } #elif defined(__sun__) +#define TUNNEWPPA (('T'<<16) | 0x0001) +/* + * Allocate TAP device, returns opened fd. + * Stores dev name in the first arg(must be large enough). + */ +int tap_alloc(char *dev) +{ + int tap_fd, if_fd, ppa = -1; + static int ip_fd = 0; + char *ptr; + + static int arp_fd = 0; + int ip_muxid, arp_muxid; + struct strioctl strioc_if, strioc_ppa; + int link_type = I_PLINK;; + struct lifreq ifr; + char actual_name[32] = ""; + + memset(&ifr, 0x0, sizeof(ifr)); + + if( *dev ){ + ptr = dev; + while( *ptr && !isdigit((int)*ptr) ) ptr++; + ppa = atoi(ptr); + } + + /* Check if IP device was opened */ + if( ip_fd ) + close(ip_fd); + + if( (ip_fd = open("/dev/udp", O_RDWR, 0)) < 0){ + syslog(LOG_ERR, "Can't open /dev/ip (actually /dev/udp)"); + return -1; + } + + if( (tap_fd = open("/dev/tap", O_RDWR, 0)) < 0){ + syslog(LOG_ERR, "Can't open /dev/tap"); + return -1; + } + + /* Assign a new PPA and get its unit number. */ + strioc_ppa.ic_cmd = TUNNEWPPA; + strioc_ppa.ic_timout = 0; + strioc_ppa.ic_len = sizeof(ppa); + strioc_ppa.ic_dp = (char *)&ppa; + if ((ppa = ioctl (tap_fd, I_STR, &strioc_ppa)) < 0) + syslog (LOG_ERR, "Can't assign new interface"); + + if( (if_fd = open("/dev/tap", O_RDWR, 0)) < 0){ + syslog(LOG_ERR, "Can't open /dev/tap (2)"); + return -1; + } + if(ioctl(if_fd, I_PUSH, "ip") < 0){ + syslog(LOG_ERR, "Can't push IP module"); + return -1; + } + + if (ioctl(if_fd, SIOCGLIFFLAGS, &ifr) < 0) + syslog(LOG_ERR, "Can't get flags\n"); + + snprintf (actual_name, 32, "tap%d", ppa); + strncpy (ifr.lifr_name, actual_name, sizeof (ifr.lifr_name)); + + ifr.lifr_ppa = ppa; + /* Assign ppa according to the unit number returned by tun device */ + + if (ioctl (if_fd, SIOCSLIFNAME, &ifr) < 0) + syslog (LOG_ERR, "Can't set PPA %d", ppa); + if (ioctl(if_fd, SIOCGLIFFLAGS, &ifr) <0) + syslog (LOG_ERR, "Can't get flags\n"); + /* Push arp module to if_fd */ + if (ioctl (if_fd, I_PUSH, "arp") < 0) + syslog (LOG_ERR, "Can't push ARP module (2)"); + + /* Push arp module to ip_fd */ + if (ioctl (ip_fd, I_POP, NULL) < 0) + syslog (LOG_ERR, "I_POP failed\n"); + if (ioctl (ip_fd, I_PUSH, "arp") < 0) + syslog (LOG_ERR, "Can't push ARP module (3)\n"); + /* Open arp_fd */ + if ((arp_fd = open ("/dev/tap", O_RDWR, 0)) < 0) + syslog (LOG_ERR, "Can't open %s\n", "/dev/tap"); + /* Push arp module to arp_fd */ + if (ioctl (arp_fd, I_PUSH, "arp") < 0) + syslog (LOG_ERR, "Can't push ARP module (3)\n"); + + /* Set ifname to arp */ + strioc_if.ic_cmd = SIOCSLIFNAME; + strioc_if.ic_timout = 0; + strioc_if.ic_len = sizeof(ifr); + strioc_if.ic_dp = (char *)𝔦 + if (ioctl(arp_fd, I_STR, &strioc_if) < 0){ + syslog (LOG_ERR, "Can't set ifname to arp\n"); + } + + if((ip_muxid = ioctl(ip_fd, I_LINK, if_fd)) < 0){ + syslog(LOG_ERR, "Can't link TAP device to IP"); + return -1; + } + + if ((arp_muxid = ioctl (ip_fd, link_type, arp_fd)) < 0) + syslog (LOG_ERR, "Can't link TAP device to ARP"); + + close (if_fd); + + memset(&ifr, 0x0, sizeof(ifr)); + strncpy (ifr.lifr_name, actual_name, sizeof (ifr.lifr_name)); + ifr.lifr_ip_muxid = ip_muxid; + ifr.lifr_arp_muxid = arp_muxid; + + if (ioctl (ip_fd, SIOCSLIFMUXID, &ifr) < 0) + { + ioctl (ip_fd, I_PUNLINK , arp_muxid); + ioctl (ip_fd, I_PUNLINK, ip_muxid); + syslog (LOG_ERR, "Can't set multiplexor id"); + } + + sprintf(dev, "tap%d", ppa); + return tap_fd; +} + static int tap_open(char *ifname, int ifname_size) { - fprintf(stderr, "warning: tap_open not yet implemented\n"); - return -1; + char dev[10]=""; + int fd; + if( (fd = tap_alloc(dev)) < 0 ){ + fprintf(stderr, "Cannot allocate TAP device\n"); + return -1; + } + pstrcpy(ifname, ifname_size, dev); + fcntl(fd, F_SETFL, O_NONBLOCK); + return fd; } #else static int tap_open(char *ifname, int ifname_size) ------=_Part_11632_8961580.1171110977219 Content-Type: application/octet-stream; name=qemu-ifup Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename=qemu-ifup #!/bin/ksh # /etc/qemu-if: QEMU's TUN network setup script for Solaris # $1 = tun0, tun1, ... if [ -z "$1" ] then echo "Usage: $0 interface" exit 1 fi DEV=${1%%[0-9]} PPA=${1##*[a-z]} NETMASK="255.255.255.0" case "$OS" in s10) HOST_IP="192.168.1.25$PPA" GUEST_IP="192.168.1.1$PPA" ;; winxp) HOST_IP="192.168.2.250" GUEST_IP="192.168.2.10" ;; win2k3) HOST_IP="192.168.3.250" GUEST_IP="192.168.3.10" ;; *) HOST_IP="192.168.1.25$PPA" GUEST_IP="192.168.1.1$PPA" ;; esac set -x /sbin/ifconfig $1 $HOST_IP destination $GUEST_IP netmask $NETMASK up exit $? ------=_Part_11632_8961580.1171110977219 Content-Type: text/x-csrc; name=qemu_tap.c Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename=qemu_tap.c /* ** qemu_tap.c: SUID wrapper program to allow non-root user to use tap network ** on Solaris, derived from qemu_tun.c by Sittichai Palansong ** with guidance from the tap code he wrote in qemu/vl.c ** ** Modified by: Ben Taylor ** Updated: 02/09/2007 ** ** Author: Sittichai Palanisong ** Updated: 05/20/2005 ** ** You are expected to be able to write a shell script wrapper to invoke ** qemu with the right parameters for a tap device passed in as a file ** descriptor. SUID privileges are only for setting the TAP device up for use. ** */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_NETINET_IN_H #include #endif #ifdef HAVE_NETINET_IN_SYSTM_H #include #endif #ifdef HAVE_NETINET_IP_H #include #endif #ifdef HAVE_NETINET_TCP_H #include #endif #define TUNNEWPPA (('T'<<16) | 0x0001) int main(int argc, char *argv[]) { char buf[2048], ifname[10]=""; int fd, len; int uid, pid, status; char tap_fd[32]; char *args[4]; char *qemu_script = "./qemu.sh"; char *network_script = "/etc/qemu-ifup"; if(argc > 1){ qemu_script = argv[1]; } uid = getuid(); if( (fd = tap_alloc(ifname)) < 0 ){ printf("Cannot allocate TAP device\n"); exit(1); } /* try to launch network init script */ args[0] = network_script; args[1] = ifname; args[2] = NULL; pid = fork(); if (pid >= 0) { if (pid == 0) { /* child */ execv(network_script, args); exit(1); } /* parent */ while (waitpid(pid, &status, 0) != pid); if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { fprintf(stderr, "%s: could not launch network script\n", network_script); exit(1); } } /* now switch to back to calling user */ if(setuid( uid) < 0){ printf("Cannot switch to UID %d\n", uid); exit(1); } printf("Switch to UID %d\n", uid); /* try to launch qemu script*/ sprintf( tap_fd, "%d", fd); args[0] = qemu_script; args[1] = "-t"; args[2] = tap_fd; args[3] = NULL; printf("Invoking %s %s %s\n", args[0], args[1], args[2]); execv( qemu_script, args); exit(1); } /* * Allocate TAP device, returns opened fd. * Stores dev name in the first arg(must be large enough). */ int tap_alloc(char *dev) { int tap_fd, if_fd, ppa = -1; static int ip_fd = 0; char *ptr; static int arp_fd = 0; int ip_muxid, arp_muxid; struct strioctl strioc_if, strioc_ppa; int link_type = I_PLINK;; struct lifreq ifr; char actual_name[32] = ""; memset(&ifr, 0x0, sizeof(ifr)); if ( *dev ) { ptr = dev; while ( *ptr && !isdigit((int)*ptr) ) ptr++; ppa = atoi(ptr); } /* Check if IP device was opened */ if ( ip_fd ) close(ip_fd); if ( (ip_fd = open("/dev/udp", O_RDWR, 0)) < 0 ) { syslog(LOG_ERR, "Can't open /dev/udp"); return -1; } if ( (tap_fd = open("/dev/tap", O_RDWR, 0)) < 0 ) { syslog(LOG_ERR, "Can't open /dev/tap"); return -1; } /* Assign a new PPA and get its unit number. */ strioc_ppa.ic_cmd = TUNNEWPPA; strioc_ppa.ic_timout = 0; strioc_ppa.ic_len = sizeof(ppa); strioc_ppa.ic_dp = (char *)&ppa; if ( (ppa = ioctl (tap_fd, I_STR, &strioc_ppa)) < 0 ) syslog (LOG_ERR, "Can't assign new interface"); if ( (if_fd = open("/dev/tap", O_RDWR, 0)) < 0 ) { syslog(LOG_ERR, "Can't open /dev/tap (2)"); return -1; } if ( ioctl(if_fd, I_PUSH, "ip") < 0 ) { syslog(LOG_ERR, "Can't push IP module"); return -1; } if ( ioctl(if_fd, SIOCGLIFFLAGS, &ifr) < 0 ) syslog(LOG_ERR, "Can't get flags\n"); snprintf (actual_name, 32, "tap%d", ppa); strncpy (ifr.lifr_name, actual_name, sizeof (ifr.lifr_name)); ifr.lifr_ppa = ppa; /* Assign ppa according to the unit number returned by tun device */ if ( ioctl (if_fd, SIOCSLIFNAME, &ifr) < 0 ) syslog (LOG_ERR, "Can't set PPA %d", ppa); if ( ioctl(if_fd, SIOCGLIFFLAGS, &ifr) < 0 ) syslog (LOG_ERR, "Can't get flags\n"); /* Push arp module to if_fd */ if ( ioctl (if_fd, I_PUSH, "arp") < 0 ) syslog (LOG_ERR, "Can't push ARP module (2)"); /* Push arp module to ip_fd */ if ( ioctl (ip_fd, I_POP, NULL) < 0 ) syslog (LOG_ERR, "I_POP failed\n"); if ( ioctl (ip_fd, I_PUSH, "arp") < 0 ) syslog (LOG_ERR, "Can't push ARP module (3)\n"); /* Open arp_fd */ if ( (arp_fd = open ("/dev/tap", O_RDWR, 0)) < 0 ) syslog (LOG_ERR, "Can't open /dev/tap (3)"); /* Push arp module to arp_fd */ if ( ioctl (arp_fd, I_PUSH, "arp") < 0 ) syslog (LOG_ERR, "Can't push ARP module (4)\n"); /* Set ifname to arp */ strioc_if.ic_cmd = SIOCSLIFNAME; strioc_if.ic_timout = 0; strioc_if.ic_len = sizeof(ifr); strioc_if.ic_dp = (char *)𝔦 if ( ioctl(arp_fd, I_STR, &strioc_if) < 0 ) { syslog (LOG_ERR, "Can't set ifname to arp\n"); } if ( (ip_muxid = ioctl(ip_fd, I_LINK, if_fd)) < 0 ) { syslog(LOG_ERR, "Can't link TAP device to IP"); return -1; } if ( (arp_muxid = ioctl (ip_fd, link_type, arp_fd)) < 0 ) syslog (LOG_ERR, "Can't link TAP device to ARP"); close (if_fd); memset(&ifr, 0x0, sizeof(ifr)); strncpy (ifr.lifr_name, actual_name, sizeof (ifr.lifr_name)); ifr.lifr_ip_muxid = ip_muxid; ifr.lifr_arp_muxid = arp_muxid; if ( ioctl (ip_fd, SIOCSLIFMUXID, &ifr) < 0 ) { ioctl (ip_fd, I_PUNLINK , arp_muxid); ioctl (ip_fd, I_PUNLINK, ip_muxid); syslog (LOG_ERR, "Can't set multiplexor id"); } sprintf(dev, "tap%d", ppa); return tap_fd; } ------=_Part_11632_8961580.1171110977219 Content-Type: application/x-sh; name=dsl.sh Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename=dsl.sh #!/bin/ksh -x # qemu.sh: QEMU wrapper script # updated: 05/09/05 #LD_LIBRARY_PATH=/opt/csw/gcc3/lib:/opt/csw/lib:/usr/local/lib:/usr/lib #export LD_LIBRARY_PATH SCRIPT=${0##*/} OS=${SCRIPT%.sh} export OS AUDIO="" NETWORK="" OPTS="-k en-us" NICS="" # Boot: c-HD d-CDROM BOOT="d" #BOOT="d" MEM=256 HDIMG="$OS.img" #FDIMG="floppy.img" CDROM="$OS.iso" #CDROM="/dev/dsk/c1t0d0s2" VM="$OS.vm" if [ -f $VM ] then if [ $VM -ot $HDIMG ] then echo "Attention: VM file $VM is older than image file $HDIMG" exit 1 fi OPTS="$OPTS -loadvm $VM" fi QEMU="/tmp/qemu/bin/qemu" while getopts ab:c:df:h:i:m:nt: name do case $name in a) AUDIO="-enable-audio" ;; b) BOOT="$OPTARG" ;; c) CDROM="$OPTARG" ;; d) QEMU=/tmp/qemutest/bin/qemu ;; f) FDIMG="$OPTARG" ;; h) HDIMG="$OPTARG" ;; i) NICS="$OPTARG" ;; m) MEM="$OPTARG" ;; t) TAP_FD="$OPTARG" OPTS="$OPTS -net nic,model=rtl8139 -net tap,fd=${TAP_FD}" ;; ?) printf "Usage: %s: options ...\n" $0 echo "options:" echo "\t-a # Enable audio (default: ${AUDIO:-disable})" echo "\t-b c|d # Boot from c=HD, d=CD (default: $BOOT)" echo "\t-c file # CDROM device (default: $CDROM)" echo "\t-d # Debug" echo "\t-f file # FD image (default: $FDIMG)" echo "\t-h file # HD image (default: $HDIMG)" echo "\t-i num # Number of LAN card (default: $NICS)" echo "\t-m megs # Memory size in megabytes (default: $MEM)" echo "\t-n # Use user network (default: ${NETWORK:-TAP})" echo "\t-t num # TAP FD (default: ${TAP_FD})" exit 2 ;; esac done set -x priocntl -s -c IA $$ exec $QEMU \ $AUDIO $NETWORK -localtime \ -hda $HDIMG -cdrom $CDROM \ -boot $BOOT -m $MEM $OPTS ------=_Part_11632_8961580.1171110977219--