All of lore.kernel.org
 help / color / mirror / Atom feed
* Re: [Qemu-devel] Patch: solaris TAP patch
@ 2007-02-10 13:29 Ben Taylor
  0 siblings, 0 replies; 2+ messages in thread
From: Ben Taylor @ 2007-02-10 13:29 UTC (permalink / raw)
  To: qemu-devel



Attribution for the TAP patch goes to Sittichai Palanisong 
(palanisong@yahoo.com).    The qemu_tap.c is a derivitive
work of a previous version called qemu_tun.c, and the scripts
are also by Sittichai with derivations by me.

---- Ben Taylor <sol10x86@cox.net> wrote: 
> 
> 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.

^ permalink raw reply	[flat|nested] 2+ messages in thread

* [Qemu-devel] Patch: solaris TAP patch
@ 2007-02-10 12:36 Ben Taylor
  0 siblings, 0 replies; 2+ messages in thread
From: Ben Taylor @ 2007-02-10 12:36 UTC (permalink / raw)
  To: Qemu-devel

[-- Attachment #1: Type: text/plain, Size: 665 bytes --]


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.

[-- Attachment #2: qemu-solaris-tap-patch --]
[-- Type: application/octet-stream, Size: 4845 bytes --]

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 <malloc.h>
 #include <linux/rtc.h>
 #include <linux/ppdev.h>
+#else
+#include <sys/stat.h>
+#include <sys/ethernet.h>
+#include <sys/sockio.h>
+#include <arpa/inet.h>
+#include <netinet/arp.h>
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/ip_icmp.h> // must come after ip.h
+#include <netinet/udp.h>
+#include <netinet/tcp.h>
+#include <net/if.h>
+#include <syslog.h>
+#include <stropts.h>
 #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 *)&ifr;
+    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)

[-- Attachment #3: qemu-ifup --]
[-- Type: application/octet-stream, Size: 562 bytes --]

#!/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 $?

[-- Attachment #4: qemu_tap.c --]
[-- Type: text/x-csrc, Size: 6231 bytes --]

/*
** 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 <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdarg.h>
#include <sys/time.h>
#include <sys/wait.h>
#include <syslog.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/sockio.h>
#include <sys/ioctl.h>
#include <errno.h>
#include <signal.h>
#include <stropts.h>
#include <net/if.h>

#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
#endif

#ifdef HAVE_NETINET_IN_SYSTM_H
#include <netinet/in_systm.h>
#endif

#ifdef HAVE_NETINET_IP_H
#include <netinet/ip.h>
#endif

#ifdef HAVE_NETINET_TCP_H
#include <netinet/tcp.h>
#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 *)&ifr;
    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;
}

[-- Attachment #5: dsl.sh --]
[-- Type: application/x-sh, Size: 1806 bytes --]

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2007-02-10 13:29 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-02-10 13:29 [Qemu-devel] Patch: solaris TAP patch Ben Taylor
  -- strict thread matches above, loose matches on Subject: below --
2007-02-10 12:36 Ben Taylor

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.