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 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ 29 30 #include <sys/param.h> 31 #ifndef WITHOUT_CAPSICUM 32 #include <sys/capsicum.h> 33 #endif 34 #include <sys/endian.h> 35 #include <sys/socket.h> 36 #include <sys/select.h> 37 #include <sys/time.h> 38 #include <sys/un.h> 39 #include <arpa/inet.h> 40 #include <stdatomic.h> 41 #include <machine/cpufunc.h> 42 #include <machine/specialreg.h> 43 #include <netinet/in.h> 44 #include <netdb.h> 45 46 #include <assert.h> 47 #ifndef WITHOUT_CAPSICUM 48 #include <capsicum_helpers.h> 49 #endif 50 #include <err.h> 51 #include <errno.h> 52 #include <pthread.h> 53 #include <pthread_np.h> 54 #include <signal.h> 55 #include <stdbool.h> 56 #include <stdlib.h> 57 #include <stdio.h> 58 #include <string.h> 59 #include <sysexits.h> 60 #include <unistd.h> 61 62 #include <zlib.h> 63 64 #include "bhyvegc.h" 65 #include "debug.h" 66 #include "console.h" 67 #include "config.h" 68 #include "rfb.h" 69 #include "sockstream.h" 70 71 #ifndef NO_OPENSSL 72 #include <openssl/des.h> 73 #endif 74 75 /* Delays in microseconds */ 76 #define CFD_SEL_DELAY 10000 77 #define SCREEN_REFRESH_DELAY 33300 /* 30Hz */ 78 #define SCREEN_POLL_DELAY (SCREEN_REFRESH_DELAY / 2) 79 80 static int rfb_debug = 0; 81 #define DPRINTF(params) if (rfb_debug) PRINTLN params 82 #define WPRINTF(params) PRINTLN params 83 84 #define VERSION_LENGTH 12 85 #define AUTH_LENGTH 16 86 #define PASSWD_LENGTH 8 87 88 /* Protocol versions */ 89 #define CVERS_3_3 '3' 90 #define CVERS_3_7 '7' 91 #define CVERS_3_8 '8' 92 93 /* Client-to-server msg types */ 94 #define CS_SET_PIXEL_FORMAT 0 95 #define CS_SET_ENCODINGS 2 96 #define CS_UPDATE_MSG 3 97 #define CS_KEY_EVENT 4 98 #define CS_POINTER_EVENT 5 99 #define CS_CUT_TEXT 6 100 #define CS_MSG_CLIENT_QEMU 255 101 102 #define SECURITY_TYPE_NONE 1 103 #define SECURITY_TYPE_VNC_AUTH 2 104 105 #define AUTH_FAILED_UNAUTH 1 106 #define AUTH_FAILED_ERROR 2 107 108 struct pixfmt { 109 bool adjust_pixels; 110 uint8_t red_shift; 111 uint8_t green_shift; 112 uint8_t blue_shift; 113 }; 114 115 struct rfb_softc { 116 int sfd; 117 pthread_t tid; 118 119 int cfd; 120 121 int width, height; 122 123 const char *password; 124 125 bool enc_raw_ok; 126 bool enc_zlib_ok; 127 bool enc_resize_ok; 128 bool enc_extkeyevent_ok; 129 130 bool enc_extkeyevent_send; 131 132 z_stream zstream; 133 uint8_t *zbuf; 134 int zbuflen; 135 136 int conn_wait; 137 int wrcount; 138 139 atomic_bool sending; 140 atomic_bool pending; 141 atomic_bool update_all; 142 atomic_bool input_detected; 143 atomic_bool update_pixfmt; 144 145 pthread_mutex_t mtx; 146 pthread_mutex_t pixfmt_mtx; 147 pthread_cond_t cond; 148 149 int hw_crc; 150 uint32_t *crc; /* WxH crc cells */ 151 uint32_t *crc_tmp; /* buffer to store single crc row */ 152 int crc_width, crc_height; 153 154 struct pixfmt pixfmt; /* owned by the write thread */ 155 struct pixfmt new_pixfmt; /* managed with pixfmt_mtx */ 156 uint32_t *pixrow; 157 char *fbname; 158 int fbnamelen; 159 }; 160 161 struct rfb_pixfmt { 162 uint8_t bpp; 163 uint8_t depth; 164 uint8_t bigendian; 165 uint8_t truecolor; 166 uint16_t red_max; 167 uint16_t green_max; 168 uint16_t blue_max; 169 uint8_t red_shift; 170 uint8_t green_shift; 171 uint8_t blue_shift; 172 uint8_t pad[3]; 173 }; 174 175 struct rfb_srvr_info { 176 uint16_t width; 177 uint16_t height; 178 struct rfb_pixfmt pixfmt; 179 uint32_t namelen; 180 }; 181 182 struct rfb_pixfmt_msg { 183 uint8_t type; 184 uint8_t pad[3]; 185 struct rfb_pixfmt pixfmt; 186 }; 187 188 #define RFB_ENCODING_RAW 0 189 #define RFB_ENCODING_ZLIB 6 190 #define RFB_ENCODING_RESIZE -223 191 #define RFB_ENCODING_EXT_KEYEVENT -258 192 193 #define RFB_CLIENTMSG_EXT_KEYEVENT 0 194 195 #define RFB_MAX_WIDTH 2000 196 #define RFB_MAX_HEIGHT 1200 197 #define RFB_ZLIB_BUFSZ RFB_MAX_WIDTH*RFB_MAX_HEIGHT*4 198 199 #define PIXEL_RED_SHIFT 16 200 #define PIXEL_GREEN_SHIFT 8 201 #define PIXEL_BLUE_SHIFT 0 202 203 /* percentage changes to screen before sending the entire screen */ 204 #define RFB_SEND_ALL_THRESH 25 205 206 struct rfb_enc_msg { 207 uint8_t type; 208 uint8_t pad; 209 uint16_t numencs; 210 }; 211 212 struct rfb_updt_msg { 213 uint8_t type; 214 uint8_t incremental; 215 uint16_t x; 216 uint16_t y; 217 uint16_t width; 218 uint16_t height; 219 }; 220 221 struct rfb_key_msg { 222 uint8_t type; 223 uint8_t down; 224 uint16_t pad; 225 uint32_t sym; 226 }; 227 228 struct rfb_client_msg { 229 uint8_t type; 230 uint8_t subtype; 231 }; 232 233 struct rfb_extended_key_msg { 234 uint8_t type; 235 uint8_t subtype; 236 uint16_t down; 237 uint32_t sym; 238 uint32_t code; 239 }; 240 241 struct rfb_ptr_msg { 242 uint8_t type; 243 uint8_t button; 244 uint16_t x; 245 uint16_t y; 246 }; 247 248 struct rfb_srvr_updt_msg { 249 uint8_t type; 250 uint8_t pad; 251 uint16_t numrects; 252 }; 253 254 struct rfb_srvr_rect_hdr { 255 uint16_t x; 256 uint16_t y; 257 uint16_t width; 258 uint16_t height; 259 uint32_t encoding; 260 }; 261 262 struct rfb_cuttext_msg { 263 uint8_t type; 264 uint8_t padding[3]; 265 uint32_t length; 266 }; 267 268 static void 269 rfb_send_server_init_msg(struct rfb_softc *rc, int cfd) 270 { 271 struct bhyvegc_image *gc_image; 272 struct rfb_srvr_info sinfo; 273 274 gc_image = console_get_image(); 275 276 sinfo.width = htons(gc_image->width); 277 sinfo.height = htons(gc_image->height); 278 sinfo.pixfmt.bpp = 32; 279 sinfo.pixfmt.depth = 32; 280 sinfo.pixfmt.bigendian = 0; 281 sinfo.pixfmt.truecolor = 1; 282 sinfo.pixfmt.red_max = htons(255); 283 sinfo.pixfmt.green_max = htons(255); 284 sinfo.pixfmt.blue_max = htons(255); 285 sinfo.pixfmt.red_shift = PIXEL_RED_SHIFT; 286 sinfo.pixfmt.green_shift = PIXEL_GREEN_SHIFT; 287 sinfo.pixfmt.blue_shift = PIXEL_BLUE_SHIFT; 288 sinfo.pixfmt.pad[0] = 0; 289 sinfo.pixfmt.pad[1] = 0; 290 sinfo.pixfmt.pad[2] = 0; 291 sinfo.namelen = htonl(rc->fbnamelen); 292 (void)stream_write(cfd, &sinfo, sizeof(sinfo)); 293 (void)stream_write(cfd, rc->fbname, rc->fbnamelen); 294 } 295 296 static void 297 rfb_send_resize_update_msg(struct rfb_softc *rc, int cfd) 298 { 299 struct rfb_srvr_updt_msg supdt_msg; 300 struct rfb_srvr_rect_hdr srect_hdr; 301 302 /* Number of rectangles: 1 */ 303 supdt_msg.type = 0; 304 supdt_msg.pad = 0; 305 supdt_msg.numrects = htons(1); 306 stream_write(cfd, &supdt_msg, sizeof(struct rfb_srvr_updt_msg)); 307 308 /* Rectangle header */ 309 srect_hdr.x = htons(0); 310 srect_hdr.y = htons(0); 311 srect_hdr.width = htons(rc->width); 312 srect_hdr.height = htons(rc->height); 313 srect_hdr.encoding = htonl(RFB_ENCODING_RESIZE); 314 stream_write(cfd, &srect_hdr, sizeof(struct rfb_srvr_rect_hdr)); 315 } 316 317 static void 318 rfb_send_extended_keyevent_update_msg(struct rfb_softc *rc, int cfd) 319 { 320 struct rfb_srvr_updt_msg supdt_msg; 321 struct rfb_srvr_rect_hdr srect_hdr; 322 323 /* Number of rectangles: 1 */ 324 supdt_msg.type = 0; 325 supdt_msg.pad = 0; 326 supdt_msg.numrects = htons(1); 327 stream_write(cfd, &supdt_msg, sizeof(struct rfb_srvr_updt_msg)); 328 329 /* Rectangle header */ 330 srect_hdr.x = htons(0); 331 srect_hdr.y = htons(0); 332 srect_hdr.width = htons(rc->width); 333 srect_hdr.height = htons(rc->height); 334 srect_hdr.encoding = htonl(RFB_ENCODING_EXT_KEYEVENT); 335 stream_write(cfd, &srect_hdr, sizeof(struct rfb_srvr_rect_hdr)); 336 } 337 338 static int 339 rfb_recv_set_pixfmt_msg(struct rfb_softc *rc __unused, int cfd) 340 { 341 struct rfb_pixfmt_msg pixfmt_msg; 342 uint8_t red_shift, green_shift, blue_shift; 343 uint16_t red_max, green_max, blue_max; 344 bool adjust_pixels = true; 345 int len; 346 347 len = stream_read(cfd, (uint8_t *)&pixfmt_msg + 1, 348 sizeof(pixfmt_msg) - 1); 349 if (len <= 0) 350 return (-1); 351 352 /* 353 * The framebuffer is fixed at 32 bit and orders the colors 354 * as RGB bytes. However, some VNC clients request a different 355 * ordering. We will still require the same bit depth and size 356 * but allow the colors to be shifted when sent to the client. 357 */ 358 if (pixfmt_msg.pixfmt.bpp != 32 || pixfmt_msg.pixfmt.truecolor != 1) { 359 WPRINTF(("rfb: pixfmt unsupported bitdepth bpp: %d " 360 "truecolor: %d", 361 pixfmt_msg.pixfmt.bpp, pixfmt_msg.pixfmt.truecolor)); 362 return (0); 363 } 364 365 red_max = ntohs(pixfmt_msg.pixfmt.red_max); 366 green_max = ntohs(pixfmt_msg.pixfmt.green_max); 367 blue_max = ntohs(pixfmt_msg.pixfmt.blue_max); 368 369 /* Check for valid max values */ 370 if (red_max != 255 || green_max != 255 || blue_max != 255) { 371 WPRINTF(("rfb: pixfmt unsupported max values " 372 "r: %d g: %d b: %d", 373 red_max, green_max, blue_max)); 374 return (0); 375 } 376 377 red_shift = pixfmt_msg.pixfmt.red_shift; 378 green_shift = pixfmt_msg.pixfmt.green_shift; 379 blue_shift = pixfmt_msg.pixfmt.blue_shift; 380 381 /* Check shifts are 8 bit aligned */ 382 if ((red_shift & 0x7) != 0 || 383 (green_shift & 0x7) != 0 || 384 (blue_shift & 0x7) != 0) { 385 WPRINTF(("rfb: pixfmt unsupported shift values " 386 "r: %d g: %d b: %d", 387 red_shift, green_shift, blue_shift)); 388 return (0); 389 } 390 391 if (red_shift == PIXEL_RED_SHIFT && 392 green_shift == PIXEL_GREEN_SHIFT && 393 blue_shift == PIXEL_BLUE_SHIFT) { 394 adjust_pixels = false; 395 } 396 397 pthread_mutex_lock(&rc->pixfmt_mtx); 398 rc->new_pixfmt.red_shift = red_shift; 399 rc->new_pixfmt.green_shift = green_shift; 400 rc->new_pixfmt.blue_shift = blue_shift; 401 rc->new_pixfmt.adjust_pixels = adjust_pixels; 402 pthread_mutex_unlock(&rc->pixfmt_mtx); 403 404 /* Notify the write thread to update */ 405 rc->update_pixfmt = true; 406 407 return (0); 408 } 409 410 static int 411 rfb_recv_set_encodings_msg(struct rfb_softc *rc, int cfd) 412 { 413 struct rfb_enc_msg enc_msg; 414 int i; 415 uint32_t encoding; 416 int len; 417 418 len = stream_read(cfd, (uint8_t *)&enc_msg + 1, sizeof(enc_msg) - 1); 419 if (len <= 0) 420 return (-1); 421 422 for (i = 0; i < htons(enc_msg.numencs); i++) { 423 len = stream_read(cfd, &encoding, sizeof(encoding)); 424 if (len <= 0) 425 return (-1); 426 427 switch (htonl(encoding)) { 428 case RFB_ENCODING_RAW: 429 rc->enc_raw_ok = true; 430 break; 431 case RFB_ENCODING_ZLIB: 432 if (!rc->enc_zlib_ok) { 433 deflateInit(&rc->zstream, Z_BEST_SPEED); 434 rc->enc_zlib_ok = true; 435 } 436 break; 437 case RFB_ENCODING_RESIZE: 438 rc->enc_resize_ok = true; 439 break; 440 case RFB_ENCODING_EXT_KEYEVENT: 441 rc->enc_extkeyevent_ok = true; 442 break; 443 } 444 } 445 446 return (0); 447 } 448 449 /* 450 * Calculate CRC32 using SSE4.2; Intel or AMD Bulldozer+ CPUs only 451 */ 452 static __inline uint32_t 453 fast_crc32(void *buf, int len, uint32_t crcval) 454 { 455 uint32_t q = len / sizeof(uint32_t); 456 uint32_t *p = (uint32_t *)buf; 457 458 while (q--) { 459 asm volatile ( 460 ".byte 0xf2, 0xf, 0x38, 0xf1, 0xf1;" 461 :"=S" (crcval) 462 :"0" (crcval), "c" (*p) 463 ); 464 p++; 465 } 466 467 return (crcval); 468 } 469 470 static int 471 rfb_send_update_header(struct rfb_softc *rc __unused, int cfd, int numrects) 472 { 473 struct rfb_srvr_updt_msg supdt_msg; 474 475 supdt_msg.type = 0; 476 supdt_msg.pad = 0; 477 supdt_msg.numrects = htons(numrects); 478 479 return stream_write(cfd, &supdt_msg, 480 sizeof(struct rfb_srvr_updt_msg)); 481 } 482 483 static uint32_t * 484 rfb_adjust_pixels(struct rfb_softc *rc, uint32_t *gcptr, int width) 485 { 486 uint32_t *pixelp; 487 uint32_t red, green, blue; 488 int i; 489 490 /* If no pixel adjustment needed, send in server format */ 491 if (!rc->pixfmt.adjust_pixels) { 492 return (gcptr); 493 } 494 495 for (i = 0, pixelp = rc->pixrow; i < width; i++, pixelp++, gcptr++) { 496 red = (*gcptr >> 16) & 0xFF; 497 green = (*gcptr >> 8) & 0xFF; 498 blue = (*gcptr & 0xFF); 499 *pixelp = (red << rc->pixfmt.red_shift) | 500 (green << rc->pixfmt.green_shift) | 501 (blue << rc->pixfmt.blue_shift); 502 } 503 504 return (rc->pixrow); 505 } 506 507 static int 508 rfb_send_rect(struct rfb_softc *rc, int cfd, struct bhyvegc_image *gc, 509 int x, int y, int w, int h) 510 { 511 struct rfb_srvr_rect_hdr srect_hdr; 512 unsigned long zlen; 513 ssize_t nwrite, total; 514 int err, width; 515 uint32_t *p, *pixelp; 516 uint8_t *zbufp; 517 518 /* 519 * Send a single rectangle of the given x, y, w h dimensions. 520 */ 521 522 /* Rectangle header */ 523 srect_hdr.x = htons(x); 524 srect_hdr.y = htons(y); 525 srect_hdr.width = htons(w); 526 srect_hdr.height = htons(h); 527 528 width = w; 529 h = y + h; 530 w *= sizeof(uint32_t); 531 if (rc->enc_zlib_ok) { 532 zbufp = rc->zbuf; 533 rc->zstream.total_in = 0; 534 rc->zstream.total_out = 0; 535 for (p = &gc->data[y * gc->width + x]; y < h; y++) { 536 pixelp = rfb_adjust_pixels(rc, p, width); 537 rc->zstream.next_in = (Bytef *)pixelp; 538 rc->zstream.avail_in = w; 539 rc->zstream.next_out = (Bytef *)zbufp; 540 rc->zstream.avail_out = RFB_ZLIB_BUFSZ + 16 - 541 rc->zstream.total_out; 542 rc->zstream.data_type = Z_BINARY; 543 544 /* Compress with zlib */ 545 err = deflate(&rc->zstream, Z_SYNC_FLUSH); 546 if (err != Z_OK) { 547 WPRINTF(("zlib[rect] deflate err: %d", err)); 548 rc->enc_zlib_ok = false; 549 deflateEnd(&rc->zstream); 550 goto doraw; 551 } 552 zbufp = rc->zbuf + rc->zstream.total_out; 553 p += gc->width; 554 } 555 srect_hdr.encoding = htonl(RFB_ENCODING_ZLIB); 556 nwrite = stream_write(cfd, &srect_hdr, 557 sizeof(struct rfb_srvr_rect_hdr)); 558 if (nwrite <= 0) 559 return (nwrite); 560 561 zlen = htonl(rc->zstream.total_out); 562 nwrite = stream_write(cfd, &zlen, sizeof(uint32_t)); 563 if (nwrite <= 0) 564 return (nwrite); 565 return (stream_write(cfd, rc->zbuf, rc->zstream.total_out)); 566 } 567 568 doraw: 569 570 total = 0; 571 zbufp = rc->zbuf; 572 for (p = &gc->data[y * gc->width + x]; y < h; y++) { 573 pixelp = rfb_adjust_pixels(rc, p, width); 574 memcpy(zbufp, pixelp, w); 575 zbufp += w; 576 total += w; 577 p += gc->width; 578 } 579 580 srect_hdr.encoding = htonl(RFB_ENCODING_RAW); 581 nwrite = stream_write(cfd, &srect_hdr, 582 sizeof(struct rfb_srvr_rect_hdr)); 583 if (nwrite <= 0) 584 return (nwrite); 585 586 total = stream_write(cfd, rc->zbuf, total); 587 588 return (total); 589 } 590 591 static int 592 rfb_send_all(struct rfb_softc *rc, int cfd, struct bhyvegc_image *gc) 593 { 594 struct rfb_srvr_updt_msg supdt_msg; 595 struct rfb_srvr_rect_hdr srect_hdr; 596 ssize_t nwrite; 597 unsigned long zlen; 598 int err; 599 600 /* 601 * Send the whole thing 602 */ 603 604 /* Number of rectangles: 1 */ 605 supdt_msg.type = 0; 606 supdt_msg.pad = 0; 607 supdt_msg.numrects = htons(1); 608 nwrite = stream_write(cfd, &supdt_msg, 609 sizeof(struct rfb_srvr_updt_msg)); 610 if (nwrite <= 0) 611 return (nwrite); 612 613 if (rc->pixfmt.adjust_pixels) { 614 return (rfb_send_rect(rc, cfd, gc, 0, 0, 615 gc->width, gc->height)); 616 } 617 618 /* Rectangle header */ 619 srect_hdr.x = 0; 620 srect_hdr.y = 0; 621 srect_hdr.width = htons(gc->width); 622 srect_hdr.height = htons(gc->height); 623 if (rc->enc_zlib_ok) { 624 rc->zstream.next_in = (Bytef *)gc->data; 625 rc->zstream.avail_in = gc->width * gc->height * 626 sizeof(uint32_t); 627 rc->zstream.next_out = (Bytef *)rc->zbuf; 628 rc->zstream.avail_out = RFB_ZLIB_BUFSZ + 16; 629 rc->zstream.data_type = Z_BINARY; 630 631 rc->zstream.total_in = 0; 632 rc->zstream.total_out = 0; 633 634 /* Compress with zlib */ 635 err = deflate(&rc->zstream, Z_SYNC_FLUSH); 636 if (err != Z_OK) { 637 WPRINTF(("zlib deflate err: %d", err)); 638 rc->enc_zlib_ok = false; 639 deflateEnd(&rc->zstream); 640 goto doraw; 641 } 642 643 srect_hdr.encoding = htonl(RFB_ENCODING_ZLIB); 644 nwrite = stream_write(cfd, &srect_hdr, 645 sizeof(struct rfb_srvr_rect_hdr)); 646 if (nwrite <= 0) 647 return (nwrite); 648 649 zlen = htonl(rc->zstream.total_out); 650 nwrite = stream_write(cfd, &zlen, sizeof(uint32_t)); 651 if (nwrite <= 0) 652 return (nwrite); 653 return (stream_write(cfd, rc->zbuf, rc->zstream.total_out)); 654 } 655 656 doraw: 657 srect_hdr.encoding = htonl(RFB_ENCODING_RAW); 658 nwrite = stream_write(cfd, &srect_hdr, 659 sizeof(struct rfb_srvr_rect_hdr)); 660 if (nwrite <= 0) 661 return (nwrite); 662 663 nwrite = stream_write(cfd, gc->data, 664 gc->width * gc->height * sizeof(uint32_t)); 665 666 return (nwrite); 667 } 668 669 #define PIX_PER_CELL 32 670 #define PIXCELL_SHIFT 5 671 #define PIXCELL_MASK 0x1F 672 673 static void 674 rfb_set_pixel_adjustment(struct rfb_softc *rc) 675 { 676 pthread_mutex_lock(&rc->pixfmt_mtx); 677 rc->pixfmt = rc->new_pixfmt; 678 pthread_mutex_unlock(&rc->pixfmt_mtx); 679 } 680 681 static int 682 rfb_send_screen(struct rfb_softc *rc, int cfd) 683 { 684 struct bhyvegc_image *gc_image; 685 ssize_t nwrite; 686 int x, y; 687 int celly, cellwidth; 688 int xcells, ycells; 689 int w, h; 690 uint32_t *p; 691 int rem_x, rem_y; /* remainder for resolutions not x32 pixels ratio */ 692 int retval; 693 uint32_t *crc_p, *orig_crc; 694 int changes; 695 bool expected; 696 697 /* Return if another thread sending */ 698 expected = false; 699 if (atomic_compare_exchange_strong(&rc->sending, &expected, true) == false) 700 return (1); 701 702 retval = 1; 703 704 /* Updates require a preceding update request */ 705 if (atomic_exchange(&rc->pending, false) == false) 706 goto done; 707 708 if (atomic_exchange(&rc->update_pixfmt, false) == true) { 709 rfb_set_pixel_adjustment(rc); 710 } 711 712 console_refresh(); 713 gc_image = console_get_image(); 714 715 /* Clear old CRC values when the size changes */ 716 if (rc->crc_width != gc_image->width || 717 rc->crc_height != gc_image->height) { 718 memset(rc->crc, 0, sizeof(uint32_t) * 719 howmany(RFB_MAX_WIDTH, PIX_PER_CELL) * 720 howmany(RFB_MAX_HEIGHT, PIX_PER_CELL)); 721 rc->crc_width = gc_image->width; 722 rc->crc_height = gc_image->height; 723 } 724 725 /* A size update counts as an update in itself */ 726 if (rc->width != gc_image->width || 727 rc->height != gc_image->height) { 728 rc->width = gc_image->width; 729 rc->height = gc_image->height; 730 if (rc->enc_resize_ok) { 731 rfb_send_resize_update_msg(rc, cfd); 732 rc->update_all = true; 733 goto done; 734 } 735 } 736 737 if (atomic_exchange(&rc->update_all, false) == true) { 738 retval = rfb_send_all(rc, cfd, gc_image); 739 goto done; 740 } 741 742 /* 743 * Calculate the checksum for each 32x32 cell. Send each that 744 * has changed since the last scan. 745 */ 746 747 w = rc->crc_width; 748 h = rc->crc_height; 749 xcells = howmany(rc->crc_width, PIX_PER_CELL); 750 ycells = howmany(rc->crc_height, PIX_PER_CELL); 751 752 rem_x = w & PIXCELL_MASK; 753 754 rem_y = h & PIXCELL_MASK; 755 if (!rem_y) 756 rem_y = PIX_PER_CELL; 757 758 p = gc_image->data; 759 760 /* 761 * Go through all cells and calculate crc. If significant number 762 * of changes, then send entire screen. 763 * crc_tmp is dual purpose: to store the new crc and to flag as 764 * a cell that has changed. 765 */ 766 crc_p = rc->crc_tmp - xcells; 767 orig_crc = rc->crc - xcells; 768 changes = 0; 769 memset(rc->crc_tmp, 0, sizeof(uint32_t) * xcells * ycells); 770 for (y = 0; y < h; y++) { 771 if ((y & PIXCELL_MASK) == 0) { 772 crc_p += xcells; 773 orig_crc += xcells; 774 } 775 776 for (x = 0; x < xcells; x++) { 777 if (x == (xcells - 1) && rem_x > 0) 778 cellwidth = rem_x; 779 else 780 cellwidth = PIX_PER_CELL; 781 782 if (rc->hw_crc) 783 crc_p[x] = fast_crc32(p, 784 cellwidth * sizeof(uint32_t), 785 crc_p[x]); 786 else 787 crc_p[x] = (uint32_t)crc32(crc_p[x], 788 (Bytef *)p, 789 cellwidth * sizeof(uint32_t)); 790 791 p += cellwidth; 792 793 /* check for crc delta if last row in cell */ 794 if ((y & PIXCELL_MASK) == PIXCELL_MASK || y == (h-1)) { 795 if (orig_crc[x] != crc_p[x]) { 796 orig_crc[x] = crc_p[x]; 797 crc_p[x] = 1; 798 changes++; 799 } else { 800 crc_p[x] = 0; 801 } 802 } 803 } 804 } 805 806 /* 807 * We only send the update if there are changes. 808 * Restore the pending flag since it was unconditionally cleared 809 * above. 810 */ 811 if (!changes) { 812 rc->pending = true; 813 goto done; 814 } 815 816 /* If number of changes is > THRESH percent, send the whole screen */ 817 if (((changes * 100) / (xcells * ycells)) >= RFB_SEND_ALL_THRESH) { 818 retval = rfb_send_all(rc, cfd, gc_image); 819 goto done; 820 } 821 822 rfb_send_update_header(rc, cfd, changes); 823 824 /* Go through all cells, and send only changed ones */ 825 crc_p = rc->crc_tmp; 826 for (y = 0; y < h; y += PIX_PER_CELL) { 827 /* previous cell's row */ 828 celly = (y >> PIXCELL_SHIFT); 829 830 /* Delta check crc to previous set */ 831 for (x = 0; x < xcells; x++) { 832 if (*crc_p++ == 0) 833 continue; 834 835 if (x == (xcells - 1) && rem_x > 0) 836 cellwidth = rem_x; 837 else 838 cellwidth = PIX_PER_CELL; 839 nwrite = rfb_send_rect(rc, cfd, 840 gc_image, 841 x * PIX_PER_CELL, 842 celly * PIX_PER_CELL, 843 cellwidth, 844 y + PIX_PER_CELL >= h ? rem_y : PIX_PER_CELL); 845 if (nwrite <= 0) { 846 retval = nwrite; 847 goto done; 848 } 849 } 850 } 851 852 done: 853 rc->sending = false; 854 855 return (retval); 856 } 857 858 859 static int 860 rfb_recv_update_msg(struct rfb_softc *rc, int cfd) 861 { 862 struct rfb_updt_msg updt_msg; 863 int len; 864 865 len = stream_read(cfd, (uint8_t *)&updt_msg + 1, 866 sizeof(updt_msg) - 1); 867 if (len <= 0) 868 return (-1); 869 870 if (rc->enc_extkeyevent_ok && (!rc->enc_extkeyevent_send)) { 871 rfb_send_extended_keyevent_update_msg(rc, cfd); 872 rc->enc_extkeyevent_send = true; 873 } 874 875 rc->pending = true; 876 if (!updt_msg.incremental) 877 rc->update_all = true; 878 879 return (0); 880 } 881 882 static int 883 rfb_recv_key_msg(struct rfb_softc *rc, int cfd) 884 { 885 struct rfb_key_msg key_msg; 886 int len; 887 888 len = stream_read(cfd, (uint8_t *)&key_msg + 1, 889 sizeof(key_msg) - 1); 890 if (len <= 0) 891 return (-1); 892 893 console_key_event(key_msg.down, htonl(key_msg.sym), htonl(0)); 894 rc->input_detected = true; 895 896 return (0); 897 } 898 899 static int 900 rfb_recv_client_msg(struct rfb_softc *rc, int cfd) 901 { 902 struct rfb_client_msg client_msg; 903 struct rfb_extended_key_msg extkey_msg; 904 int len; 905 906 len = stream_read(cfd, (uint8_t *)&client_msg + 1, 907 sizeof(client_msg) - 1); 908 if (len <= 0) 909 return (-1); 910 911 if (client_msg.subtype == RFB_CLIENTMSG_EXT_KEYEVENT) { 912 len = stream_read(cfd, (uint8_t *)&extkey_msg + 2, 913 sizeof(extkey_msg) - 2); 914 if (len <= 0) 915 return (-1); 916 console_key_event((int)extkey_msg.down, htonl(extkey_msg.sym), htonl(extkey_msg.code)); 917 rc->input_detected = true; 918 } 919 920 return (0); 921 } 922 923 static int 924 rfb_recv_ptr_msg(struct rfb_softc *rc, int cfd) 925 { 926 struct rfb_ptr_msg ptr_msg; 927 int len; 928 929 len = stream_read(cfd, (uint8_t *)&ptr_msg + 1, sizeof(ptr_msg) - 1); 930 if (len <= 0) 931 return (-1); 932 933 console_ptr_event(ptr_msg.button, htons(ptr_msg.x), htons(ptr_msg.y)); 934 rc->input_detected = true; 935 936 return (0); 937 } 938 939 static int 940 rfb_recv_cuttext_msg(struct rfb_softc *rc __unused, int cfd) 941 { 942 struct rfb_cuttext_msg ct_msg; 943 unsigned char buf[32]; 944 int len; 945 946 len = stream_read(cfd, (uint8_t *)&ct_msg + 1, sizeof(ct_msg) - 1); 947 if (len <= 0) 948 return (-1); 949 950 ct_msg.length = htonl(ct_msg.length); 951 while (ct_msg.length > 0) { 952 len = stream_read(cfd, buf, ct_msg.length > sizeof(buf) ? 953 sizeof(buf) : ct_msg.length); 954 if (len <= 0) 955 return (-1); 956 ct_msg.length -= len; 957 } 958 959 return (0); 960 } 961 962 static int64_t 963 timeval_delta(struct timeval *prev, struct timeval *now) 964 { 965 int64_t n1, n2; 966 n1 = now->tv_sec * 1000000 + now->tv_usec; 967 n2 = prev->tv_sec * 1000000 + prev->tv_usec; 968 return (n1 - n2); 969 } 970 971 static void * 972 rfb_wr_thr(void *arg) 973 { 974 struct rfb_softc *rc; 975 fd_set rfds; 976 struct timeval tv; 977 struct timeval prev_tv; 978 int64_t tdiff; 979 int cfd; 980 int err; 981 982 rc = arg; 983 cfd = rc->cfd; 984 985 prev_tv.tv_sec = 0; 986 prev_tv.tv_usec = 0; 987 while (rc->cfd >= 0) { 988 FD_ZERO(&rfds); 989 FD_SET(cfd, &rfds); 990 tv.tv_sec = 0; 991 tv.tv_usec = CFD_SEL_DELAY; 992 993 err = select(cfd+1, &rfds, NULL, NULL, &tv); 994 if (err < 0) 995 return (NULL); 996 997 /* Determine if its time to push screen; ~24hz */ 998 gettimeofday(&tv, NULL); 999 tdiff = timeval_delta(&prev_tv, &tv); 1000 if (tdiff >= SCREEN_POLL_DELAY) { 1001 bool input; 1002 prev_tv.tv_sec = tv.tv_sec; 1003 prev_tv.tv_usec = tv.tv_usec; 1004 input = atomic_exchange(&rc->input_detected, false); 1005 /* 1006 * Refresh the screen on every second trip through the loop, 1007 * or if keyboard/mouse input has been detected. 1008 */ 1009 if ((++rc->wrcount & 1) || input) { 1010 if (rfb_send_screen(rc, cfd) <= 0) { 1011 return (NULL); 1012 } 1013 } 1014 } else { 1015 /* sleep */ 1016 usleep(SCREEN_POLL_DELAY - tdiff); 1017 } 1018 } 1019 1020 return (NULL); 1021 } 1022 1023 static void 1024 rfb_handle(struct rfb_softc *rc, int cfd) 1025 { 1026 const char *vbuf = "RFB 003.008\n"; 1027 unsigned char buf[80]; 1028 unsigned const char *message; 1029 1030 #ifndef NO_OPENSSL 1031 unsigned char challenge[AUTH_LENGTH]; 1032 unsigned char keystr[PASSWD_LENGTH]; 1033 unsigned char crypt_expected[AUTH_LENGTH]; 1034 1035 DES_key_schedule ks; 1036 int i; 1037 #endif 1038 uint8_t client_ver; 1039 uint8_t auth_type; 1040 pthread_t tid; 1041 uint32_t sres = 0; 1042 int len; 1043 int perror = 1; 1044 1045 rc->cfd = cfd; 1046 1047 /* 1a. Send server version */ 1048 stream_write(cfd, vbuf, strlen(vbuf)); 1049 1050 /* 1b. Read client version */ 1051 len = stream_read(cfd, buf, VERSION_LENGTH); 1052 if (len != VERSION_LENGTH || 1053 strncmp(vbuf, buf, VERSION_LENGTH - 2) != 0) { 1054 goto done; 1055 } 1056 1057 client_ver = buf[VERSION_LENGTH - 2]; 1058 if (client_ver != CVERS_3_8 && client_ver != CVERS_3_7) { 1059 /* only recognize 3.3, 3.7 & 3.8. Others dflt to 3.3 */ 1060 client_ver = CVERS_3_3; 1061 } 1062 1063 /* 2a. Send security type */ 1064 buf[0] = 1; 1065 1066 /* In versions 3.7 & 3.8, it's 2-way handshake */ 1067 /* For version 3.3, server says what the authentication type must be */ 1068 #ifndef NO_OPENSSL 1069 if (rc->password) { 1070 auth_type = SECURITY_TYPE_VNC_AUTH; 1071 } else { 1072 auth_type = SECURITY_TYPE_NONE; 1073 } 1074 #else 1075 auth_type = SECURITY_TYPE_NONE; 1076 #endif 1077 1078 switch (client_ver) { 1079 case CVERS_3_7: 1080 case CVERS_3_8: 1081 buf[0] = 1; 1082 buf[1] = auth_type; 1083 stream_write(cfd, buf, 2); 1084 1085 /* 2b. Read agreed security type */ 1086 len = stream_read(cfd, buf, 1); 1087 if (buf[0] != auth_type) { 1088 /* deny */ 1089 sres = htonl(1); 1090 message = "Auth failed: authentication type mismatch"; 1091 goto report_and_done; 1092 } 1093 break; 1094 case CVERS_3_3: 1095 default: 1096 be32enc(buf, auth_type); 1097 stream_write(cfd, buf, 4); 1098 break; 1099 } 1100 1101 /* 2c. Do VNC authentication */ 1102 switch (auth_type) { 1103 case SECURITY_TYPE_NONE: 1104 break; 1105 case SECURITY_TYPE_VNC_AUTH: 1106 /* 1107 * The client encrypts the challenge with DES, using a password 1108 * supplied by the user as the key. 1109 * To form the key, the password is truncated to 1110 * eight characters, or padded with null bytes on the right. 1111 * The client then sends the resulting 16-bytes response. 1112 */ 1113 #ifndef NO_OPENSSL 1114 strncpy(keystr, rc->password, PASSWD_LENGTH); 1115 1116 /* VNC clients encrypts the challenge with all the bit fields 1117 * in each byte of the password mirrored. 1118 * Here we flip each byte of the keystr. 1119 */ 1120 for (i = 0; i < PASSWD_LENGTH; i++) { 1121 keystr[i] = (keystr[i] & 0xF0) >> 4 1122 | (keystr[i] & 0x0F) << 4; 1123 keystr[i] = (keystr[i] & 0xCC) >> 2 1124 | (keystr[i] & 0x33) << 2; 1125 keystr[i] = (keystr[i] & 0xAA) >> 1 1126 | (keystr[i] & 0x55) << 1; 1127 } 1128 1129 /* Initialize a 16-byte random challenge */ 1130 arc4random_buf(challenge, sizeof(challenge)); 1131 stream_write(cfd, challenge, AUTH_LENGTH); 1132 1133 /* Receive the 16-byte challenge response */ 1134 stream_read(cfd, buf, AUTH_LENGTH); 1135 1136 memcpy(crypt_expected, challenge, AUTH_LENGTH); 1137 1138 /* Encrypt the Challenge with DES */ 1139 DES_set_key((const_DES_cblock *)keystr, &ks); 1140 DES_ecb_encrypt((const_DES_cblock *)challenge, 1141 (const_DES_cblock *)crypt_expected, 1142 &ks, DES_ENCRYPT); 1143 DES_ecb_encrypt((const_DES_cblock *)(challenge + PASSWD_LENGTH), 1144 (const_DES_cblock *)(crypt_expected + 1145 PASSWD_LENGTH), 1146 &ks, DES_ENCRYPT); 1147 1148 if (memcmp(crypt_expected, buf, AUTH_LENGTH) != 0) { 1149 message = "Auth Failed: Invalid Password."; 1150 sres = htonl(1); 1151 } else { 1152 sres = 0; 1153 } 1154 #else 1155 sres = htonl(1); 1156 WPRINTF(("Auth not supported, no OpenSSL in your system")); 1157 #endif 1158 1159 break; 1160 } 1161 1162 switch (client_ver) { 1163 case CVERS_3_7: 1164 case CVERS_3_8: 1165 report_and_done: 1166 /* 2d. Write back a status */ 1167 stream_write(cfd, &sres, 4); 1168 1169 if (sres) { 1170 /* 3.7 does not want string explaining cause */ 1171 if (client_ver == CVERS_3_8) { 1172 be32enc(buf, strlen(message)); 1173 stream_write(cfd, buf, 4); 1174 stream_write(cfd, message, strlen(message)); 1175 } 1176 goto done; 1177 } 1178 break; 1179 case CVERS_3_3: 1180 default: 1181 /* for VNC auth case send status */ 1182 if (auth_type == SECURITY_TYPE_VNC_AUTH) { 1183 /* 2d. Write back a status */ 1184 stream_write(cfd, &sres, 4); 1185 } 1186 if (sres) { 1187 goto done; 1188 } 1189 break; 1190 } 1191 /* 3a. Read client shared-flag byte */ 1192 len = stream_read(cfd, buf, 1); 1193 1194 /* 4a. Write server-init info */ 1195 rfb_send_server_init_msg(rc, cfd); 1196 1197 if (!rc->zbuf) { 1198 rc->zbuf = malloc(RFB_ZLIB_BUFSZ + 16); 1199 assert(rc->zbuf != NULL); 1200 } 1201 1202 perror = pthread_create(&tid, NULL, rfb_wr_thr, rc); 1203 if (perror == 0) 1204 pthread_set_name_np(tid, "rfbout"); 1205 1206 /* Now read in client requests. 1st byte identifies type */ 1207 for (;;) { 1208 len = read(cfd, buf, 1); 1209 if (len <= 0) { 1210 DPRINTF(("rfb client exiting")); 1211 break; 1212 } 1213 1214 switch (buf[0]) { 1215 case CS_SET_PIXEL_FORMAT: 1216 if (rfb_recv_set_pixfmt_msg(rc, cfd) < 0) 1217 goto done; 1218 break; 1219 case CS_SET_ENCODINGS: 1220 if (rfb_recv_set_encodings_msg(rc, cfd) < 0) 1221 goto done; 1222 break; 1223 case CS_UPDATE_MSG: 1224 if (rfb_recv_update_msg(rc, cfd) < 0) 1225 goto done; 1226 break; 1227 case CS_KEY_EVENT: 1228 if (rfb_recv_key_msg(rc, cfd) < 0) 1229 goto done; 1230 break; 1231 case CS_POINTER_EVENT: 1232 if (rfb_recv_ptr_msg(rc, cfd) < 0) 1233 goto done; 1234 break; 1235 case CS_CUT_TEXT: 1236 if (rfb_recv_cuttext_msg(rc, cfd) < 0) 1237 goto done; 1238 break; 1239 case CS_MSG_CLIENT_QEMU: 1240 if (rfb_recv_client_msg(rc, cfd) < 0) 1241 goto done; 1242 break; 1243 default: 1244 WPRINTF(("rfb unknown cli-code %d!", buf[0] & 0xff)); 1245 goto done; 1246 } 1247 } 1248 done: 1249 rc->cfd = -1; 1250 if (perror == 0) 1251 pthread_join(tid, NULL); 1252 if (rc->enc_zlib_ok) 1253 deflateEnd(&rc->zstream); 1254 } 1255 1256 static void * 1257 rfb_thr(void *arg) 1258 { 1259 struct rfb_softc *rc; 1260 sigset_t set; 1261 1262 int cfd; 1263 1264 rc = arg; 1265 1266 sigemptyset(&set); 1267 sigaddset(&set, SIGPIPE); 1268 if (pthread_sigmask(SIG_BLOCK, &set, NULL) != 0) { 1269 perror("pthread_sigmask"); 1270 return (NULL); 1271 } 1272 1273 for (;;) { 1274 rc->enc_raw_ok = false; 1275 rc->enc_zlib_ok = false; 1276 rc->enc_resize_ok = false; 1277 rc->enc_extkeyevent_ok = false; 1278 1279 rc->enc_extkeyevent_send = false; 1280 1281 cfd = accept(rc->sfd, NULL, NULL); 1282 if (rc->conn_wait) { 1283 pthread_mutex_lock(&rc->mtx); 1284 pthread_cond_signal(&rc->cond); 1285 pthread_mutex_unlock(&rc->mtx); 1286 rc->conn_wait = 0; 1287 } 1288 rfb_handle(rc, cfd); 1289 close(cfd); 1290 } 1291 1292 /* NOTREACHED */ 1293 return (NULL); 1294 } 1295 1296 static int 1297 sse42_supported(void) 1298 { 1299 u_int cpu_registers[4], ecx; 1300 1301 do_cpuid(1, cpu_registers); 1302 1303 ecx = cpu_registers[2]; 1304 1305 return ((ecx & CPUID2_SSE42) != 0); 1306 } 1307 1308 int 1309 rfb_init(sa_family_t family, const char *hostname, int port, int wait, 1310 const char *password) 1311 { 1312 int e; 1313 char servname[6]; 1314 struct rfb_softc *rc; 1315 struct addrinfo *ai = NULL; 1316 struct addrinfo hints; 1317 struct sockaddr_un sun; 1318 int on = 1; 1319 int cnt; 1320 #ifndef WITHOUT_CAPSICUM 1321 cap_rights_t rights; 1322 #endif 1323 1324 rc = calloc(1, sizeof(struct rfb_softc)); 1325 1326 cnt = howmany(RFB_MAX_WIDTH, PIX_PER_CELL) * 1327 howmany(RFB_MAX_HEIGHT, PIX_PER_CELL); 1328 rc->crc = calloc(cnt, sizeof(uint32_t)); 1329 rc->crc_tmp = calloc(cnt, sizeof(uint32_t)); 1330 rc->crc_width = RFB_MAX_WIDTH; 1331 rc->crc_height = RFB_MAX_HEIGHT; 1332 rc->sfd = -1; 1333 1334 rc->password = password; 1335 1336 rc->fbnamelen = asprintf(&rc->fbname, "bhyve:%s", 1337 get_config_value("name")); 1338 if (rc->fbnamelen < 0) { 1339 EPRINTLN("rfb: failed to allocate memory for VNC title"); 1340 goto error; 1341 } 1342 1343 rc->pixrow = malloc(RFB_MAX_WIDTH * sizeof(uint32_t)); 1344 if (rc->pixrow == NULL) { 1345 EPRINTLN("rfb: failed to allocate memory for pixrow buffer"); 1346 goto error; 1347 } 1348 1349 snprintf(servname, sizeof(servname), "%d", port ? port : 5900); 1350 1351 if (!hostname || strlen(hostname) == 0) 1352 #if defined(INET) 1353 hostname = "127.0.0.1"; 1354 #elif defined(INET6) 1355 hostname = "[::1]"; 1356 #endif 1357 1358 if (family == AF_UNIX) { 1359 memset(&sun, 0, sizeof(sun)); 1360 sun.sun_family = AF_UNIX; 1361 if (strlcpy(sun.sun_path, hostname, sizeof(sun.sun_path)) >= 1362 sizeof(sun.sun_path)) { 1363 EPRINTLN("rfb: socket path too long"); 1364 goto error; 1365 } 1366 rc->sfd = socket(AF_UNIX, SOCK_STREAM, 0); 1367 } else { 1368 memset(&hints, 0, sizeof(hints)); 1369 hints.ai_socktype = SOCK_STREAM; 1370 hints.ai_family = family; 1371 hints.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV | AI_PASSIVE; 1372 1373 if ((e = getaddrinfo(hostname, servname, &hints, &ai)) != 0) { 1374 EPRINTLN("getaddrinfo: %s", gai_strerror(e)); 1375 goto error; 1376 } 1377 rc->sfd = socket(ai->ai_family, ai->ai_socktype, 0); 1378 } 1379 1380 if (rc->sfd < 0) { 1381 perror("socket"); 1382 goto error; 1383 } 1384 1385 /* No effect for UNIX domain sockets. */ 1386 setsockopt(rc->sfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); 1387 1388 if (family == AF_UNIX) { 1389 unlink(hostname); 1390 e = bind(rc->sfd, (struct sockaddr *)&sun, SUN_LEN(&sun)); 1391 } else 1392 e = bind(rc->sfd, ai->ai_addr, ai->ai_addrlen); 1393 if (e < 0) { 1394 perror("bind"); 1395 goto error; 1396 } 1397 1398 if (listen(rc->sfd, 1) < 0) { 1399 perror("listen"); 1400 goto error; 1401 } 1402 1403 #ifndef WITHOUT_CAPSICUM 1404 cap_rights_init(&rights, CAP_ACCEPT, CAP_EVENT, CAP_READ, CAP_WRITE); 1405 if (caph_rights_limit(rc->sfd, &rights) == -1) 1406 errx(EX_OSERR, "Unable to apply rights for sandbox"); 1407 #endif 1408 1409 rc->hw_crc = sse42_supported(); 1410 1411 rc->conn_wait = wait; 1412 if (wait) { 1413 pthread_mutex_init(&rc->mtx, NULL); 1414 pthread_cond_init(&rc->cond, NULL); 1415 } 1416 1417 pthread_mutex_init(&rc->pixfmt_mtx, NULL); 1418 pthread_create(&rc->tid, NULL, rfb_thr, rc); 1419 pthread_set_name_np(rc->tid, "rfb"); 1420 1421 if (wait) { 1422 DPRINTF(("Waiting for rfb client...")); 1423 pthread_mutex_lock(&rc->mtx); 1424 pthread_cond_wait(&rc->cond, &rc->mtx); 1425 pthread_mutex_unlock(&rc->mtx); 1426 DPRINTF(("rfb client connected")); 1427 } 1428 1429 if (family != AF_UNIX) 1430 freeaddrinfo(ai); 1431 return (0); 1432 1433 error: 1434 if (rc->pixfmt_mtx) 1435 pthread_mutex_destroy(&rc->pixfmt_mtx); 1436 if (ai != NULL) { 1437 assert(family != AF_UNIX); 1438 freeaddrinfo(ai); 1439 } 1440 if (rc->sfd != -1) 1441 close(rc->sfd); 1442 free(rc->crc); 1443 free(rc->crc_tmp); 1444 free(rc->pixrow); 1445 free(rc->fbname); 1446 free(rc); 1447 return (-1); 1448 } 1449