slirp: -nooutgoing
authorAndreas Färber <afaerber@suse.de>
Wed, 29 Aug 2012 16:42:56 +0000 (18:42 +0200)
committerhyokeun <hyokeun.jeon@samsung.com>
Tue, 6 Sep 2016 06:55:33 +0000 (15:55 +0900)
TBD (from SUSE Studio team)

qemu-options.hx
slirp/socket.c
slirp/tcp_subr.c
vl.c

index a71aaf8..7f32069 100644 (file)
@@ -3132,6 +3132,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
index 280050a..4fe68bb 100644 (file)
@@ -608,6 +608,8 @@ sorecvfrom(struct socket *so)
        } /* if ping packet */
 }
 
+extern int slirp_nooutgoing;
+
 /*
  * sendto() a socket
  */
@@ -625,6 +627,12 @@ sosendto(struct socket *so, struct mbuf *m)
        DEBUG_CALL(" sendto()ing)");
        sotranslate_out(so, &addr);
 
+       /* Only allow DNS requests */
+       if (slirp_nooutgoing && ntohs(((struct sockaddr_in *)&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, sockaddr_size(&addr));
index ed16e18..b2c7a8c 100644 (file)
@@ -391,6 +391,8 @@ 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, unsigned short af)
 {
   int ret=0;
@@ -398,6 +400,11 @@ int tcp_fconnect(struct socket *so, unsigned short af)
   DEBUG_CALL("tcp_fconnect");
   DEBUG_ARG("so = %p", so);
 
+  if (slirp_nooutgoing) {
+    errno = EHOSTUNREACH;
+    return -1;
+  }
+
   ret = so->s = qemu_socket(af, SOCK_STREAM, 0);
   if (ret >= 0) {
     int opt, s=so->s;
@@ -478,6 +485,11 @@ void tcp_connect(struct socket *inso)
         tcp_close(sototcpcb(so)); /* This will sofree() as well */
         return;
     }
+    if (slirp_nooutgoing && ((struct sockaddr_in *)&addr)->sin_addr.s_addr != slirp_nooutgoing) {
+        tcp_close(sototcpcb(so)); /* This will sofree() as well */
+        closesocket(s);
+        return;
+    }
     qemu_set_nonblock(s);
     socket_set_fast_reuse(s);
     opt = 1;
diff --git a/vl.c b/vl.c
index b3c80d5..1b8e591 100644 (file)
--- a/vl.c
+++ b/vl.c
@@ -160,6 +160,7 @@ int smp_threads = 1;
 int acpi_enabled = 1;
 int no_hpet = 0;
 int fd_bootchk = 1;
+int slirp_nooutgoing = 0;
 static int no_reboot;
 int no_shutdown = 0;
 int cursor_hide = 1;
@@ -3363,6 +3364,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;