From 2ae0060bdee3c7a3ae14d3d322c577551d451a91 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 5 Aug 2009 17:26:39 +0000 Subject: [PATCH] * qemu-kvm: a quick hack to support connecting a Unix domain socket on the host to a TCP port on the guest. This will be useful for automated testing using QEMU virtual machines. Using TCP ports on the host is insecure and hard to manage (since you need to pick an available host port). For example: $ qemu-system-x86_64 ... -redir tcp:65535::514 creates a Unix domain socket `./65535.socket' on the host. (There is no proper syntax yet, so as a hack all host "ports" above 0xff00 are treated in this way.) Connections to that socket are then forwarded to TCP port 514 on the guest. So the guest can do $ nc -l -p 514 -e /bin/sh to execute a shell for incoming connections on port 514, and then the host can do $ socat stdio ./65535.socket to run a shell on the guest. svn path=/nixpkgs/trunk/; revision=16593 --- pkgs/os-specific/linux/qemu-kvm/default.nix | 2 + .../linux/qemu-kvm/unix-domain.patch | 82 +++++++++++++++++++ 2 files changed, 84 insertions(+) create mode 100644 pkgs/os-specific/linux/qemu-kvm/unix-domain.patch diff --git a/pkgs/os-specific/linux/qemu-kvm/default.nix b/pkgs/os-specific/linux/qemu-kvm/default.nix index 9aad2cc587a..44b6c617d35 100644 --- a/pkgs/os-specific/linux/qemu-kvm/default.nix +++ b/pkgs/os-specific/linux/qemu-kvm/default.nix @@ -10,6 +10,8 @@ stdenv.mkDerivation rec { sha256 = "0gmz42ckjjv6p9fd767k1sqh319aplsddschjp86m526d082rik9"; }; + patches = [ ./unix-domain.patch ]; + buildInputs = [zlib SDL alsaLib pkgconfig pciutils]; preBuild = diff --git a/pkgs/os-specific/linux/qemu-kvm/unix-domain.patch b/pkgs/os-specific/linux/qemu-kvm/unix-domain.patch new file mode 100644 index 00000000000..26e133f1ebf --- /dev/null +++ b/pkgs/os-specific/linux/qemu-kvm/unix-domain.patch @@ -0,0 +1,82 @@ +diff -rc qemu-kvm-0.11.0-rc1-orig/slirp/socket.c qemu-kvm-0.11.0-rc1/slirp/socket.c +*** qemu-kvm-0.11.0-rc1-orig/slirp/socket.c 2009-08-02 15:38:42.000000000 +0200 +--- qemu-kvm-0.11.0-rc1/slirp/socket.c 2009-08-05 18:09:20.000000000 +0200 +*************** +*** 587,592 **** +--- 587,593 ---- + u_int lport, int flags) + { + struct sockaddr_in addr; ++ struct sockaddr_un addr_un; + struct socket *so; + int s, opt = 1; + socklen_t addrlen = sizeof(addr); +*************** +*** 621,633 **** + so->so_lport = lport; /* Kept in network format */ + so->so_laddr.s_addr = laddr; /* Ditto */ + +! addr.sin_family = AF_INET; +! addr.sin_addr.s_addr = haddr; +! addr.sin_port = hport; + +! if (((s = socket(AF_INET,SOCK_STREAM,0)) < 0) || + (setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(int)) < 0) || +! (bind(s,(struct sockaddr *)&addr, sizeof(addr)) < 0) || + (listen(s,1) < 0)) { + int tmperrno = errno; /* Don't clobber the real reason we failed */ + +--- 622,642 ---- + so->so_lport = lport; /* Kept in network format */ + so->so_laddr.s_addr = laddr; /* Ditto */ + +! int unix_socket = hport >= 0xff00; + +! if (unix_socket) { +! addr_un.sun_family = AF_UNIX; +! sprintf(addr_un.sun_path, "./%d.socket", hport); +! } else { +! addr.sin_family = AF_INET; +! addr.sin_addr.s_addr = haddr; +! addr.sin_port = hport; +! } +! +! if (((s = socket(unix_socket ? PF_UNIX : AF_INET, SOCK_STREAM, 0)) < 0) || + (setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(int)) < 0) || +! (bind(s, unix_socket ? (struct sockaddr *) &addr_un : (struct sockaddr *) &addr, +! unix_socket ? sizeof(addr_un) : sizeof(addr)) < 0) || + (listen(s,1) < 0)) { + int tmperrno = errno; /* Don't clobber the real reason we failed */ + +*************** +*** 643,654 **** + } + setsockopt(s,SOL_SOCKET,SO_OOBINLINE,(char *)&opt,sizeof(int)); + +! getsockname(s,(struct sockaddr *)&addr,&addrlen); +! so->so_fport = addr.sin_port; +! if (addr.sin_addr.s_addr == 0 || addr.sin_addr.s_addr == loopback_addr.s_addr) +! so->so_faddr = slirp->vhost_addr; +! else +! so->so_faddr = addr.sin_addr; + + so->s = s; + return so; +--- 652,668 ---- + } + setsockopt(s,SOL_SOCKET,SO_OOBINLINE,(char *)&opt,sizeof(int)); + +! if (unix_socket) { +! so->so_fport = haddr; +! so->so_faddr = slirp->vhost_addr; +! } else { +! getsockname(s,(struct sockaddr *)&addr,&addrlen); +! so->so_fport = addr.sin_port; +! if (addr.sin_addr.s_addr == 0 || addr.sin_addr.s_addr == loopback_addr.s_addr) +! so->so_faddr = slirp->vhost_addr; +! else +! so->so_faddr = addr.sin_addr; +! } + + so->s = s; + return so;