* 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 *)𝔦
+ 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 *)𝔦
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.