summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Färber <afaerber@suse.de>2012-08-29 18:42:56 +0200
committerAnas Nashif <anas.nashif@intel.com>2013-01-15 13:41:18 -0800
commitb41dd4dbc85e2d0003958a027fab9d887181a656 (patch)
tree35ed951cd882d9758c670e60b63db38aa9fdfec1
parent569d183aff5cf16102f573a96d5f5e7706b8d5dc (diff)
downloadqemu-b41dd4dbc85e2d0003958a027fab9d887181a656.tar.gz
qemu-b41dd4dbc85e2d0003958a027fab9d887181a656.tar.bz2
qemu-b41dd4dbc85e2d0003958a027fab9d887181a656.zip
slirp: -nooutgoing
TBD (from SUSE Studio team)
-rw-r--r--qemu-options.hx10
-rw-r--r--slirp/socket.c8
-rw-r--r--slirp/tcp_subr.c16
-rw-r--r--vl.c9
4 files changed, 43 insertions, 0 deletions
diff --git a/qemu-options.hx b/qemu-options.hx
index 94a1c50b7..9635327ae 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -2426,6 +2426,16 @@ Store the QEMU process PID in @var{file}. It is useful if you launch QEMU
from a script.
ETEXI
+DEF("nooutgoing", HAS_ARG, QEMU_OPTION_nooutgoing, \
+ "-nooutgoing <IP>\n" \
+ " incoming traffic only from IP, no outgoing\n", \
+ QEMU_ARCH_ALL)
+STEXI
+@item -nooutgoing
+Forbid userspace networking to make outgoing connections. Only accept incoming
+connections from ip address IP.
+ETEXI
+
DEF("singlestep", 0, QEMU_OPTION_singlestep, \
"-singlestep always run in singlestep mode\n", QEMU_ARCH_ALL)
STEXI
diff --git a/slirp/socket.c b/slirp/socket.c
index 77b0c9819..94dcd9a80 100644
--- a/slirp/socket.c
+++ b/slirp/socket.c
@@ -531,6 +531,8 @@ sorecvfrom(struct socket *so)
} /* if ping packet */
}
+extern int slirp_nooutgoing;
+
/*
* sendto() a socket
*/
@@ -561,6 +563,12 @@ sosendto(struct socket *so, struct mbuf *m)
DEBUG_MISC((dfd, " sendto()ing, addr.sin_port=%d, addr.sin_addr.s_addr=%.16s\n", ntohs(addr.sin_port), inet_ntoa(addr.sin_addr)));
+ /* Only allow DNS requests */
+ if (slirp_nooutgoing && ntohs(addr.sin_port) != 53) {
+ errno = EHOSTUNREACH;
+ return -1;
+ }
+
/* Don't care what port we get */
ret = sendto(so->s, m->m_data, m->m_len, 0,
(struct sockaddr *)&addr, sizeof (struct sockaddr));
diff --git a/slirp/tcp_subr.c b/slirp/tcp_subr.c
index 1542e4361..a25d94910 100644
--- a/slirp/tcp_subr.c
+++ b/slirp/tcp_subr.c
@@ -324,6 +324,9 @@ tcp_sockclosed(struct tcpcb *tp)
* nonblocking. Connect returns after the SYN is sent, and does
* not wait for ACK+SYN.
*/
+
+extern int slirp_nooutgoing;
+
int tcp_fconnect(struct socket *so)
{
Slirp *slirp = so->slirp;
@@ -332,6 +335,11 @@ int tcp_fconnect(struct socket *so)
DEBUG_CALL("tcp_fconnect");
DEBUG_ARG("so = %lx", (long )so);
+ if (slirp_nooutgoing) {
+ errno = EHOSTUNREACH;
+ return -1;
+ }
+
if( (ret = so->s = qemu_socket(AF_INET,SOCK_STREAM,0)) >= 0) {
int opt, s=so->s;
struct sockaddr_in addr;
@@ -424,6 +432,13 @@ tcp_connect(struct socket *inso)
tcp_close(sototcpcb(so)); /* This will sofree() as well */
return;
}
+
+ if (slirp_nooutgoing && addr.sin_addr.s_addr != slirp_nooutgoing) {
+ tcp_close(sototcpcb(so)); /* This will sofree() as well */
+ close(s);
+ return;
+ }
+
socket_set_nonblock(s);
opt = 1;
setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(int));
@@ -434,6 +449,7 @@ tcp_connect(struct socket *inso)
so->so_fport = addr.sin_port;
so->so_faddr = addr.sin_addr;
+
/* Translate connections from localhost to the real hostname */
if (so->so_faddr.s_addr == 0 ||
(so->so_faddr.s_addr & loopback_mask) ==
diff --git a/vl.c b/vl.c
index a13012e57..14fe97bb9 100644
--- a/vl.c
+++ b/vl.c
@@ -218,6 +218,7 @@ int acpi_enabled = 1;
int no_hpet = 0;
int fd_bootchk = 1;
static int no_reboot;
+int slirp_nooutgoing = 0;
int no_shutdown = 0;
int cursor_hide = 1;
int graphic_rotate = 0;
@@ -2969,6 +2970,14 @@ int main(int argc, char **argv, char **envp)
case QEMU_OPTION_singlestep:
singlestep = 1;
break;
+ case QEMU_OPTION_nooutgoing:
+ slirp_nooutgoing = inet_addr(optarg);
+ if (slirp_nooutgoing == INADDR_NONE) {
+ printf("Invalid address: %s.\nOnly addresses of the format "
+ "xxx.xxx.xxx.xxx are supported.\n", optarg);
+ exit(1);
+ }
+ break;
case QEMU_OPTION_S:
autostart = 0;
break;