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