qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH 2/3] Add unix domain socket and interface restrictio


From: Anthony Liguori
Subject: [Qemu-devel] [PATCH 2/3] Add unix domain socket and interface restriction to VNC
Date: Sat, 16 Dec 2006 12:04:50 -0600
User-agent: Thunderbird 1.5.0.8 (X11/20061115)

The following patch allows a user to restrict which interface the VNC server will listen on. It also adds unix domain socket support to VNC.

N.B. The old syntax of:

qemu -vnc 1

Is now:

qemu -vnc :1

Also, the syntax between the unix char devices and VNC is a bit different. This is because the current VNC server does not support reverse connections. I don't really think supporting reverse connections is all that useful so I'm happy to leave it this way.

Some example usages:

qemu -hda ~/win2k.img -vnc :1 # listen on 0.0.0.0:5901 TCP
qemu -hda ~/win2k.img -vnc 192.168.1.0:1 # listen on 192.168.1.0:5901 TCP
qemu -hda ~/win2k.img -vnc unix:/home/anthony/vga.sock # listen on unix socket /home/anthony/vga.sock

Regards,

Anthony Liguori
diff -r 9b429747f69c qemu-doc.texi
--- a/qemu-doc.texi     Sat Dec 16 11:45:18 2006 -0600
+++ b/qemu-doc.texi     Sat Dec 16 11:50:07 2006 -0600
@@ -247,14 +247,21 @@ the console. Therefore, you can still us
 the console. Therefore, you can still use QEMU to debug a Linux kernel
 with a serial console.
 
address@hidden -vnc d
address@hidden -vnc display
 
 Normally, QEMU uses SDL to display the VGA output.  With this option,
-you can have QEMU listen on VNC display @var{d} and redirect the VGA
+you can have QEMU listen on VNC display @var{display} and redirect the VGA
 display over the VNC session.  It is very useful to enable the usb
 tablet device when using this option (option @option{-usbdevice
 tablet}). When using the VNC display, you must use the @option{-k}
-option to set the keyboard layout.
+option to set the keyboard layout if you are not using en-us.
+
address@hidden may be in the form @var{interface:d}, in which case connections
+will only be allowed from @var{interface} on display @var{d}. Optionally,
address@hidden can be omitted.  @var{display} can also be in the form
address@hidden:path} where @var{path} is the location of a unix socket to 
listen for
+connections on.
+
 
 @item -k language
 
diff -r 9b429747f69c vl.c
--- a/vl.c      Sat Dec 16 11:45:18 2006 -0600
+++ b/vl.c      Sat Dec 16 11:49:32 2006 -0600
@@ -152,7 +152,7 @@ int usb_enabled = 0;
 int usb_enabled = 0;
 static VLANState *first_vlan;
 int smp_cpus = 1;
-int vnc_display = -1;
+const char *vnc_display;
 #if defined(TARGET_SPARC)
 #define MAX_CPUS 16
 #elif defined(TARGET_I386)
@@ -6818,11 +6818,7 @@ int main(int argc, char **argv)
                 }
                 break;
            case QEMU_OPTION_vnc:
-               vnc_display = atoi(optarg);
-               if (vnc_display < 0) {
-                   fprintf(stderr, "Invalid VNC display\n");
-                   exit(1);
-               }
+               vnc_display = optarg;
                break;
             case QEMU_OPTION_no_acpi:
                 acpi_enabled = 0;
@@ -6946,7 +6942,7 @@ int main(int argc, char **argv)
     /* terminal init */
     if (nographic) {
         dumb_display_init(ds);
-    } else if (vnc_display != -1) {
+    } else if (vnc_display != NULL) {
        vnc_display_init(ds, vnc_display);
     } else {
 #if defined(CONFIG_SDL)
diff -r 9b429747f69c vl.h
--- a/vl.h      Sat Dec 16 11:45:18 2006 -0600
+++ b/vl.h      Sat Dec 16 11:45:25 2006 -0600
@@ -867,7 +867,7 @@ void cocoa_display_init(DisplayState *ds
 void cocoa_display_init(DisplayState *ds, int full_screen);
 
 /* vnc.c */
-void vnc_display_init(DisplayState *ds, int display);
+void vnc_display_init(DisplayState *ds, const char *display);
 
 /* ide.c */
 #define MAX_DISKS 4
diff -r 9b429747f69c vnc.c
--- a/vnc.c     Sat Dec 16 11:45:18 2006 -0600
+++ b/vnc.c     Sat Dec 16 11:45:25 2006 -0600
@@ -1101,10 +1101,18 @@ static void vnc_listen_read(void *opaque
     }
 }
 
-void vnc_display_init(DisplayState *ds, int display)
-{
-    struct sockaddr_in addr;
+extern int parse_host_port(struct sockaddr_in *saddr, const char *str);
+
+void vnc_display_init(DisplayState *ds, const char *arg)
+{
+    struct sockaddr *addr;
+    struct sockaddr_in iaddr;
+#ifndef _WIN32
+    struct sockaddr_un uaddr;
+#endif
     int reuse_addr, ret;
+    socklen_t addrlen;
+    const char *p;
     VncState *vs;
 
     vs = qemu_mallocz(sizeof(VncState));
@@ -1125,39 +1133,6 @@ void vnc_display_init(DisplayState *ds, 
     vs->kbd_layout = init_keyboard_layout(keyboard_layout);
     if (!vs->kbd_layout)
        exit(1);
-
-    vs->lsock = socket(PF_INET, SOCK_STREAM, 0);
-    if (vs->lsock == -1) {
-       fprintf(stderr, "Could not create socket\n");
-       exit(1);
-    }
-
-    addr.sin_family = AF_INET;
-    addr.sin_port = htons(5900 + display);
-    memset(&addr.sin_addr, 0, sizeof(addr.sin_addr));
-
-    reuse_addr = 1;
-    ret = setsockopt(vs->lsock, SOL_SOCKET, SO_REUSEADDR,
-                    (const char *)&reuse_addr, sizeof(reuse_addr));
-    if (ret == -1) {
-       fprintf(stderr, "setsockopt() failed\n");
-       exit(1);
-    }
-
-    if (bind(vs->lsock, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
-       fprintf(stderr, "bind() failed\n");
-       exit(1);
-    }
-
-    if (listen(vs->lsock, 1) == -1) {
-       fprintf(stderr, "listen() failed\n");
-       exit(1);
-    }
-
-    ret = qemu_set_fd_handler2(vs->lsock, vnc_listen_poll, vnc_listen_read, 
NULL, vs);
-    if (ret == -1) {
-       exit(1);
-    }
 
     vs->ds->data = NULL;
     vs->ds->dpy_update = vnc_dpy_update;
@@ -1167,4 +1142,63 @@ void vnc_display_init(DisplayState *ds, 
     memset(vs->dirty_row, 0xFF, sizeof(vs->dirty_row));
 
     vnc_dpy_resize(vs->ds, 640, 400);
-}
+
+#ifndef _WIN32
+    if (strstart(arg, "unix:", &p)) {
+       addr = (struct sockaddr *)&uaddr;
+       addrlen = sizeof(uaddr);
+
+       vs->lsock = socket(PF_UNIX, SOCK_STREAM, 0);
+       if (vs->lsock == -1) {
+           fprintf(stderr, "Could not create socket\n");
+           exit(1);
+       }
+
+       uaddr.sun_family = AF_UNIX;
+       memset(uaddr.sun_path, 0, 108);
+       snprintf(uaddr.sun_path, 108, "%s", p);
+
+       unlink(uaddr.sun_path);
+    } else
+#endif
+    {
+       addr = (struct sockaddr *)&iaddr;
+       addrlen = sizeof(iaddr);
+
+       vs->lsock = socket(PF_INET, SOCK_STREAM, 0);
+       if (vs->lsock == -1) {
+           fprintf(stderr, "Could not create socket\n");
+           exit(1);
+       }
+
+       if (parse_host_port(&iaddr, arg) < 0) {
+           fprintf(stderr, "Could not parse VNC address\n");
+           exit(1);
+       }
+           
+       iaddr.sin_port = htons(ntohs(iaddr.sin_port) + 5900);
+
+       reuse_addr = 1;
+       ret = setsockopt(vs->lsock, SOL_SOCKET, SO_REUSEADDR,
+                        (const char *)&reuse_addr, sizeof(reuse_addr));
+       if (ret == -1) {
+           fprintf(stderr, "setsockopt() failed\n");
+           exit(1);
+       }
+    }
+
+    if (bind(vs->lsock, addr, addrlen) == -1) {
+       fprintf(stderr, "bind() failed\n");
+       exit(1);
+    }
+
+    if (listen(vs->lsock, 1) == -1) {
+       fprintf(stderr, "listen() failed\n");
+       exit(1);
+    }
+
+    ret = qemu_set_fd_handler2(vs->lsock, vnc_listen_poll, vnc_listen_read, 
NULL, vs);
+    if (ret == -1) {
+       exit(1);
+    }
+}

reply via email to

[Prev in Thread] Current Thread [Next in Thread]