1 /* $NetBSD: thunk.c,v 1.93 2024/03/17 21:48:01 andvar Exp $ */ 2 3 /*- 4 * Copyright (c) 2011 Jared D. McNeill <jmcneill (at) invisible.ca> 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #include <sys/cdefs.h> 30 #ifdef __NetBSD__ 31 __RCSID("$NetBSD: thunk.c,v 1.93 2024/03/17 21:48:01 andvar Exp $"); 32 #endif 33 34 #define _KMEMUSER 35 #define _X86_64_MACHTYPES_H_ 36 #define _I386_MACHTYPES_H_ 37 38 #include "../include/types.h" 39 40 #include <sys/mman.h> 41 #include <stdarg.h> 42 #include <sys/reboot.h> 43 #include <sys/poll.h> 44 #include <sys/sysctl.h> 45 #include <sys/socket.h> 46 #include <sys/audioio.h> 47 #include <sys/shm.h> 48 #include <sys/ioctl.h> 49 50 #include <machine/vmparam.h> 51 52 #include <net/if.h> 53 #include <net/if_dl.h> 54 #include <net/if_ether.h> 55 #include <net/if_tap.h> 56 #include <netinet/in.h> 57 #include <arpa/inet.h> 58 59 #include <aio.h> 60 #include <assert.h> 61 #include <ctype.h> 62 #include <err.h> 63 #include <errno.h> 64 #include <fcntl.h> 65 #include <ifaddrs.h> 66 #include <sched.h> 67 #include <stdarg.h> 68 #include <stdint.h> 69 #include <stdio.h> 70 #include <stdlib.h> 71 #include <signal.h> 72 #include <string.h> 73 #include <termios.h> 74 #include <time.h> 75 #include <ucontext.h> 76 #include <unistd.h> 77 #include <stdbool.h> 78 79 #include "../include/thunk.h" 80 81 #ifdef __NetBSD__ 82 #define SYS_syscallemu 511 83 #endif 84 85 #ifndef __arraycount 86 #define __arraycount(x) (sizeof((x)) / sizeof((x)[0])) 87 #endif 88 89 #ifndef MAP_ANON 90 #define MAP_ANON MAP_ANONYMOUS 91 #endif 92 93 //#define RFB_DEBUG 94 95 static ssize_t safe_recv(int s, void *buf, int len); 96 static ssize_t safe_send(int s, const void *msg, int len); 97 98 extern int boothowto; 99 100 void 101 thunk_printf_debug(const char *fmt, ...) 102 { 103 if (boothowto & AB_DEBUG) { 104 va_list ap; 105 106 va_start(ap, fmt); 107 vfprintf(stderr, fmt, ap); 108 va_end(ap); 109 } 110 } 111 112 void 113 thunk_printf(const char *fmt, ...) 114 { 115 va_list ap; 116 117 va_start(ap, fmt); 118 vfprintf(stderr, fmt, ap); 119 va_end(ap); 120 fflush(stderr); 121 } 122 123 int 124 thunk_syscallemu_init(void *ustart, void *uend) 125 { 126 int error; 127 128 errno = 0; 129 error = syscall(SYS_syscallemu, (uintptr_t)ustart, (uintptr_t)uend); 130 if (error == -1 && errno == EACCES) { 131 /* syscallemu already active for this pid */ 132 error = 0; 133 } 134 135 return error; 136 } 137 138 static void 139 thunk_to_timeval(const struct thunk_timeval *ttv, struct timeval *tv) 140 { 141 tv->tv_sec = ttv->tv_sec; 142 tv->tv_usec = ttv->tv_usec; 143 } 144 145 static void 146 thunk_from_timeval(const struct timeval *tv, struct thunk_timeval *ttv) 147 { 148 ttv->tv_sec = tv->tv_sec; 149 ttv->tv_usec = tv->tv_usec; 150 } 151 152 static void 153 thunk_to_itimerval(const struct thunk_itimerval *tit, struct itimerval *it) 154 { 155 thunk_to_timeval(&tit->it_interval, &it->it_interval); 156 thunk_to_timeval(&tit->it_value, &it->it_value); 157 } 158 159 static void 160 thunk_from_itimerval(const struct itimerval *it, struct thunk_itimerval *tit) 161 { 162 thunk_from_timeval(&it->it_interval, &tit->it_interval); 163 thunk_from_timeval(&it->it_value, &tit->it_value); 164 } 165 166 static void 167 thunk_to_termios(const struct thunk_termios *tt, struct termios *t) 168 { 169 int i; 170 171 t->c_iflag = tt->c_iflag; 172 t->c_oflag = tt->c_oflag; 173 t->c_cflag = tt->c_cflag; 174 t->c_lflag = tt->c_lflag; 175 for (i = 0; i < __arraycount(t->c_cc); i++) 176 t->c_cc[i] = tt->c_cc[i]; 177 t->c_ispeed = tt->c_ispeed; 178 t->c_ospeed= tt->c_ospeed; 179 } 180 181 static void 182 thunk_from_termios(const struct termios *t, struct thunk_termios *tt) 183 { 184 int i; 185 186 tt->c_iflag = t->c_iflag; 187 tt->c_oflag = t->c_oflag; 188 tt->c_cflag = t->c_cflag; 189 tt->c_lflag = t->c_lflag; 190 for (i = 0; i < __arraycount(tt->c_cc); i++) 191 tt->c_cc[i] = t->c_cc[i]; 192 tt->c_ispeed = t->c_ispeed; 193 tt->c_ospeed= t->c_ospeed; 194 } 195 196 static int 197 thunk_to_native_prot(int prot) 198 { 199 int nprot = PROT_NONE; 200 201 if (prot & THUNK_PROT_READ) 202 nprot |= PROT_READ; 203 if (prot & THUNK_PROT_WRITE) 204 nprot |= PROT_WRITE; 205 if (prot & THUNK_PROT_EXEC) 206 nprot |= PROT_EXEC; 207 208 return nprot; 209 } 210 211 static int 212 thunk_to_native_mapflags(int flags) 213 { 214 int nflags = 0; 215 216 if (flags & THUNK_MAP_ANON) 217 nflags |= MAP_ANON; 218 if (flags & THUNK_MAP_FIXED) 219 nflags |= MAP_FIXED; 220 if (flags & THUNK_MAP_FILE) 221 nflags |= MAP_FILE; 222 if (flags & THUNK_MAP_SHARED) 223 nflags |= MAP_SHARED; 224 if (flags & THUNK_MAP_PRIVATE) 225 nflags |= MAP_PRIVATE; 226 227 return nflags; 228 } 229 230 static int 231 thunk_to_native_madviseflags(int flags) 232 { 233 int nflags = 0; 234 235 if (flags & THUNK_MADV_NORMAL) 236 nflags |= MADV_NORMAL; 237 if (flags & THUNK_MADV_RANDOM) 238 nflags |= MADV_RANDOM; 239 if (flags & THUNK_MADV_SEQUENTIAL) 240 nflags |= MADV_SEQUENTIAL; 241 if (flags & THUNK_MADV_WILLNEED) 242 nflags |= MADV_WILLNEED; 243 if (flags & THUNK_MADV_DONTNEED) 244 nflags |= MADV_DONTNEED; 245 if (flags & THUNK_MADV_FREE) 246 nflags |= MADV_FREE; 247 248 return nflags; 249 } 250 251 int 252 thunk_setitimer(int which, const struct thunk_itimerval *value, 253 struct thunk_itimerval *ovalue) 254 { 255 struct itimerval it, oit; 256 int error; 257 258 thunk_to_itimerval(value, &it); 259 error = setitimer(which, &it, &oit); 260 if (error) 261 return error; 262 if (ovalue) 263 thunk_from_itimerval(&oit, ovalue); 264 265 return 0; 266 } 267 268 int 269 thunk_gettimeofday(struct thunk_timeval *tp, void *tzp) 270 { 271 struct timeval tv; 272 int error; 273 274 error = gettimeofday(&tv, tzp); 275 if (error) 276 return error; 277 278 thunk_from_timeval(&tv, tp); 279 280 return 0; 281 } 282 283 unsigned int 284 thunk_getcounter(void) 285 { 286 struct timespec ts; 287 int error; 288 289 error = clock_gettime(CLOCK_MONOTONIC, &ts); 290 if (error == -1) { 291 warn("clock_gettime CLOCK_MONOTONIC"); 292 abort(); 293 } 294 295 return (unsigned int)(ts.tv_nsec % 1000000000ULL); 296 } 297 298 long 299 thunk_clock_getres_monotonic(void) 300 { 301 struct timespec res; 302 int error; 303 304 error = clock_getres(CLOCK_MONOTONIC, &res); 305 if (error == -1) 306 return -1; 307 308 return (long)(res.tv_sec * 1000000000ULL + res.tv_nsec); 309 } 310 311 timer_t 312 thunk_timer_attach(void) 313 { 314 timer_t timerid; 315 int error; 316 317 error = timer_create(CLOCK_MONOTONIC, NULL, &timerid); 318 if (error == -1) { 319 warn("timer_create CLOCK_MONOTONIC"); 320 abort(); 321 } 322 323 return timerid; 324 } 325 326 int 327 thunk_timer_start(timer_t timerid, int freq) 328 { 329 struct itimerspec tim; 330 331 tim.it_interval.tv_sec = 0; 332 tim.it_interval.tv_nsec = 1000000000 / freq; 333 tim.it_value = tim.it_interval; 334 335 return timer_settime(timerid, TIMER_RELTIME, &tim, NULL); 336 } 337 338 int 339 thunk_timer_getoverrun(timer_t timerid) 340 { 341 return timer_getoverrun(timerid); 342 } 343 344 int 345 thunk_usleep(useconds_t microseconds) 346 { 347 return usleep(microseconds); 348 } 349 350 void 351 thunk_kill(pid_t pid, int sig) 352 { 353 kill(pid, sig); 354 } 355 356 void 357 thunk_exit(int status) 358 { 359 return exit(status); 360 } 361 362 void 363 thunk_abort(void) 364 { 365 abort(); 366 } 367 368 int 369 thunk_geterrno(void) 370 { 371 return errno; 372 } 373 374 void 375 thunk_seterrno(int nerrno) 376 { 377 errno = nerrno; 378 } 379 380 int 381 thunk_getcontext(ucontext_t *ucp) 382 { 383 return getcontext(ucp); 384 } 385 386 int 387 thunk_setcontext(const ucontext_t *ucp) 388 { 389 return setcontext(ucp); 390 } 391 392 void 393 thunk_makecontext(ucontext_t *ucp, void (*func)(void), 394 int nargs, void *arg1, void *arg2, void *arg3, void *arg4) 395 { 396 switch (nargs) { 397 case 0: 398 makecontext(ucp, func, 0); 399 break; 400 case 1: 401 makecontext(ucp, func, 1, arg1); 402 break; 403 case 2: 404 makecontext(ucp, func, 2, arg1, arg2); 405 break; 406 case 3: 407 makecontext(ucp, func, 3, arg1, arg2, arg3); 408 break; 409 case 4: 410 makecontext(ucp, func, 4, arg1, arg2, arg3, arg4); 411 break; 412 default: 413 warnx("%s: nargs (%d) too big\n", __func__, nargs); 414 abort(); 415 } 416 } 417 418 int 419 thunk_swapcontext(ucontext_t *oucp, ucontext_t *ucp) 420 { 421 return swapcontext(oucp, ucp); 422 } 423 424 int 425 thunk_tcgetattr(int fd, struct thunk_termios *tt) 426 { 427 struct termios t; 428 int error; 429 430 error = tcgetattr(fd, &t); 431 if (error == -1) 432 return error; 433 thunk_from_termios(&t, tt); 434 return 0; 435 } 436 437 int 438 thunk_tcsetattr(int fd, int action, const struct thunk_termios *tt) 439 { 440 struct termios t; 441 442 thunk_to_termios(tt, &t); 443 return tcsetattr(fd, action, &t); 444 } 445 446 int 447 thunk_set_stdin_sigio(int onoff) 448 { 449 int flags; 450 451 flags = fcntl(STDIN_FILENO, F_GETFL, 0); 452 453 if (onoff) 454 flags |= O_ASYNC; 455 else 456 flags &= ~O_ASYNC; 457 458 return fcntl(STDIN_FILENO, F_SETFL, flags); 459 } 460 461 int 462 thunk_pollchar(void) 463 { 464 struct pollfd fds[1]; 465 uint8_t c; 466 467 fds[0].fd = STDIN_FILENO; 468 fds[0].events = POLLIN; 469 fds[0].revents = 0; 470 471 if (poll(fds, __arraycount(fds), 0) > 0) { 472 if (fds[0].revents & POLLIN) { 473 if (read(STDIN_FILENO, &c, 1) != 1) 474 return EOF; 475 return c; 476 } 477 } 478 479 return EOF; 480 } 481 482 int 483 thunk_getchar(void) 484 { 485 return getchar(); 486 } 487 488 void 489 thunk_putchar(int c) 490 { 491 char wc = (char) c; 492 write(1, &wc, 1); 493 } 494 495 int 496 thunk_execv(const char *path, char * const argv[]) 497 { 498 return execv(path, argv); 499 } 500 501 int 502 thunk_open(const char *path, int flags, mode_t mode) 503 { 504 return open(path, flags, mode); 505 } 506 507 int 508 thunk_close(int fd) 509 { 510 return close(fd); 511 } 512 513 int 514 thunk_fstat_getsize(int fd, off_t *size, ssize_t *blksize) 515 { 516 struct stat st; 517 int error; 518 519 error = fstat(fd, &st); 520 if (error) 521 return -1; 522 523 if (size) 524 *size = st.st_size; 525 if (blksize) 526 *blksize = st.st_blksize; 527 528 return 0; 529 } 530 531 ssize_t 532 thunk_pread(int d, void *buf, size_t nbytes, off_t offset) 533 { 534 return pread(d, buf, nbytes, offset); 535 } 536 537 ssize_t 538 thunk_pwrite(int d, const void *buf, size_t nbytes, off_t offset) 539 { 540 return pwrite(d, buf, nbytes, offset); 541 } 542 543 ssize_t 544 thunk_read(int d, void *buf, size_t nbytes) 545 { 546 return read(d, buf, nbytes); 547 } 548 549 ssize_t 550 thunk_write(int d, const void *buf, size_t nbytes) 551 { 552 return write(d, buf, nbytes); 553 } 554 555 int 556 thunk_fsync(int fd) 557 { 558 return fsync(fd); 559 } 560 561 int 562 thunk_mkstemp(char *template) 563 { 564 return mkstemp(template); 565 } 566 567 int 568 thunk_unlink(const char *path) 569 { 570 return unlink(path); 571 } 572 573 pid_t 574 thunk_getpid(void) 575 { 576 return getpid(); 577 } 578 579 int 580 thunk_sigaction(int sig, const struct sigaction *act, struct sigaction *oact) 581 { 582 return sigaction(sig, act, oact); 583 } 584 585 int 586 thunk_sigaltstack(const stack_t *ss, stack_t *oss) 587 { 588 return sigaltstack(ss, oss); 589 } 590 591 void 592 thunk_signal(int sig, void (*func)(int)) 593 { 594 struct sigaction sa; 595 596 sa.sa_flags = SA_RESTART | SA_ONSTACK; 597 sa.sa_sigaction = (void (*)(int, siginfo_t *, void *))func; 598 sigemptyset(&sa.sa_mask); 599 sigaction(sig, &sa, NULL); 600 } 601 602 int 603 thunk_sigblock(int sig) 604 { 605 sigset_t set; 606 607 sigemptyset(&set); 608 sigaddset(&set, sig); 609 return sigprocmask(SIG_BLOCK, &set, NULL); 610 } 611 612 int 613 thunk_sigunblock(int sig) 614 { 615 sigset_t set; 616 617 sigemptyset(&set); 618 sigaddset(&set, sig); 619 return sigprocmask(SIG_UNBLOCK, &set, NULL); 620 } 621 622 int 623 thunk_sigemptyset(sigset_t *sa_mask) 624 { 625 return sigemptyset(sa_mask); 626 } 627 628 629 int 630 thunk_sigfillset(sigset_t *sa_mask) 631 { 632 return sigfillset(sa_mask); 633 } 634 635 636 void 637 thunk_sigaddset(sigset_t *sa_mask, int sig) 638 { 639 int retval; 640 retval = sigaddset(sa_mask, sig); 641 if (retval == -1) { 642 warn("bad signal added"); 643 abort(); 644 } 645 } 646 647 int 648 thunk_sigprocmask(int how, const sigset_t * set, sigset_t *oset) 649 { 650 return sigprocmask(how, set, oset); 651 } 652 653 int 654 thunk_atexit(void (*function)(void)) 655 { 656 return atexit(function); 657 } 658 659 pid_t 660 thunk_fork(void) 661 { 662 return fork(); 663 } 664 665 int 666 thunk_ioctl(int fd, unsigned long request, void *opaque) 667 { 668 return ioctl(fd, request, opaque); 669 } 670 671 int 672 thunk_aio_read(struct aiocb *aiocbp) 673 { 674 return aio_read(aiocbp); 675 } 676 677 int 678 thunk_aio_write(struct aiocb *aiocbp) 679 { 680 return aio_write(aiocbp); 681 } 682 683 int 684 thunk_aio_error(const struct aiocb *aiocbp) 685 { 686 return aio_error(aiocbp); 687 } 688 689 int 690 thunk_aio_return(struct aiocb *aiocbp) 691 { 692 return aio_return(aiocbp); 693 } 694 695 void * 696 thunk_malloc(size_t len) 697 { 698 return malloc(len); 699 } 700 701 void 702 thunk_free(void *addr) 703 { 704 free(addr); 705 } 706 707 void * 708 thunk_sbrk(intptr_t len) 709 { 710 return sbrk(len); 711 } 712 713 void * 714 thunk_mmap(void *addr, size_t len, int prot, int flags, int fd, off_t offset) 715 { 716 int nflags, nprot; 717 void *a; 718 719 nprot = thunk_to_native_prot(prot); 720 nflags = thunk_to_native_mapflags(flags); 721 722 a = mmap(addr, len, nprot, nflags, fd, offset); 723 if (a == MAP_FAILED) 724 warn("mmap"); 725 return a; 726 } 727 728 int 729 thunk_munmap(void *addr, size_t len) 730 { 731 return munmap(addr, len); 732 } 733 734 int 735 thunk_mprotect(void *addr, size_t len, int prot) 736 { 737 int nprot; 738 739 nprot = thunk_to_native_prot(prot); 740 741 return mprotect(addr, len, nprot); 742 } 743 744 int 745 thunk_madvise(void *addr, size_t len, int behav) 746 { 747 int nbehav; 748 749 nbehav = thunk_to_native_madviseflags(behav); 750 751 return madvise(addr, len, nbehav); 752 } 753 754 int 755 thunk_posix_memalign(void **ptr, size_t alignment, size_t size) 756 { 757 return posix_memalign(ptr, alignment, size); 758 } 759 760 char * 761 thunk_getenv(const char *name) 762 { 763 return getenv(name); 764 } 765 766 vaddr_t 767 thunk_get_vm_min_address(void) 768 { 769 return VM_MIN_ADDRESS; 770 } 771 772 int 773 thunk_idle(void) 774 { 775 sigset_t sigmask; 776 777 sigemptyset(&sigmask); 778 779 return sigsuspend(&sigmask); 780 } 781 782 int 783 thunk_getcpuinfo(char *cp, size_t *len) 784 { 785 ssize_t rlen; 786 int fd; 787 788 fd = open("/proc/cpuinfo", O_RDONLY); 789 if (fd == -1) 790 goto out; 791 rlen = read(fd, cp, *len); 792 close(fd); 793 794 if (rlen == -1) 795 goto out; 796 797 cp[rlen ? rlen - 1 : 0] = '\0'; 798 *len = rlen; 799 return 0; 800 out: 801 *len = 0; 802 return -1; 803 } 804 805 int 806 thunk_getmachine(char *machine, size_t machinelen, 807 char *machine_arch, size_t machine_archlen) 808 { 809 size_t len; 810 811 memset(machine, 0, machinelen); 812 len = machinelen - 1; 813 if (sysctlbyname("hw.machine", machine, &len, NULL, 0) == -1) { 814 warn("sysctlbyname hw.machine failed"); 815 abort(); 816 } 817 818 memset(machine_arch, 0, machine_archlen); 819 len = machine_archlen - 1; 820 if (sysctlbyname("hw.machine_arch", machine_arch, &len, NULL, 0) == -1) { 821 warn("sysctlbyname hw.machine_arch failed"); 822 abort(); 823 } 824 825 return 0; 826 } 827 828 int 829 thunk_setown(int fd) 830 { 831 return fcntl(fd, F_SETOWN, getpid()); 832 } 833 834 int 835 thunk_open_tap(const char *device) 836 { 837 int fd, error, enable; 838 839 /* open tap device */ 840 fd = open(device, O_RDWR); 841 if (fd == -1) 842 return -1; 843 844 /* set async mode */ 845 enable = 1; 846 error = ioctl(fd, FIOASYNC, &enable); 847 if (error == -1) 848 return -1; 849 850 return fd; 851 } 852 853 int 854 thunk_pollin_tap(int fd, int timeout) 855 { 856 #if 0 857 struct pollfd fds[1]; 858 859 fds[0].fd = fd; 860 fds[0].events = POLLIN|POLLRDNORM; 861 fds[0].revents = 0; 862 863 return poll(fds, __arraycount(fds), timeout); 864 #else 865 int error, len; 866 867 error = ioctl(fd, FIONREAD, &len); 868 if (error == -1) 869 return 0; 870 871 return len; 872 #endif 873 } 874 875 int 876 thunk_pollout_tap(int fd, int timeout) 877 { 878 struct pollfd fds[1]; 879 880 fds[0].fd = fd; 881 fds[0].events = POLLOUT|POLLWRNORM; 882 fds[0].revents = 0; 883 884 return poll(fds, __arraycount(fds), timeout); 885 } 886 887 888 /* simply make sure its present... yeah its silly */ 889 int 890 thunk_assert_presence(vaddr_t from, size_t size) 891 { 892 vaddr_t va; 893 int t = 0; 894 895 for (va = from; va < from + (vaddr_t) size; va += PAGE_SIZE) { 896 t += *(int *) va; 897 } 898 return t; 899 } 900 901 902 int 903 thunk_audio_open(const char *path) 904 { 905 return open(path, O_RDWR); 906 } 907 908 int 909 thunk_audio_close(int fd) 910 { 911 return close(fd); 912 } 913 914 int 915 thunk_audio_config(int fd, const thunk_audio_config_t *pconf, 916 const thunk_audio_config_t *rconf) 917 { 918 struct audio_info info; 919 int error; 920 921 AUDIO_INITINFO(&info); 922 info.play.sample_rate = pconf->sample_rate; 923 info.play.channels = pconf->channels; 924 info.play.precision = pconf->precision; 925 info.play.encoding = AUDIO_ENCODING_SLINEAR_LE; 926 info.record.sample_rate = rconf->sample_rate; 927 info.record.channels = rconf->channels; 928 info.record.precision = rconf->precision; 929 info.record.encoding = AUDIO_ENCODING_SLINEAR_LE; 930 info.mode = AUMODE_PLAY_ALL|AUMODE_RECORD; 931 932 error = ioctl(fd, AUDIO_SETINFO, &info); 933 if (error == -1) 934 printf("AUDIO_SETINFO failed: %s\n", strerror(errno)); 935 936 return error; 937 } 938 939 int 940 thunk_audio_pollout(int fd) 941 { 942 struct audio_info info; 943 int error; 944 945 AUDIO_INITINFO(&info); 946 error = ioctl(fd, AUDIO_GETBUFINFO, &info); 947 if (error == -1) 948 return -1; 949 950 return info.play.buffer_size - info.play.seek; 951 } 952 953 int 954 thunk_audio_pollin(int fd) 955 { 956 struct audio_info info; 957 int error; 958 959 AUDIO_INITINFO(&info); 960 error = ioctl(fd, AUDIO_GETBUFINFO, &info); 961 if (error == -1) 962 return -1; 963 964 return info.record.seek; 965 } 966 967 ssize_t 968 thunk_audio_write(int fd, const void *buf, size_t buflen) 969 { 970 return write(fd, buf, buflen); 971 } 972 973 ssize_t 974 thunk_audio_read(int fd, void *buf, size_t buflen) 975 { 976 return read(fd, buf, buflen); 977 } 978 979 int 980 thunk_rfb_open(thunk_rfb_t *rfb, uint16_t port) 981 { 982 struct sockaddr_in sin; 983 int serrno; 984 985 rfb->clientfd = -1; 986 rfb->connected = false; 987 988 /* create socket */ 989 rfb->sockfd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); 990 if (rfb->sockfd == -1) { 991 serrno = errno; 992 warn("rfb: couldn't create socket"); 993 return serrno; 994 } 995 /* bind to requested port */ 996 memset(&sin, 0, sizeof(sin)); 997 sin.sin_family = AF_INET; 998 sin.sin_addr.s_addr = htonl(INADDR_ANY); 999 sin.sin_port = htons(port); 1000 if (bind(rfb->sockfd, (struct sockaddr *)&sin, sizeof(sin)) == -1) { 1001 serrno = errno; 1002 warn("rfb: couldn't bind port %d", port); 1003 close(rfb->sockfd); 1004 return serrno; 1005 } 1006 /* listen for connections */ 1007 if (listen(rfb->sockfd, 1) != 0) { 1008 serrno = errno; 1009 warn("rfb: couldn't listen on socket"); 1010 close(rfb->sockfd); 1011 return errno; 1012 } 1013 1014 return 0; 1015 } 1016 1017 int 1018 thunk_gdb_open(void) 1019 { 1020 struct sockaddr_in sin; 1021 int sockfd; 1022 int portnr = 5001; /* XXX configurable or random */ 1023 1024 /* create socket */ 1025 sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 1026 if (sockfd < 0) { 1027 warn("kgdb stub: couldn't create socket"); 1028 return 0; 1029 } 1030 1031 /* bind to requested port */ 1032 memset(&sin, 0, sizeof(sin)); 1033 sin.sin_family = AF_INET; 1034 sin.sin_addr.s_addr = htonl(INADDR_ANY); 1035 sin.sin_port = htons(portnr); 1036 1037 if (bind(sockfd, (struct sockaddr *)&sin, sizeof(sin)) < 0) { 1038 warn("kgdb stub: couldn't bind port %d", portnr); 1039 close(sockfd); 1040 return 0; 1041 } 1042 1043 /* listen for connections */ 1044 if (listen(sockfd, 1) < 0) { 1045 warn("kgdb stub: couldn't listen on socket"); 1046 close(sockfd); 1047 return 0; 1048 } 1049 printf("kgdb stub: accepting connections on port %d\n", portnr); 1050 1051 return sockfd; 1052 } 1053 1054 int 1055 thunk_gdb_accept(int sockfd) 1056 { 1057 struct sockaddr_in client_addr; 1058 socklen_t client_addrlen; 1059 int fd, flags; 1060 1061 fd = accept(sockfd, (struct sockaddr *) &client_addr, &client_addrlen); 1062 if (fd < 0) { 1063 warn("kgdb_stub: connect error"); 1064 return 0; 1065 } 1066 1067 /* make FIFO unblocking */ 1068 flags = fcntl(fd, F_GETFL, 0); 1069 if (flags == -1) 1070 flags = 0; 1071 if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0) { 1072 warn("kgdb_stub: can't make socket non blocking"); 1073 } 1074 return fd; 1075 } 1076 1077 int 1078 thunk_kgdb_getc(int fd, char *ch) 1079 { 1080 return safe_recv(fd, ch, 1); 1081 } 1082 1083 int 1084 thunk_kgdb_putc(int fd, char ch) 1085 { 1086 return safe_send(fd, &ch, 1); 1087 } 1088 1089 static ssize_t 1090 safe_send(int s, const void *msg, int len) 1091 { 1092 const uint8_t *p; 1093 ssize_t sent_len; 1094 1095 p = msg; 1096 while (len) { 1097 assert(len >= 0); 1098 sent_len = send(s, p, len, MSG_NOSIGNAL); 1099 if (sent_len == -1) { 1100 if (errno == EAGAIN || errno == EINTR) 1101 continue; 1102 return -1; 1103 } 1104 1105 p += sent_len; 1106 len -= sent_len; 1107 } 1108 return len; 1109 } 1110 1111 static ssize_t 1112 safe_recv(int s, void *buf, int len) 1113 { 1114 uint8_t *p; 1115 int recv_len; 1116 1117 p = buf; 1118 while (len) { 1119 assert(len >= 0); 1120 recv_len = recv(s, p, len, MSG_NOSIGNAL); 1121 if (recv_len == -1) { 1122 if (errno == EAGAIN || errno == EINTR) 1123 continue; 1124 return -1; 1125 } 1126 p += recv_len; 1127 len -= recv_len; 1128 } 1129 return len; 1130 } 1131 1132 static ssize_t 1133 thunk_rfb_server_init(thunk_rfb_t *rfb) 1134 { 1135 char msgbuf[80]; 1136 char *p = msgbuf; 1137 uint32_t namelen = strlen(rfb->name); 1138 1139 *(uint16_t *)p = htons(rfb->width); p += 2; 1140 *(uint16_t *)p = htons(rfb->height); p += 2; 1141 *(uint8_t *)p = rfb->depth; p += 1; 1142 *(uint8_t *)p = rfb->depth; p += 1; 1143 *(uint8_t *)p = 0; p += 1; /* endian */ 1144 *(uint8_t *)p = 1; p += 1; /* true color */ 1145 *(uint16_t *)p = htons(0xff); p += 2; /* red max */ 1146 *(uint16_t *)p = htons(0xff); p += 2; /* green max */ 1147 *(uint16_t *)p = htons(0xff); p += 2; /* blue max */ 1148 *(uint8_t *)p = 0; p += 1; /* red shift */ 1149 *(uint8_t *)p = 8; p += 1; /* green shift */ 1150 *(uint8_t *)p = 16; p += 1; /* blue shift */ 1151 *(uint8_t *)p = 0; p += 1; /* padding x3 */ 1152 *(uint8_t *)p = 0; p += 1; 1153 *(uint8_t *)p = 0; p += 1; 1154 *(uint32_t *)p = htonl(namelen); p += 4; /* name length */ 1155 memcpy(p, rfb->name, namelen); p += namelen; 1156 1157 return safe_send(rfb->clientfd, msgbuf, p - msgbuf); 1158 } 1159 1160 static int 1161 thunk_rfb_handshake(thunk_rfb_t *rfb) 1162 { 1163 ssize_t len; 1164 const char *protover = "RFB 003.003\n"; 1165 uint32_t security_type; 1166 uint8_t shared_flag; 1167 char dummy; 1168 1169 /* send server protocol version */ 1170 len = safe_send(rfb->clientfd, protover, strlen(protover)); 1171 if (len == -1) 1172 return errno; 1173 1174 /* receive client protocol version */ 1175 do { 1176 len = safe_recv(rfb->clientfd, &dummy, sizeof(dummy)); 1177 if (len == -1) 1178 return errno; 1179 } while (dummy != '\n'); 1180 1181 /* send security capabilities */ 1182 security_type = htonl(1); /* no security */ 1183 len = safe_send(rfb->clientfd, &security_type, sizeof(security_type)); 1184 if (len == -1) 1185 return errno; 1186 1187 /* receive client init message */ 1188 len = safe_recv(rfb->clientfd, &shared_flag, sizeof(shared_flag)); 1189 if (len == -1) 1190 return errno; 1191 1192 /* send server init message */ 1193 len = thunk_rfb_server_init(rfb); 1194 if (len == -1) 1195 return errno; 1196 1197 return 0; 1198 } 1199 1200 static void 1201 thunk_rfb_send_pending(thunk_rfb_t *rfb) 1202 { 1203 thunk_rfb_update_t *update; 1204 uint8_t buf[32]; 1205 uint8_t *p; 1206 unsigned int n; 1207 unsigned int bytes_per_pixel; 1208 ssize_t stride, line_len, len; 1209 1210 if (rfb->connected == false || rfb->nupdates == 0) 1211 return; 1212 1213 /* If we have too many updates queued, just send a single update */ 1214 if (rfb->nupdates >= __arraycount(rfb->update)) { 1215 rfb->nupdates = 1; 1216 rfb->update[0].enc = THUNK_RFB_TYPE_RAW; 1217 rfb->update[0].x = 0; 1218 rfb->update[0].y = 0; 1219 rfb->update[0].w = rfb->width; 1220 rfb->update[0].h = rfb->height; 1221 } 1222 1223 #ifdef RFB_DEBUG 1224 fprintf(stdout, "rfb: sending %d updates\n", rfb->nupdates); 1225 #endif 1226 1227 p = buf; 1228 *(uint8_t *)p = 0; p += 1; /* FramebufferUpdate */ 1229 *(uint8_t *)p = 0; p += 1; /* padding */ 1230 *(uint16_t *)p = htons(rfb->nupdates); p += 2; /* # rects */ 1231 1232 len = safe_send(rfb->clientfd, buf, 4); 1233 if (len == -1) 1234 goto disco; 1235 1236 bytes_per_pixel = rfb->depth / 8; 1237 stride = rfb->width * bytes_per_pixel; 1238 for (n = 0; n < rfb->nupdates; n++) { 1239 p = buf; 1240 update = &rfb->update[n]; 1241 *(uint16_t *)p = htons(update->x); p += 2; 1242 *(uint16_t *)p = htons(update->y); p += 2; 1243 *(uint16_t *)p = htons(update->w); p += 2; 1244 *(uint16_t *)p = htons(update->h); p += 2; 1245 *(uint32_t *)p = htonl(update->enc); p += 4; /* encoding */ 1246 1247 #ifdef RFB_DEBUG 1248 fprintf(stdout, "rfb: [%u] enc %d, [%d, %d] - [%d, %d]", 1249 n, update->enc, update->x, update->y, update->w, update->h); 1250 if (update->enc == THUNK_RFB_TYPE_COPYRECT) 1251 fprintf(stdout, " from [%d, %d]", 1252 update->srcx, update->srcy); 1253 if (update->enc == THUNK_RFB_TYPE_RRE) 1254 fprintf(stdout, " pixel [%02x %02x %02x %02x]", 1255 update->pixel[0], update->pixel[1], 1256 update->pixel[2], update->pixel[3]); 1257 fprintf(stdout, "\n"); 1258 #endif 1259 1260 len = safe_send(rfb->clientfd, buf, 12); 1261 if (len == -1) 1262 goto disco; 1263 1264 if (update->enc == THUNK_RFB_TYPE_COPYRECT) { 1265 p = buf; 1266 *(uint16_t *)p = htons(update->srcx); p += 2; 1267 *(uint16_t *)p = htons(update->srcy); p += 2; 1268 len = safe_send(rfb->clientfd, buf, 4); 1269 if (len == -1) 1270 goto disco; 1271 } 1272 1273 if (update->enc == THUNK_RFB_TYPE_RRE) { 1274 p = buf; 1275 1276 /* header */ 1277 *(uint32_t *)p = htonl(1); p += 4; 1278 memcpy(p, update->pixel, 4); p += 4; 1279 /* subrectangle */ 1280 memcpy(p, update->pixel, 4); p += 4; 1281 *(uint16_t *)p = htons(update->x); p += 2; 1282 *(uint16_t *)p = htons(update->y); p += 2; 1283 *(uint16_t *)p = htons(update->w); p += 2; 1284 *(uint16_t *)p = htons(update->h); p += 2; 1285 /* send it */ 1286 len = safe_send(rfb->clientfd, buf, 20); 1287 if (len == -1) 1288 goto disco; 1289 } 1290 1291 if (update->enc == THUNK_RFB_TYPE_RAW) { 1292 p = rfb->framebuf + (update->y * stride) 1293 + (update->x * bytes_per_pixel); 1294 line_len = update->w * bytes_per_pixel; 1295 while (update->h-- > 0) { 1296 len = safe_send(rfb->clientfd, p, line_len); 1297 if (len == -1) 1298 goto disco; 1299 p += stride; 1300 } 1301 } 1302 } 1303 1304 rfb->nupdates = 0; 1305 rfb->first_mergable = 0; 1306 1307 return; 1308 1309 disco: 1310 fprintf(stdout, "rfb: client disconnected: %s\n", strerror(errno)); 1311 close(rfb->clientfd); 1312 rfb->clientfd = -1; 1313 rfb->connected = false; 1314 } 1315 1316 int 1317 thunk_rfb_poll(thunk_rfb_t *rfb, thunk_rfb_event_t *event) 1318 { 1319 int error, len, msg_len; 1320 uint8_t set_pixel_format[19]; 1321 uint8_t set_encodings[3]; 1322 uint8_t framebuffer_update_request[9]; 1323 uint8_t key_event[7]; 1324 uint8_t pointer_event[5]; 1325 uint8_t client_cut_text[7]; 1326 uint8_t ch; 1327 1328 if (rfb->clientfd == -1) { 1329 struct sockaddr_in sin; 1330 struct pollfd fds[1]; 1331 socklen_t sinlen; 1332 int flags; 1333 1334 #ifdef RFB_DEBUG 1335 fprintf(stdout, "rfb: poll connection\n"); 1336 #endif 1337 1338 /* poll for connections */ 1339 fds[0].fd = rfb->sockfd; 1340 fds[0].events = POLLIN; 1341 fds[0].revents = 0; 1342 if (poll(fds, __arraycount(fds), 0) != 1) { 1343 #ifdef RFB_DEBUG 1344 fprintf(stdout, "rfb: NO connection\n"); 1345 #endif 1346 return -1; 1347 } 1348 1349 #ifdef RFB_DEBUG 1350 fprintf(stdout, "rfb: try accept\n"); 1351 #endif 1352 1353 sinlen = sizeof(sin); 1354 rfb->clientfd = accept(rfb->sockfd, (struct sockaddr *)&sin, 1355 &sinlen); 1356 if (rfb->clientfd == -1) 1357 return -1; 1358 1359 fprintf(stdout, "rfb: connection from %s:%d\n", 1360 inet_ntoa(sin.sin_addr), ntohs(sin.sin_port)); 1361 1362 /* rfb handshake */ 1363 if (thunk_rfb_handshake(rfb) != 0) { 1364 fprintf(stdout, "rfb: handshake failed\n"); 1365 close(rfb->clientfd); 1366 rfb->clientfd = -1; 1367 return -1; 1368 } 1369 1370 rfb->connected = true; 1371 1372 /* enable sigio on input */ 1373 flags = fcntl(rfb->clientfd, F_GETFL, 0); 1374 fcntl(rfb->clientfd, F_SETFL, flags | O_ASYNC); 1375 error = fcntl(rfb->clientfd, F_SETOWN, getpid()); 1376 if (error) { 1377 fprintf(stdout, "rfb: setown failed: %s\n", 1378 strerror(errno)); 1379 close(rfb->clientfd); 1380 rfb->clientfd = -1; 1381 return -1; 1382 } 1383 1384 rfb->schedule_bell = false; 1385 rfb->nupdates = 0; 1386 rfb->first_mergable = 0; 1387 thunk_rfb_update(rfb, 0, 0, rfb->width, rfb->height); 1388 } 1389 1390 thunk_rfb_send_pending(rfb); 1391 1392 if (rfb->clientfd == -1) 1393 return -1; 1394 1395 if (event == NULL) 1396 return 0; 1397 1398 if (rfb->schedule_bell) { 1399 uint8_t msg_type = 2; /* bell */ 1400 safe_send(rfb->clientfd, &msg_type, sizeof(msg_type)); 1401 rfb->schedule_bell = false; 1402 } 1403 1404 error = ioctl(rfb->clientfd, FIONREAD, &len); 1405 if (error == -1) 1406 goto discon; 1407 if (len == 0) 1408 return 0; 1409 1410 len = safe_recv(rfb->clientfd, &ch, sizeof(ch)); 1411 if (len == -1) 1412 goto discon; 1413 1414 event->message_type = ch; 1415 switch (ch) { 1416 case THUNK_RFB_SET_PIXEL_FORMAT: 1417 msg_len = sizeof(set_pixel_format); 1418 break; 1419 case THUNK_RFB_SET_ENCODINGS: 1420 len = safe_recv(rfb->clientfd, 1421 set_encodings, sizeof(set_encodings)); 1422 if (len == -1) 1423 goto discon; 1424 msg_len = 4 * ntohs(*(uint16_t *)&set_encodings[1]); 1425 break; 1426 case THUNK_RFB_FRAMEBUFFER_UPDATE_REQUEST: 1427 len = safe_recv(rfb->clientfd, 1428 framebuffer_update_request, 1429 sizeof(framebuffer_update_request)); 1430 if (len == -1) 1431 goto discon; 1432 #ifdef RFB_DEBUG 1433 fprintf(stdout, "framebuffer update request: "); 1434 fprintf(stdout, "[%d, %d] + [%d, %d] %s\n", 1435 framebuffer_update_request[1], 1436 framebuffer_update_request[2], 1437 framebuffer_update_request[3], 1438 framebuffer_update_request[4], 1439 framebuffer_update_request[0]?"Incremental":"Complete"); 1440 #endif 1441 1442 if (framebuffer_update_request[0] == 0) { 1443 /* complete redraw request -> buffer full */ 1444 rfb->nupdates = __arraycount(rfb->update) + 1; 1445 } 1446 // thunk_rfb_send_pending(rfb); 1447 msg_len = 0; 1448 break; 1449 case THUNK_RFB_KEY_EVENT: 1450 len = safe_recv(rfb->clientfd, key_event, sizeof(key_event)); 1451 if (len == -1) 1452 goto discon; 1453 event->data.key_event.down_flag = key_event[0]; 1454 event->data.key_event.keysym = 1455 ntohl(*(uint32_t *)&key_event[3]); 1456 #ifdef RFB_DEBUG 1457 fprintf(stdout, "rfb: key %04x %s\n", 1458 event->data.key_event.keysym, 1459 event->data.key_event.down_flag ? "pressed" : "released"); 1460 #endif 1461 msg_len = 0; 1462 break; 1463 case THUNK_RFB_POINTER_EVENT: 1464 len = safe_recv(rfb->clientfd, 1465 pointer_event, sizeof(pointer_event)); 1466 if (len == -1) 1467 goto discon; 1468 event->data.pointer_event.button_mask = pointer_event[0]; 1469 event->data.pointer_event.absx = 1470 ntohs(*(uint16_t *)&pointer_event[1]); 1471 event->data.pointer_event.absy = 1472 ntohs(*(uint16_t *)&pointer_event[3]); 1473 #ifdef RFB_DEBUG 1474 fprintf(stdout, "rfb: pointer mask %02x abs %dx%d\n", 1475 event->data.pointer_event.button_mask, 1476 event->data.pointer_event.absx, 1477 event->data.pointer_event.absy); 1478 #endif 1479 msg_len = 0; 1480 break; 1481 case THUNK_RFB_CLIENT_CUT_TEXT: 1482 len = safe_recv(rfb->clientfd, 1483 client_cut_text, sizeof(client_cut_text)); 1484 if (len == -1) 1485 goto discon; 1486 msg_len = ntohl(*(uint32_t *)&client_cut_text[3]); 1487 break; 1488 default: 1489 fprintf(stdout, "rfb: unknown message type %d\n", ch); 1490 goto discon; 1491 } 1492 1493 if (len == -1) 1494 goto discon; 1495 1496 /* discard any remaining bytes */ 1497 while (msg_len-- > 0) { 1498 len = safe_recv(rfb->clientfd, &ch, sizeof(ch)); 1499 if (len == -1) 1500 goto discon; 1501 } 1502 1503 return 1; 1504 1505 discon: 1506 //printf("rfb: safe_recv failed: %s\n", strerror(errno)); 1507 close(rfb->clientfd); 1508 rfb->clientfd = -1; 1509 1510 return -1; 1511 } 1512 1513 void 1514 thunk_rfb_update(thunk_rfb_t *rfb, int x, int y, int w, int h) 1515 { 1516 thunk_rfb_update_t *update = NULL; 1517 unsigned int n; 1518 1519 /* if the queue is full, just return */ 1520 if (rfb->nupdates >= __arraycount(rfb->update)) 1521 return; 1522 1523 /* no sense in queueing duplicate updates */ 1524 for (n = rfb->first_mergable; n < rfb->nupdates; n++) { 1525 if (rfb->update[n].x == x && rfb->update[n].y == y && 1526 rfb->update[n].w == w && rfb->update[n].h == h) 1527 return; 1528 } 1529 1530 #ifdef RFB_DEBUG 1531 fprintf(stdout, "rfb: update queue slot %d, x=%d y=%d w=%d h=%d\n", 1532 rfb->nupdates, x, y, w, h); 1533 #endif 1534 1535 /* add the update request to the queue */ 1536 update = &rfb->update[rfb->nupdates++]; 1537 update->enc = THUNK_RFB_TYPE_RAW; 1538 update->x = x; 1539 update->y = y; 1540 update->w = w; 1541 update->h = h; 1542 } 1543 1544 void 1545 thunk_rfb_bell(thunk_rfb_t *rfb) 1546 { 1547 #ifdef RFB_DEBUG 1548 fprintf(stdout, "rfb: schedule bell\n"); 1549 #endif 1550 rfb->schedule_bell = true; 1551 } 1552 1553 void 1554 thunk_rfb_copyrect(thunk_rfb_t *rfb, int x, int y, int w, int h, 1555 int srcx, int srcy) 1556 { 1557 thunk_rfb_update_t *update = NULL; 1558 1559 /* if the queue is full, just return */ 1560 if (rfb->nupdates >= __arraycount(rfb->update)) 1561 return; 1562 1563 #ifdef RFB_DEBUG 1564 fprintf(stdout, "rfb: copyrect queue slot %d, x=%d y=%d w=%d h=%d\n", 1565 rfb->nupdates, x, y, w, h); 1566 #endif 1567 1568 /* add the update request to the queue */ 1569 update = &rfb->update[rfb->nupdates++]; 1570 update->enc = THUNK_RFB_TYPE_COPYRECT; 1571 update->x = x; 1572 update->y = y; 1573 update->w = w; 1574 update->h = h; 1575 update->srcx = srcx; 1576 update->srcy = srcy; 1577 1578 rfb->first_mergable = rfb->nupdates; 1579 } 1580 1581 void 1582 thunk_rfb_fillrect(thunk_rfb_t *rfb, int x, int y, int w, int h, uint8_t *pixel) 1583 { 1584 thunk_rfb_update_t *update = NULL; 1585 1586 /* if the queue is full, just return */ 1587 if (rfb->nupdates >= __arraycount(rfb->update)) 1588 return; 1589 1590 #ifdef RFB_DEBUG 1591 fprintf(stdout, "rfb: fillrect queue slot %d, x=%d y=%d w=%d h=%d\n", 1592 rfb->nupdates, x, y, w, h); 1593 #endif 1594 1595 /* add the update request to the queue */ 1596 update = &rfb->update[rfb->nupdates++]; 1597 update->enc = THUNK_RFB_TYPE_RRE; 1598 update->x = x; 1599 update->y = y; 1600 update->w = w; 1601 update->h = h; 1602 memcpy(update->pixel, pixel, 4); 1603 1604 rfb->first_mergable = rfb->nupdates; 1605 } 1606