Statistics
| Branch: | Revision:

root / vnc.c @ f5049756

History | View | Annotate | Download (65 kB)

1 7d510b8c bellard
/*
2 7d510b8c bellard
 * QEMU VNC display driver
3 5fafdf24 ths
 *
4 7d510b8c bellard
 * Copyright (C) 2006 Anthony Liguori <anthony@codemonkey.ws>
5 7d510b8c bellard
 * Copyright (C) 2006 Fabrice Bellard
6 5fafdf24 ths
 *
7 7d510b8c bellard
 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 7d510b8c bellard
 * of this software and associated documentation files (the "Software"), to deal
9 7d510b8c bellard
 * in the Software without restriction, including without limitation the rights
10 7d510b8c bellard
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 7d510b8c bellard
 * copies of the Software, and to permit persons to whom the Software is
12 7d510b8c bellard
 * furnished to do so, subject to the following conditions:
13 7d510b8c bellard
 *
14 7d510b8c bellard
 * The above copyright notice and this permission notice shall be included in
15 7d510b8c bellard
 * all copies or substantial portions of the Software.
16 7d510b8c bellard
 *
17 7d510b8c bellard
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 7d510b8c bellard
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 7d510b8c bellard
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 7d510b8c bellard
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 7d510b8c bellard
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 7d510b8c bellard
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 7d510b8c bellard
 * THE SOFTWARE.
24 7d510b8c bellard
 */
25 7d510b8c bellard
26 87ecb68b pbrook
#include "qemu-common.h"
27 87ecb68b pbrook
#include "console.h"
28 87ecb68b pbrook
#include "sysemu.h"
29 6ca957f0 bellard
#include "qemu_socket.h"
30 87ecb68b pbrook
#include "qemu-timer.h"
31 24236869 bellard
32 24236869 bellard
#define VNC_REFRESH_INTERVAL (1000 / 30)
33 24236869 bellard
34 24236869 bellard
#include "vnc_keysym.h"
35 24236869 bellard
#include "keymaps.c"
36 70848515 ths
#include "d3des.h"
37 70848515 ths
38 eb38c52c blueswir1
#ifdef CONFIG_VNC_TLS
39 8d5d2d4c ths
#include <gnutls/gnutls.h>
40 8d5d2d4c ths
#include <gnutls/x509.h>
41 8d5d2d4c ths
#endif /* CONFIG_VNC_TLS */
42 70848515 ths
43 8d5d2d4c ths
// #define _VNC_DEBUG 1
44 8d5d2d4c ths
45 eb38c52c blueswir1
#ifdef _VNC_DEBUG
46 70848515 ths
#define VNC_DEBUG(fmt, ...) do { fprintf(stderr, fmt, ## __VA_ARGS__); } while (0)
47 8d5d2d4c ths
48 8d5d2d4c ths
#if CONFIG_VNC_TLS && _VNC_DEBUG >= 2
49 8d5d2d4c ths
/* Very verbose, so only enabled for _VNC_DEBUG >= 2 */
50 8d5d2d4c ths
static void vnc_debug_gnutls_log(int level, const char* str) {
51 8d5d2d4c ths
    VNC_DEBUG("%d %s", level, str);
52 8d5d2d4c ths
}
53 8d5d2d4c ths
#endif /* CONFIG_VNC_TLS && _VNC_DEBUG */
54 70848515 ths
#else
55 70848515 ths
#define VNC_DEBUG(fmt, ...) do { } while (0)
56 70848515 ths
#endif
57 24236869 bellard
58 8d5d2d4c ths
59 24236869 bellard
typedef struct Buffer
60 24236869 bellard
{
61 24236869 bellard
    size_t capacity;
62 24236869 bellard
    size_t offset;
63 60fe76f3 ths
    uint8_t *buffer;
64 24236869 bellard
} Buffer;
65 24236869 bellard
66 24236869 bellard
typedef struct VncState VncState;
67 24236869 bellard
68 60fe76f3 ths
typedef int VncReadEvent(VncState *vs, uint8_t *data, size_t len);
69 24236869 bellard
70 3512779a bellard
typedef void VncWritePixels(VncState *vs, void *data, int size);
71 3512779a bellard
72 3512779a bellard
typedef void VncSendHextileTile(VncState *vs,
73 3512779a bellard
                                int x, int y, int w, int h,
74 7eac3a87 aliguori
                                void *last_bg,
75 7eac3a87 aliguori
                                void *last_fg,
76 3512779a bellard
                                int *has_bg, int *has_fg);
77 3512779a bellard
78 99589bdc bellard
#define VNC_MAX_WIDTH 2048
79 99589bdc bellard
#define VNC_MAX_HEIGHT 2048
80 99589bdc bellard
#define VNC_DIRTY_WORDS (VNC_MAX_WIDTH / (16 * 32))
81 99589bdc bellard
82 70848515 ths
#define VNC_AUTH_CHALLENGE_SIZE 16
83 70848515 ths
84 70848515 ths
enum {
85 70848515 ths
    VNC_AUTH_INVALID = 0,
86 70848515 ths
    VNC_AUTH_NONE = 1,
87 70848515 ths
    VNC_AUTH_VNC = 2,
88 70848515 ths
    VNC_AUTH_RA2 = 5,
89 70848515 ths
    VNC_AUTH_RA2NE = 6,
90 70848515 ths
    VNC_AUTH_TIGHT = 16,
91 70848515 ths
    VNC_AUTH_ULTRA = 17,
92 70848515 ths
    VNC_AUTH_TLS = 18,
93 70848515 ths
    VNC_AUTH_VENCRYPT = 19
94 70848515 ths
};
95 70848515 ths
96 eb38c52c blueswir1
#ifdef CONFIG_VNC_TLS
97 8d5d2d4c ths
enum {
98 8d5d2d4c ths
    VNC_WIREMODE_CLEAR,
99 8d5d2d4c ths
    VNC_WIREMODE_TLS,
100 8d5d2d4c ths
};
101 8d5d2d4c ths
102 8d5d2d4c ths
enum {
103 8d5d2d4c ths
    VNC_AUTH_VENCRYPT_PLAIN = 256,
104 8d5d2d4c ths
    VNC_AUTH_VENCRYPT_TLSNONE = 257,
105 8d5d2d4c ths
    VNC_AUTH_VENCRYPT_TLSVNC = 258,
106 8d5d2d4c ths
    VNC_AUTH_VENCRYPT_TLSPLAIN = 259,
107 8d5d2d4c ths
    VNC_AUTH_VENCRYPT_X509NONE = 260,
108 8d5d2d4c ths
    VNC_AUTH_VENCRYPT_X509VNC = 261,
109 8d5d2d4c ths
    VNC_AUTH_VENCRYPT_X509PLAIN = 262,
110 8d5d2d4c ths
};
111 3a702699 ths
112 3a702699 ths
#define X509_CA_CERT_FILE "ca-cert.pem"
113 3a702699 ths
#define X509_CA_CRL_FILE "ca-crl.pem"
114 3a702699 ths
#define X509_SERVER_KEY_FILE "server-key.pem"
115 3a702699 ths
#define X509_SERVER_CERT_FILE "server-cert.pem"
116 3a702699 ths
117 8d5d2d4c ths
#endif /* CONFIG_VNC_TLS */
118 8d5d2d4c ths
119 24236869 bellard
struct VncState
120 24236869 bellard
{
121 24236869 bellard
    QEMUTimer *timer;
122 24236869 bellard
    int lsock;
123 24236869 bellard
    int csock;
124 24236869 bellard
    DisplayState *ds;
125 24236869 bellard
    int need_update;
126 24236869 bellard
    int width;
127 24236869 bellard
    int height;
128 99589bdc bellard
    uint32_t dirty_row[VNC_MAX_HEIGHT][VNC_DIRTY_WORDS];
129 24236869 bellard
    char *old_data;
130 3512779a bellard
    int depth; /* internal VNC frame buffer byte per pixel */
131 24236869 bellard
    int has_resize;
132 24236869 bellard
    int has_hextile;
133 564c337e bellard
    int has_pointer_type_change;
134 ca4cca4d aliguori
    int has_WMVi;
135 564c337e bellard
    int absolute;
136 564c337e bellard
    int last_x;
137 564c337e bellard
    int last_y;
138 564c337e bellard
139 70848515 ths
    int major;
140 70848515 ths
    int minor;
141 70848515 ths
142 71cab5ca ths
    char *display;
143 70848515 ths
    char *password;
144 70848515 ths
    int auth;
145 eb38c52c blueswir1
#ifdef CONFIG_VNC_TLS
146 8d5d2d4c ths
    int subauth;
147 469b15c6 ths
    int x509verify;
148 6f43024c ths
149 6f43024c ths
    char *x509cacert;
150 6f43024c ths
    char *x509cacrl;
151 6f43024c ths
    char *x509cert;
152 6f43024c ths
    char *x509key;
153 8d5d2d4c ths
#endif
154 70848515 ths
    char challenge[VNC_AUTH_CHALLENGE_SIZE];
155 a9ce8590 bellard
156 eb38c52c blueswir1
#ifdef CONFIG_VNC_TLS
157 8d5d2d4c ths
    int wiremode;
158 8d5d2d4c ths
    gnutls_session_t tls_session;
159 8d5d2d4c ths
#endif
160 8d5d2d4c ths
161 24236869 bellard
    Buffer output;
162 24236869 bellard
    Buffer input;
163 24236869 bellard
    kbd_layout_t *kbd_layout;
164 3512779a bellard
    /* current output mode information */
165 3512779a bellard
    VncWritePixels *write_pixels;
166 3512779a bellard
    VncSendHextileTile *send_hextile_tile;
167 3512779a bellard
    int pix_bpp, pix_big_endian;
168 7eac3a87 aliguori
    int client_red_shift, client_red_max, server_red_shift, server_red_max;
169 7eac3a87 aliguori
    int client_green_shift, client_green_max, server_green_shift, server_green_max;
170 7eac3a87 aliguori
    int client_blue_shift, client_blue_max, server_blue_shift, server_blue_max;
171 24236869 bellard
172 24236869 bellard
    VncReadEvent *read_handler;
173 24236869 bellard
    size_t read_handler_expect;
174 64f5a135 bellard
    /* input */
175 64f5a135 bellard
    uint8_t modifiers_state[256];
176 24236869 bellard
};
177 24236869 bellard
178 a9ce8590 bellard
static VncState *vnc_state; /* needed for info vnc */
179 a9ce8590 bellard
180 a9ce8590 bellard
void do_info_vnc(void)
181 a9ce8590 bellard
{
182 a9ce8590 bellard
    if (vnc_state == NULL)
183 a9ce8590 bellard
        term_printf("VNC server disabled\n");
184 a9ce8590 bellard
    else {
185 a9ce8590 bellard
        term_printf("VNC server active on: ");
186 a9ce8590 bellard
        term_print_filename(vnc_state->display);
187 a9ce8590 bellard
        term_printf("\n");
188 a9ce8590 bellard
189 a9ce8590 bellard
        if (vnc_state->csock == -1)
190 a9ce8590 bellard
            term_printf("No client connected\n");
191 a9ce8590 bellard
        else
192 a9ce8590 bellard
            term_printf("Client connected\n");
193 a9ce8590 bellard
    }
194 a9ce8590 bellard
}
195 a9ce8590 bellard
196 24236869 bellard
/* TODO
197 24236869 bellard
   1) Get the queue working for IO.
198 24236869 bellard
   2) there is some weirdness when using the -S option (the screen is grey
199 24236869 bellard
      and not totally invalidated
200 24236869 bellard
   3) resolutions > 1024
201 24236869 bellard
*/
202 24236869 bellard
203 24236869 bellard
static void vnc_write(VncState *vs, const void *data, size_t len);
204 24236869 bellard
static void vnc_write_u32(VncState *vs, uint32_t value);
205 24236869 bellard
static void vnc_write_s32(VncState *vs, int32_t value);
206 24236869 bellard
static void vnc_write_u16(VncState *vs, uint16_t value);
207 24236869 bellard
static void vnc_write_u8(VncState *vs, uint8_t value);
208 24236869 bellard
static void vnc_flush(VncState *vs);
209 24236869 bellard
static void vnc_update_client(void *opaque);
210 24236869 bellard
static void vnc_client_read(void *opaque);
211 24236869 bellard
212 7eac3a87 aliguori
static void vnc_colordepth(DisplayState *ds, int depth);
213 7eac3a87 aliguori
214 99589bdc bellard
static inline void vnc_set_bit(uint32_t *d, int k)
215 99589bdc bellard
{
216 99589bdc bellard
    d[k >> 5] |= 1 << (k & 0x1f);
217 99589bdc bellard
}
218 99589bdc bellard
219 99589bdc bellard
static inline void vnc_clear_bit(uint32_t *d, int k)
220 99589bdc bellard
{
221 99589bdc bellard
    d[k >> 5] &= ~(1 << (k & 0x1f));
222 99589bdc bellard
}
223 99589bdc bellard
224 99589bdc bellard
static inline void vnc_set_bits(uint32_t *d, int n, int nb_words)
225 99589bdc bellard
{
226 99589bdc bellard
    int j;
227 99589bdc bellard
228 99589bdc bellard
    j = 0;
229 99589bdc bellard
    while (n >= 32) {
230 99589bdc bellard
        d[j++] = -1;
231 99589bdc bellard
        n -= 32;
232 99589bdc bellard
    }
233 5fafdf24 ths
    if (n > 0)
234 99589bdc bellard
        d[j++] = (1 << n) - 1;
235 99589bdc bellard
    while (j < nb_words)
236 99589bdc bellard
        d[j++] = 0;
237 99589bdc bellard
}
238 99589bdc bellard
239 99589bdc bellard
static inline int vnc_get_bit(const uint32_t *d, int k)
240 99589bdc bellard
{
241 99589bdc bellard
    return (d[k >> 5] >> (k & 0x1f)) & 1;
242 99589bdc bellard
}
243 99589bdc bellard
244 5fafdf24 ths
static inline int vnc_and_bits(const uint32_t *d1, const uint32_t *d2,
245 99589bdc bellard
                               int nb_words)
246 99589bdc bellard
{
247 99589bdc bellard
    int i;
248 99589bdc bellard
    for(i = 0; i < nb_words; i++) {
249 99589bdc bellard
        if ((d1[i] & d2[i]) != 0)
250 99589bdc bellard
            return 1;
251 99589bdc bellard
    }
252 99589bdc bellard
    return 0;
253 99589bdc bellard
}
254 99589bdc bellard
255 24236869 bellard
static void vnc_dpy_update(DisplayState *ds, int x, int y, int w, int h)
256 24236869 bellard
{
257 24236869 bellard
    VncState *vs = ds->opaque;
258 24236869 bellard
    int i;
259 24236869 bellard
260 24236869 bellard
    h += y;
261 24236869 bellard
262 0486e8a7 balrog
    /* round x down to ensure the loop only spans one 16-pixel block per,
263 0486e8a7 balrog
       iteration.  otherwise, if (x % 16) != 0, the last iteration may span
264 0486e8a7 balrog
       two 16-pixel blocks but we only mark the first as dirty
265 0486e8a7 balrog
    */
266 0486e8a7 balrog
    w += (x % 16);
267 0486e8a7 balrog
    x -= (x % 16);
268 0486e8a7 balrog
269 788abf8e balrog
    x = MIN(x, vs->width);
270 788abf8e balrog
    y = MIN(y, vs->height);
271 788abf8e balrog
    w = MIN(x + w, vs->width) - x;
272 731dd637 balrog
    h = MIN(h, vs->height);
273 788abf8e balrog
274 24236869 bellard
    for (; y < h; y++)
275 24236869 bellard
        for (i = 0; i < w; i += 16)
276 99589bdc bellard
            vnc_set_bit(vs->dirty_row[y], (x + i) / 16);
277 24236869 bellard
}
278 24236869 bellard
279 24236869 bellard
static void vnc_framebuffer_update(VncState *vs, int x, int y, int w, int h,
280 24236869 bellard
                                   int32_t encoding)
281 24236869 bellard
{
282 24236869 bellard
    vnc_write_u16(vs, x);
283 24236869 bellard
    vnc_write_u16(vs, y);
284 24236869 bellard
    vnc_write_u16(vs, w);
285 24236869 bellard
    vnc_write_u16(vs, h);
286 24236869 bellard
287 24236869 bellard
    vnc_write_s32(vs, encoding);
288 24236869 bellard
}
289 24236869 bellard
290 24236869 bellard
static void vnc_dpy_resize(DisplayState *ds, int w, int h)
291 24236869 bellard
{
292 73e14b62 ths
    int size_changed;
293 24236869 bellard
    VncState *vs = ds->opaque;
294 24236869 bellard
295 2137b4cc ths
    ds->data = qemu_realloc(ds->data, w * h * vs->depth);
296 2137b4cc ths
    vs->old_data = qemu_realloc(vs->old_data, w * h * vs->depth);
297 24236869 bellard
298 24236869 bellard
    if (ds->data == NULL || vs->old_data == NULL) {
299 24236869 bellard
        fprintf(stderr, "vnc: memory allocation failed\n");
300 24236869 bellard
        exit(1);
301 24236869 bellard
    }
302 24236869 bellard
303 a528b80c balrog
    if (ds->depth != vs->depth * 8) {
304 a528b80c balrog
        ds->depth = vs->depth * 8;
305 a528b80c balrog
        console_color_init(ds);
306 a528b80c balrog
    }
307 73e14b62 ths
    size_changed = ds->width != w || ds->height != h;
308 24236869 bellard
    ds->width = w;
309 24236869 bellard
    ds->height = h;
310 24236869 bellard
    ds->linesize = w * vs->depth;
311 b94eb43f balrog
    if (size_changed) {
312 b94eb43f balrog
        vs->width = ds->width;
313 b94eb43f balrog
        vs->height = ds->height;
314 b94eb43f balrog
        if (vs->csock != -1 && vs->has_resize) {
315 b94eb43f balrog
            vnc_write_u8(vs, 0);  /* msg id */
316 b94eb43f balrog
            vnc_write_u8(vs, 0);
317 b94eb43f balrog
            vnc_write_u16(vs, 1); /* number of rects */
318 b94eb43f balrog
            vnc_framebuffer_update(vs, 0, 0, ds->width, ds->height, -223);
319 b94eb43f balrog
            vnc_flush(vs);
320 b94eb43f balrog
        }
321 24236869 bellard
    }
322 8bba5c81 balrog
323 8bba5c81 balrog
    memset(vs->dirty_row, 0xFF, sizeof(vs->dirty_row));
324 8bba5c81 balrog
    memset(vs->old_data, 42, vs->ds->linesize * vs->ds->height);
325 24236869 bellard
}
326 24236869 bellard
327 3512779a bellard
/* fastest code */
328 3512779a bellard
static void vnc_write_pixels_copy(VncState *vs, void *pixels, int size)
329 3512779a bellard
{
330 3512779a bellard
    vnc_write(vs, pixels, size);
331 3512779a bellard
}
332 3512779a bellard
333 3512779a bellard
/* slowest but generic code. */
334 3512779a bellard
static void vnc_convert_pixel(VncState *vs, uint8_t *buf, uint32_t v)
335 3512779a bellard
{
336 7eac3a87 aliguori
    uint8_t r, g, b;
337 7eac3a87 aliguori
338 7eac3a87 aliguori
    r = ((v >> vs->server_red_shift) & vs->server_red_max) * (vs->client_red_max + 1) /
339 7eac3a87 aliguori
        (vs->server_red_max + 1);
340 7eac3a87 aliguori
    g = ((v >> vs->server_green_shift) & vs->server_green_max) * (vs->client_green_max + 1) /
341 7eac3a87 aliguori
        (vs->server_green_max + 1);
342 7eac3a87 aliguori
    b = ((v >> vs->server_blue_shift) & vs->server_blue_max) * (vs->client_blue_max + 1) /
343 7eac3a87 aliguori
        (vs->server_blue_max + 1);
344 7eac3a87 aliguori
    v = (r << vs->client_red_shift) |
345 7eac3a87 aliguori
        (g << vs->client_green_shift) |
346 7eac3a87 aliguori
        (b << vs->client_blue_shift);
347 3512779a bellard
    switch(vs->pix_bpp) {
348 3512779a bellard
    case 1:
349 3512779a bellard
        buf[0] = v;
350 3512779a bellard
        break;
351 3512779a bellard
    case 2:
352 3512779a bellard
        if (vs->pix_big_endian) {
353 3512779a bellard
            buf[0] = v >> 8;
354 3512779a bellard
            buf[1] = v;
355 3512779a bellard
        } else {
356 3512779a bellard
            buf[1] = v >> 8;
357 3512779a bellard
            buf[0] = v;
358 3512779a bellard
        }
359 3512779a bellard
        break;
360 3512779a bellard
    default:
361 3512779a bellard
    case 4:
362 3512779a bellard
        if (vs->pix_big_endian) {
363 3512779a bellard
            buf[0] = v >> 24;
364 3512779a bellard
            buf[1] = v >> 16;
365 3512779a bellard
            buf[2] = v >> 8;
366 3512779a bellard
            buf[3] = v;
367 3512779a bellard
        } else {
368 3512779a bellard
            buf[3] = v >> 24;
369 3512779a bellard
            buf[2] = v >> 16;
370 3512779a bellard
            buf[1] = v >> 8;
371 3512779a bellard
            buf[0] = v;
372 3512779a bellard
        }
373 3512779a bellard
        break;
374 3512779a bellard
    }
375 3512779a bellard
}
376 3512779a bellard
377 3512779a bellard
static void vnc_write_pixels_generic(VncState *vs, void *pixels1, int size)
378 3512779a bellard
{
379 3512779a bellard
    uint8_t buf[4];
380 3512779a bellard
381 7eac3a87 aliguori
    if (vs->depth == 4) {
382 7eac3a87 aliguori
        uint32_t *pixels = pixels1;
383 7eac3a87 aliguori
        int n, i;
384 7eac3a87 aliguori
        n = size >> 2;
385 7eac3a87 aliguori
        for(i = 0; i < n; i++) {
386 7eac3a87 aliguori
            vnc_convert_pixel(vs, buf, pixels[i]);
387 7eac3a87 aliguori
            vnc_write(vs, buf, vs->pix_bpp);
388 7eac3a87 aliguori
        }
389 7eac3a87 aliguori
    } else if (vs->depth == 2) {
390 7eac3a87 aliguori
        uint16_t *pixels = pixels1;
391 7eac3a87 aliguori
        int n, i;
392 7eac3a87 aliguori
        n = size >> 1;
393 7eac3a87 aliguori
        for(i = 0; i < n; i++) {
394 7eac3a87 aliguori
            vnc_convert_pixel(vs, buf, pixels[i]);
395 7eac3a87 aliguori
            vnc_write(vs, buf, vs->pix_bpp);
396 7eac3a87 aliguori
        }
397 7eac3a87 aliguori
    } else if (vs->depth == 1) {
398 7eac3a87 aliguori
        uint8_t *pixels = pixels1;
399 7eac3a87 aliguori
        int n, i;
400 7eac3a87 aliguori
        n = size;
401 7eac3a87 aliguori
        for(i = 0; i < n; i++) {
402 7eac3a87 aliguori
            vnc_convert_pixel(vs, buf, pixels[i]);
403 7eac3a87 aliguori
            vnc_write(vs, buf, vs->pix_bpp);
404 7eac3a87 aliguori
        }
405 7eac3a87 aliguori
    } else {
406 7eac3a87 aliguori
        fprintf(stderr, "vnc_write_pixels_generic: VncState color depth not supported\n");
407 3512779a bellard
    }
408 3512779a bellard
}
409 3512779a bellard
410 24236869 bellard
static void send_framebuffer_update_raw(VncState *vs, int x, int y, int w, int h)
411 24236869 bellard
{
412 24236869 bellard
    int i;
413 60fe76f3 ths
    uint8_t *row;
414 24236869 bellard
415 24236869 bellard
    vnc_framebuffer_update(vs, x, y, w, h, 0);
416 24236869 bellard
417 24236869 bellard
    row = vs->ds->data + y * vs->ds->linesize + x * vs->depth;
418 24236869 bellard
    for (i = 0; i < h; i++) {
419 3512779a bellard
        vs->write_pixels(vs, row, w * vs->depth);
420 24236869 bellard
        row += vs->ds->linesize;
421 24236869 bellard
    }
422 24236869 bellard
}
423 24236869 bellard
424 24236869 bellard
static void hextile_enc_cord(uint8_t *ptr, int x, int y, int w, int h)
425 24236869 bellard
{
426 24236869 bellard
    ptr[0] = ((x & 0x0F) << 4) | (y & 0x0F);
427 24236869 bellard
    ptr[1] = (((w - 1) & 0x0F) << 4) | ((h - 1) & 0x0F);
428 24236869 bellard
}
429 24236869 bellard
430 24236869 bellard
#define BPP 8
431 24236869 bellard
#include "vnchextile.h"
432 24236869 bellard
#undef BPP
433 24236869 bellard
434 24236869 bellard
#define BPP 16
435 24236869 bellard
#include "vnchextile.h"
436 24236869 bellard
#undef BPP
437 24236869 bellard
438 24236869 bellard
#define BPP 32
439 24236869 bellard
#include "vnchextile.h"
440 24236869 bellard
#undef BPP
441 24236869 bellard
442 3512779a bellard
#define GENERIC
443 7eac3a87 aliguori
#define BPP 8
444 7eac3a87 aliguori
#include "vnchextile.h"
445 7eac3a87 aliguori
#undef BPP
446 7eac3a87 aliguori
#undef GENERIC
447 7eac3a87 aliguori
448 7eac3a87 aliguori
#define GENERIC
449 7eac3a87 aliguori
#define BPP 16
450 7eac3a87 aliguori
#include "vnchextile.h"
451 7eac3a87 aliguori
#undef BPP
452 7eac3a87 aliguori
#undef GENERIC
453 7eac3a87 aliguori
454 7eac3a87 aliguori
#define GENERIC
455 3512779a bellard
#define BPP 32
456 3512779a bellard
#include "vnchextile.h"
457 3512779a bellard
#undef BPP
458 3512779a bellard
#undef GENERIC
459 3512779a bellard
460 24236869 bellard
static void send_framebuffer_update_hextile(VncState *vs, int x, int y, int w, int h)
461 24236869 bellard
{
462 24236869 bellard
    int i, j;
463 24236869 bellard
    int has_fg, has_bg;
464 7eac3a87 aliguori
    uint8_t *last_fg, *last_bg;
465 24236869 bellard
466 24236869 bellard
    vnc_framebuffer_update(vs, x, y, w, h, 5);
467 24236869 bellard
468 7eac3a87 aliguori
    last_fg = (uint8_t *) malloc(vs->depth);
469 7eac3a87 aliguori
    last_bg = (uint8_t *) malloc(vs->depth);
470 24236869 bellard
    has_fg = has_bg = 0;
471 24236869 bellard
    for (j = y; j < (y + h); j += 16) {
472 24236869 bellard
        for (i = x; i < (x + w); i += 16) {
473 5fafdf24 ths
            vs->send_hextile_tile(vs, i, j,
474 3512779a bellard
                                  MIN(16, x + w - i), MIN(16, y + h - j),
475 7eac3a87 aliguori
                                  last_bg, last_fg, &has_bg, &has_fg);
476 24236869 bellard
        }
477 24236869 bellard
    }
478 7eac3a87 aliguori
    free(last_fg);
479 7eac3a87 aliguori
    free(last_bg);
480 7eac3a87 aliguori
481 24236869 bellard
}
482 24236869 bellard
483 24236869 bellard
static void send_framebuffer_update(VncState *vs, int x, int y, int w, int h)
484 24236869 bellard
{
485 24236869 bellard
        if (vs->has_hextile)
486 24236869 bellard
            send_framebuffer_update_hextile(vs, x, y, w, h);
487 24236869 bellard
        else
488 24236869 bellard
            send_framebuffer_update_raw(vs, x, y, w, h);
489 24236869 bellard
}
490 24236869 bellard
491 24236869 bellard
static void vnc_copy(DisplayState *ds, int src_x, int src_y, int dst_x, int dst_y, int w, int h)
492 24236869 bellard
{
493 24236869 bellard
    int src, dst;
494 60fe76f3 ths
    uint8_t *src_row;
495 60fe76f3 ths
    uint8_t *dst_row;
496 24236869 bellard
    char *old_row;
497 24236869 bellard
    int y = 0;
498 24236869 bellard
    int pitch = ds->linesize;
499 24236869 bellard
    VncState *vs = ds->opaque;
500 24236869 bellard
501 24236869 bellard
    vnc_update_client(vs);
502 24236869 bellard
503 24236869 bellard
    if (dst_y > src_y) {
504 24236869 bellard
        y = h - 1;
505 24236869 bellard
        pitch = -pitch;
506 24236869 bellard
    }
507 24236869 bellard
508 24236869 bellard
    src = (ds->linesize * (src_y + y) + vs->depth * src_x);
509 24236869 bellard
    dst = (ds->linesize * (dst_y + y) + vs->depth * dst_x);
510 24236869 bellard
511 24236869 bellard
    src_row = ds->data + src;
512 24236869 bellard
    dst_row = ds->data + dst;
513 24236869 bellard
    old_row = vs->old_data + dst;
514 24236869 bellard
515 24236869 bellard
    for (y = 0; y < h; y++) {
516 24236869 bellard
        memmove(old_row, src_row, w * vs->depth);
517 24236869 bellard
        memmove(dst_row, src_row, w * vs->depth);
518 24236869 bellard
        src_row += pitch;
519 24236869 bellard
        dst_row += pitch;
520 24236869 bellard
        old_row += pitch;
521 24236869 bellard
    }
522 24236869 bellard
523 24236869 bellard
    vnc_write_u8(vs, 0);  /* msg id */
524 24236869 bellard
    vnc_write_u8(vs, 0);
525 24236869 bellard
    vnc_write_u16(vs, 1); /* number of rects */
526 24236869 bellard
    vnc_framebuffer_update(vs, dst_x, dst_y, w, h, 1);
527 24236869 bellard
    vnc_write_u16(vs, src_x);
528 24236869 bellard
    vnc_write_u16(vs, src_y);
529 24236869 bellard
    vnc_flush(vs);
530 24236869 bellard
}
531 24236869 bellard
532 24236869 bellard
static int find_dirty_height(VncState *vs, int y, int last_x, int x)
533 24236869 bellard
{
534 24236869 bellard
    int h;
535 24236869 bellard
536 24236869 bellard
    for (h = 1; h < (vs->height - y); h++) {
537 24236869 bellard
        int tmp_x;
538 99589bdc bellard
        if (!vnc_get_bit(vs->dirty_row[y + h], last_x))
539 24236869 bellard
            break;
540 24236869 bellard
        for (tmp_x = last_x; tmp_x < x; tmp_x++)
541 99589bdc bellard
            vnc_clear_bit(vs->dirty_row[y + h], tmp_x);
542 24236869 bellard
    }
543 24236869 bellard
544 24236869 bellard
    return h;
545 24236869 bellard
}
546 24236869 bellard
547 24236869 bellard
static void vnc_update_client(void *opaque)
548 24236869 bellard
{
549 24236869 bellard
    VncState *vs = opaque;
550 24236869 bellard
551 24236869 bellard
    if (vs->need_update && vs->csock != -1) {
552 24236869 bellard
        int y;
553 60fe76f3 ths
        uint8_t *row;
554 24236869 bellard
        char *old_row;
555 99589bdc bellard
        uint32_t width_mask[VNC_DIRTY_WORDS];
556 24236869 bellard
        int n_rectangles;
557 24236869 bellard
        int saved_offset;
558 24236869 bellard
        int has_dirty = 0;
559 24236869 bellard
560 a0ecfb73 balrog
        vga_hw_update();
561 a0ecfb73 balrog
562 99589bdc bellard
        vnc_set_bits(width_mask, (vs->width / 16), VNC_DIRTY_WORDS);
563 24236869 bellard
564 24236869 bellard
        /* Walk through the dirty map and eliminate tiles that
565 24236869 bellard
           really aren't dirty */
566 24236869 bellard
        row = vs->ds->data;
567 24236869 bellard
        old_row = vs->old_data;
568 24236869 bellard
569 24236869 bellard
        for (y = 0; y < vs->height; y++) {
570 99589bdc bellard
            if (vnc_and_bits(vs->dirty_row[y], width_mask, VNC_DIRTY_WORDS)) {
571 24236869 bellard
                int x;
572 60fe76f3 ths
                uint8_t *ptr;
573 60fe76f3 ths
                char *old_ptr;
574 24236869 bellard
575 24236869 bellard
                ptr = row;
576 60fe76f3 ths
                old_ptr = (char*)old_row;
577 24236869 bellard
578 24236869 bellard
                for (x = 0; x < vs->ds->width; x += 16) {
579 24236869 bellard
                    if (memcmp(old_ptr, ptr, 16 * vs->depth) == 0) {
580 99589bdc bellard
                        vnc_clear_bit(vs->dirty_row[y], (x / 16));
581 24236869 bellard
                    } else {
582 24236869 bellard
                        has_dirty = 1;
583 24236869 bellard
                        memcpy(old_ptr, ptr, 16 * vs->depth);
584 24236869 bellard
                    }
585 24236869 bellard
586 24236869 bellard
                    ptr += 16 * vs->depth;
587 24236869 bellard
                    old_ptr += 16 * vs->depth;
588 24236869 bellard
                }
589 24236869 bellard
            }
590 24236869 bellard
591 24236869 bellard
            row += vs->ds->linesize;
592 24236869 bellard
            old_row += vs->ds->linesize;
593 24236869 bellard
        }
594 24236869 bellard
595 24236869 bellard
        if (!has_dirty) {
596 24236869 bellard
            qemu_mod_timer(vs->timer, qemu_get_clock(rt_clock) + VNC_REFRESH_INTERVAL);
597 24236869 bellard
            return;
598 24236869 bellard
        }
599 24236869 bellard
600 24236869 bellard
        /* Count rectangles */
601 24236869 bellard
        n_rectangles = 0;
602 24236869 bellard
        vnc_write_u8(vs, 0);  /* msg id */
603 24236869 bellard
        vnc_write_u8(vs, 0);
604 24236869 bellard
        saved_offset = vs->output.offset;
605 24236869 bellard
        vnc_write_u16(vs, 0);
606 24236869 bellard
607 24236869 bellard
        for (y = 0; y < vs->height; y++) {
608 24236869 bellard
            int x;
609 24236869 bellard
            int last_x = -1;
610 24236869 bellard
            for (x = 0; x < vs->width / 16; x++) {
611 99589bdc bellard
                if (vnc_get_bit(vs->dirty_row[y], x)) {
612 24236869 bellard
                    if (last_x == -1) {
613 24236869 bellard
                        last_x = x;
614 24236869 bellard
                    }
615 99589bdc bellard
                    vnc_clear_bit(vs->dirty_row[y], x);
616 24236869 bellard
                } else {
617 24236869 bellard
                    if (last_x != -1) {
618 24236869 bellard
                        int h = find_dirty_height(vs, y, last_x, x);
619 24236869 bellard
                        send_framebuffer_update(vs, last_x * 16, y, (x - last_x) * 16, h);
620 24236869 bellard
                        n_rectangles++;
621 24236869 bellard
                    }
622 24236869 bellard
                    last_x = -1;
623 24236869 bellard
                }
624 24236869 bellard
            }
625 24236869 bellard
            if (last_x != -1) {
626 24236869 bellard
                int h = find_dirty_height(vs, y, last_x, x);
627 24236869 bellard
                send_framebuffer_update(vs, last_x * 16, y, (x - last_x) * 16, h);
628 24236869 bellard
                n_rectangles++;
629 24236869 bellard
            }
630 24236869 bellard
        }
631 24236869 bellard
        vs->output.buffer[saved_offset] = (n_rectangles >> 8) & 0xFF;
632 24236869 bellard
        vs->output.buffer[saved_offset + 1] = n_rectangles & 0xFF;
633 24236869 bellard
        vnc_flush(vs);
634 24236869 bellard
635 24236869 bellard
    }
636 24236869 bellard
637 a0ecfb73 balrog
    if (vs->csock != -1) {
638 a0ecfb73 balrog
        qemu_mod_timer(vs->timer, qemu_get_clock(rt_clock) + VNC_REFRESH_INTERVAL);
639 24236869 bellard
    }
640 24236869 bellard
641 24236869 bellard
}
642 24236869 bellard
643 24236869 bellard
static int vnc_listen_poll(void *opaque)
644 24236869 bellard
{
645 24236869 bellard
    VncState *vs = opaque;
646 24236869 bellard
    if (vs->csock == -1)
647 24236869 bellard
        return 1;
648 24236869 bellard
    return 0;
649 24236869 bellard
}
650 24236869 bellard
651 24236869 bellard
static void buffer_reserve(Buffer *buffer, size_t len)
652 24236869 bellard
{
653 24236869 bellard
    if ((buffer->capacity - buffer->offset) < len) {
654 24236869 bellard
        buffer->capacity += (len + 1024);
655 2137b4cc ths
        buffer->buffer = qemu_realloc(buffer->buffer, buffer->capacity);
656 24236869 bellard
        if (buffer->buffer == NULL) {
657 24236869 bellard
            fprintf(stderr, "vnc: out of memory\n");
658 24236869 bellard
            exit(1);
659 24236869 bellard
        }
660 24236869 bellard
    }
661 24236869 bellard
}
662 24236869 bellard
663 24236869 bellard
static int buffer_empty(Buffer *buffer)
664 24236869 bellard
{
665 24236869 bellard
    return buffer->offset == 0;
666 24236869 bellard
}
667 24236869 bellard
668 60fe76f3 ths
static uint8_t *buffer_end(Buffer *buffer)
669 24236869 bellard
{
670 24236869 bellard
    return buffer->buffer + buffer->offset;
671 24236869 bellard
}
672 24236869 bellard
673 24236869 bellard
static void buffer_reset(Buffer *buffer)
674 24236869 bellard
{
675 24236869 bellard
        buffer->offset = 0;
676 24236869 bellard
}
677 24236869 bellard
678 24236869 bellard
static void buffer_append(Buffer *buffer, const void *data, size_t len)
679 24236869 bellard
{
680 24236869 bellard
    memcpy(buffer->buffer + buffer->offset, data, len);
681 24236869 bellard
    buffer->offset += len;
682 24236869 bellard
}
683 24236869 bellard
684 6ca957f0 bellard
static int vnc_client_io_error(VncState *vs, int ret, int last_errno)
685 24236869 bellard
{
686 24236869 bellard
    if (ret == 0 || ret == -1) {
687 ea01e5fd balrog
        if (ret == -1) {
688 ea01e5fd balrog
            switch (last_errno) {
689 ea01e5fd balrog
                case EINTR:
690 ea01e5fd balrog
                case EAGAIN:
691 ea01e5fd balrog
#ifdef _WIN32
692 ea01e5fd balrog
                case WSAEWOULDBLOCK:
693 ea01e5fd balrog
#endif
694 ea01e5fd balrog
                    return 0;
695 ea01e5fd balrog
                default:
696 ea01e5fd balrog
                    break;
697 ea01e5fd balrog
            }
698 ea01e5fd balrog
        }
699 24236869 bellard
700 8d5d2d4c ths
        VNC_DEBUG("Closing down client sock %d %d\n", ret, ret < 0 ? last_errno : 0);
701 24236869 bellard
        qemu_set_fd_handler2(vs->csock, NULL, NULL, NULL, NULL);
702 6ca957f0 bellard
        closesocket(vs->csock);
703 24236869 bellard
        vs->csock = -1;
704 bcfad70f aliguori
        vs->ds->idle = 1;
705 24236869 bellard
        buffer_reset(&vs->input);
706 24236869 bellard
        buffer_reset(&vs->output);
707 24236869 bellard
        vs->need_update = 0;
708 eb38c52c blueswir1
#ifdef CONFIG_VNC_TLS
709 8d5d2d4c ths
        if (vs->tls_session) {
710 8d5d2d4c ths
            gnutls_deinit(vs->tls_session);
711 8d5d2d4c ths
            vs->tls_session = NULL;
712 8d5d2d4c ths
        }
713 8d5d2d4c ths
        vs->wiremode = VNC_WIREMODE_CLEAR;
714 8d5d2d4c ths
#endif /* CONFIG_VNC_TLS */
715 24236869 bellard
        return 0;
716 24236869 bellard
    }
717 24236869 bellard
    return ret;
718 24236869 bellard
}
719 24236869 bellard
720 24236869 bellard
static void vnc_client_error(VncState *vs)
721 24236869 bellard
{
722 6ca957f0 bellard
    vnc_client_io_error(vs, -1, EINVAL);
723 24236869 bellard
}
724 24236869 bellard
725 24236869 bellard
static void vnc_client_write(void *opaque)
726 24236869 bellard
{
727 ceb5caaf bellard
    long ret;
728 24236869 bellard
    VncState *vs = opaque;
729 24236869 bellard
730 eb38c52c blueswir1
#ifdef CONFIG_VNC_TLS
731 8d5d2d4c ths
    if (vs->tls_session) {
732 8d5d2d4c ths
        ret = gnutls_write(vs->tls_session, vs->output.buffer, vs->output.offset);
733 8d5d2d4c ths
        if (ret < 0) {
734 8d5d2d4c ths
            if (ret == GNUTLS_E_AGAIN)
735 8d5d2d4c ths
                errno = EAGAIN;
736 8d5d2d4c ths
            else
737 8d5d2d4c ths
                errno = EIO;
738 8d5d2d4c ths
            ret = -1;
739 8d5d2d4c ths
        }
740 8d5d2d4c ths
    } else
741 8d5d2d4c ths
#endif /* CONFIG_VNC_TLS */
742 8d5d2d4c ths
        ret = send(vs->csock, vs->output.buffer, vs->output.offset, 0);
743 6ca957f0 bellard
    ret = vnc_client_io_error(vs, ret, socket_error());
744 24236869 bellard
    if (!ret)
745 24236869 bellard
        return;
746 24236869 bellard
747 24236869 bellard
    memmove(vs->output.buffer, vs->output.buffer + ret, (vs->output.offset - ret));
748 24236869 bellard
    vs->output.offset -= ret;
749 24236869 bellard
750 24236869 bellard
    if (vs->output.offset == 0) {
751 24236869 bellard
        qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, NULL, vs);
752 24236869 bellard
    }
753 24236869 bellard
}
754 24236869 bellard
755 24236869 bellard
static void vnc_read_when(VncState *vs, VncReadEvent *func, size_t expecting)
756 24236869 bellard
{
757 24236869 bellard
    vs->read_handler = func;
758 24236869 bellard
    vs->read_handler_expect = expecting;
759 24236869 bellard
}
760 24236869 bellard
761 24236869 bellard
static void vnc_client_read(void *opaque)
762 24236869 bellard
{
763 24236869 bellard
    VncState *vs = opaque;
764 ceb5caaf bellard
    long ret;
765 24236869 bellard
766 24236869 bellard
    buffer_reserve(&vs->input, 4096);
767 24236869 bellard
768 eb38c52c blueswir1
#ifdef CONFIG_VNC_TLS
769 8d5d2d4c ths
    if (vs->tls_session) {
770 8d5d2d4c ths
        ret = gnutls_read(vs->tls_session, buffer_end(&vs->input), 4096);
771 8d5d2d4c ths
        if (ret < 0) {
772 8d5d2d4c ths
            if (ret == GNUTLS_E_AGAIN)
773 8d5d2d4c ths
                errno = EAGAIN;
774 8d5d2d4c ths
            else
775 8d5d2d4c ths
                errno = EIO;
776 8d5d2d4c ths
            ret = -1;
777 8d5d2d4c ths
        }
778 8d5d2d4c ths
    } else
779 8d5d2d4c ths
#endif /* CONFIG_VNC_TLS */
780 8d5d2d4c ths
        ret = recv(vs->csock, buffer_end(&vs->input), 4096, 0);
781 6ca957f0 bellard
    ret = vnc_client_io_error(vs, ret, socket_error());
782 24236869 bellard
    if (!ret)
783 24236869 bellard
        return;
784 24236869 bellard
785 24236869 bellard
    vs->input.offset += ret;
786 24236869 bellard
787 24236869 bellard
    while (vs->read_handler && vs->input.offset >= vs->read_handler_expect) {
788 24236869 bellard
        size_t len = vs->read_handler_expect;
789 24236869 bellard
        int ret;
790 24236869 bellard
791 24236869 bellard
        ret = vs->read_handler(vs, vs->input.buffer, len);
792 24236869 bellard
        if (vs->csock == -1)
793 24236869 bellard
            return;
794 24236869 bellard
795 24236869 bellard
        if (!ret) {
796 24236869 bellard
            memmove(vs->input.buffer, vs->input.buffer + len, (vs->input.offset - len));
797 24236869 bellard
            vs->input.offset -= len;
798 24236869 bellard
        } else {
799 24236869 bellard
            vs->read_handler_expect = ret;
800 24236869 bellard
        }
801 24236869 bellard
    }
802 24236869 bellard
}
803 24236869 bellard
804 24236869 bellard
static void vnc_write(VncState *vs, const void *data, size_t len)
805 24236869 bellard
{
806 24236869 bellard
    buffer_reserve(&vs->output, len);
807 24236869 bellard
808 24236869 bellard
    if (buffer_empty(&vs->output)) {
809 24236869 bellard
        qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, vnc_client_write, vs);
810 24236869 bellard
    }
811 24236869 bellard
812 24236869 bellard
    buffer_append(&vs->output, data, len);
813 24236869 bellard
}
814 24236869 bellard
815 24236869 bellard
static void vnc_write_s32(VncState *vs, int32_t value)
816 24236869 bellard
{
817 24236869 bellard
    vnc_write_u32(vs, *(uint32_t *)&value);
818 24236869 bellard
}
819 24236869 bellard
820 24236869 bellard
static void vnc_write_u32(VncState *vs, uint32_t value)
821 24236869 bellard
{
822 24236869 bellard
    uint8_t buf[4];
823 24236869 bellard
824 24236869 bellard
    buf[0] = (value >> 24) & 0xFF;
825 24236869 bellard
    buf[1] = (value >> 16) & 0xFF;
826 24236869 bellard
    buf[2] = (value >>  8) & 0xFF;
827 24236869 bellard
    buf[3] = value & 0xFF;
828 24236869 bellard
829 24236869 bellard
    vnc_write(vs, buf, 4);
830 24236869 bellard
}
831 24236869 bellard
832 24236869 bellard
static void vnc_write_u16(VncState *vs, uint16_t value)
833 24236869 bellard
{
834 64f5a135 bellard
    uint8_t buf[2];
835 24236869 bellard
836 24236869 bellard
    buf[0] = (value >> 8) & 0xFF;
837 24236869 bellard
    buf[1] = value & 0xFF;
838 24236869 bellard
839 24236869 bellard
    vnc_write(vs, buf, 2);
840 24236869 bellard
}
841 24236869 bellard
842 24236869 bellard
static void vnc_write_u8(VncState *vs, uint8_t value)
843 24236869 bellard
{
844 24236869 bellard
    vnc_write(vs, (char *)&value, 1);
845 24236869 bellard
}
846 24236869 bellard
847 24236869 bellard
static void vnc_flush(VncState *vs)
848 24236869 bellard
{
849 24236869 bellard
    if (vs->output.offset)
850 24236869 bellard
        vnc_client_write(vs);
851 24236869 bellard
}
852 24236869 bellard
853 64f5a135 bellard
static uint8_t read_u8(uint8_t *data, size_t offset)
854 24236869 bellard
{
855 24236869 bellard
    return data[offset];
856 24236869 bellard
}
857 24236869 bellard
858 64f5a135 bellard
static uint16_t read_u16(uint8_t *data, size_t offset)
859 24236869 bellard
{
860 24236869 bellard
    return ((data[offset] & 0xFF) << 8) | (data[offset + 1] & 0xFF);
861 24236869 bellard
}
862 24236869 bellard
863 64f5a135 bellard
static int32_t read_s32(uint8_t *data, size_t offset)
864 24236869 bellard
{
865 24236869 bellard
    return (int32_t)((data[offset] << 24) | (data[offset + 1] << 16) |
866 24236869 bellard
                     (data[offset + 2] << 8) | data[offset + 3]);
867 24236869 bellard
}
868 24236869 bellard
869 64f5a135 bellard
static uint32_t read_u32(uint8_t *data, size_t offset)
870 24236869 bellard
{
871 24236869 bellard
    return ((data[offset] << 24) | (data[offset + 1] << 16) |
872 24236869 bellard
            (data[offset + 2] << 8) | data[offset + 3]);
873 24236869 bellard
}
874 24236869 bellard
875 eb38c52c blueswir1
#ifdef CONFIG_VNC_TLS
876 9596ebb7 pbrook
static ssize_t vnc_tls_push(gnutls_transport_ptr_t transport,
877 9596ebb7 pbrook
                            const void *data,
878 9596ebb7 pbrook
                            size_t len) {
879 8d5d2d4c ths
    struct VncState *vs = (struct VncState *)transport;
880 8d5d2d4c ths
    int ret;
881 8d5d2d4c ths
882 8d5d2d4c ths
 retry:
883 8d5d2d4c ths
    ret = send(vs->csock, data, len, 0);
884 8d5d2d4c ths
    if (ret < 0) {
885 8d5d2d4c ths
        if (errno == EINTR)
886 8d5d2d4c ths
            goto retry;
887 8d5d2d4c ths
        return -1;
888 8d5d2d4c ths
    }
889 8d5d2d4c ths
    return ret;
890 8d5d2d4c ths
}
891 8d5d2d4c ths
892 8d5d2d4c ths
893 9596ebb7 pbrook
static ssize_t vnc_tls_pull(gnutls_transport_ptr_t transport,
894 9596ebb7 pbrook
                            void *data,
895 9596ebb7 pbrook
                            size_t len) {
896 8d5d2d4c ths
    struct VncState *vs = (struct VncState *)transport;
897 8d5d2d4c ths
    int ret;
898 8d5d2d4c ths
899 8d5d2d4c ths
 retry:
900 8d5d2d4c ths
    ret = recv(vs->csock, data, len, 0);
901 8d5d2d4c ths
    if (ret < 0) {
902 8d5d2d4c ths
        if (errno == EINTR)
903 8d5d2d4c ths
            goto retry;
904 8d5d2d4c ths
        return -1;
905 8d5d2d4c ths
    }
906 8d5d2d4c ths
    return ret;
907 8d5d2d4c ths
}
908 8d5d2d4c ths
#endif /* CONFIG_VNC_TLS */
909 8d5d2d4c ths
910 60fe76f3 ths
static void client_cut_text(VncState *vs, size_t len, uint8_t *text)
911 24236869 bellard
{
912 24236869 bellard
}
913 24236869 bellard
914 564c337e bellard
static void check_pointer_type_change(VncState *vs, int absolute)
915 564c337e bellard
{
916 564c337e bellard
    if (vs->has_pointer_type_change && vs->absolute != absolute) {
917 564c337e bellard
        vnc_write_u8(vs, 0);
918 564c337e bellard
        vnc_write_u8(vs, 0);
919 564c337e bellard
        vnc_write_u16(vs, 1);
920 564c337e bellard
        vnc_framebuffer_update(vs, absolute, 0,
921 564c337e bellard
                               vs->ds->width, vs->ds->height, -257);
922 564c337e bellard
        vnc_flush(vs);
923 564c337e bellard
    }
924 564c337e bellard
    vs->absolute = absolute;
925 564c337e bellard
}
926 564c337e bellard
927 24236869 bellard
static void pointer_event(VncState *vs, int button_mask, int x, int y)
928 24236869 bellard
{
929 24236869 bellard
    int buttons = 0;
930 24236869 bellard
    int dz = 0;
931 24236869 bellard
932 24236869 bellard
    if (button_mask & 0x01)
933 24236869 bellard
        buttons |= MOUSE_EVENT_LBUTTON;
934 24236869 bellard
    if (button_mask & 0x02)
935 24236869 bellard
        buttons |= MOUSE_EVENT_MBUTTON;
936 24236869 bellard
    if (button_mask & 0x04)
937 24236869 bellard
        buttons |= MOUSE_EVENT_RBUTTON;
938 24236869 bellard
    if (button_mask & 0x08)
939 24236869 bellard
        dz = -1;
940 24236869 bellard
    if (button_mask & 0x10)
941 24236869 bellard
        dz = 1;
942 564c337e bellard
943 564c337e bellard
    if (vs->absolute) {
944 b94ed577 aurel32
        kbd_mouse_event(x * 0x7FFF / (vs->ds->width - 1),
945 b94ed577 aurel32
                        y * 0x7FFF / (vs->ds->height - 1),
946 24236869 bellard
                        dz, buttons);
947 564c337e bellard
    } else if (vs->has_pointer_type_change) {
948 564c337e bellard
        x -= 0x7FFF;
949 564c337e bellard
        y -= 0x7FFF;
950 24236869 bellard
951 564c337e bellard
        kbd_mouse_event(x, y, dz, buttons);
952 564c337e bellard
    } else {
953 564c337e bellard
        if (vs->last_x != -1)
954 564c337e bellard
            kbd_mouse_event(x - vs->last_x,
955 564c337e bellard
                            y - vs->last_y,
956 564c337e bellard
                            dz, buttons);
957 564c337e bellard
        vs->last_x = x;
958 564c337e bellard
        vs->last_y = y;
959 24236869 bellard
    }
960 564c337e bellard
961 564c337e bellard
    check_pointer_type_change(vs, kbd_mouse_is_absolute());
962 24236869 bellard
}
963 24236869 bellard
964 64f5a135 bellard
static void reset_keys(VncState *vs)
965 64f5a135 bellard
{
966 64f5a135 bellard
    int i;
967 64f5a135 bellard
    for(i = 0; i < 256; i++) {
968 64f5a135 bellard
        if (vs->modifiers_state[i]) {
969 64f5a135 bellard
            if (i & 0x80)
970 64f5a135 bellard
                kbd_put_keycode(0xe0);
971 64f5a135 bellard
            kbd_put_keycode(i | 0x80);
972 64f5a135 bellard
            vs->modifiers_state[i] = 0;
973 64f5a135 bellard
        }
974 64f5a135 bellard
    }
975 64f5a135 bellard
}
976 64f5a135 bellard
977 a528b80c balrog
static void press_key(VncState *vs, int keysym)
978 a528b80c balrog
{
979 a528b80c balrog
    kbd_put_keycode(keysym2scancode(vs->kbd_layout, keysym) & 0x7f);
980 a528b80c balrog
    kbd_put_keycode(keysym2scancode(vs->kbd_layout, keysym) | 0x80);
981 a528b80c balrog
}
982 a528b80c balrog
983 9ca313aa aliguori
static void do_key_event(VncState *vs, int down, int keycode, int sym)
984 24236869 bellard
{
985 64f5a135 bellard
    /* QEMU console switch */
986 64f5a135 bellard
    switch(keycode) {
987 64f5a135 bellard
    case 0x2a:                          /* Left Shift */
988 64f5a135 bellard
    case 0x36:                          /* Right Shift */
989 64f5a135 bellard
    case 0x1d:                          /* Left CTRL */
990 64f5a135 bellard
    case 0x9d:                          /* Right CTRL */
991 64f5a135 bellard
    case 0x38:                          /* Left ALT */
992 64f5a135 bellard
    case 0xb8:                          /* Right ALT */
993 64f5a135 bellard
        if (down)
994 64f5a135 bellard
            vs->modifiers_state[keycode] = 1;
995 64f5a135 bellard
        else
996 64f5a135 bellard
            vs->modifiers_state[keycode] = 0;
997 64f5a135 bellard
        break;
998 5fafdf24 ths
    case 0x02 ... 0x0a: /* '1' to '9' keys */
999 64f5a135 bellard
        if (down && vs->modifiers_state[0x1d] && vs->modifiers_state[0x38]) {
1000 64f5a135 bellard
            /* Reset the modifiers sent to the current console */
1001 64f5a135 bellard
            reset_keys(vs);
1002 64f5a135 bellard
            console_select(keycode - 0x02);
1003 64f5a135 bellard
            return;
1004 64f5a135 bellard
        }
1005 64f5a135 bellard
        break;
1006 4d3b6f6e balrog
    case 0x3a:                        /* CapsLock */
1007 a528b80c balrog
    case 0x45:                        /* NumLock */
1008 a528b80c balrog
        if (!down)
1009 a528b80c balrog
            vs->modifiers_state[keycode] ^= 1;
1010 a528b80c balrog
        break;
1011 a528b80c balrog
    }
1012 a528b80c balrog
1013 a528b80c balrog
    if (keycode_is_keypad(vs->kbd_layout, keycode)) {
1014 a528b80c balrog
        /* If the numlock state needs to change then simulate an additional
1015 a528b80c balrog
           keypress before sending this one.  This will happen if the user
1016 a528b80c balrog
           toggles numlock away from the VNC window.
1017 a528b80c balrog
        */
1018 a528b80c balrog
        if (keysym_is_numlock(vs->kbd_layout, sym & 0xFFFF)) {
1019 a528b80c balrog
            if (!vs->modifiers_state[0x45]) {
1020 a528b80c balrog
                vs->modifiers_state[0x45] = 1;
1021 a528b80c balrog
                press_key(vs, 0xff7f);
1022 a528b80c balrog
            }
1023 a528b80c balrog
        } else {
1024 a528b80c balrog
            if (vs->modifiers_state[0x45]) {
1025 a528b80c balrog
                vs->modifiers_state[0x45] = 0;
1026 a528b80c balrog
                press_key(vs, 0xff7f);
1027 a528b80c balrog
            }
1028 a528b80c balrog
        }
1029 64f5a135 bellard
    }
1030 24236869 bellard
1031 64f5a135 bellard
    if (is_graphic_console()) {
1032 64f5a135 bellard
        if (keycode & 0x80)
1033 64f5a135 bellard
            kbd_put_keycode(0xe0);
1034 64f5a135 bellard
        if (down)
1035 64f5a135 bellard
            kbd_put_keycode(keycode & 0x7f);
1036 64f5a135 bellard
        else
1037 64f5a135 bellard
            kbd_put_keycode(keycode | 0x80);
1038 64f5a135 bellard
    } else {
1039 64f5a135 bellard
        /* QEMU console emulation */
1040 64f5a135 bellard
        if (down) {
1041 64f5a135 bellard
            switch (keycode) {
1042 64f5a135 bellard
            case 0x2a:                          /* Left Shift */
1043 64f5a135 bellard
            case 0x36:                          /* Right Shift */
1044 64f5a135 bellard
            case 0x1d:                          /* Left CTRL */
1045 64f5a135 bellard
            case 0x9d:                          /* Right CTRL */
1046 64f5a135 bellard
            case 0x38:                          /* Left ALT */
1047 64f5a135 bellard
            case 0xb8:                          /* Right ALT */
1048 64f5a135 bellard
                break;
1049 64f5a135 bellard
            case 0xc8:
1050 64f5a135 bellard
                kbd_put_keysym(QEMU_KEY_UP);
1051 64f5a135 bellard
                break;
1052 64f5a135 bellard
            case 0xd0:
1053 64f5a135 bellard
                kbd_put_keysym(QEMU_KEY_DOWN);
1054 64f5a135 bellard
                break;
1055 64f5a135 bellard
            case 0xcb:
1056 64f5a135 bellard
                kbd_put_keysym(QEMU_KEY_LEFT);
1057 64f5a135 bellard
                break;
1058 64f5a135 bellard
            case 0xcd:
1059 64f5a135 bellard
                kbd_put_keysym(QEMU_KEY_RIGHT);
1060 64f5a135 bellard
                break;
1061 64f5a135 bellard
            case 0xd3:
1062 64f5a135 bellard
                kbd_put_keysym(QEMU_KEY_DELETE);
1063 64f5a135 bellard
                break;
1064 64f5a135 bellard
            case 0xc7:
1065 64f5a135 bellard
                kbd_put_keysym(QEMU_KEY_HOME);
1066 64f5a135 bellard
                break;
1067 64f5a135 bellard
            case 0xcf:
1068 64f5a135 bellard
                kbd_put_keysym(QEMU_KEY_END);
1069 64f5a135 bellard
                break;
1070 64f5a135 bellard
            case 0xc9:
1071 64f5a135 bellard
                kbd_put_keysym(QEMU_KEY_PAGEUP);
1072 64f5a135 bellard
                break;
1073 64f5a135 bellard
            case 0xd1:
1074 64f5a135 bellard
                kbd_put_keysym(QEMU_KEY_PAGEDOWN);
1075 64f5a135 bellard
                break;
1076 64f5a135 bellard
            default:
1077 64f5a135 bellard
                kbd_put_keysym(sym);
1078 64f5a135 bellard
                break;
1079 64f5a135 bellard
            }
1080 64f5a135 bellard
        }
1081 64f5a135 bellard
    }
1082 24236869 bellard
}
1083 24236869 bellard
1084 bdbd7676 bellard
static void key_event(VncState *vs, int down, uint32_t sym)
1085 bdbd7676 bellard
{
1086 9ca313aa aliguori
    int keycode;
1087 9ca313aa aliguori
1088 a528b80c balrog
    if (sym >= 'A' && sym <= 'Z' && is_graphic_console())
1089 bdbd7676 bellard
        sym = sym - 'A' + 'a';
1090 9ca313aa aliguori
1091 9ca313aa aliguori
    keycode = keysym2scancode(vs->kbd_layout, sym & 0xFFFF);
1092 9ca313aa aliguori
    do_key_event(vs, down, keycode, sym);
1093 9ca313aa aliguori
}
1094 9ca313aa aliguori
1095 9ca313aa aliguori
static void ext_key_event(VncState *vs, int down,
1096 9ca313aa aliguori
                          uint32_t sym, uint16_t keycode)
1097 9ca313aa aliguori
{
1098 9ca313aa aliguori
    /* if the user specifies a keyboard layout, always use it */
1099 9ca313aa aliguori
    if (keyboard_layout)
1100 9ca313aa aliguori
        key_event(vs, down, sym);
1101 9ca313aa aliguori
    else
1102 9ca313aa aliguori
        do_key_event(vs, down, keycode, sym);
1103 bdbd7676 bellard
}
1104 bdbd7676 bellard
1105 24236869 bellard
static void framebuffer_update_request(VncState *vs, int incremental,
1106 24236869 bellard
                                       int x_position, int y_position,
1107 24236869 bellard
                                       int w, int h)
1108 24236869 bellard
{
1109 cf2d385c ths
    if (x_position > vs->ds->width)
1110 cf2d385c ths
        x_position = vs->ds->width;
1111 cf2d385c ths
    if (y_position > vs->ds->height)
1112 cf2d385c ths
        y_position = vs->ds->height;
1113 cf2d385c ths
    if (x_position + w >= vs->ds->width)
1114 cf2d385c ths
        w = vs->ds->width  - x_position;
1115 cf2d385c ths
    if (y_position + h >= vs->ds->height)
1116 cf2d385c ths
        h = vs->ds->height - y_position;
1117 cf2d385c ths
1118 24236869 bellard
    int i;
1119 24236869 bellard
    vs->need_update = 1;
1120 24236869 bellard
    if (!incremental) {
1121 24236869 bellard
        char *old_row = vs->old_data + y_position * vs->ds->linesize;
1122 24236869 bellard
1123 24236869 bellard
        for (i = 0; i < h; i++) {
1124 5fafdf24 ths
            vnc_set_bits(vs->dirty_row[y_position + i],
1125 99589bdc bellard
                         (vs->ds->width / 16), VNC_DIRTY_WORDS);
1126 24236869 bellard
            memset(old_row, 42, vs->ds->width * vs->depth);
1127 24236869 bellard
            old_row += vs->ds->linesize;
1128 24236869 bellard
        }
1129 24236869 bellard
    }
1130 24236869 bellard
}
1131 24236869 bellard
1132 9ca313aa aliguori
static void send_ext_key_event_ack(VncState *vs)
1133 9ca313aa aliguori
{
1134 9ca313aa aliguori
    vnc_write_u8(vs, 0);
1135 9ca313aa aliguori
    vnc_write_u8(vs, 0);
1136 9ca313aa aliguori
    vnc_write_u16(vs, 1);
1137 9ca313aa aliguori
    vnc_framebuffer_update(vs, 0, 0, vs->ds->width, vs->ds->height, -258);
1138 9ca313aa aliguori
    vnc_flush(vs);
1139 9ca313aa aliguori
}
1140 9ca313aa aliguori
1141 24236869 bellard
static void set_encodings(VncState *vs, int32_t *encodings, size_t n_encodings)
1142 24236869 bellard
{
1143 24236869 bellard
    int i;
1144 24236869 bellard
1145 24236869 bellard
    vs->has_hextile = 0;
1146 24236869 bellard
    vs->has_resize = 0;
1147 564c337e bellard
    vs->has_pointer_type_change = 0;
1148 ca4cca4d aliguori
    vs->has_WMVi = 0;
1149 564c337e bellard
    vs->absolute = -1;
1150 24236869 bellard
    vs->ds->dpy_copy = NULL;
1151 24236869 bellard
1152 24236869 bellard
    for (i = n_encodings - 1; i >= 0; i--) {
1153 24236869 bellard
        switch (encodings[i]) {
1154 24236869 bellard
        case 0: /* Raw */
1155 24236869 bellard
            vs->has_hextile = 0;
1156 24236869 bellard
            break;
1157 24236869 bellard
        case 1: /* CopyRect */
1158 24236869 bellard
            vs->ds->dpy_copy = vnc_copy;
1159 24236869 bellard
            break;
1160 24236869 bellard
        case 5: /* Hextile */
1161 24236869 bellard
            vs->has_hextile = 1;
1162 24236869 bellard
            break;
1163 24236869 bellard
        case -223: /* DesktopResize */
1164 24236869 bellard
            vs->has_resize = 1;
1165 24236869 bellard
            break;
1166 564c337e bellard
        case -257:
1167 564c337e bellard
            vs->has_pointer_type_change = 1;
1168 564c337e bellard
            break;
1169 9ca313aa aliguori
        case -258:
1170 9ca313aa aliguori
            send_ext_key_event_ack(vs);
1171 9ca313aa aliguori
            break;
1172 ca4cca4d aliguori
        case 0x574D5669:
1173 ca4cca4d aliguori
            vs->has_WMVi = 1;
1174 ca4cca4d aliguori
            break;
1175 24236869 bellard
        default:
1176 24236869 bellard
            break;
1177 24236869 bellard
        }
1178 24236869 bellard
    }
1179 564c337e bellard
1180 564c337e bellard
    check_pointer_type_change(vs, kbd_mouse_is_absolute());
1181 24236869 bellard
}
1182 24236869 bellard
1183 24236869 bellard
static void set_pixel_format(VncState *vs,
1184 24236869 bellard
                             int bits_per_pixel, int depth,
1185 24236869 bellard
                             int big_endian_flag, int true_color_flag,
1186 24236869 bellard
                             int red_max, int green_max, int blue_max,
1187 24236869 bellard
                             int red_shift, int green_shift, int blue_shift)
1188 24236869 bellard
{
1189 3512779a bellard
    int host_big_endian_flag;
1190 24236869 bellard
1191 3512779a bellard
#ifdef WORDS_BIGENDIAN
1192 3512779a bellard
    host_big_endian_flag = 1;
1193 3512779a bellard
#else
1194 3512779a bellard
    host_big_endian_flag = 0;
1195 3512779a bellard
#endif
1196 3512779a bellard
    if (!true_color_flag) {
1197 3512779a bellard
    fail:
1198 24236869 bellard
        vnc_client_error(vs);
1199 3512779a bellard
        return;
1200 3512779a bellard
    }
1201 5fafdf24 ths
    if (bits_per_pixel == 32 &&
1202 7eac3a87 aliguori
        bits_per_pixel == vs->depth * 8 &&
1203 3512779a bellard
        host_big_endian_flag == big_endian_flag &&
1204 3512779a bellard
        red_max == 0xff && green_max == 0xff && blue_max == 0xff &&
1205 3512779a bellard
        red_shift == 16 && green_shift == 8 && blue_shift == 0) {
1206 3512779a bellard
        vs->depth = 4;
1207 3512779a bellard
        vs->write_pixels = vnc_write_pixels_copy;
1208 3512779a bellard
        vs->send_hextile_tile = send_hextile_tile_32;
1209 5fafdf24 ths
    } else
1210 5fafdf24 ths
    if (bits_per_pixel == 16 &&
1211 7eac3a87 aliguori
        bits_per_pixel == vs->depth * 8 && 
1212 3512779a bellard
        host_big_endian_flag == big_endian_flag &&
1213 3512779a bellard
        red_max == 31 && green_max == 63 && blue_max == 31 &&
1214 3512779a bellard
        red_shift == 11 && green_shift == 5 && blue_shift == 0) {
1215 3512779a bellard
        vs->depth = 2;
1216 3512779a bellard
        vs->write_pixels = vnc_write_pixels_copy;
1217 3512779a bellard
        vs->send_hextile_tile = send_hextile_tile_16;
1218 5fafdf24 ths
    } else
1219 5fafdf24 ths
    if (bits_per_pixel == 8 &&
1220 7eac3a87 aliguori
        bits_per_pixel == vs->depth * 8 &&
1221 3512779a bellard
        red_max == 7 && green_max == 7 && blue_max == 3 &&
1222 3512779a bellard
        red_shift == 5 && green_shift == 2 && blue_shift == 0) {
1223 3512779a bellard
        vs->depth = 1;
1224 3512779a bellard
        vs->write_pixels = vnc_write_pixels_copy;
1225 3512779a bellard
        vs->send_hextile_tile = send_hextile_tile_8;
1226 5fafdf24 ths
    } else
1227 3512779a bellard
    {
1228 3512779a bellard
        /* generic and slower case */
1229 3512779a bellard
        if (bits_per_pixel != 8 &&
1230 3512779a bellard
            bits_per_pixel != 16 &&
1231 3512779a bellard
            bits_per_pixel != 32)
1232 3512779a bellard
            goto fail;
1233 7eac3a87 aliguori
        if (vs->depth == 4) {
1234 7eac3a87 aliguori
            vs->send_hextile_tile = send_hextile_tile_generic_32;
1235 7eac3a87 aliguori
        } else if (vs->depth == 2) {
1236 7eac3a87 aliguori
           vs->send_hextile_tile = send_hextile_tile_generic_16;
1237 7eac3a87 aliguori
        } else {
1238 7eac3a87 aliguori
            vs->send_hextile_tile = send_hextile_tile_generic_8;
1239 7eac3a87 aliguori
        }
1240 7eac3a87 aliguori
1241 3512779a bellard
        vs->pix_big_endian = big_endian_flag;
1242 3512779a bellard
        vs->write_pixels = vnc_write_pixels_generic;
1243 3512779a bellard
    }
1244 24236869 bellard
1245 7eac3a87 aliguori
    vs->client_red_shift = red_shift;
1246 7eac3a87 aliguori
    vs->client_red_max = red_max;
1247 7eac3a87 aliguori
    vs->client_green_shift = green_shift;
1248 7eac3a87 aliguori
    vs->client_green_max = green_max;
1249 7eac3a87 aliguori
    vs->client_blue_shift = blue_shift;
1250 7eac3a87 aliguori
    vs->client_blue_max = blue_max;
1251 7eac3a87 aliguori
    vs->pix_bpp = bits_per_pixel / 8;
1252 24236869 bellard
1253 24236869 bellard
    vga_hw_invalidate();
1254 24236869 bellard
    vga_hw_update();
1255 24236869 bellard
}
1256 24236869 bellard
1257 ca4cca4d aliguori
static void pixel_format_message (VncState *vs) {
1258 ca4cca4d aliguori
    char pad[3] = { 0, 0, 0 };
1259 ca4cca4d aliguori
1260 ca4cca4d aliguori
    vnc_write_u8(vs, vs->depth * 8); /* bits-per-pixel */
1261 ca4cca4d aliguori
    if (vs->depth == 4) vnc_write_u8(vs, 24); /* depth */
1262 ca4cca4d aliguori
    else vnc_write_u8(vs, vs->depth * 8); /* depth */
1263 ca4cca4d aliguori
1264 ca4cca4d aliguori
#ifdef WORDS_BIGENDIAN
1265 ca4cca4d aliguori
    vnc_write_u8(vs, 1);             /* big-endian-flag */
1266 ca4cca4d aliguori
#else
1267 ca4cca4d aliguori
    vnc_write_u8(vs, 0);             /* big-endian-flag */
1268 ca4cca4d aliguori
#endif
1269 ca4cca4d aliguori
    vnc_write_u8(vs, 1);             /* true-color-flag */
1270 ca4cca4d aliguori
    if (vs->depth == 4) {
1271 ca4cca4d aliguori
        vnc_write_u16(vs, 0xFF);     /* red-max */
1272 ca4cca4d aliguori
        vnc_write_u16(vs, 0xFF);     /* green-max */
1273 ca4cca4d aliguori
        vnc_write_u16(vs, 0xFF);     /* blue-max */
1274 ca4cca4d aliguori
        vnc_write_u8(vs, 16);        /* red-shift */
1275 ca4cca4d aliguori
        vnc_write_u8(vs, 8);         /* green-shift */
1276 ca4cca4d aliguori
        vnc_write_u8(vs, 0);         /* blue-shift */
1277 ca4cca4d aliguori
        vs->send_hextile_tile = send_hextile_tile_32;
1278 ca4cca4d aliguori
    } else if (vs->depth == 2) {
1279 ca4cca4d aliguori
        vnc_write_u16(vs, 31);       /* red-max */
1280 ca4cca4d aliguori
        vnc_write_u16(vs, 63);       /* green-max */
1281 ca4cca4d aliguori
        vnc_write_u16(vs, 31);       /* blue-max */
1282 ca4cca4d aliguori
        vnc_write_u8(vs, 11);        /* red-shift */
1283 ca4cca4d aliguori
        vnc_write_u8(vs, 5);         /* green-shift */
1284 ca4cca4d aliguori
        vnc_write_u8(vs, 0);         /* blue-shift */
1285 ca4cca4d aliguori
        vs->send_hextile_tile = send_hextile_tile_16;
1286 ca4cca4d aliguori
    } else if (vs->depth == 1) {
1287 ca4cca4d aliguori
        /* XXX: change QEMU pixel 8 bit pixel format to match the VNC one ? */
1288 ca4cca4d aliguori
        vnc_write_u16(vs, 7);        /* red-max */
1289 ca4cca4d aliguori
        vnc_write_u16(vs, 7);        /* green-max */
1290 ca4cca4d aliguori
        vnc_write_u16(vs, 3);        /* blue-max */
1291 ca4cca4d aliguori
        vnc_write_u8(vs, 5);         /* red-shift */
1292 ca4cca4d aliguori
        vnc_write_u8(vs, 2);         /* green-shift */
1293 ca4cca4d aliguori
        vnc_write_u8(vs, 0);         /* blue-shift */
1294 ca4cca4d aliguori
        vs->send_hextile_tile = send_hextile_tile_8;
1295 ca4cca4d aliguori
    }
1296 ca4cca4d aliguori
    vs->client_red_max = vs->server_red_max;
1297 ca4cca4d aliguori
    vs->client_green_max = vs->server_green_max;
1298 ca4cca4d aliguori
    vs->client_blue_max = vs->server_blue_max;
1299 ca4cca4d aliguori
    vs->client_red_shift = vs->server_red_shift;
1300 ca4cca4d aliguori
    vs->client_green_shift = vs->server_green_shift;
1301 ca4cca4d aliguori
    vs->client_blue_shift = vs->server_blue_shift;
1302 ca4cca4d aliguori
    vs->pix_bpp = vs->depth * 8;
1303 ca4cca4d aliguori
    vs->write_pixels = vnc_write_pixels_copy;
1304 ca4cca4d aliguori
1305 ca4cca4d aliguori
    vnc_write(vs, pad, 3);           /* padding */
1306 ca4cca4d aliguori
}
1307 ca4cca4d aliguori
1308 7eac3a87 aliguori
static void vnc_colordepth(DisplayState *ds, int depth)
1309 7eac3a87 aliguori
{
1310 7eac3a87 aliguori
    int host_big_endian_flag;
1311 7eac3a87 aliguori
    struct VncState *vs = ds->opaque;
1312 7eac3a87 aliguori
1313 7eac3a87 aliguori
    switch (depth) {
1314 7eac3a87 aliguori
        case 24:
1315 7eac3a87 aliguori
            if (ds->depth == 32) return;
1316 7eac3a87 aliguori
            depth = 32;
1317 7eac3a87 aliguori
            break;
1318 7eac3a87 aliguori
        case 15:
1319 7eac3a87 aliguori
        case 8:
1320 7eac3a87 aliguori
        case 0:
1321 7eac3a87 aliguori
            return;
1322 7eac3a87 aliguori
        default:
1323 7eac3a87 aliguori
            break;
1324 7eac3a87 aliguori
    }
1325 7eac3a87 aliguori
1326 7eac3a87 aliguori
#ifdef WORDS_BIGENDIAN
1327 7eac3a87 aliguori
    host_big_endian_flag = 1;
1328 7eac3a87 aliguori
#else
1329 7eac3a87 aliguori
    host_big_endian_flag = 0;
1330 7eac3a87 aliguori
#endif   
1331 7eac3a87 aliguori
    
1332 7eac3a87 aliguori
    switch (depth) {
1333 7eac3a87 aliguori
        case 8:
1334 7eac3a87 aliguori
            vs->depth = depth / 8;
1335 7eac3a87 aliguori
            vs->server_red_max = 7;
1336 7eac3a87 aliguori
            vs->server_green_max = 7;
1337 7eac3a87 aliguori
            vs->server_blue_max = 3;
1338 7eac3a87 aliguori
            vs->server_red_shift = 5;
1339 7eac3a87 aliguori
            vs->server_green_shift = 2;
1340 7eac3a87 aliguori
            vs->server_blue_shift = 0;
1341 7eac3a87 aliguori
            break;
1342 7eac3a87 aliguori
        case 16:
1343 7eac3a87 aliguori
            vs->depth = depth / 8;
1344 7eac3a87 aliguori
            vs->server_red_max = 31;
1345 7eac3a87 aliguori
            vs->server_green_max = 63;
1346 7eac3a87 aliguori
            vs->server_blue_max = 31;
1347 7eac3a87 aliguori
            vs->server_red_shift = 11;
1348 7eac3a87 aliguori
            vs->server_green_shift = 5;
1349 7eac3a87 aliguori
            vs->server_blue_shift = 0;
1350 7eac3a87 aliguori
            break;
1351 7eac3a87 aliguori
        case 32:
1352 7eac3a87 aliguori
            vs->depth = 4;
1353 7eac3a87 aliguori
            vs->server_red_max = 255;
1354 7eac3a87 aliguori
            vs->server_green_max = 255;
1355 7eac3a87 aliguori
            vs->server_blue_max = 255;
1356 7eac3a87 aliguori
            vs->server_red_shift = 16;
1357 7eac3a87 aliguori
            vs->server_green_shift = 8;
1358 7eac3a87 aliguori
            vs->server_blue_shift = 0;
1359 7eac3a87 aliguori
            break;
1360 7eac3a87 aliguori
        default:
1361 7eac3a87 aliguori
            return;
1362 7eac3a87 aliguori
    }
1363 7eac3a87 aliguori
1364 ca4cca4d aliguori
    if (vs->csock != -1 && vs->has_WMVi) {
1365 ca4cca4d aliguori
        /* Sending a WMVi message to notify the client*/
1366 ca4cca4d aliguori
        vnc_write_u8(vs, 0);  /* msg id */
1367 ca4cca4d aliguori
        vnc_write_u8(vs, 0);
1368 ca4cca4d aliguori
        vnc_write_u16(vs, 1); /* number of rects */
1369 ca4cca4d aliguori
        vnc_framebuffer_update(vs, 0, 0, ds->width, ds->height, 0x574D5669);
1370 ca4cca4d aliguori
        pixel_format_message(vs);
1371 ca4cca4d aliguori
        vnc_flush(vs);
1372 7eac3a87 aliguori
    } else {
1373 ca4cca4d aliguori
        if (vs->pix_bpp == 4 && vs->depth == 4 &&
1374 ca4cca4d aliguori
                host_big_endian_flag == vs->pix_big_endian &&
1375 ca4cca4d aliguori
                vs->client_red_max == 0xff && vs->client_green_max == 0xff && vs->client_blue_max == 0xff &&
1376 ca4cca4d aliguori
                vs->client_red_shift == 16 && vs->client_green_shift == 8 && vs->client_blue_shift == 0) {
1377 ca4cca4d aliguori
            vs->write_pixels = vnc_write_pixels_copy;
1378 ca4cca4d aliguori
            vs->send_hextile_tile = send_hextile_tile_32;
1379 ca4cca4d aliguori
        } else if (vs->pix_bpp == 2 && vs->depth == 2 &&
1380 ca4cca4d aliguori
                host_big_endian_flag == vs->pix_big_endian &&
1381 ca4cca4d aliguori
                vs->client_red_max == 31 && vs->client_green_max == 63 && vs->client_blue_max == 31 &&
1382 ca4cca4d aliguori
                vs->client_red_shift == 11 && vs->client_green_shift == 5 && vs->client_blue_shift == 0) {
1383 ca4cca4d aliguori
            vs->write_pixels = vnc_write_pixels_copy;
1384 ca4cca4d aliguori
            vs->send_hextile_tile = send_hextile_tile_16;
1385 ca4cca4d aliguori
        } else if (vs->pix_bpp == 1 && vs->depth == 1 &&
1386 ca4cca4d aliguori
                host_big_endian_flag == vs->pix_big_endian &&
1387 ca4cca4d aliguori
                vs->client_red_max == 7 && vs->client_green_max == 7 && vs->client_blue_max == 3 &&
1388 ca4cca4d aliguori
                vs->client_red_shift == 5 && vs->client_green_shift == 2 && vs->client_blue_shift == 0) {
1389 ca4cca4d aliguori
            vs->write_pixels = vnc_write_pixels_copy;
1390 ca4cca4d aliguori
            vs->send_hextile_tile = send_hextile_tile_8;
1391 7eac3a87 aliguori
        } else {
1392 ca4cca4d aliguori
            if (vs->depth == 4) {
1393 ca4cca4d aliguori
                vs->send_hextile_tile = send_hextile_tile_generic_32;
1394 ca4cca4d aliguori
            } else if (vs->depth == 2) {
1395 ca4cca4d aliguori
                vs->send_hextile_tile = send_hextile_tile_generic_16;
1396 ca4cca4d aliguori
            } else {
1397 ca4cca4d aliguori
                vs->send_hextile_tile = send_hextile_tile_generic_8;
1398 ca4cca4d aliguori
            }
1399 ca4cca4d aliguori
            vs->write_pixels = vnc_write_pixels_generic;
1400 7eac3a87 aliguori
        }
1401 7eac3a87 aliguori
    }
1402 7eac3a87 aliguori
}
1403 7eac3a87 aliguori
1404 60fe76f3 ths
static int protocol_client_msg(VncState *vs, uint8_t *data, size_t len)
1405 24236869 bellard
{
1406 24236869 bellard
    int i;
1407 24236869 bellard
    uint16_t limit;
1408 24236869 bellard
1409 24236869 bellard
    switch (data[0]) {
1410 24236869 bellard
    case 0:
1411 24236869 bellard
        if (len == 1)
1412 24236869 bellard
            return 20;
1413 24236869 bellard
1414 24236869 bellard
        set_pixel_format(vs, read_u8(data, 4), read_u8(data, 5),
1415 24236869 bellard
                         read_u8(data, 6), read_u8(data, 7),
1416 24236869 bellard
                         read_u16(data, 8), read_u16(data, 10),
1417 24236869 bellard
                         read_u16(data, 12), read_u8(data, 14),
1418 24236869 bellard
                         read_u8(data, 15), read_u8(data, 16));
1419 24236869 bellard
        break;
1420 24236869 bellard
    case 2:
1421 24236869 bellard
        if (len == 1)
1422 24236869 bellard
            return 4;
1423 24236869 bellard
1424 24236869 bellard
        if (len == 4)
1425 24236869 bellard
            return 4 + (read_u16(data, 2) * 4);
1426 24236869 bellard
1427 24236869 bellard
        limit = read_u16(data, 2);
1428 24236869 bellard
        for (i = 0; i < limit; i++) {
1429 24236869 bellard
            int32_t val = read_s32(data, 4 + (i * 4));
1430 24236869 bellard
            memcpy(data + 4 + (i * 4), &val, sizeof(val));
1431 24236869 bellard
        }
1432 24236869 bellard
1433 24236869 bellard
        set_encodings(vs, (int32_t *)(data + 4), limit);
1434 24236869 bellard
        break;
1435 24236869 bellard
    case 3:
1436 24236869 bellard
        if (len == 1)
1437 24236869 bellard
            return 10;
1438 24236869 bellard
1439 24236869 bellard
        framebuffer_update_request(vs,
1440 24236869 bellard
                                   read_u8(data, 1), read_u16(data, 2), read_u16(data, 4),
1441 24236869 bellard
                                   read_u16(data, 6), read_u16(data, 8));
1442 24236869 bellard
        break;
1443 24236869 bellard
    case 4:
1444 24236869 bellard
        if (len == 1)
1445 24236869 bellard
            return 8;
1446 24236869 bellard
1447 24236869 bellard
        key_event(vs, read_u8(data, 1), read_u32(data, 4));
1448 24236869 bellard
        break;
1449 24236869 bellard
    case 5:
1450 24236869 bellard
        if (len == 1)
1451 24236869 bellard
            return 6;
1452 24236869 bellard
1453 24236869 bellard
        pointer_event(vs, read_u8(data, 1), read_u16(data, 2), read_u16(data, 4));
1454 24236869 bellard
        break;
1455 24236869 bellard
    case 6:
1456 24236869 bellard
        if (len == 1)
1457 24236869 bellard
            return 8;
1458 24236869 bellard
1459 baa7666c ths
        if (len == 8) {
1460 baa7666c ths
            uint32_t dlen = read_u32(data, 4);
1461 baa7666c ths
            if (dlen > 0)
1462 baa7666c ths
                return 8 + dlen;
1463 baa7666c ths
        }
1464 24236869 bellard
1465 24236869 bellard
        client_cut_text(vs, read_u32(data, 4), data + 8);
1466 24236869 bellard
        break;
1467 9ca313aa aliguori
    case 255:
1468 9ca313aa aliguori
        if (len == 1)
1469 9ca313aa aliguori
            return 2;
1470 9ca313aa aliguori
1471 9ca313aa aliguori
        switch (read_u8(data, 1)) {
1472 9ca313aa aliguori
        case 0:
1473 9ca313aa aliguori
            if (len == 2)
1474 9ca313aa aliguori
                return 12;
1475 9ca313aa aliguori
1476 9ca313aa aliguori
            ext_key_event(vs, read_u16(data, 2),
1477 9ca313aa aliguori
                          read_u32(data, 4), read_u32(data, 8));
1478 9ca313aa aliguori
            break;
1479 9ca313aa aliguori
        default:
1480 9ca313aa aliguori
            printf("Msg: %d\n", read_u16(data, 0));
1481 9ca313aa aliguori
            vnc_client_error(vs);
1482 9ca313aa aliguori
            break;
1483 9ca313aa aliguori
        }
1484 9ca313aa aliguori
        break;
1485 24236869 bellard
    default:
1486 24236869 bellard
        printf("Msg: %d\n", data[0]);
1487 24236869 bellard
        vnc_client_error(vs);
1488 24236869 bellard
        break;
1489 24236869 bellard
    }
1490 5fafdf24 ths
1491 24236869 bellard
    vnc_read_when(vs, protocol_client_msg, 1);
1492 24236869 bellard
    return 0;
1493 24236869 bellard
}
1494 24236869 bellard
1495 60fe76f3 ths
static int protocol_client_init(VncState *vs, uint8_t *data, size_t len)
1496 24236869 bellard
{
1497 c35734b2 ths
    char buf[1024];
1498 c35734b2 ths
    int size;
1499 24236869 bellard
1500 24236869 bellard
    vs->width = vs->ds->width;
1501 24236869 bellard
    vs->height = vs->ds->height;
1502 24236869 bellard
    vnc_write_u16(vs, vs->ds->width);
1503 24236869 bellard
    vnc_write_u16(vs, vs->ds->height);
1504 24236869 bellard
1505 ca4cca4d aliguori
    pixel_format_message(vs);
1506 24236869 bellard
1507 c35734b2 ths
    if (qemu_name)
1508 c35734b2 ths
        size = snprintf(buf, sizeof(buf), "QEMU (%s)", qemu_name);
1509 c35734b2 ths
    else
1510 c35734b2 ths
        size = snprintf(buf, sizeof(buf), "QEMU");
1511 c35734b2 ths
1512 c35734b2 ths
    vnc_write_u32(vs, size);
1513 c35734b2 ths
    vnc_write(vs, buf, size);
1514 24236869 bellard
    vnc_flush(vs);
1515 24236869 bellard
1516 24236869 bellard
    vnc_read_when(vs, protocol_client_msg, 1);
1517 24236869 bellard
1518 24236869 bellard
    return 0;
1519 24236869 bellard
}
1520 24236869 bellard
1521 70848515 ths
static void make_challenge(VncState *vs)
1522 70848515 ths
{
1523 70848515 ths
    int i;
1524 70848515 ths
1525 70848515 ths
    srand(time(NULL)+getpid()+getpid()*987654+rand());
1526 70848515 ths
1527 70848515 ths
    for (i = 0 ; i < sizeof(vs->challenge) ; i++)
1528 70848515 ths
        vs->challenge[i] = (int) (256.0*rand()/(RAND_MAX+1.0));
1529 70848515 ths
}
1530 70848515 ths
1531 60fe76f3 ths
static int protocol_client_auth_vnc(VncState *vs, uint8_t *data, size_t len)
1532 70848515 ths
{
1533 60fe76f3 ths
    unsigned char response[VNC_AUTH_CHALLENGE_SIZE];
1534 70848515 ths
    int i, j, pwlen;
1535 60fe76f3 ths
    unsigned char key[8];
1536 70848515 ths
1537 70848515 ths
    if (!vs->password || !vs->password[0]) {
1538 70848515 ths
        VNC_DEBUG("No password configured on server");
1539 70848515 ths
        vnc_write_u32(vs, 1); /* Reject auth */
1540 70848515 ths
        if (vs->minor >= 8) {
1541 70848515 ths
            static const char err[] = "Authentication failed";
1542 70848515 ths
            vnc_write_u32(vs, sizeof(err));
1543 70848515 ths
            vnc_write(vs, err, sizeof(err));
1544 70848515 ths
        }
1545 70848515 ths
        vnc_flush(vs);
1546 70848515 ths
        vnc_client_error(vs);
1547 70848515 ths
        return 0;
1548 70848515 ths
    }
1549 70848515 ths
1550 70848515 ths
    memcpy(response, vs->challenge, VNC_AUTH_CHALLENGE_SIZE);
1551 70848515 ths
1552 70848515 ths
    /* Calculate the expected challenge response */
1553 70848515 ths
    pwlen = strlen(vs->password);
1554 70848515 ths
    for (i=0; i<sizeof(key); i++)
1555 70848515 ths
        key[i] = i<pwlen ? vs->password[i] : 0;
1556 70848515 ths
    deskey(key, EN0);
1557 70848515 ths
    for (j = 0; j < VNC_AUTH_CHALLENGE_SIZE; j += 8)
1558 70848515 ths
        des(response+j, response+j);
1559 70848515 ths
1560 70848515 ths
    /* Compare expected vs actual challenge response */
1561 70848515 ths
    if (memcmp(response, data, VNC_AUTH_CHALLENGE_SIZE) != 0) {
1562 70848515 ths
        VNC_DEBUG("Client challenge reponse did not match\n");
1563 70848515 ths
        vnc_write_u32(vs, 1); /* Reject auth */
1564 70848515 ths
        if (vs->minor >= 8) {
1565 70848515 ths
            static const char err[] = "Authentication failed";
1566 70848515 ths
            vnc_write_u32(vs, sizeof(err));
1567 70848515 ths
            vnc_write(vs, err, sizeof(err));
1568 70848515 ths
        }
1569 70848515 ths
        vnc_flush(vs);
1570 70848515 ths
        vnc_client_error(vs);
1571 70848515 ths
    } else {
1572 70848515 ths
        VNC_DEBUG("Accepting VNC challenge response\n");
1573 70848515 ths
        vnc_write_u32(vs, 0); /* Accept auth */
1574 70848515 ths
        vnc_flush(vs);
1575 70848515 ths
1576 70848515 ths
        vnc_read_when(vs, protocol_client_init, 1);
1577 70848515 ths
    }
1578 70848515 ths
    return 0;
1579 70848515 ths
}
1580 70848515 ths
1581 70848515 ths
static int start_auth_vnc(VncState *vs)
1582 70848515 ths
{
1583 70848515 ths
    make_challenge(vs);
1584 70848515 ths
    /* Send client a 'random' challenge */
1585 70848515 ths
    vnc_write(vs, vs->challenge, sizeof(vs->challenge));
1586 70848515 ths
    vnc_flush(vs);
1587 70848515 ths
1588 70848515 ths
    vnc_read_when(vs, protocol_client_auth_vnc, sizeof(vs->challenge));
1589 70848515 ths
    return 0;
1590 70848515 ths
}
1591 70848515 ths
1592 8d5d2d4c ths
1593 eb38c52c blueswir1
#ifdef CONFIG_VNC_TLS
1594 8d5d2d4c ths
#define DH_BITS 1024
1595 8d5d2d4c ths
static gnutls_dh_params_t dh_params;
1596 8d5d2d4c ths
1597 8d5d2d4c ths
static int vnc_tls_initialize(void)
1598 8d5d2d4c ths
{
1599 8d5d2d4c ths
    static int tlsinitialized = 0;
1600 8d5d2d4c ths
1601 8d5d2d4c ths
    if (tlsinitialized)
1602 8d5d2d4c ths
        return 1;
1603 8d5d2d4c ths
1604 8d5d2d4c ths
    if (gnutls_global_init () < 0)
1605 8d5d2d4c ths
        return 0;
1606 8d5d2d4c ths
1607 8d5d2d4c ths
    /* XXX ought to re-generate diffie-hellmen params periodically */
1608 8d5d2d4c ths
    if (gnutls_dh_params_init (&dh_params) < 0)
1609 8d5d2d4c ths
        return 0;
1610 8d5d2d4c ths
    if (gnutls_dh_params_generate2 (dh_params, DH_BITS) < 0)
1611 8d5d2d4c ths
        return 0;
1612 8d5d2d4c ths
1613 234c9bcd ths
#if defined(_VNC_DEBUG) && _VNC_DEBUG >= 2
1614 8d5d2d4c ths
    gnutls_global_set_log_level(10);
1615 8d5d2d4c ths
    gnutls_global_set_log_function(vnc_debug_gnutls_log);
1616 8d5d2d4c ths
#endif
1617 8d5d2d4c ths
1618 8d5d2d4c ths
    tlsinitialized = 1;
1619 8d5d2d4c ths
1620 8d5d2d4c ths
    return 1;
1621 8d5d2d4c ths
}
1622 8d5d2d4c ths
1623 8d5d2d4c ths
static gnutls_anon_server_credentials vnc_tls_initialize_anon_cred(void)
1624 8d5d2d4c ths
{
1625 8d5d2d4c ths
    gnutls_anon_server_credentials anon_cred;
1626 8d5d2d4c ths
    int ret;
1627 8d5d2d4c ths
1628 8d5d2d4c ths
    if ((ret = gnutls_anon_allocate_server_credentials(&anon_cred)) < 0) {
1629 8d5d2d4c ths
        VNC_DEBUG("Cannot allocate credentials %s\n", gnutls_strerror(ret));
1630 8d5d2d4c ths
        return NULL;
1631 8d5d2d4c ths
    }
1632 8d5d2d4c ths
1633 8d5d2d4c ths
    gnutls_anon_set_server_dh_params(anon_cred, dh_params);
1634 8d5d2d4c ths
1635 8d5d2d4c ths
    return anon_cred;
1636 8d5d2d4c ths
}
1637 8d5d2d4c ths
1638 8d5d2d4c ths
1639 6f43024c ths
static gnutls_certificate_credentials_t vnc_tls_initialize_x509_cred(VncState *vs)
1640 3a702699 ths
{
1641 3a702699 ths
    gnutls_certificate_credentials_t x509_cred;
1642 3a702699 ths
    int ret;
1643 6f43024c ths
1644 6f43024c ths
    if (!vs->x509cacert) {
1645 6f43024c ths
        VNC_DEBUG("No CA x509 certificate specified\n");
1646 6f43024c ths
        return NULL;
1647 6f43024c ths
    }
1648 6f43024c ths
    if (!vs->x509cert) {
1649 6f43024c ths
        VNC_DEBUG("No server x509 certificate specified\n");
1650 6f43024c ths
        return NULL;
1651 6f43024c ths
    }
1652 6f43024c ths
    if (!vs->x509key) {
1653 6f43024c ths
        VNC_DEBUG("No server private key specified\n");
1654 6f43024c ths
        return NULL;
1655 6f43024c ths
    }
1656 3a702699 ths
1657 3a702699 ths
    if ((ret = gnutls_certificate_allocate_credentials(&x509_cred)) < 0) {
1658 3a702699 ths
        VNC_DEBUG("Cannot allocate credentials %s\n", gnutls_strerror(ret));
1659 3a702699 ths
        return NULL;
1660 3a702699 ths
    }
1661 6f43024c ths
    if ((ret = gnutls_certificate_set_x509_trust_file(x509_cred,
1662 6f43024c ths
                                                      vs->x509cacert,
1663 6f43024c ths
                                                      GNUTLS_X509_FMT_PEM)) < 0) {
1664 3a702699 ths
        VNC_DEBUG("Cannot load CA certificate %s\n", gnutls_strerror(ret));
1665 3a702699 ths
        gnutls_certificate_free_credentials(x509_cred);
1666 3a702699 ths
        return NULL;
1667 3a702699 ths
    }
1668 3a702699 ths
1669 6f43024c ths
    if ((ret = gnutls_certificate_set_x509_key_file (x509_cred,
1670 6f43024c ths
                                                     vs->x509cert,
1671 6f43024c ths
                                                     vs->x509key,
1672 3a702699 ths
                                                     GNUTLS_X509_FMT_PEM)) < 0) {
1673 3a702699 ths
        VNC_DEBUG("Cannot load certificate & key %s\n", gnutls_strerror(ret));
1674 3a702699 ths
        gnutls_certificate_free_credentials(x509_cred);
1675 3a702699 ths
        return NULL;
1676 3a702699 ths
    }
1677 3a702699 ths
1678 6f43024c ths
    if (vs->x509cacrl) {
1679 6f43024c ths
        if ((ret = gnutls_certificate_set_x509_crl_file(x509_cred,
1680 6f43024c ths
                                                        vs->x509cacrl,
1681 6f43024c ths
                                                        GNUTLS_X509_FMT_PEM)) < 0) {
1682 3a702699 ths
            VNC_DEBUG("Cannot load CRL %s\n", gnutls_strerror(ret));
1683 3a702699 ths
            gnutls_certificate_free_credentials(x509_cred);
1684 3a702699 ths
            return NULL;
1685 3a702699 ths
        }
1686 3a702699 ths
    }
1687 3a702699 ths
1688 3a702699 ths
    gnutls_certificate_set_dh_params (x509_cred, dh_params);
1689 3a702699 ths
1690 3a702699 ths
    return x509_cred;
1691 3a702699 ths
}
1692 3a702699 ths
1693 469b15c6 ths
static int vnc_validate_certificate(struct VncState *vs)
1694 469b15c6 ths
{
1695 469b15c6 ths
    int ret;
1696 469b15c6 ths
    unsigned int status;
1697 469b15c6 ths
    const gnutls_datum_t *certs;
1698 469b15c6 ths
    unsigned int nCerts, i;
1699 469b15c6 ths
    time_t now;
1700 469b15c6 ths
1701 469b15c6 ths
    VNC_DEBUG("Validating client certificate\n");
1702 469b15c6 ths
    if ((ret = gnutls_certificate_verify_peers2 (vs->tls_session, &status)) < 0) {
1703 469b15c6 ths
        VNC_DEBUG("Verify failed %s\n", gnutls_strerror(ret));
1704 469b15c6 ths
        return -1;
1705 469b15c6 ths
    }
1706 469b15c6 ths
1707 469b15c6 ths
    if ((now = time(NULL)) == ((time_t)-1)) {
1708 469b15c6 ths
        return -1;
1709 469b15c6 ths
    }
1710 469b15c6 ths
1711 469b15c6 ths
    if (status != 0) {
1712 469b15c6 ths
        if (status & GNUTLS_CERT_INVALID)
1713 469b15c6 ths
            VNC_DEBUG("The certificate is not trusted.\n");
1714 469b15c6 ths
1715 469b15c6 ths
        if (status & GNUTLS_CERT_SIGNER_NOT_FOUND)
1716 469b15c6 ths
            VNC_DEBUG("The certificate hasn't got a known issuer.\n");
1717 469b15c6 ths
1718 469b15c6 ths
        if (status & GNUTLS_CERT_REVOKED)
1719 469b15c6 ths
            VNC_DEBUG("The certificate has been revoked.\n");
1720 469b15c6 ths
1721 469b15c6 ths
        if (status & GNUTLS_CERT_INSECURE_ALGORITHM)
1722 469b15c6 ths
            VNC_DEBUG("The certificate uses an insecure algorithm\n");
1723 469b15c6 ths
1724 469b15c6 ths
        return -1;
1725 469b15c6 ths
    } else {
1726 469b15c6 ths
        VNC_DEBUG("Certificate is valid!\n");
1727 469b15c6 ths
    }
1728 469b15c6 ths
1729 469b15c6 ths
    /* Only support x509 for now */
1730 469b15c6 ths
    if (gnutls_certificate_type_get(vs->tls_session) != GNUTLS_CRT_X509)
1731 469b15c6 ths
        return -1;
1732 469b15c6 ths
1733 469b15c6 ths
    if (!(certs = gnutls_certificate_get_peers(vs->tls_session, &nCerts)))
1734 469b15c6 ths
        return -1;
1735 469b15c6 ths
1736 469b15c6 ths
    for (i = 0 ; i < nCerts ; i++) {
1737 469b15c6 ths
        gnutls_x509_crt_t cert;
1738 469b15c6 ths
        VNC_DEBUG ("Checking certificate chain %d\n", i);
1739 469b15c6 ths
        if (gnutls_x509_crt_init (&cert) < 0)
1740 469b15c6 ths
            return -1;
1741 469b15c6 ths
1742 469b15c6 ths
        if (gnutls_x509_crt_import(cert, &certs[i], GNUTLS_X509_FMT_DER) < 0) {
1743 469b15c6 ths
            gnutls_x509_crt_deinit (cert);
1744 469b15c6 ths
            return -1;
1745 469b15c6 ths
        }
1746 469b15c6 ths
1747 469b15c6 ths
        if (gnutls_x509_crt_get_expiration_time (cert) < now) {
1748 469b15c6 ths
            VNC_DEBUG("The certificate has expired\n");
1749 469b15c6 ths
            gnutls_x509_crt_deinit (cert);
1750 469b15c6 ths
            return -1;
1751 469b15c6 ths
        }
1752 469b15c6 ths
1753 469b15c6 ths
        if (gnutls_x509_crt_get_activation_time (cert) > now) {
1754 469b15c6 ths
            VNC_DEBUG("The certificate is not yet activated\n");
1755 469b15c6 ths
            gnutls_x509_crt_deinit (cert);
1756 469b15c6 ths
            return -1;
1757 469b15c6 ths
        }
1758 469b15c6 ths
1759 469b15c6 ths
        if (gnutls_x509_crt_get_activation_time (cert) > now) {
1760 469b15c6 ths
            VNC_DEBUG("The certificate is not yet activated\n");
1761 469b15c6 ths
            gnutls_x509_crt_deinit (cert);
1762 469b15c6 ths
            return -1;
1763 469b15c6 ths
        }
1764 469b15c6 ths
1765 469b15c6 ths
        gnutls_x509_crt_deinit (cert);
1766 469b15c6 ths
    }
1767 469b15c6 ths
1768 469b15c6 ths
    return 0;
1769 469b15c6 ths
}
1770 469b15c6 ths
1771 469b15c6 ths
1772 8d5d2d4c ths
static int start_auth_vencrypt_subauth(VncState *vs)
1773 8d5d2d4c ths
{
1774 8d5d2d4c ths
    switch (vs->subauth) {
1775 8d5d2d4c ths
    case VNC_AUTH_VENCRYPT_TLSNONE:
1776 3a702699 ths
    case VNC_AUTH_VENCRYPT_X509NONE:
1777 8d5d2d4c ths
       VNC_DEBUG("Accept TLS auth none\n");
1778 8d5d2d4c ths
       vnc_write_u32(vs, 0); /* Accept auth completion */
1779 8d5d2d4c ths
       vnc_read_when(vs, protocol_client_init, 1);
1780 8d5d2d4c ths
       break;
1781 8d5d2d4c ths
1782 8d5d2d4c ths
    case VNC_AUTH_VENCRYPT_TLSVNC:
1783 3a702699 ths
    case VNC_AUTH_VENCRYPT_X509VNC:
1784 8d5d2d4c ths
       VNC_DEBUG("Start TLS auth VNC\n");
1785 8d5d2d4c ths
       return start_auth_vnc(vs);
1786 8d5d2d4c ths
1787 8d5d2d4c ths
    default: /* Should not be possible, but just in case */
1788 8d5d2d4c ths
       VNC_DEBUG("Reject auth %d\n", vs->auth);
1789 8d5d2d4c ths
       vnc_write_u8(vs, 1);
1790 8d5d2d4c ths
       if (vs->minor >= 8) {
1791 8d5d2d4c ths
           static const char err[] = "Unsupported authentication type";
1792 8d5d2d4c ths
           vnc_write_u32(vs, sizeof(err));
1793 8d5d2d4c ths
           vnc_write(vs, err, sizeof(err));
1794 8d5d2d4c ths
       }
1795 8d5d2d4c ths
       vnc_client_error(vs);
1796 8d5d2d4c ths
    }
1797 8d5d2d4c ths
1798 8d5d2d4c ths
    return 0;
1799 8d5d2d4c ths
}
1800 8d5d2d4c ths
1801 8d5d2d4c ths
static void vnc_handshake_io(void *opaque);
1802 8d5d2d4c ths
1803 8d5d2d4c ths
static int vnc_continue_handshake(struct VncState *vs) {
1804 8d5d2d4c ths
    int ret;
1805 8d5d2d4c ths
1806 8d5d2d4c ths
    if ((ret = gnutls_handshake(vs->tls_session)) < 0) {
1807 8d5d2d4c ths
       if (!gnutls_error_is_fatal(ret)) {
1808 8d5d2d4c ths
           VNC_DEBUG("Handshake interrupted (blocking)\n");
1809 8d5d2d4c ths
           if (!gnutls_record_get_direction(vs->tls_session))
1810 8d5d2d4c ths
               qemu_set_fd_handler(vs->csock, vnc_handshake_io, NULL, vs);
1811 8d5d2d4c ths
           else
1812 8d5d2d4c ths
               qemu_set_fd_handler(vs->csock, NULL, vnc_handshake_io, vs);
1813 8d5d2d4c ths
           return 0;
1814 8d5d2d4c ths
       }
1815 8d5d2d4c ths
       VNC_DEBUG("Handshake failed %s\n", gnutls_strerror(ret));
1816 8d5d2d4c ths
       vnc_client_error(vs);
1817 8d5d2d4c ths
       return -1;
1818 8d5d2d4c ths
    }
1819 8d5d2d4c ths
1820 469b15c6 ths
    if (vs->x509verify) {
1821 469b15c6 ths
        if (vnc_validate_certificate(vs) < 0) {
1822 469b15c6 ths
            VNC_DEBUG("Client verification failed\n");
1823 469b15c6 ths
            vnc_client_error(vs);
1824 469b15c6 ths
            return -1;
1825 469b15c6 ths
        } else {
1826 469b15c6 ths
            VNC_DEBUG("Client verification passed\n");
1827 469b15c6 ths
        }
1828 469b15c6 ths
    }
1829 469b15c6 ths
1830 8d5d2d4c ths
    VNC_DEBUG("Handshake done, switching to TLS data mode\n");
1831 8d5d2d4c ths
    vs->wiremode = VNC_WIREMODE_TLS;
1832 8d5d2d4c ths
    qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, vnc_client_write, vs);
1833 8d5d2d4c ths
1834 8d5d2d4c ths
    return start_auth_vencrypt_subauth(vs);
1835 8d5d2d4c ths
}
1836 8d5d2d4c ths
1837 8d5d2d4c ths
static void vnc_handshake_io(void *opaque) {
1838 8d5d2d4c ths
    struct VncState *vs = (struct VncState *)opaque;
1839 8d5d2d4c ths
1840 8d5d2d4c ths
    VNC_DEBUG("Handshake IO continue\n");
1841 8d5d2d4c ths
    vnc_continue_handshake(vs);
1842 8d5d2d4c ths
}
1843 8d5d2d4c ths
1844 3a702699 ths
#define NEED_X509_AUTH(vs)                              \
1845 3a702699 ths
    ((vs)->subauth == VNC_AUTH_VENCRYPT_X509NONE ||   \
1846 3a702699 ths
     (vs)->subauth == VNC_AUTH_VENCRYPT_X509VNC ||    \
1847 3a702699 ths
     (vs)->subauth == VNC_AUTH_VENCRYPT_X509PLAIN)
1848 3a702699 ths
1849 3a702699 ths
1850 8d5d2d4c ths
static int vnc_start_tls(struct VncState *vs) {
1851 8d5d2d4c ths
    static const int cert_type_priority[] = { GNUTLS_CRT_X509, 0 };
1852 8d5d2d4c ths
    static const int protocol_priority[]= { GNUTLS_TLS1_1, GNUTLS_TLS1_0, GNUTLS_SSL3, 0 };
1853 8d5d2d4c ths
    static const int kx_anon[] = {GNUTLS_KX_ANON_DH, 0};
1854 3a702699 ths
    static const int kx_x509[] = {GNUTLS_KX_DHE_DSS, GNUTLS_KX_RSA, GNUTLS_KX_DHE_RSA, GNUTLS_KX_SRP, 0};
1855 8d5d2d4c ths
1856 8d5d2d4c ths
    VNC_DEBUG("Do TLS setup\n");
1857 8d5d2d4c ths
    if (vnc_tls_initialize() < 0) {
1858 8d5d2d4c ths
        VNC_DEBUG("Failed to init TLS\n");
1859 8d5d2d4c ths
        vnc_client_error(vs);
1860 8d5d2d4c ths
        return -1;
1861 8d5d2d4c ths
    }
1862 8d5d2d4c ths
    if (vs->tls_session == NULL) {
1863 8d5d2d4c ths
        if (gnutls_init(&vs->tls_session, GNUTLS_SERVER) < 0) {
1864 8d5d2d4c ths
            vnc_client_error(vs);
1865 8d5d2d4c ths
            return -1;
1866 8d5d2d4c ths
        }
1867 8d5d2d4c ths
1868 8d5d2d4c ths
        if (gnutls_set_default_priority(vs->tls_session) < 0) {
1869 8d5d2d4c ths
            gnutls_deinit(vs->tls_session);
1870 8d5d2d4c ths
            vs->tls_session = NULL;
1871 8d5d2d4c ths
            vnc_client_error(vs);
1872 8d5d2d4c ths
            return -1;
1873 8d5d2d4c ths
        }
1874 8d5d2d4c ths
1875 3a702699 ths
        if (gnutls_kx_set_priority(vs->tls_session, NEED_X509_AUTH(vs) ? kx_x509 : kx_anon) < 0) {
1876 8d5d2d4c ths
            gnutls_deinit(vs->tls_session);
1877 8d5d2d4c ths
            vs->tls_session = NULL;
1878 8d5d2d4c ths
            vnc_client_error(vs);
1879 8d5d2d4c ths
            return -1;
1880 8d5d2d4c ths
        }
1881 8d5d2d4c ths
1882 8d5d2d4c ths
        if (gnutls_certificate_type_set_priority(vs->tls_session, cert_type_priority) < 0) {
1883 8d5d2d4c ths
            gnutls_deinit(vs->tls_session);
1884 8d5d2d4c ths
            vs->tls_session = NULL;
1885 8d5d2d4c ths
            vnc_client_error(vs);
1886 8d5d2d4c ths
            return -1;
1887 8d5d2d4c ths
        }
1888 8d5d2d4c ths
1889 8d5d2d4c ths
        if (gnutls_protocol_set_priority(vs->tls_session, protocol_priority) < 0) {
1890 8d5d2d4c ths
            gnutls_deinit(vs->tls_session);
1891 8d5d2d4c ths
            vs->tls_session = NULL;
1892 8d5d2d4c ths
            vnc_client_error(vs);
1893 8d5d2d4c ths
            return -1;
1894 8d5d2d4c ths
        }
1895 8d5d2d4c ths
1896 3a702699 ths
        if (NEED_X509_AUTH(vs)) {
1897 6f43024c ths
            gnutls_certificate_server_credentials x509_cred = vnc_tls_initialize_x509_cred(vs);
1898 3a702699 ths
            if (!x509_cred) {
1899 3a702699 ths
                gnutls_deinit(vs->tls_session);
1900 3a702699 ths
                vs->tls_session = NULL;
1901 3a702699 ths
                vnc_client_error(vs);
1902 3a702699 ths
                return -1;
1903 3a702699 ths
            }
1904 3a702699 ths
            if (gnutls_credentials_set(vs->tls_session, GNUTLS_CRD_CERTIFICATE, x509_cred) < 0) {
1905 3a702699 ths
                gnutls_deinit(vs->tls_session);
1906 3a702699 ths
                vs->tls_session = NULL;
1907 3a702699 ths
                gnutls_certificate_free_credentials(x509_cred);
1908 3a702699 ths
                vnc_client_error(vs);
1909 3a702699 ths
                return -1;
1910 3a702699 ths
            }
1911 469b15c6 ths
            if (vs->x509verify) {
1912 469b15c6 ths
                VNC_DEBUG("Requesting a client certificate\n");
1913 469b15c6 ths
                gnutls_certificate_server_set_request (vs->tls_session, GNUTLS_CERT_REQUEST);
1914 469b15c6 ths
            }
1915 469b15c6 ths
1916 3a702699 ths
        } else {
1917 3a702699 ths
            gnutls_anon_server_credentials anon_cred = vnc_tls_initialize_anon_cred();
1918 3a702699 ths
            if (!anon_cred) {
1919 3a702699 ths
                gnutls_deinit(vs->tls_session);
1920 3a702699 ths
                vs->tls_session = NULL;
1921 3a702699 ths
                vnc_client_error(vs);
1922 3a702699 ths
                return -1;
1923 3a702699 ths
            }
1924 3a702699 ths
            if (gnutls_credentials_set(vs->tls_session, GNUTLS_CRD_ANON, anon_cred) < 0) {
1925 3a702699 ths
                gnutls_deinit(vs->tls_session);
1926 3a702699 ths
                vs->tls_session = NULL;
1927 3a702699 ths
                gnutls_anon_free_server_credentials(anon_cred);
1928 3a702699 ths
                vnc_client_error(vs);
1929 3a702699 ths
                return -1;
1930 3a702699 ths
            }
1931 8d5d2d4c ths
        }
1932 8d5d2d4c ths
1933 8d5d2d4c ths
        gnutls_transport_set_ptr(vs->tls_session, (gnutls_transport_ptr_t)vs);
1934 8d5d2d4c ths
        gnutls_transport_set_push_function(vs->tls_session, vnc_tls_push);
1935 8d5d2d4c ths
        gnutls_transport_set_pull_function(vs->tls_session, vnc_tls_pull);
1936 8d5d2d4c ths
    }
1937 8d5d2d4c ths
1938 8d5d2d4c ths
    VNC_DEBUG("Start TLS handshake process\n");
1939 8d5d2d4c ths
    return vnc_continue_handshake(vs);
1940 8d5d2d4c ths
}
1941 8d5d2d4c ths
1942 60fe76f3 ths
static int protocol_client_vencrypt_auth(VncState *vs, uint8_t *data, size_t len)
1943 8d5d2d4c ths
{
1944 8d5d2d4c ths
    int auth = read_u32(data, 0);
1945 8d5d2d4c ths
1946 8d5d2d4c ths
    if (auth != vs->subauth) {
1947 8d5d2d4c ths
        VNC_DEBUG("Rejecting auth %d\n", auth);
1948 8d5d2d4c ths
        vnc_write_u8(vs, 0); /* Reject auth */
1949 8d5d2d4c ths
        vnc_flush(vs);
1950 8d5d2d4c ths
        vnc_client_error(vs);
1951 8d5d2d4c ths
    } else {
1952 8d5d2d4c ths
        VNC_DEBUG("Accepting auth %d, starting handshake\n", auth);
1953 8d5d2d4c ths
        vnc_write_u8(vs, 1); /* Accept auth */
1954 8d5d2d4c ths
        vnc_flush(vs);
1955 8d5d2d4c ths
1956 8d5d2d4c ths
        if (vnc_start_tls(vs) < 0) {
1957 8d5d2d4c ths
            VNC_DEBUG("Failed to complete TLS\n");
1958 8d5d2d4c ths
            return 0;
1959 8d5d2d4c ths
        }
1960 8d5d2d4c ths
1961 8d5d2d4c ths
        if (vs->wiremode == VNC_WIREMODE_TLS) {
1962 8d5d2d4c ths
            VNC_DEBUG("Starting VeNCrypt subauth\n");
1963 8d5d2d4c ths
            return start_auth_vencrypt_subauth(vs);
1964 8d5d2d4c ths
        } else {
1965 8d5d2d4c ths
            VNC_DEBUG("TLS handshake blocked\n");
1966 8d5d2d4c ths
            return 0;
1967 8d5d2d4c ths
        }
1968 8d5d2d4c ths
    }
1969 8d5d2d4c ths
    return 0;
1970 8d5d2d4c ths
}
1971 8d5d2d4c ths
1972 60fe76f3 ths
static int protocol_client_vencrypt_init(VncState *vs, uint8_t *data, size_t len)
1973 8d5d2d4c ths
{
1974 8d5d2d4c ths
    if (data[0] != 0 ||
1975 8d5d2d4c ths
        data[1] != 2) {
1976 8d5d2d4c ths
        VNC_DEBUG("Unsupported VeNCrypt protocol %d.%d\n", (int)data[0], (int)data[1]);
1977 8d5d2d4c ths
        vnc_write_u8(vs, 1); /* Reject version */
1978 8d5d2d4c ths
        vnc_flush(vs);
1979 8d5d2d4c ths
        vnc_client_error(vs);
1980 8d5d2d4c ths
    } else {
1981 8d5d2d4c ths
        VNC_DEBUG("Sending allowed auth %d\n", vs->subauth);
1982 8d5d2d4c ths
        vnc_write_u8(vs, 0); /* Accept version */
1983 8d5d2d4c ths
        vnc_write_u8(vs, 1); /* Number of sub-auths */
1984 8d5d2d4c ths
        vnc_write_u32(vs, vs->subauth); /* The supported auth */
1985 8d5d2d4c ths
        vnc_flush(vs);
1986 8d5d2d4c ths
        vnc_read_when(vs, protocol_client_vencrypt_auth, 4);
1987 8d5d2d4c ths
    }
1988 8d5d2d4c ths
    return 0;
1989 8d5d2d4c ths
}
1990 8d5d2d4c ths
1991 8d5d2d4c ths
static int start_auth_vencrypt(VncState *vs)
1992 8d5d2d4c ths
{
1993 8d5d2d4c ths
    /* Send VeNCrypt version 0.2 */
1994 8d5d2d4c ths
    vnc_write_u8(vs, 0);
1995 8d5d2d4c ths
    vnc_write_u8(vs, 2);
1996 8d5d2d4c ths
1997 8d5d2d4c ths
    vnc_read_when(vs, protocol_client_vencrypt_init, 2);
1998 8d5d2d4c ths
    return 0;
1999 8d5d2d4c ths
}
2000 8d5d2d4c ths
#endif /* CONFIG_VNC_TLS */
2001 8d5d2d4c ths
2002 60fe76f3 ths
static int protocol_client_auth(VncState *vs, uint8_t *data, size_t len)
2003 70848515 ths
{
2004 70848515 ths
    /* We only advertise 1 auth scheme at a time, so client
2005 70848515 ths
     * must pick the one we sent. Verify this */
2006 70848515 ths
    if (data[0] != vs->auth) { /* Reject auth */
2007 70848515 ths
       VNC_DEBUG("Reject auth %d\n", (int)data[0]);
2008 70848515 ths
       vnc_write_u32(vs, 1);
2009 70848515 ths
       if (vs->minor >= 8) {
2010 70848515 ths
           static const char err[] = "Authentication failed";
2011 70848515 ths
           vnc_write_u32(vs, sizeof(err));
2012 70848515 ths
           vnc_write(vs, err, sizeof(err));
2013 70848515 ths
       }
2014 70848515 ths
       vnc_client_error(vs);
2015 70848515 ths
    } else { /* Accept requested auth */
2016 70848515 ths
       VNC_DEBUG("Client requested auth %d\n", (int)data[0]);
2017 70848515 ths
       switch (vs->auth) {
2018 70848515 ths
       case VNC_AUTH_NONE:
2019 70848515 ths
           VNC_DEBUG("Accept auth none\n");
2020 a26c97ad balrog
           if (vs->minor >= 8) {
2021 a26c97ad balrog
               vnc_write_u32(vs, 0); /* Accept auth completion */
2022 a26c97ad balrog
               vnc_flush(vs);
2023 a26c97ad balrog
           }
2024 70848515 ths
           vnc_read_when(vs, protocol_client_init, 1);
2025 70848515 ths
           break;
2026 70848515 ths
2027 70848515 ths
       case VNC_AUTH_VNC:
2028 70848515 ths
           VNC_DEBUG("Start VNC auth\n");
2029 70848515 ths
           return start_auth_vnc(vs);
2030 70848515 ths
2031 eb38c52c blueswir1
#ifdef CONFIG_VNC_TLS
2032 8d5d2d4c ths
       case VNC_AUTH_VENCRYPT:
2033 8d5d2d4c ths
           VNC_DEBUG("Accept VeNCrypt auth\n");;
2034 8d5d2d4c ths
           return start_auth_vencrypt(vs);
2035 8d5d2d4c ths
#endif /* CONFIG_VNC_TLS */
2036 8d5d2d4c ths
2037 70848515 ths
       default: /* Should not be possible, but just in case */
2038 70848515 ths
           VNC_DEBUG("Reject auth %d\n", vs->auth);
2039 70848515 ths
           vnc_write_u8(vs, 1);
2040 70848515 ths
           if (vs->minor >= 8) {
2041 70848515 ths
               static const char err[] = "Authentication failed";
2042 70848515 ths
               vnc_write_u32(vs, sizeof(err));
2043 70848515 ths
               vnc_write(vs, err, sizeof(err));
2044 70848515 ths
           }
2045 70848515 ths
           vnc_client_error(vs);
2046 70848515 ths
       }
2047 70848515 ths
    }
2048 70848515 ths
    return 0;
2049 70848515 ths
}
2050 70848515 ths
2051 60fe76f3 ths
static int protocol_version(VncState *vs, uint8_t *version, size_t len)
2052 24236869 bellard
{
2053 24236869 bellard
    char local[13];
2054 24236869 bellard
2055 24236869 bellard
    memcpy(local, version, 12);
2056 24236869 bellard
    local[12] = 0;
2057 24236869 bellard
2058 70848515 ths
    if (sscanf(local, "RFB %03d.%03d\n", &vs->major, &vs->minor) != 2) {
2059 70848515 ths
        VNC_DEBUG("Malformed protocol version %s\n", local);
2060 24236869 bellard
        vnc_client_error(vs);
2061 24236869 bellard
        return 0;
2062 24236869 bellard
    }
2063 70848515 ths
    VNC_DEBUG("Client request protocol version %d.%d\n", vs->major, vs->minor);
2064 70848515 ths
    if (vs->major != 3 ||
2065 70848515 ths
        (vs->minor != 3 &&
2066 b0566f4f ths
         vs->minor != 4 &&
2067 70848515 ths
         vs->minor != 5 &&
2068 70848515 ths
         vs->minor != 7 &&
2069 70848515 ths
         vs->minor != 8)) {
2070 70848515 ths
        VNC_DEBUG("Unsupported client version\n");
2071 70848515 ths
        vnc_write_u32(vs, VNC_AUTH_INVALID);
2072 70848515 ths
        vnc_flush(vs);
2073 70848515 ths
        vnc_client_error(vs);
2074 70848515 ths
        return 0;
2075 70848515 ths
    }
2076 b0566f4f ths
    /* Some broken clients report v3.4 or v3.5, which spec requires to be treated
2077 70848515 ths
     * as equivalent to v3.3 by servers
2078 70848515 ths
     */
2079 b0566f4f ths
    if (vs->minor == 4 || vs->minor == 5)
2080 70848515 ths
        vs->minor = 3;
2081 70848515 ths
2082 70848515 ths
    if (vs->minor == 3) {
2083 70848515 ths
        if (vs->auth == VNC_AUTH_NONE) {
2084 70848515 ths
            VNC_DEBUG("Tell client auth none\n");
2085 70848515 ths
            vnc_write_u32(vs, vs->auth);
2086 70848515 ths
            vnc_flush(vs);
2087 70848515 ths
            vnc_read_when(vs, protocol_client_init, 1);
2088 70848515 ths
       } else if (vs->auth == VNC_AUTH_VNC) {
2089 70848515 ths
            VNC_DEBUG("Tell client VNC auth\n");
2090 70848515 ths
            vnc_write_u32(vs, vs->auth);
2091 70848515 ths
            vnc_flush(vs);
2092 70848515 ths
            start_auth_vnc(vs);
2093 70848515 ths
       } else {
2094 70848515 ths
            VNC_DEBUG("Unsupported auth %d for protocol 3.3\n", vs->auth);
2095 70848515 ths
            vnc_write_u32(vs, VNC_AUTH_INVALID);
2096 70848515 ths
            vnc_flush(vs);
2097 70848515 ths
            vnc_client_error(vs);
2098 70848515 ths
       }
2099 70848515 ths
    } else {
2100 70848515 ths
        VNC_DEBUG("Telling client we support auth %d\n", vs->auth);
2101 70848515 ths
        vnc_write_u8(vs, 1); /* num auth */
2102 70848515 ths
        vnc_write_u8(vs, vs->auth);
2103 70848515 ths
        vnc_read_when(vs, protocol_client_auth, 1);
2104 70848515 ths
        vnc_flush(vs);
2105 70848515 ths
    }
2106 24236869 bellard
2107 24236869 bellard
    return 0;
2108 24236869 bellard
}
2109 24236869 bellard
2110 3aa3eea3 balrog
static void vnc_connect(VncState *vs)
2111 3aa3eea3 balrog
{
2112 3aa3eea3 balrog
    VNC_DEBUG("New client on socket %d\n", vs->csock);
2113 bcfad70f aliguori
    vs->ds->idle = 0;
2114 3aa3eea3 balrog
    socket_set_nonblock(vs->csock);
2115 3aa3eea3 balrog
    qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, NULL, vs);
2116 3aa3eea3 balrog
    vnc_write(vs, "RFB 003.008\n", 12);
2117 3aa3eea3 balrog
    vnc_flush(vs);
2118 3aa3eea3 balrog
    vnc_read_when(vs, protocol_version, 12);
2119 3aa3eea3 balrog
    memset(vs->old_data, 0, vs->ds->linesize * vs->ds->height);
2120 3aa3eea3 balrog
    memset(vs->dirty_row, 0xFF, sizeof(vs->dirty_row));
2121 3aa3eea3 balrog
    vs->has_resize = 0;
2122 3aa3eea3 balrog
    vs->has_hextile = 0;
2123 3aa3eea3 balrog
    vs->ds->dpy_copy = NULL;
2124 3aa3eea3 balrog
    vnc_update_client(vs);
2125 3aa3eea3 balrog
}
2126 3aa3eea3 balrog
2127 24236869 bellard
static void vnc_listen_read(void *opaque)
2128 24236869 bellard
{
2129 24236869 bellard
    VncState *vs = opaque;
2130 24236869 bellard
    struct sockaddr_in addr;
2131 24236869 bellard
    socklen_t addrlen = sizeof(addr);
2132 24236869 bellard
2133 9f60ad50 balrog
    /* Catch-up */
2134 9f60ad50 balrog
    vga_hw_update();
2135 9f60ad50 balrog
2136 24236869 bellard
    vs->csock = accept(vs->lsock, (struct sockaddr *)&addr, &addrlen);
2137 24236869 bellard
    if (vs->csock != -1) {
2138 3aa3eea3 balrog
        vnc_connect(vs);
2139 24236869 bellard
    }
2140 24236869 bellard
}
2141 24236869 bellard
2142 73fc9742 ths
extern int parse_host_port(struct sockaddr_in *saddr, const char *str);
2143 73fc9742 ths
2144 71cab5ca ths
void vnc_display_init(DisplayState *ds)
2145 24236869 bellard
{
2146 24236869 bellard
    VncState *vs;
2147 24236869 bellard
2148 24236869 bellard
    vs = qemu_mallocz(sizeof(VncState));
2149 24236869 bellard
    if (!vs)
2150 24236869 bellard
        exit(1);
2151 24236869 bellard
2152 24236869 bellard
    ds->opaque = vs;
2153 bcfad70f aliguori
    ds->idle = 1;
2154 a9ce8590 bellard
    vnc_state = vs;
2155 71cab5ca ths
    vs->display = NULL;
2156 70848515 ths
    vs->password = NULL;
2157 24236869 bellard
2158 24236869 bellard
    vs->lsock = -1;
2159 24236869 bellard
    vs->csock = -1;
2160 564c337e bellard
    vs->last_x = -1;
2161 564c337e bellard
    vs->last_y = -1;
2162 24236869 bellard
2163 24236869 bellard
    vs->ds = ds;
2164 24236869 bellard
2165 9ca313aa aliguori
    if (keyboard_layout)
2166 9ca313aa aliguori
        vs->kbd_layout = init_keyboard_layout(keyboard_layout);
2167 9ca313aa aliguori
    else
2168 9ca313aa aliguori
        vs->kbd_layout = init_keyboard_layout("en-us");
2169 24236869 bellard
2170 24236869 bellard
    if (!vs->kbd_layout)
2171 24236869 bellard
        exit(1);
2172 24236869 bellard
2173 a0ecfb73 balrog
    vs->timer = qemu_new_timer(rt_clock, vnc_update_client, vs);
2174 a0ecfb73 balrog
2175 73fc9742 ths
    vs->ds->data = NULL;
2176 73fc9742 ths
    vs->ds->dpy_update = vnc_dpy_update;
2177 73fc9742 ths
    vs->ds->dpy_resize = vnc_dpy_resize;
2178 a0ecfb73 balrog
    vs->ds->dpy_refresh = NULL;
2179 73fc9742 ths
2180 7eac3a87 aliguori
    vnc_colordepth(vs->ds, 32);
2181 73fc9742 ths
    vnc_dpy_resize(vs->ds, 640, 400);
2182 71cab5ca ths
}
2183 71cab5ca ths
2184 eb38c52c blueswir1
#ifdef CONFIG_VNC_TLS
2185 6f43024c ths
static int vnc_set_x509_credential(VncState *vs,
2186 6f43024c ths
                                   const char *certdir,
2187 6f43024c ths
                                   const char *filename,
2188 6f43024c ths
                                   char **cred,
2189 6f43024c ths
                                   int ignoreMissing)
2190 6f43024c ths
{
2191 6f43024c ths
    struct stat sb;
2192 6f43024c ths
2193 6f43024c ths
    if (*cred) {
2194 6f43024c ths
        qemu_free(*cred);
2195 6f43024c ths
        *cred = NULL;
2196 6f43024c ths
    }
2197 6f43024c ths
2198 6f43024c ths
    if (!(*cred = qemu_malloc(strlen(certdir) + strlen(filename) + 2)))
2199 6f43024c ths
        return -1;
2200 6f43024c ths
2201 6f43024c ths
    strcpy(*cred, certdir);
2202 6f43024c ths
    strcat(*cred, "/");
2203 6f43024c ths
    strcat(*cred, filename);
2204 6f43024c ths
2205 6f43024c ths
    VNC_DEBUG("Check %s\n", *cred);
2206 6f43024c ths
    if (stat(*cred, &sb) < 0) {
2207 6f43024c ths
        qemu_free(*cred);
2208 6f43024c ths
        *cred = NULL;
2209 6f43024c ths
        if (ignoreMissing && errno == ENOENT)
2210 6f43024c ths
            return 0;
2211 6f43024c ths
        return -1;
2212 6f43024c ths
    }
2213 6f43024c ths
2214 6f43024c ths
    return 0;
2215 6f43024c ths
}
2216 6f43024c ths
2217 6f43024c ths
static int vnc_set_x509_credential_dir(VncState *vs,
2218 6f43024c ths
                                       const char *certdir)
2219 6f43024c ths
{
2220 6f43024c ths
    if (vnc_set_x509_credential(vs, certdir, X509_CA_CERT_FILE, &vs->x509cacert, 0) < 0)
2221 6f43024c ths
        goto cleanup;
2222 6f43024c ths
    if (vnc_set_x509_credential(vs, certdir, X509_CA_CRL_FILE, &vs->x509cacrl, 1) < 0)
2223 6f43024c ths
        goto cleanup;
2224 6f43024c ths
    if (vnc_set_x509_credential(vs, certdir, X509_SERVER_CERT_FILE, &vs->x509cert, 0) < 0)
2225 6f43024c ths
        goto cleanup;
2226 6f43024c ths
    if (vnc_set_x509_credential(vs, certdir, X509_SERVER_KEY_FILE, &vs->x509key, 0) < 0)
2227 6f43024c ths
        goto cleanup;
2228 6f43024c ths
2229 6f43024c ths
    return 0;
2230 6f43024c ths
2231 6f43024c ths
 cleanup:
2232 6f43024c ths
    qemu_free(vs->x509cacert);
2233 6f43024c ths
    qemu_free(vs->x509cacrl);
2234 6f43024c ths
    qemu_free(vs->x509cert);
2235 6f43024c ths
    qemu_free(vs->x509key);
2236 6f43024c ths
    vs->x509cacert = vs->x509cacrl = vs->x509cert = vs->x509key = NULL;
2237 6f43024c ths
    return -1;
2238 6f43024c ths
}
2239 6f43024c ths
#endif /* CONFIG_VNC_TLS */
2240 6f43024c ths
2241 71cab5ca ths
void vnc_display_close(DisplayState *ds)
2242 71cab5ca ths
{
2243 e25a5822 ths
    VncState *vs = ds ? (VncState *)ds->opaque : vnc_state;
2244 71cab5ca ths
2245 71cab5ca ths
    if (vs->display) {
2246 71cab5ca ths
        qemu_free(vs->display);
2247 71cab5ca ths
        vs->display = NULL;
2248 71cab5ca ths
    }
2249 71cab5ca ths
    if (vs->lsock != -1) {
2250 71cab5ca ths
        qemu_set_fd_handler2(vs->lsock, NULL, NULL, NULL, NULL);
2251 71cab5ca ths
        close(vs->lsock);
2252 71cab5ca ths
        vs->lsock = -1;
2253 71cab5ca ths
    }
2254 71cab5ca ths
    if (vs->csock != -1) {
2255 71cab5ca ths
        qemu_set_fd_handler2(vs->csock, NULL, NULL, NULL, NULL);
2256 71cab5ca ths
        closesocket(vs->csock);
2257 71cab5ca ths
        vs->csock = -1;
2258 71cab5ca ths
        buffer_reset(&vs->input);
2259 71cab5ca ths
        buffer_reset(&vs->output);
2260 71cab5ca ths
        vs->need_update = 0;
2261 eb38c52c blueswir1
#ifdef CONFIG_VNC_TLS
2262 8d5d2d4c ths
        if (vs->tls_session) {
2263 8d5d2d4c ths
            gnutls_deinit(vs->tls_session);
2264 8d5d2d4c ths
            vs->tls_session = NULL;
2265 8d5d2d4c ths
        }
2266 8d5d2d4c ths
        vs->wiremode = VNC_WIREMODE_CLEAR;
2267 8d5d2d4c ths
#endif /* CONFIG_VNC_TLS */
2268 71cab5ca ths
    }
2269 70848515 ths
    vs->auth = VNC_AUTH_INVALID;
2270 eb38c52c blueswir1
#ifdef CONFIG_VNC_TLS
2271 8d5d2d4c ths
    vs->subauth = VNC_AUTH_INVALID;
2272 469b15c6 ths
    vs->x509verify = 0;
2273 8d5d2d4c ths
#endif
2274 70848515 ths
}
2275 70848515 ths
2276 70848515 ths
int vnc_display_password(DisplayState *ds, const char *password)
2277 70848515 ths
{
2278 70848515 ths
    VncState *vs = ds ? (VncState *)ds->opaque : vnc_state;
2279 70848515 ths
2280 70848515 ths
    if (vs->password) {
2281 70848515 ths
        qemu_free(vs->password);
2282 70848515 ths
        vs->password = NULL;
2283 70848515 ths
    }
2284 70848515 ths
    if (password && password[0]) {
2285 70848515 ths
        if (!(vs->password = qemu_strdup(password)))
2286 70848515 ths
            return -1;
2287 70848515 ths
    }
2288 70848515 ths
2289 70848515 ths
    return 0;
2290 71cab5ca ths
}
2291 71cab5ca ths
2292 70848515 ths
int vnc_display_open(DisplayState *ds, const char *display)
2293 71cab5ca ths
{
2294 71cab5ca ths
    struct sockaddr *addr;
2295 71cab5ca ths
    struct sockaddr_in iaddr;
2296 71cab5ca ths
#ifndef _WIN32
2297 71cab5ca ths
    struct sockaddr_un uaddr;
2298 ea01e5fd balrog
    const char *p;
2299 71cab5ca ths
#endif
2300 71cab5ca ths
    int reuse_addr, ret;
2301 71cab5ca ths
    socklen_t addrlen;
2302 e25a5822 ths
    VncState *vs = ds ? (VncState *)ds->opaque : vnc_state;
2303 70848515 ths
    const char *options;
2304 70848515 ths
    int password = 0;
2305 3aa3eea3 balrog
    int reverse = 0;
2306 eb38c52c blueswir1
#ifdef CONFIG_VNC_TLS
2307 3a702699 ths
    int tls = 0, x509 = 0;
2308 8d5d2d4c ths
#endif
2309 71cab5ca ths
2310 71cab5ca ths
    vnc_display_close(ds);
2311 70848515 ths
    if (strcmp(display, "none") == 0)
2312 71cab5ca ths
        return 0;
2313 24236869 bellard
2314 70848515 ths
    if (!(vs->display = strdup(display)))
2315 71cab5ca ths
        return -1;
2316 70848515 ths
2317 70848515 ths
    options = display;
2318 70848515 ths
    while ((options = strchr(options, ','))) {
2319 70848515 ths
        options++;
2320 469b15c6 ths
        if (strncmp(options, "password", 8) == 0) {
2321 70848515 ths
            password = 1; /* Require password auth */
2322 3aa3eea3 balrog
        } else if (strncmp(options, "reverse", 7) == 0) {
2323 3aa3eea3 balrog
            reverse = 1;
2324 eb38c52c blueswir1
#ifdef CONFIG_VNC_TLS
2325 469b15c6 ths
        } else if (strncmp(options, "tls", 3) == 0) {
2326 8d5d2d4c ths
            tls = 1; /* Require TLS */
2327 469b15c6 ths
        } else if (strncmp(options, "x509", 4) == 0) {
2328 6f43024c ths
            char *start, *end;
2329 3a702699 ths
            x509 = 1; /* Require x509 certificates */
2330 6f43024c ths
            if (strncmp(options, "x509verify", 10) == 0)
2331 6f43024c ths
                vs->x509verify = 1; /* ...and verify client certs */
2332 6f43024c ths
2333 6f43024c ths
            /* Now check for 'x509=/some/path' postfix
2334 6f43024c ths
             * and use that to setup x509 certificate/key paths */
2335 6f43024c ths
            start = strchr(options, '=');
2336 6f43024c ths
            end = strchr(options, ',');
2337 6f43024c ths
            if (start && (!end || (start < end))) {
2338 6f43024c ths
                int len = end ? end-(start+1) : strlen(start+1);
2339 6f43024c ths
                char *path = qemu_malloc(len+1);
2340 6f43024c ths
                strncpy(path, start+1, len);
2341 6f43024c ths
                path[len] = '\0';
2342 6f43024c ths
                VNC_DEBUG("Trying certificate path '%s'\n", path);
2343 6f43024c ths
                if (vnc_set_x509_credential_dir(vs, path) < 0) {
2344 6f43024c ths
                    fprintf(stderr, "Failed to find x509 certificates/keys in %s\n", path);
2345 6f43024c ths
                    qemu_free(path);
2346 6f43024c ths
                    qemu_free(vs->display);
2347 6f43024c ths
                    vs->display = NULL;
2348 6f43024c ths
                    return -1;
2349 6f43024c ths
                }
2350 6f43024c ths
                qemu_free(path);
2351 6f43024c ths
            } else {
2352 6f43024c ths
                fprintf(stderr, "No certificate path provided\n");
2353 6f43024c ths
                qemu_free(vs->display);
2354 6f43024c ths
                vs->display = NULL;
2355 6f43024c ths
                return -1;
2356 6f43024c ths
            }
2357 8d5d2d4c ths
#endif
2358 469b15c6 ths
        }
2359 70848515 ths
    }
2360 70848515 ths
2361 70848515 ths
    if (password) {
2362 eb38c52c blueswir1
#ifdef CONFIG_VNC_TLS
2363 8d5d2d4c ths
        if (tls) {
2364 8d5d2d4c ths
            vs->auth = VNC_AUTH_VENCRYPT;
2365 3a702699 ths
            if (x509) {
2366 3a702699 ths
                VNC_DEBUG("Initializing VNC server with x509 password auth\n");
2367 3a702699 ths
                vs->subauth = VNC_AUTH_VENCRYPT_X509VNC;
2368 3a702699 ths
            } else {
2369 3a702699 ths
                VNC_DEBUG("Initializing VNC server with TLS password auth\n");
2370 3a702699 ths
                vs->subauth = VNC_AUTH_VENCRYPT_TLSVNC;
2371 3a702699 ths
            }
2372 8d5d2d4c ths
        } else {
2373 8d5d2d4c ths
#endif
2374 8d5d2d4c ths
            VNC_DEBUG("Initializing VNC server with password auth\n");
2375 8d5d2d4c ths
            vs->auth = VNC_AUTH_VNC;
2376 eb38c52c blueswir1
#ifdef CONFIG_VNC_TLS
2377 8d5d2d4c ths
            vs->subauth = VNC_AUTH_INVALID;
2378 8d5d2d4c ths
        }
2379 8d5d2d4c ths
#endif
2380 70848515 ths
    } else {
2381 eb38c52c blueswir1
#ifdef CONFIG_VNC_TLS
2382 8d5d2d4c ths
        if (tls) {
2383 8d5d2d4c ths
            vs->auth = VNC_AUTH_VENCRYPT;
2384 3a702699 ths
            if (x509) {
2385 3a702699 ths
                VNC_DEBUG("Initializing VNC server with x509 no auth\n");
2386 3a702699 ths
                vs->subauth = VNC_AUTH_VENCRYPT_X509NONE;
2387 3a702699 ths
            } else {
2388 3a702699 ths
                VNC_DEBUG("Initializing VNC server with TLS no auth\n");
2389 3a702699 ths
                vs->subauth = VNC_AUTH_VENCRYPT_TLSNONE;
2390 3a702699 ths
            }
2391 8d5d2d4c ths
        } else {
2392 8d5d2d4c ths
#endif
2393 8d5d2d4c ths
            VNC_DEBUG("Initializing VNC server with no auth\n");
2394 8d5d2d4c ths
            vs->auth = VNC_AUTH_NONE;
2395 eb38c52c blueswir1
#ifdef CONFIG_VNC_TLS
2396 8d5d2d4c ths
            vs->subauth = VNC_AUTH_INVALID;
2397 8d5d2d4c ths
        }
2398 8d5d2d4c ths
#endif
2399 70848515 ths
    }
2400 73fc9742 ths
#ifndef _WIN32
2401 70848515 ths
    if (strstart(display, "unix:", &p)) {
2402 73fc9742 ths
        addr = (struct sockaddr *)&uaddr;
2403 73fc9742 ths
        addrlen = sizeof(uaddr);
2404 73fc9742 ths
2405 73fc9742 ths
        vs->lsock = socket(PF_UNIX, SOCK_STREAM, 0);
2406 73fc9742 ths
        if (vs->lsock == -1) {
2407 73fc9742 ths
            fprintf(stderr, "Could not create socket\n");
2408 71cab5ca ths
            free(vs->display);
2409 71cab5ca ths
            vs->display = NULL;
2410 71cab5ca ths
            return -1;
2411 73fc9742 ths
        }
2412 73fc9742 ths
2413 73fc9742 ths
        uaddr.sun_family = AF_UNIX;
2414 73fc9742 ths
        memset(uaddr.sun_path, 0, 108);
2415 73fc9742 ths
        snprintf(uaddr.sun_path, 108, "%s", p);
2416 73fc9742 ths
2417 3aa3eea3 balrog
        if (!reverse) {
2418 3aa3eea3 balrog
            unlink(uaddr.sun_path);
2419 3aa3eea3 balrog
        }
2420 73fc9742 ths
    } else
2421 73fc9742 ths
#endif
2422 73fc9742 ths
    {
2423 73fc9742 ths
        addr = (struct sockaddr *)&iaddr;
2424 73fc9742 ths
        addrlen = sizeof(iaddr);
2425 73fc9742 ths
2426 70848515 ths
        if (parse_host_port(&iaddr, display) < 0) {
2427 73fc9742 ths
            fprintf(stderr, "Could not parse VNC address\n");
2428 71cab5ca ths
            free(vs->display);
2429 71cab5ca ths
            vs->display = NULL;
2430 71cab5ca ths
            return -1;
2431 73fc9742 ths
        }
2432 71cab5ca ths
2433 3aa3eea3 balrog
        iaddr.sin_port = htons(ntohs(iaddr.sin_port) + (reverse ? 0 : 5900));
2434 73fc9742 ths
2435 71cab5ca ths
        vs->lsock = socket(PF_INET, SOCK_STREAM, 0);
2436 71cab5ca ths
        if (vs->lsock == -1) {
2437 71cab5ca ths
            fprintf(stderr, "Could not create socket\n");
2438 71cab5ca ths
            free(vs->display);
2439 71cab5ca ths
            vs->display = NULL;
2440 71cab5ca ths
            return -1;
2441 71cab5ca ths
        }
2442 71cab5ca ths
2443 73fc9742 ths
        reuse_addr = 1;
2444 73fc9742 ths
        ret = setsockopt(vs->lsock, SOL_SOCKET, SO_REUSEADDR,
2445 73fc9742 ths
                         (const char *)&reuse_addr, sizeof(reuse_addr));
2446 73fc9742 ths
        if (ret == -1) {
2447 73fc9742 ths
            fprintf(stderr, "setsockopt() failed\n");
2448 71cab5ca ths
            close(vs->lsock);
2449 71cab5ca ths
            vs->lsock = -1;
2450 71cab5ca ths
            free(vs->display);
2451 71cab5ca ths
            vs->display = NULL;
2452 71cab5ca ths
            return -1;
2453 73fc9742 ths
        }
2454 24236869 bellard
    }
2455 24236869 bellard
2456 3aa3eea3 balrog
    if (reverse) {
2457 3aa3eea3 balrog
        if (connect(vs->lsock, addr, addrlen) == -1) {
2458 3aa3eea3 balrog
            fprintf(stderr, "Connection to VNC client failed\n");
2459 3aa3eea3 balrog
            close(vs->lsock);
2460 3aa3eea3 balrog
            vs->lsock = -1;
2461 3aa3eea3 balrog
            free(vs->display);
2462 3aa3eea3 balrog
            vs->display = NULL;
2463 3aa3eea3 balrog
            return -1;
2464 3aa3eea3 balrog
        } else {
2465 3aa3eea3 balrog
            vs->csock = vs->lsock;
2466 3aa3eea3 balrog
            vs->lsock = -1;
2467 3aa3eea3 balrog
            vnc_connect(vs);
2468 3aa3eea3 balrog
            return 0;
2469 3aa3eea3 balrog
        }
2470 3aa3eea3 balrog
    }
2471 3aa3eea3 balrog
2472 73fc9742 ths
    if (bind(vs->lsock, addr, addrlen) == -1) {
2473 24236869 bellard
        fprintf(stderr, "bind() failed\n");
2474 71cab5ca ths
        close(vs->lsock);
2475 71cab5ca ths
        vs->lsock = -1;
2476 71cab5ca ths
        free(vs->display);
2477 71cab5ca ths
        vs->display = NULL;
2478 71cab5ca ths
        return -1;
2479 24236869 bellard
    }
2480 24236869 bellard
2481 24236869 bellard
    if (listen(vs->lsock, 1) == -1) {
2482 24236869 bellard
        fprintf(stderr, "listen() failed\n");
2483 71cab5ca ths
        close(vs->lsock);
2484 71cab5ca ths
        vs->lsock = -1;
2485 71cab5ca ths
        free(vs->display);
2486 71cab5ca ths
        vs->display = NULL;
2487 71cab5ca ths
        return -1;
2488 24236869 bellard
    }
2489 24236869 bellard
2490 71cab5ca ths
    return qemu_set_fd_handler2(vs->lsock, vnc_listen_poll, vnc_listen_read, NULL, vs);
2491 24236869 bellard
}