From: Ben Taylor <sol10x86@cox.net>
To: Qemu-devel@nongnu.org
Subject: [Qemu-devel] Patch: solaris TAP patch
Date: Sat, 10 Feb 2007 7:36:17 -0500 [thread overview]
Message-ID: <24999020.1171110977264.JavaMail.root@eastrmwml08.mgt.cox.net> (raw)
[-- 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 --]
next reply other threads:[~2007-02-10 12:36 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-02-10 12:36 Ben Taylor [this message]
-- strict thread matches above, loose matches on Subject: below --
2007-02-10 13:29 [Qemu-devel] Patch: solaris TAP patch Ben Taylor
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=24999020.1171110977264.JavaMail.root@eastrmwml08.mgt.cox.net \
--to=sol10x86@cox.net \
--cc=Qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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.