xref: /illumos-gate/usr/src/cmd/bhyve/rfb.c (revision 2a22bccab8733d6de38ab1e1fbe8c810122a4427)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3  *
4  * Copyright (c) 2015 Tycho Nightingale <tycho.nightingale@pluribusnetworks.com>
5  * Copyright (c) 2015 Leon Dang
6  * Copyright 2020 Joyent, Inc.
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGE.
29  */
30 /*
31  * This file and its contents are supplied under the terms of the
32  * Common Development and Distribution License ("CDDL"), version 1.0.
33  * You may only use this file in accordance with the terms of version
34  * 1.0 of the CDDL.
35  *
36  * A full copy of the text of the CDDL should have accompanied this
37  * source.  A copy of the CDDL is also available via the Internet at
38  * http://www.illumos.org/license/CDDL.
39  *
40  * Copyright 2022 OmniOS Community Edition (OmniOSce) Association.
41  */
42 
43 /*
44  * References to the RFB protocol specification refer to:
45  * - [1] https://github.com/rfbproto/rfbproto/blob/master/rfbproto.rst
46  */
47 
48 #include <err.h>
49 #include <errno.h>
50 #include <libidspace.h>
51 #include <netdb.h>
52 #include <pthread.h>
53 #include <pthread_np.h>
54 #include <signal.h>
55 #include <stdatomic.h>
56 #include <stdbool.h>
57 #include <stdio.h>
58 #include <stdlib.h>
59 #include <string.h>
60 #include <unistd.h>
61 #include <zlib.h>
62 #include <machine/cpufunc.h>
63 #include <machine/specialreg.h>
64 #include <netinet/in.h>
65 #ifndef NO_OPENSSL
66 #include <openssl/des.h>
67 #endif
68 #include <sys/debug.h>
69 #include <sys/endian.h>
70 #include <sys/list.h>
71 #include <sys/socket.h>
72 #include <sys/types.h>
73 #ifndef WITHOUT_CAPSICUM
74 #include <sysexits.h>
75 #include <sys/capsicum.h>
76 #include <capsicum_helpers.h>
77 #endif
78 
79 #include "bhyvegc.h"
80 #include "config.h"
81 #include "debug.h"
82 #include "console.h"
83 #include "rfb.h"
84 #include "rfb_impl.h"
85 #include "sockstream.h"
86 
87 static uint_t rfb_debug = 0;
88 static list_t rfb_list;
89 static id_space_t *rfb_idspace;
90 
91 static bool rfb_sse42;
92 static pthread_once_t rfb_once = PTHREAD_ONCE_INIT;
93 
94 extern int raw_stdio;
95 
96 static void rfb_send_extended_keyevent_update_msg(rfb_client_t *);
97 
98 static void
99 rfb_printf(rfb_client_t *c, rfb_loglevel_t level, const char *fmt, ...)
100 {
101 	FILE *fp = stdout;
102 	va_list ap;
103 
104 	switch (level) {
105 	case RFB_LOGDEBUG:
106 		if (rfb_debug == 0)
107 			return;
108 		/* FALLTHROUGH */
109 	case RFB_LOGERR:
110 		fp = stderr;
111 		/* FALLTHROUGH */
112 	case RFB_LOGWARN:
113 		if (c != NULL)
114 			(void) fprintf(fp, "rfb%u: ", c->rc_instance);
115 		else
116 			(void) fprintf(fp, "rfb: ");
117 		va_start(ap, fmt);
118 		(void) vfprintf(fp, fmt, ap);
119 		va_end(ap);
120 		if (raw_stdio)
121 			(void) fprintf(fp, "\r\n");
122 		else
123 			(void) fprintf(fp, "\n");
124 		(void) fflush(fp);
125 	}
126 }
127 
128 static void
129 rfb_init_once(void)
130 {
131 	uint_t cpu_registers[4], ecx;
132 
133 	do_cpuid(1, cpu_registers);
134 	ecx = cpu_registers[2];
135 	rfb_sse42 = (ecx & CPUID2_SSE42) != 0;
136 
137 	if (rfb_sse42)
138 		rfb_printf(NULL, RFB_LOGDEBUG, "enabled fast crc32");
139 	else
140 		rfb_printf(NULL, RFB_LOGWARN, "no support for fast crc32");
141 
142 	if (get_config_bool_default("rfb.debug", false))
143 		rfb_debug = 1;
144 
145 	list_create(&rfb_list, sizeof (rfb_server_t),
146 	    offsetof(rfb_server_t, rs_node));
147 
148 	rfb_idspace = id_space_create("rfb", 0, INT32_MAX);
149 }
150 
151 static void
152 rfb_free_client(rfb_client_t *c)
153 {
154 	free(c->rc_crc);
155 	free(c->rc_crc_tmp);
156 	free(c->rc_zbuf);
157 	free(c->rc_gci.data);
158 
159 	if (c->rc_encodings & RFB_ENCODING_ZLIB)
160 		(void) deflateEnd(&c->rc_zstream);
161 
162 	if (c->rc_fd != -1)
163 		(void) close(c->rc_fd);
164 
165 	free(c);
166 }
167 
168 /*
169  * Calculate CRC32 using SSE4.2; Intel or AMD Bulldozer+ CPUs only
170  */
171 static inline uint32_t
172 fast_crc32(void *buf, int len, uint32_t crcval)
173 {
174 	uint32_t q = len / sizeof (uint32_t);
175 	uint32_t *p = (uint32_t *)buf;
176 
177 	while (q--) {
178 		/* BEGIN CSTYLED */
179 		asm volatile (
180 		    /* crc32l %ecx,%esi */
181 		    ".byte 0xf2, 0xf, 0x38, 0xf1, 0xf1;"
182 		    :"=S" (crcval)
183 		    :"0" (crcval), "c" (*p)
184 		);
185 		/* END CSTYLED */
186 		p++;
187 	}
188 
189 	return (crcval);
190 }
191 
192 static void
193 rfb_send_client_status(rfb_client_t *c, uint32_t status, const char *msg)
194 {
195 	status = htonl(status);
196 
197 	(void) stream_write(c->rc_fd, &status, sizeof (status));
198 
199 	if (msg != NULL && status != 0 && c->rc_cver == RFB_CVER_3_8) {
200 		char buf[4];
201 
202 		rfb_printf(c, RFB_LOGWARN, msg);
203 
204 		be32enc(buf, strlen((char *)msg));
205 		(void) stream_write(c->rc_fd, buf, 4);
206 		(void) stream_write(c->rc_fd, msg, strlen((char *)msg));
207 	}
208 }
209 
210 static bool
211 rfb_handshake_version(rfb_client_t *c)
212 {
213 	unsigned char buf[RFB_VERSION_LEN];
214 	ssize_t l;
215 
216 	rfb_printf(c, RFB_LOGDEBUG,  "handshake version");
217 
218 	if (stream_write(c->rc_fd, RFB_VERSION, RFB_VERSION_LEN) !=
219 	    RFB_VERSION_LEN) {
220 		rfb_printf(c, RFB_LOGWARN, "could not send server version.");
221 		return (false);
222 	}
223 
224 	l = stream_read(c->rc_fd, buf, sizeof (buf));
225 	if (l <= 0) {
226 		rfb_printf(c, RFB_LOGWARN, "client version not read");
227 		return (false);
228 	} else if (l != RFB_VERSION_LEN) {
229 		rfb_printf(c, RFB_LOGWARN, "client sent short version - '%.*s'",
230 		    l, buf);
231 		return (false);
232 	}
233 
234 	rfb_printf(c, RFB_LOGDEBUG, "version handshake, client ver '%.*s'",
235 	    l - 1, buf);
236 
237 	if (strncmp(RFB_VERSION, (char *)buf, RFB_VERSION_LEN - 2) != 0) {
238 		rfb_printf(c, RFB_LOGERR, "bad client version '%.*s'", l, buf);
239 		return (false);
240 	}
241 
242 	switch (buf[RFB_VERSION_LEN - 2]) {
243 	case '8':
244 		c->rc_cver = RFB_CVER_3_8;
245 		break;
246 	case '7':
247 		c->rc_cver = RFB_CVER_3_7;
248 		break;
249 	case '5':
250 		/*
251 		 * From the RFB specification[1], section 7.1.1:
252 		 * "version 3.5 was wrongly reported by some clients, but this
253 		 *  should be interpreted by all servers as 3.3."
254 		 */
255 	case '3':
256 		c->rc_cver = RFB_CVER_3_3;
257 		break;
258 	default:
259 		rfb_printf(c, RFB_LOGERR, "unsupported client version '%.*s'",
260 		    l - 1, buf);
261 		return (false);
262 	}
263 
264 	return (true);
265 }
266 
267 static bool
268 rfb_handshake_auth(rfb_client_t *c)
269 {
270 	unsigned char buf[RFBP_SECURITY_VNC_AUTH_LEN];
271 	int auth_type;
272 
273 	rfb_printf(c, RFB_LOGDEBUG, "handshake auth");
274 
275 	auth_type = RFBP_SECURITY_NONE;
276 #ifndef NO_OPENSSL
277 	if (c->rc_s->rs_password != NULL)
278 		auth_type = RFBP_SECURITY_VNC_AUTH;
279 #endif
280 
281 	switch (c->rc_cver) {
282 	case RFB_CVER_3_3:
283 		/*
284 		 * RFB specification[1] section 7.1.2:
285 		 * The server decides the security type and sends a single word.
286 		 */
287 		be32enc(buf, auth_type);
288 		(void) stream_write(c->rc_fd, buf, 4);
289 
290 		break;
291 
292 	case RFB_CVER_3_7:
293 	case RFB_CVER_3_8:
294 		/* Send list of supported types. */
295 		buf[0] = 1;	/* list length */
296 		buf[1] = auth_type;
297 		(void) stream_write(c->rc_fd, buf, 2);
298 
299 		/* Read agreed security type. */
300 		if (stream_read(c->rc_fd, buf, 1) != 1) {
301 			rfb_printf(c, RFB_LOGWARN,
302 			    "auth fail, no type from client");
303 			return (false);
304 		}
305 
306 		if (buf[0] != auth_type) {
307 			rfb_send_client_status(c, 1,
308 			    "Auth failed: authentication type mismatch");
309 			return (false);
310 		}
311 
312 		break;
313 	}
314 
315 	if (auth_type == RFBP_SECURITY_NONE) {
316 		/*
317 		 * According to the RFB specification[1], section 7.2.1, for a
318 		 * security type of 'None', client versions 3.3 and 3.7 expect
319 		 * to move straight to the ClientInit phase, without the server
320 		 * sending a response. For version 3.8, a SecurityResult word
321 		 * needs to be sent indicating success.
322 		 */
323 		switch (c->rc_cver) {
324 		case RFB_CVER_3_3:
325 		case RFB_CVER_3_7:
326 			break;
327 		case RFB_CVER_3_8:
328 			rfb_send_client_status(c, 0, NULL);
329 			break;
330 		}
331 		return (true);
332 	}
333 
334 	/* Perform VNC authentication. */
335 
336 #ifdef NO_OPENSSL
337 	rfb_printf(c, RFB_LOGERR,
338 	    "Auth not supported, no OpenSSL in your system");
339 	rfb_send_client_status(c, 1, "Auth failed.");
340 	return (false);
341 #else
342 	unsigned char challenge[RFBP_SECURITY_VNC_AUTH_LEN];
343 	unsigned char keystr[RFBP_SECURITY_VNC_PASSWD_LEN];
344 	unsigned char crypt_expected[RFBP_SECURITY_VNC_AUTH_LEN];
345 	DES_key_schedule ks;
346 
347 	/*
348 	 * The client encrypts the challenge with DES, using a password
349 	 * supplied by the user as the key.
350 	 * To form the key, the password is truncated to eight characters, or
351 	 * padded with null bytes on the right.
352 	 * The client then sends the resulting 16-bytes response.
353 	 */
354 	(void) strncpy((char *)keystr, c->rc_s->rs_password,
355 	    RFBP_SECURITY_VNC_PASSWD_LEN);
356 
357 	/*
358 	 * VNC clients encrypt the challenge with all the bit fields in each
359 	 * byte of the password mirrored.
360 	 * Here we flip each byte of the keystr.
361 	 */
362 	for (uint_t i = 0; i < RFBP_SECURITY_VNC_PASSWD_LEN; i++) {
363 		keystr[i] = (keystr[i] & 0xf0) >> 4 | (keystr[i] & 0x0f) << 4;
364 		keystr[i] = (keystr[i] & 0xcc) >> 2 | (keystr[i] & 0x33) << 2;
365 		keystr[i] = (keystr[i] & 0xaa) >> 1 | (keystr[i] & 0x55) << 1;
366 	}
367 
368 	/* Initialize a 16-byte random challenge. */
369 	arc4random_buf(challenge, sizeof (challenge));
370 	(void) stream_write(c->rc_fd, challenge, RFBP_SECURITY_VNC_AUTH_LEN);
371 
372 	/* Receive the 16-byte challenge response. */
373 	if (stream_read(c->rc_fd, buf, RFBP_SECURITY_VNC_AUTH_LEN)
374 	    != RFBP_SECURITY_VNC_AUTH_LEN) {
375 		rfb_send_client_status(c, 1, "response read failed");
376 		return (false);
377 	}
378 
379 	memcpy(crypt_expected, challenge, RFBP_SECURITY_VNC_AUTH_LEN);
380 
381 	/* Encrypt the Challenge with DES. */
382 	DES_set_key_unchecked((const_DES_cblock *)keystr, &ks);
383 	DES_ecb_encrypt((const_DES_cblock *)challenge,
384 	    (const_DES_cblock *)crypt_expected, &ks, DES_ENCRYPT);
385 	DES_ecb_encrypt(
386 	    (const_DES_cblock *)(challenge + RFBP_SECURITY_VNC_PASSWD_LEN),
387 	    (const_DES_cblock *)(crypt_expected + RFBP_SECURITY_VNC_PASSWD_LEN),
388 	    &ks, DES_ENCRYPT);
389 
390 	if (memcmp(crypt_expected, buf, RFBP_SECURITY_VNC_AUTH_LEN) != 0) {
391 		rfb_send_client_status(c, 1, "Auth failed: Invalid password.");
392 		return (false);
393 	}
394 
395 	rfb_printf(c, RFB_LOGDEBUG, "authentication succeeded");
396 	rfb_send_client_status(c, 0, NULL);
397 #endif
398 
399 	return (true);
400 }
401 
402 static bool
403 rfb_handshake_init_message(rfb_client_t *c)
404 {
405 	struct bhyvegc_image *gci;
406 	char buf[1];
407 	char *name;
408 
409 	rfb_printf(c, RFB_LOGDEBUG, "handshake server init");
410 
411 	/* Read the client init message. */
412 	if (stream_read(c->rc_fd, buf, 1) != 1) {
413 		rfb_printf(c, RFB_LOGWARN, "client did not send init");
414 		return (false);
415 	}
416 
417 	if (buf[0] == 0) {
418 		rfb_client_t *oc;
419 
420 		rfb_printf(c, RFB_LOGDEBUG,
421 		    "client requested exclusive access");
422 
423 		pthread_mutex_lock(&c->rc_s->rs_clientlock);
424 		c->rc_s->rs_exclusive = true;
425 		/* Disconnect all other clients. */
426 		for (oc = list_head(&c->rc_s->rs_clients); oc != NULL;
427 		    oc = list_next(&c->rc_s->rs_clients, oc)) {
428 			if (oc != c)
429 				oc->rc_closing = true;
430 		}
431 		pthread_mutex_unlock(&c->rc_s->rs_clientlock);
432 	} else {
433 		rfb_printf(c, RFB_LOGDEBUG, "client requested shared access");
434 
435 		pthread_mutex_lock(&c->rc_s->rs_clientlock);
436 		if (c->rc_s->rs_exclusive) {
437 			rfb_printf(c, RFB_LOGWARN,
438 			    "deny due to existing exclusive session");
439 			pthread_mutex_unlock(&c->rc_s->rs_clientlock);
440 			return (false);
441 		}
442 		pthread_mutex_unlock(&c->rc_s->rs_clientlock);
443 	}
444 
445 	gci = console_get_image();
446 
447 	c->rc_sinfo.rsi_width = htons(gci->width);
448 	c->rc_sinfo.rsi_height = htons(gci->height);
449 	c->rc_width = gci->width;
450 	c->rc_height = gci->height;
451 
452 	if (c->rc_s->rs_name != NULL)
453 		name = (char *)c->rc_s->rs_name;
454 	else
455 		name = "bhyve";
456 
457 	c->rc_sinfo.rsi_namelen = htonl(strlen(name));
458 	(void) stream_write(c->rc_fd, &c->rc_sinfo, sizeof (c->rc_sinfo));
459 	(void) stream_write(c->rc_fd, name, strlen(name));
460 
461 	return (true);
462 }
463 
464 static bool
465 rfb_handshake(rfb_client_t *c)
466 {
467 	if (!rfb_handshake_version(c))
468 		return (false);
469 
470 	if (!rfb_handshake_auth(c))
471 		return (false);
472 
473 	if (!rfb_handshake_init_message(c))
474 		return (false);
475 
476 	return (true);
477 }
478 
479 static void
480 rfb_print_pixfmt(rfb_client_t *c, rfb_pixfmt_t *px, rfb_loglevel_t level)
481 {
482 	rfb_printf(c, level, "%20s: %u", "bpp", px->rp_bpp);
483 	rfb_printf(c, level, "%20s: %u", "depth", px->rp_depth);
484 	rfb_printf(c, level, "%20s: %u", "bigendian", px->rp_bigendian);
485 	rfb_printf(c, level, "%20s: %u", "truecolour", px->rp_truecolour);
486 	rfb_printf(c, level, "%20s: %u", "r_max", ntohs(px->rp_r_max));
487 	rfb_printf(c, level, "%20s: %u", "g_max", ntohs(px->rp_g_max));
488 	rfb_printf(c, level, "%20s: %u", "b_max", ntohs(px->rp_b_max));
489 	rfb_printf(c, level, "%20s: %u", "r_shift", px->rp_r_shift);
490 	rfb_printf(c, level, "%20s: %u", "g_shift", px->rp_g_shift);
491 	rfb_printf(c, level, "%20s: %u", "b_shift", px->rp_b_shift);
492 }
493 
494 static bool
495 rfb_recv_set_pixel_format(rfb_client_t *c)
496 {
497 	rfb_cs_pixfmt_msg_t msg;
498 	rfb_pixfmt_t *newpx = &msg.rp_pixfmt;
499 	rfb_pixfmt_t *oldpx = &c->rc_sinfo.rsi_pixfmt;
500 	rfb_pixfmt_t *spx = &c->rc_s->rs_pixfmt;
501 
502 	rfb_printf(c, RFB_LOGDEBUG, "received pixel format");
503 
504 	if (stream_read(c->rc_fd, &msg, sizeof (msg)) != sizeof (msg))
505 		return (false);
506 
507 	/*
508 	 * The client has sent its desired pixel format. The protocol does not
509 	 * have a mechanism to reject this, we are supposed to just start using
510 	 * the requested format from the next update.
511 	 *
512 	 * At present, we can only support alternative rgb-shift values and
513 	 * will accept (and ignore) a new depth value.
514 	 */
515 
516 	if (oldpx->rp_bpp != newpx->rp_bpp ||
517 	    oldpx->rp_bigendian != newpx->rp_bigendian ||
518 	    oldpx->rp_truecolour != newpx->rp_truecolour ||
519 	    oldpx->rp_r_max != newpx->rp_r_max ||
520 	    oldpx->rp_g_max != newpx->rp_g_max ||
521 	    oldpx->rp_b_max != newpx->rp_b_max) {
522 		rfb_printf(c, RFB_LOGWARN, "unsupported pixfmt from client");
523 		rfb_print_pixfmt(c, newpx, RFB_LOGWARN);
524 		return (false);
525 	}
526 
527 	rfb_print_pixfmt(c, newpx, RFB_LOGDEBUG);
528 
529 	/* Check if the new shifts match the server's native values. */
530 	if (newpx->rp_r_shift != spx->rp_r_shift ||
531 	    newpx->rp_g_shift != spx->rp_g_shift ||
532 	    newpx->rp_b_shift != spx->rp_b_shift) {
533 		c->rc_custom_pixfmt = true;
534 		rfb_printf(c, RFB_LOGDEBUG, "Using custom pixfmt");
535 	} else {
536 		c->rc_custom_pixfmt = false;
537 		rfb_printf(c, RFB_LOGDEBUG, "Using native pixfmt");
538 	}
539 
540 	c->rc_sinfo.rsi_pixfmt = msg.rp_pixfmt;
541 	c->rc_crc_reset = true;
542 
543 	return (true);
544 }
545 
546 static bool
547 rfb_recv_set_encodings(rfb_client_t *c)
548 {
549 	rfb_cs_encodings_msg_t msg;
550 
551 	rfb_printf(c, RFB_LOGDEBUG, "received encodings");
552 
553 	if (stream_read(c->rc_fd, &msg, sizeof (msg)) != sizeof (msg))
554 		return (false);
555 
556 	msg.re_numencs = htons(msg.re_numencs);
557 
558 	rfb_printf(c, RFB_LOGDEBUG, "%d values", msg.re_numencs);
559 
560 	for (uint_t i = 0; i < msg.re_numencs; i++) {
561 		uint32_t enc;
562 
563 		if (stream_read(c->rc_fd, &enc, sizeof (enc)) != sizeof (enc))
564 			return (false);
565 
566 		enc = htonl(enc);
567 
568 		switch (enc) {
569 		case RFBP_ENCODING_RAW:
570 			rfb_printf(c, RFB_LOGDEBUG,
571 			    "client supports raw encoding");
572 			c->rc_encodings |= RFB_ENCODING_RAW;
573 			break;
574 		case RFBP_ENCODING_ZLIB:
575 			rfb_printf(c, RFB_LOGDEBUG,
576 			    "client supports zlib encoding");
577 			if (!(c->rc_encodings & RFB_ENCODING_ZLIB)) {
578 				if (deflateInit(&c->rc_zstream, Z_BEST_SPEED)
579 				    != Z_OK) {
580 					return (false);
581 				}
582 				c->rc_encodings |= RFB_ENCODING_ZLIB;
583 			}
584 			break;
585 		case RFBP_ENCODING_RESIZE:
586 			rfb_printf(c, RFB_LOGDEBUG, "client supports resize");
587 			c->rc_encodings |= RFB_ENCODING_RESIZE;
588 			break;
589 		case RFBP_ENCODING_EXT_KEVENT:
590 			rfb_printf(c, RFB_LOGDEBUG,
591 			    "client supports ext key event");
592 			c->rc_encodings |= RFB_ENCODING_EXT_KEVENT;
593 			break;
594 		case RFBP_ENCODING_DESKTOP_NAME:
595 			rfb_printf(c, RFB_LOGDEBUG,
596 			    "client supports desktop name");
597 			c->rc_encodings |= RFB_ENCODING_DESKTOP_NAME;
598 			break;
599 		default:
600 			rfb_printf(c, RFB_LOGDEBUG,
601 			    "client supports encoding %d", (int32_t)enc);
602 		}
603 	}
604 
605 	return (true);
606 }
607 
608 static bool
609 rfb_recv_update(rfb_client_t *c)
610 {
611 	rfb_cs_update_msg_t msg;
612 
613 	if (stream_read(c->rc_fd, &msg, sizeof (msg)) != sizeof (msg))
614 		return (false);
615 
616 	if (!c->rc_keyevent_sent &&
617 	    (c->rc_encodings & RFB_ENCODING_EXT_KEVENT)) {
618 		/*
619 		 * Take this opportunity to tell the client that we
620 		 * accept QEMU Extended Key Event Pseudo-encoding.
621 		 */
622 		c->rc_keyevent_sent = true;
623 		rfb_send_extended_keyevent_update_msg(c);
624 	}
625 
626 	c->rc_pending = true;
627 	if (msg.rum_incremental == 0) {
628 		rfb_printf(c, RFB_LOGDEBUG,
629 		    "client requested full screen update");
630 		c->rc_send_fullscreen = true;
631 	}
632 
633 	return (true);
634 }
635 
636 static bool
637 rfb_recv_key_event(rfb_client_t *c)
638 {
639 	rfb_cs_key_event_msg_t msg;
640 
641 	if (stream_read(c->rc_fd, &msg, sizeof (msg)) != sizeof (msg))
642 		return (false);
643 
644 	msg.rke_sym = htonl(msg.rke_sym);
645 
646 	rfb_printf(c, RFB_LOGDEBUG, "received key %s %x",
647 	    msg.rke_down == 0 ? "up" : "down", msg.rke_sym);
648 
649 	console_key_event(msg.rke_down, msg.rke_sym, htonl(0));
650 	c->rc_input_detected = true;
651 
652 	return (true);
653 }
654 
655 static bool
656 rfb_recv_pointer_event(rfb_client_t *c)
657 {
658 	rfb_cs_pointer_event_msg_t msg;
659 
660 	if (stream_read(c->rc_fd, &msg, sizeof (msg)) != sizeof (msg))
661 		return (false);
662 
663 	msg.rpe_x = htons(msg.rpe_x);
664 	msg.rpe_y = htons(msg.rpe_y);
665 
666 	if (rfb_debug > 1) {
667 		rfb_printf(c, RFB_LOGDEBUG, "received pointer event @ %dx%d",
668 		    msg.rpe_x, msg.rpe_y);
669 	}
670 
671 	console_ptr_event(msg.rpe_button, msg.rpe_x, msg.rpe_y);
672 	c->rc_input_detected = true;
673 
674 	return (true);
675 }
676 
677 static bool
678 rfb_recv_cut_text(rfb_client_t *c)
679 {
680 	rfb_cs_cut_text_msg_t msg;
681 	unsigned char buf[32];
682 
683 	rfb_printf(c, RFB_LOGDEBUG, "received cut text event");
684 
685 	if (stream_read(c->rc_fd, &msg, sizeof (msg)) != sizeof (msg))
686 		return (false);
687 
688 	msg.rct_length = htonl(msg.rct_length);
689 	rfb_printf(c, RFB_LOGDEBUG, "%u bytes in buffer", msg.rct_length);
690 	/* Consume the buffer */
691 	while (msg.rct_length > 0) {
692 		ssize_t l;
693 
694 		l = stream_read(c->rc_fd, buf,
695 		    MIN(sizeof (buf), msg.rct_length));
696 		if (l <= 0)
697 			return (false);
698 		msg.rct_length -= l;
699 	}
700 
701 	return (true);
702 }
703 
704 static bool
705 rfb_recv_qemu(rfb_client_t *c)
706 {
707 	rfb_cs_qemu_msg_t msg;
708 
709 	rfb_printf(c, RFB_LOGDEBUG, "received QEMU event");
710 
711 	if (stream_read(c->rc_fd, &msg, sizeof (msg)) != sizeof (msg))
712 		return (false);
713 
714 	switch (msg.rq_subtype) {
715 	case RFBP_CS_QEMU_KEVENT: {
716 		rfb_cs_qemu_extended_key_msg_t keymsg;
717 
718 		if (stream_read(c->rc_fd, &keymsg, sizeof (keymsg)) !=
719 		    sizeof (keymsg)) {
720 			return (false);
721 		}
722 
723 		keymsg.rqek_sym = htonl(keymsg.rqek_sym);
724 		keymsg.rqek_code = htonl(keymsg.rqek_code);
725 
726 		rfb_printf(c, RFB_LOGDEBUG, "QEMU key %s %x / %x",
727 		    keymsg.rqek_down == 0 ? "up" : "down",
728 		    keymsg.rqek_sym, keymsg.rqek_code);
729 
730 		console_key_event((int)keymsg.rqek_down, keymsg.rqek_sym,
731 		    keymsg.rqek_code);
732 		c->rc_input_detected = true;
733 		break;
734 	}
735 	default:
736 		rfb_printf(c, RFB_LOGWARN, "Unknown QEMU event subtype: %d\n",
737 		    msg.rq_subtype);
738 		return (false);
739 	}
740 
741 	return (true);
742 }
743 
744 static bool
745 rfb_send_update_header(rfb_client_t *c, int numrects)
746 {
747 	rfb_server_update_msg_t msg;
748 
749 	msg.rss_type = RFBP_SC_UPDATE;
750 	msg.rss_pad = 0;
751 	msg.rss_numrects = htons(numrects);
752 
753 	return (stream_write(c->rc_fd, &msg, sizeof (msg)) == sizeof (msg));
754 }
755 
756 static void
757 rfb_send_resize_update_msg(rfb_client_t *c)
758 {
759 	rfb_rect_hdr_t rect;
760 
761 	rfb_printf(c, RFB_LOGDEBUG, "sending screen resize %dx%d",
762 	    c->rc_width, c->rc_height);
763 
764 	(void) rfb_send_update_header(c, 1);
765 
766 	rect.rr_x = htons(0);
767 	rect.rr_y = htons(0);
768 	rect.rr_width = htons(c->rc_width);
769 	rect.rr_height = htons(c->rc_height);
770 	rect.rr_encoding = htonl(RFBP_ENCODING_RESIZE);
771 
772 	(void) stream_write(c->rc_fd, &rect, sizeof (rect));
773 }
774 
775 static void
776 rfb_send_extended_keyevent_update_msg(rfb_client_t *c)
777 {
778 	rfb_rect_hdr_t rect;
779 
780 	rfb_printf(c, RFB_LOGDEBUG, "sending extended keyevent update message");
781 
782 	(void) rfb_send_update_header(c, 1);
783 
784 	rect.rr_x = htons(0);
785 	rect.rr_y = htons(0);
786 	rect.rr_width = htons(c->rc_width);
787 	rect.rr_height = htons(c->rc_height);
788 	rect.rr_encoding = htonl(RFBP_ENCODING_EXT_KEVENT);
789 
790 	(void) stream_write(c->rc_fd, &rect, sizeof (rect));
791 }
792 
793 static void
794 translate_pixels(rfb_client_t *c, struct bhyvegc_image *gci,
795     int x1, int y1, int x2, int y2)
796 {
797 	rfb_pixfmt_t *px = &c->rc_sinfo.rsi_pixfmt;
798 	rfb_pixfmt_t *spx = &c->rc_s->rs_pixfmt;
799 	int w, h;
800 
801 	w = gci->width;
802 	h = gci->height;
803 	VERIFY3S(gci->width, ==, c->rc_gci.width);
804 	VERIFY3S(gci->height, ==, c->rc_gci.height);
805 
806 	for (uint_t y = y1; y < h && y < y2; y++) {
807 		for (uint_t x = x1; x < w && x < x2; x++) {
808 			uint32_t p;
809 
810 			p = gci->data[y * w + x];
811 			c->rc_gci.data[y * w + x] =
812 			    0xff000000 |
813 			    ((p >> spx->rp_r_shift) & 0xff) << px->rp_r_shift |
814 			    ((p >> spx->rp_g_shift) & 0xff) << px->rp_g_shift |
815 			    ((p >> spx->rp_b_shift) & 0xff) << px->rp_b_shift;
816 		}
817 	}
818 }
819 
820 static bool
821 rfb_send_rect(rfb_client_t *c, struct bhyvegc_image *gci,
822     int x, int y, int w, int h)
823 {
824 	rfb_rect_hdr_t rect;
825 	unsigned long zlen;
826 	ssize_t nwrite, total;
827 	int err;
828 	uint32_t *p;
829 	uint8_t *zbufp;
830 
831 	if (rfb_debug > 1) {
832 		rfb_printf(c, RFB_LOGDEBUG, "send rect %dx%d %dx%d",
833 		    x, y, w, h);
834 	}
835 
836 	/* Rectangle header. */
837 	rect.rr_x = htons(x);
838 	rect.rr_y = htons(y);
839 	rect.rr_width = htons(w);
840 	rect.rr_height = htons(h);
841 
842 	uint32_t *data = gci->data;
843 	if (c->rc_custom_pixfmt) {
844 		translate_pixels(c, gci, x, y, x + w, y + h);
845 		data = c->rc_gci.data;
846 	}
847 
848 	h = y + h;
849 	w *= sizeof (uint32_t);
850 
851 	if (c->rc_encodings & RFB_ENCODING_ZLIB) {
852 		zbufp = c->rc_zbuf;
853 		c->rc_zstream.total_in = 0;
854 		c->rc_zstream.total_out = 0;
855 		for (p = &data[y * gci->width + x]; y < h; y++) {
856 			c->rc_zstream.next_in = (Bytef *)p;
857 			c->rc_zstream.avail_in = w;
858 			c->rc_zstream.next_out = (Bytef *)zbufp;
859 			c->rc_zstream.avail_out = RFB_ZLIB_BUFSZ + 16 -
860 			    c->rc_zstream.total_out;
861 			c->rc_zstream.data_type = Z_BINARY;
862 
863 			/* Compress with zlib. */
864 			err = deflate(&c->rc_zstream, Z_SYNC_FLUSH);
865 			if (err != Z_OK) {
866 				rfb_printf(c, RFB_LOGWARN,
867 				    "zlib[rect] deflate err: %d", err);
868 				goto doraw;
869 			}
870 			zbufp = c->rc_zbuf + c->rc_zstream.total_out;
871 			p += gci->width;
872 		}
873 		rect.rr_encoding = htonl(RFBP_ENCODING_ZLIB);
874 		nwrite = stream_write(c->rc_fd, &rect, sizeof (rect));
875 		if (nwrite <= 0)
876 			return (false);
877 
878 		zlen = htonl(c->rc_zstream.total_out);
879 		nwrite = stream_write(c->rc_fd, &zlen, sizeof (uint32_t));
880 		if (nwrite <= 0)
881 			return (false);
882 		return (stream_write(c->rc_fd, c->rc_zbuf,
883 		    c->rc_zstream.total_out) == c->rc_zstream.total_out);
884 	}
885 
886 doraw:
887 
888 	total = 0;
889 	zbufp = c->rc_zbuf;
890 	for (p = &data[y * gci->width + x]; y < h; y++) {
891 		memcpy(zbufp, p, w);
892 		zbufp += w;
893 		total += w;
894 		p += gci->width;
895 	}
896 
897 	rect.rr_encoding = htonl(RFBP_ENCODING_RAW);
898 	nwrite = stream_write(c->rc_fd, &rect, sizeof (rect));
899 	if (nwrite <= 0)
900 		return (false);
901 
902 	return (stream_write(c->rc_fd, c->rc_zbuf, total) == total);
903 }
904 
905 
906 static bool
907 rfb_send_all(rfb_client_t *c, struct bhyvegc_image *gci)
908 {
909 	rfb_rect_hdr_t rect;
910 	ssize_t nwrite;
911 	unsigned long zlen;
912 	int err;
913 
914 	rfb_printf(c, RFB_LOGDEBUG, "send entire screen");
915 
916 	/* Just the one (big) rect. */
917 	if (!rfb_send_update_header(c, 1))
918 		return (false);
919 
920 	rect.rr_x = 0;
921 	rect.rr_y = 0;
922 	rect.rr_width = htons(gci->width);
923 	rect.rr_height = htons(gci->height);
924 
925 	uint32_t *data = gci->data;
926 	if (c->rc_custom_pixfmt) {
927 		translate_pixels(c, gci, 0, 0, gci->width, gci->height);
928 		data = c->rc_gci.data;
929 	}
930 
931 	if (c->rc_encodings & RFB_ENCODING_ZLIB) {
932 		c->rc_zstream.next_in = (Bytef *)data;
933 		c->rc_zstream.avail_in = gci->width * gci->height *
934 		    sizeof (uint32_t);
935 		c->rc_zstream.next_out = (Bytef *)c->rc_zbuf;
936 		c->rc_zstream.avail_out = RFB_ZLIB_BUFSZ + 16;
937 		c->rc_zstream.data_type = Z_BINARY;
938 
939 		c->rc_zstream.total_in = 0;
940 		c->rc_zstream.total_out = 0;
941 
942 		/* Compress with zlib. */
943 		err = deflate(&c->rc_zstream, Z_SYNC_FLUSH);
944 		if (err != Z_OK) {
945 			rfb_printf(c, RFB_LOGWARN, "zlib deflate err: %d", err);
946 			goto doraw;
947 		}
948 
949 		rect.rr_encoding = htonl(RFBP_ENCODING_ZLIB);
950 		nwrite = stream_write(c->rc_fd, &rect, sizeof (rect));
951 		if (nwrite <= 0)
952 			return (false);
953 
954 		zlen = htonl(c->rc_zstream.total_out);
955 		nwrite = stream_write(c->rc_fd, &zlen, sizeof (uint32_t));
956 		if (nwrite <= 0)
957 			return (false);
958 		return (stream_write(c->rc_fd, c->rc_zbuf,
959 		    c->rc_zstream.total_out) == c->rc_zstream.total_out);
960 	}
961 
962 doraw:
963 	rect.rr_encoding = htonl(RFBP_ENCODING_RAW);
964 	nwrite = stream_write(c->rc_fd, &rect, sizeof (rect));
965 	if (nwrite <= 0)
966 		return (false);
967 
968 	nwrite = gci->width * gci->height * sizeof (uint32_t);
969 	return (stream_write(c->rc_fd, data, nwrite) == nwrite);
970 }
971 
972 static bool
973 rfb_send_screen(rfb_client_t *c)
974 {
975 	struct bhyvegc_image *gci;
976 	bool retval = true;
977 	bool sendall = false;
978 	int xcells, ycells;
979 	int rem_x, rem_y;
980 	uint32_t *p, *ncrc, *ocrc;
981 	uint_t changes, perc, x, y;
982 
983 	/* Updates require a preceding client update request. */
984 	if (atomic_exchange(&c->rc_pending, false) == false)
985 		return (true);
986 
987 	console_refresh();
988 	gci = console_get_image();
989 
990 	/*
991 	 * It's helpful if the image size or data address does not change
992 	 * underneath us.
993 	 */
994 	pthread_mutex_lock(&gci->mtx);
995 
996 	/* Check for screen resolution changes. */
997 	if (c->rc_width != gci->width ||
998 	    c->rc_height != gci->height) {
999 		c->rc_width = gci->width;
1000 		c->rc_height = gci->height;
1001 		c->rc_crc_reset = true;
1002 		c->rc_send_fullscreen = true;
1003 
1004 		/* If the client supports it, send a resize event. */
1005 		if (c->rc_encodings & RFB_ENCODING_RESIZE) {
1006 			rfb_send_resize_update_msg(c);
1007 			/*
1008 			 * A resize message counts as an update in response to
1009 			 * the client's preceding request so rc->pending does
1010 			 * not need to be reset here.
1011 			 */
1012 			goto done;
1013 		}
1014 	}
1015 
1016 	/* Clear old CRC values. */
1017 	if (atomic_exchange(&c->rc_crc_reset, false))
1018 		memset(c->rc_crc, '\0', c->rc_cells * sizeof (uint32_t));
1019 
1020 	if (c->rc_custom_pixfmt && (c->rc_gci.data == NULL ||
1021 	    c->rc_gci.width != c->rc_width ||
1022 	    c->rc_gci.height != c->rc_height)) {
1023 		c->rc_gci.data = reallocarray(c->rc_gci.data,
1024 		    c->rc_width * c->rc_height, sizeof (uint32_t));
1025 		if (c->rc_gci.data == NULL) {
1026 			retval = false;
1027 			goto done;
1028 		}
1029 		c->rc_gci.width = c->rc_width;
1030 		c->rc_gci.height = c->rc_height;
1031 	} else if (!c->rc_custom_pixfmt && c->rc_gci.data != NULL) {
1032 		free(c->rc_gci.data);
1033 		c->rc_gci.data = NULL;
1034 	}
1035 
1036 	sendall = atomic_exchange(&c->rc_send_fullscreen, false);
1037 
1038 	/*
1039 	 * Calculate a checksum for each 32x32 cell. Send all that have
1040 	 * changed since the last scan.
1041 	 */
1042 
1043 	xcells = howmany(gci->width, RFB_PIX_PER_CELL);
1044 	ycells = howmany(gci->height, RFB_PIX_PER_CELL);
1045 	rem_x = gci->width & RFB_PIXCELL_MASK;
1046 	rem_y = gci->height & RFB_PIXCELL_MASK;
1047 	if (rem_y == 0)
1048 		rem_y = RFB_PIX_PER_CELL;
1049 
1050 	p = gci->data;
1051 
1052 	ncrc = c->rc_crc_tmp - xcells;
1053 	ocrc = c->rc_crc - xcells;
1054 	changes = 0;
1055 	memset(c->rc_crc_tmp, '\0', sizeof (uint32_t) * xcells * ycells);
1056 	for (y = 0; y < gci->height; y++) {
1057 		if ((y & RFB_PIXCELL_MASK) == 0) {
1058 			ncrc += xcells;
1059 			ocrc += xcells;
1060 		}
1061 
1062 		for (x = 0; x < xcells; x++) {
1063 			uint_t cellwidth;
1064 
1065 			if (x == xcells - 1 && rem_x > 0)
1066 				cellwidth = rem_x;
1067 			else
1068 				cellwidth = RFB_PIX_PER_CELL;
1069 
1070 			if (rfb_sse42) {
1071 				ncrc[x] = fast_crc32(p,
1072 				    cellwidth * sizeof (uint32_t), ncrc[x]);
1073 			} else {
1074 				ncrc[x] = (uint32_t)crc32(ncrc[x],
1075 				    (Bytef *)p, cellwidth * sizeof (uint32_t));
1076 			}
1077 
1078 			p += cellwidth;
1079 
1080 			/* check for crc delta if last row in cell. */
1081 			if ((y & RFB_PIXCELL_MASK) == RFB_PIXCELL_MASK ||
1082 			    y == gci->height - 1) {
1083 				if (ocrc[x] != ncrc[x]) {
1084 					ocrc[x] = ncrc[x];
1085 					ncrc[x] = 1;
1086 					changes++;
1087 				} else {
1088 					ncrc[x] = 0;
1089 				}
1090 			}
1091 		}
1092 	}
1093 
1094 	perc = (changes * 100) / (xcells * ycells);
1095 	if (rfb_debug > 1 && changes > 0) {
1096 		rfb_printf(c, RFB_LOGDEBUG,
1097 		    "scanned and found %u changed cell(s) - %u%%",
1098 		    changes, perc);
1099 	}
1100 
1101 	/*
1102 	 * If there are no changes, don't send an update. Restore the pending
1103 	 * flag since we still owe the client an update.
1104 	 */
1105 	if (!sendall && !changes) {
1106 		c->rc_pending = true;
1107 		goto done;
1108 	}
1109 
1110 	/* If there are a lot of changes, send the whole screen. */
1111 	if (perc >= RFB_SENDALL_THRESH)
1112 		sendall = true;
1113 
1114 	if (sendall) {
1115 		retval = rfb_send_all(c, gci);
1116 		goto done;
1117 	}
1118 
1119 	if (!rfb_send_update_header(c, changes)) {
1120 		retval = false;
1121 		goto done;
1122 	}
1123 
1124 	/* Send the changed cells as separate rects. */
1125 	ncrc = c->rc_crc_tmp;
1126 	for (y = 0; y < gci->height; y += RFB_PIX_PER_CELL) {
1127 		/* Previous cell's row. */
1128 		int celly = (y >> RFB_PIXCELL_SHIFT);
1129 
1130 		/* Delta check crc to previous set. */
1131 		for (x = 0; x < xcells; x++) {
1132 			uint_t cellwidth;
1133 
1134 			if (*ncrc++ == 0)
1135 				continue;
1136 
1137 			if (x == xcells - 1 && rem_x > 0)
1138 				cellwidth = rem_x;
1139 			else
1140 				cellwidth = RFB_PIX_PER_CELL;
1141 
1142 			if (!rfb_send_rect(c, gci,
1143 			    x * RFB_PIX_PER_CELL, celly * RFB_PIX_PER_CELL,
1144 			    cellwidth, y + RFB_PIX_PER_CELL >= gci->height ?
1145 			    rem_y : RFB_PIX_PER_CELL)) {
1146 				retval = false;
1147 				goto done;
1148 			}
1149 		}
1150 	}
1151 
1152 done:
1153 	pthread_mutex_unlock(&gci->mtx);
1154 
1155 	return (retval);
1156 }
1157 
1158 static void *
1159 rfb_client_rx_thread(void *arg)
1160 {
1161 	rfb_client_t *c = arg;
1162 	unsigned char cmd;
1163 	bool ret = true;
1164 
1165 	while (ret && !c->rc_closing && (read(c->rc_fd, &cmd, 1) == 1)) {
1166 		switch (cmd) {
1167 		case RFBP_CS_SET_PIXEL_FORMAT:
1168 			ret = rfb_recv_set_pixel_format(c);
1169 			break;
1170 		case RFBP_CS_SET_ENCODINGS:
1171 			ret = rfb_recv_set_encodings(c);
1172 			break;
1173 		case RFBP_CS_UPDATE_REQUEST:
1174 			ret = rfb_recv_update(c);
1175 			break;
1176 		case RFBP_CS_KEY_EVENT:
1177 			ret = rfb_recv_key_event(c);
1178 			break;
1179 		case RFBP_CS_POINTER_EVENT:
1180 			ret = rfb_recv_pointer_event(c);
1181 			break;
1182 		case RFBP_CS_CUT_TEXT:
1183 			ret = rfb_recv_cut_text(c);
1184 			break;
1185 		case RFBP_CS_QEMU:
1186 			ret = rfb_recv_qemu(c);
1187 			break;
1188 		default:
1189 			rfb_printf(c, RFB_LOGWARN, "unknown cs code %d",
1190 			    cmd & 0xff);
1191 			ret = false;
1192 		}
1193 	}
1194 
1195 	rfb_printf(c, RFB_LOGDEBUG, "client rx thread exiting");
1196 	c->rc_closing = true;
1197 
1198 	return (NULL);
1199 }
1200 
1201 static void *
1202 rfb_client_tx_thread(void *arg)
1203 {
1204 	rfb_client_t *c = arg;
1205 	rfb_server_t *s = c->rc_s;
1206 	char tname[MAXCOMLEN + 1];
1207 	uint_t counter = 0;
1208 	hrtime_t tprev;
1209 	void *status;
1210 	int err;
1211 
1212 	(void) snprintf(tname, sizeof (tname), "rfb%u tx", c->rc_instance);
1213 	(void) pthread_set_name_np(c->rc_tx_tid, tname);
1214 
1215 	c->rc_sinfo.rsi_pixfmt = c->rc_s->rs_pixfmt;
1216 	c->rc_encodings = RFB_ENCODING_RAW;
1217 
1218 	if (!rfb_handshake(c))
1219 		goto out;
1220 
1221 	c->rc_cells = howmany(RFB_MAX_WIDTH * RFB_MAX_HEIGHT, RFB_PIX_PER_CELL);
1222 	if ((c->rc_crc = calloc(c->rc_cells, sizeof (uint32_t))) == NULL ||
1223 	    (c->rc_crc_tmp = calloc(c->rc_cells, sizeof (uint32_t))) == NULL) {
1224 		perror("calloc crc");
1225 		goto out;
1226 	}
1227 
1228 	err = pthread_create(&c->rc_rx_tid, NULL, rfb_client_rx_thread, c);
1229 	if (err != 0) {
1230 		perror("pthread_create client rx thread");
1231 		goto out;
1232 	}
1233 
1234 	(void) snprintf(tname, sizeof (tname), "rfb%u rx", c->rc_instance);
1235 	(void) pthread_set_name_np(c->rc_rx_tid, tname);
1236 
1237 	tprev = gethrtime();
1238 
1239 	while (!c->rc_closing) {
1240 		struct timeval tv;
1241 		hrtime_t tnow;
1242 		int64_t tdiff;
1243 		fd_set rfds;
1244 		int err;
1245 
1246 		FD_ZERO(&rfds);
1247 		FD_SET(c->rc_fd, &rfds);
1248 		tv.tv_sec = 0;
1249 		tv.tv_usec = RFB_SEL_DELAY_US;
1250 
1251 		err = select(c->rc_fd + 1, &rfds, NULL, NULL, &tv);
1252 		if (err < 0)
1253 			break;
1254 
1255 		/* Determine if its time to push the screen; ~24hz. */
1256 		tnow = gethrtime();
1257 		tdiff = NSEC2USEC(tnow - tprev);
1258 		if (tdiff >= RFB_SCREEN_POLL_DELAY) {
1259 			bool input;
1260 
1261 			tprev = tnow;
1262 
1263 			input = atomic_exchange(&c->rc_input_detected, false);
1264 			/*
1265 			 * Refresh the screen on every second trip through the
1266 			 * loop, or if keyboard/mouse input has been detected.
1267 			 */
1268 			if ((++counter & 1) != 0 || input) {
1269 				if (!rfb_send_screen(c))
1270 					break;
1271 			}
1272 		} else {
1273 			(void) usleep(RFB_SCREEN_POLL_DELAY - tdiff);
1274 		}
1275 	}
1276 
1277 	rfb_printf(c, RFB_LOGWARN, "disconnected");
1278 
1279 out:
1280 
1281 	(void) pthread_join(c->rc_rx_tid, &status);
1282 	pthread_mutex_lock(&s->rs_clientlock);
1283 	s->rs_clientcount--;
1284 	list_remove(&s->rs_clients, c);
1285 	if (s->rs_exclusive && s->rs_clientcount == 0)
1286 		s->rs_exclusive = false;
1287 	id_free(rfb_idspace, c->rc_instance);
1288 	pthread_mutex_unlock(&s->rs_clientlock);
1289 
1290 	rfb_free_client(c);
1291 	return (NULL);
1292 }
1293 
1294 static void
1295 rfb_accept(int sfd, enum ev_type event, void *arg)
1296 {
1297 	rfb_server_t *s = arg;
1298 	rfb_client_t *c = NULL;
1299 	struct sockaddr_storage cliaddr;
1300 	socklen_t len;
1301 	char host[NI_MAXHOST], port[NI_MAXSERV];
1302 	int cfd, err;
1303 	uint_t cc;
1304 
1305 	rfb_printf(c, RFB_LOGDEBUG, "incoming connection");
1306 
1307 	len = sizeof (cliaddr);
1308 	cfd = accept(sfd, (struct sockaddr *)&cliaddr, &len);
1309 	if (cfd == -1) {
1310 		perror("client accept");
1311 		return;
1312 	}
1313 
1314 	*host = *port = '\0';
1315 	if (cliaddr.ss_family == AF_UNIX) {
1316 		rfb_printf(NULL, RFB_LOGDEBUG, "connection on UNIX socket");
1317 		(void) strlcpy(host, "<UNIX>", sizeof (host));
1318 	} else {
1319 		err = getnameinfo((struct sockaddr *)&cliaddr, len,
1320 		    host, sizeof (host), port, sizeof (port),
1321 		    NI_NUMERICHOST | NI_NUMERICSERV);
1322 		if (err != 0) {
1323 			rfb_printf(NULL, RFB_LOGERR, "getnameinfo: %s",
1324 			    gai_strerror(err));
1325 			*host = *port = '\0';
1326 		} else {
1327 			rfb_printf(NULL, RFB_LOGDEBUG, "connection from %s:%s",
1328 			    host, port);
1329 		}
1330 	}
1331 
1332 	pthread_mutex_lock(&s->rs_clientlock);
1333 	cc = s->rs_clientcount;
1334 	pthread_mutex_unlock(&s->rs_clientlock);
1335 	if (cc >= RFB_MAX_CLIENTS) {
1336 		rfb_printf(NULL, RFB_LOGERR,
1337 		    "too many clients, closing connection.");
1338 		goto fail;
1339 	}
1340 
1341 	if ((c = calloc(1, sizeof (rfb_client_t))) == NULL) {
1342 		perror("calloc client");
1343 		goto fail;
1344 	}
1345 
1346 	c->rc_fd = cfd;
1347 	c->rc_s = s;
1348 	c->rc_zbuf = malloc(RFB_ZLIB_BUFSZ + 16);
1349 	if (c->rc_zbuf == NULL)
1350 		goto fail;
1351 
1352 	pthread_mutex_lock(&s->rs_clientlock);
1353 
1354 	err = pthread_create(&c->rc_tx_tid, NULL, rfb_client_tx_thread, c);
1355 	if (err != 0) {
1356 		perror("pthread_create client tx thread");
1357 		pthread_mutex_unlock(&s->rs_clientlock);
1358 		goto fail;
1359 	}
1360 
1361 	s->rs_clientcount++;
1362 	list_insert_tail(&s->rs_clients, c);
1363 	c->rc_instance = id_allocff(rfb_idspace);
1364 	pthread_mutex_unlock(&s->rs_clientlock);
1365 
1366 	(void) pthread_detach(c->rc_tx_tid);
1367 
1368 	rfb_printf(c, RFB_LOGWARN, "connection from %s", host);
1369 
1370 	return;
1371 
1372 fail:
1373 	(void) close(cfd);
1374 	free(c);
1375 }
1376 
1377 int
1378 rfb_init(char *hostname, int port, int wait, const char *password,
1379     const char *name)
1380 {
1381 	rfb_server_t *s;
1382 #ifndef WITHOUT_CAPSICUM
1383 	cap_rights_t rights;
1384 #endif
1385 
1386 	(void) pthread_once(&rfb_once, rfb_init_once);
1387 
1388 	if (rfb_idspace == NULL) {
1389 		rfb_printf(NULL, RFB_LOGERR,
1390 		    "rfb_idspace could not be allocated");
1391 		return (-1);
1392 	}
1393 
1394 	if ((s = calloc(1, sizeof (rfb_server_t))) == NULL) {
1395 		perror("calloc");
1396 		return (-1);
1397 	}
1398 	s->rs_fd = -1;
1399 	s->rs_name = name;
1400 
1401 	if (password != NULL && strlen(password) > 0)
1402 		s->rs_password = password;
1403 
1404 	if (pthread_mutex_init(&s->rs_clientlock, NULL) != 0) {
1405 		perror("pthread_mutex_init");
1406 		free(s);
1407 		return (-1);
1408 	}
1409 
1410 	list_create(&s->rs_clients, sizeof (rfb_client_t),
1411 	    offsetof(rfb_client_t, rc_node));
1412 
1413 	/* Server pixel format. */
1414 	s->rs_pixfmt.rp_bpp = RFB_PIX_BPP;
1415 	s->rs_pixfmt.rp_depth = RFB_PIX_DEPTH;
1416 	s->rs_pixfmt.rp_bigendian = 0;
1417 	s->rs_pixfmt.rp_truecolour = 1;
1418 	s->rs_pixfmt.rp_r_max = htons(RFB_PIX_RMAX);
1419 	s->rs_pixfmt.rp_g_max = htons(RFB_PIX_GMAX);
1420 	s->rs_pixfmt.rp_b_max = htons(RFB_PIX_BMAX);
1421 	s->rs_pixfmt.rp_r_shift = RFB_PIX_RSHIFT;
1422 	s->rs_pixfmt.rp_g_shift = RFB_PIX_GSHIFT;
1423 	s->rs_pixfmt.rp_b_shift = RFB_PIX_BSHIFT;
1424 
1425 	/* UNIX socket. */
1426 	if (port == -1 && hostname != NULL && *hostname == '/') {
1427 		struct sockaddr_un sock;
1428 
1429 		s->rs_fd = socket(PF_UNIX, SOCK_STREAM, 0);
1430 		if (s->rs_fd < 0) {
1431 			perror("socket");
1432 			goto fail;
1433 		}
1434 
1435 		sock.sun_family = AF_UNIX;
1436 		if (strlcpy(sock.sun_path, hostname, sizeof (sock.sun_path)) >=
1437 		    sizeof (sock.sun_path)) {
1438 			rfb_printf(NULL, RFB_LOGERR,
1439 			    "socket path '%s' too long\n", hostname);
1440 			goto fail;
1441 		}
1442 
1443 		(void) unlink(hostname);
1444 		if (bind(s->rs_fd, (struct sockaddr *)&sock,
1445 		    sizeof (sock)) < 0) {
1446 			perror("bind");
1447 			goto fail;
1448 		}
1449 	} else {
1450 		struct addrinfo hints, *ai = NULL;
1451 		char servname[6];
1452 		int e;
1453 
1454 		(void) snprintf(servname, sizeof (servname), "%d",
1455 		    port ? port : RFB_DEFAULT_PORT);
1456 
1457 		if (hostname == NULL || strlen(hostname) == 0) {
1458 #if defined(INET)
1459 			hostname = "127.0.0.1";
1460 #elif defined(INET6)
1461 			hostname = "[::1]";
1462 #endif
1463 		}
1464 
1465 		memset(&hints, '\0', sizeof (hints));
1466 		hints.ai_family = AF_UNSPEC;
1467 		hints.ai_socktype = SOCK_STREAM;
1468 		hints.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV | AI_PASSIVE;
1469 
1470 		if ((e = getaddrinfo(hostname, servname, &hints, &ai)) != 0) {
1471 			rfb_printf(NULL, RFB_LOGERR, "getaddrinfo: %s",
1472 			    gai_strerror(e));
1473 			goto fail;
1474 		}
1475 
1476 		s->rs_fd = socket(ai->ai_family, ai->ai_socktype, 0);
1477 		if (s->rs_fd < 0) {
1478 			perror("socket");
1479 			freeaddrinfo(ai);
1480 			goto fail;
1481 		}
1482 
1483 		e = 1;
1484 		(void) setsockopt(s->rs_fd, SOL_SOCKET, SO_REUSEADDR,
1485 		    &e, sizeof (e));
1486 
1487 		if (bind(s->rs_fd, ai->ai_addr, ai->ai_addrlen) < 0) {
1488 			perror("bind");
1489 			freeaddrinfo(ai);
1490 			goto fail;
1491 		}
1492 		freeaddrinfo(ai);
1493 	}
1494 
1495 	if (listen(s->rs_fd, 5) < 0) {
1496 		perror("listen");
1497 		goto fail;
1498 	}
1499 
1500 #ifndef WITHOUT_CAPSICUM
1501 	cap_rights_init(&rights, CAP_ACCEPT, CAP_EVENT, CAP_READ, CAP_WRITE);
1502 	if (caph_rights_limit(s->rs_fd, &rights) == -1)
1503 		errx(EX_OSERR, "Unable to apply rights for sandbox");
1504 #endif
1505 
1506 	s->rs_connevent = mevent_add(s->rs_fd, EVF_READ, rfb_accept, s);
1507 	if (s->rs_connevent == NULL) {
1508 		rfb_printf(NULL, RFB_LOGERR,
1509 		    "Failed to set up rfb connection mevent");
1510 		goto fail;
1511 	}
1512 
1513 	list_insert_tail(&rfb_list, s);
1514 
1515 	/*
1516 	 * Wait for first connection. Since the mevent thread is
1517 	 * not yet running, we can't rely on normal incoming connection
1518 	 * handling.
1519 	 */
1520 	if (wait != 0) {
1521 		fd_set rfds;
1522 		int e;
1523 
1524 		rfb_printf(NULL, RFB_LOGWARN,
1525 		    "holding boot until first client connection");
1526 
1527 		for (;;) {
1528 			FD_ZERO(&rfds);
1529 			FD_SET(s->rs_fd, &rfds);
1530 
1531 			e = select(s->rs_fd + 1, &rfds, NULL, NULL, NULL);
1532 			if (e < 0 && errno == EINTR)
1533 				continue;
1534 			if (e < 0 || FD_ISSET(s->rs_fd, &rfds))
1535 				break;
1536 		}
1537 		rfb_printf(NULL, RFB_LOGWARN, "continuing boot");
1538 	}
1539 
1540 	return (0);
1541 
1542 fail:
1543 	if (s->rs_fd != -1)
1544 		VERIFY3S(close(s->rs_fd), ==, 0);
1545 	(void) pthread_mutex_destroy(&s->rs_clientlock);
1546 	list_destroy(&s->rs_clients);
1547 	free(s);
1548 	return (-1);
1549 }
1550