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@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
95static ssize_t safe_recv(int s, void *buf, int len);
96static ssize_t safe_send(int s, const void *msg, int len);
97
98extern int boothowto;
99
100void
101thunk_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
112void
113thunk_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
123int
124thunk_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
138static void
139thunk_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
145static void
146thunk_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
152static void
153thunk_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
159static void
160thunk_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
166static void
167thunk_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
181static void
182thunk_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
196static int
197thunk_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
211static int
212thunk_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
230static int
231thunk_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
251int
252thunk_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
268int
269thunk_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
283unsigned int
284thunk_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
298long
299thunk_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
311timer_t
312thunk_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
326int
327thunk_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
338int
339thunk_timer_getoverrun(timer_t timerid)
340{
341	return timer_getoverrun(timerid);
342}
343
344int
345thunk_usleep(useconds_t microseconds)
346{
347	return usleep(microseconds);
348}
349
350void
351thunk_kill(pid_t pid, int sig)
352{
353	kill(pid, sig);
354}
355
356void
357thunk_exit(int status)
358{
359	return exit(status);
360}
361
362void
363thunk_abort(void)
364{
365	abort();
366}
367
368int
369thunk_geterrno(void)
370{
371	return errno;
372}
373
374void
375thunk_seterrno(int nerrno)
376{
377	errno = nerrno;
378}
379
380int
381thunk_getcontext(ucontext_t *ucp)
382{
383	return getcontext(ucp);
384}
385
386int
387thunk_setcontext(const ucontext_t *ucp)
388{
389	return setcontext(ucp);
390}
391
392void
393thunk_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
418int
419thunk_swapcontext(ucontext_t *oucp, ucontext_t *ucp)
420{
421	return swapcontext(oucp, ucp);
422}
423
424int
425thunk_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
437int
438thunk_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
446int
447thunk_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
461int
462thunk_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
482int
483thunk_getchar(void)
484{
485	return getchar();
486}
487
488void
489thunk_putchar(int c)
490{
491	char wc = (char) c;
492	write(1, &wc, 1);
493}
494
495int
496thunk_execv(const char *path, char * const argv[])
497{
498	return execv(path, argv);
499}
500
501int
502thunk_open(const char *path, int flags, mode_t mode)
503{
504	return open(path, flags, mode);
505}
506
507int
508thunk_close(int fd)
509{
510	return close(fd);
511}
512
513int
514thunk_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
531ssize_t
532thunk_pread(int d, void *buf, size_t nbytes, off_t offset)
533{
534	return pread(d, buf, nbytes, offset);
535}
536
537ssize_t
538thunk_pwrite(int d, const void *buf, size_t nbytes, off_t offset)
539{
540	return pwrite(d, buf, nbytes, offset);
541}
542
543ssize_t
544thunk_read(int d, void *buf, size_t nbytes)
545{
546	return read(d, buf, nbytes);
547}
548
549ssize_t
550thunk_write(int d, const void *buf, size_t nbytes)
551{
552	return write(d, buf, nbytes);
553}
554
555int
556thunk_fsync(int fd)
557{
558	return fsync(fd);
559}
560
561int
562thunk_mkstemp(char *template)
563{
564	return mkstemp(template);
565}
566
567int
568thunk_unlink(const char *path)
569{
570	return unlink(path);
571}
572
573pid_t
574thunk_getpid(void)
575{
576	return getpid();
577}
578
579int
580thunk_sigaction(int sig, const struct sigaction *act, struct sigaction *oact)
581{
582	return sigaction(sig, act, oact);
583}
584
585int
586thunk_sigaltstack(const stack_t *ss, stack_t *oss)
587{
588	return sigaltstack(ss, oss);
589}
590
591void
592thunk_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
602int
603thunk_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
612int
613thunk_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
622int
623thunk_sigemptyset(sigset_t *sa_mask)
624{
625	return sigemptyset(sa_mask);
626}
627
628
629int
630thunk_sigfillset(sigset_t *sa_mask)
631{
632	return sigfillset(sa_mask);
633}
634
635
636void
637thunk_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
647int
648thunk_sigprocmask(int how, const sigset_t * set, sigset_t *oset)
649{
650	return sigprocmask(how, set, oset);
651}
652
653int
654thunk_atexit(void (*function)(void))
655{
656	return atexit(function);
657}
658
659pid_t
660thunk_fork(void)
661{
662	return fork();
663}
664
665int
666thunk_ioctl(int fd, unsigned long request, void *opaque)
667{
668	return ioctl(fd, request, opaque);
669}
670
671int
672thunk_aio_read(struct aiocb *aiocbp)
673{
674	return aio_read(aiocbp);
675}
676
677int
678thunk_aio_write(struct aiocb *aiocbp)
679{
680	return aio_write(aiocbp);
681}
682
683int
684thunk_aio_error(const struct aiocb *aiocbp)
685{
686	return aio_error(aiocbp);
687}
688
689int
690thunk_aio_return(struct aiocb *aiocbp)
691{
692	return aio_return(aiocbp);
693}
694
695void *
696thunk_malloc(size_t len)
697{
698	return malloc(len);
699}
700
701void
702thunk_free(void *addr)
703{
704	free(addr);
705}
706
707void *
708thunk_sbrk(intptr_t len)
709{
710	return sbrk(len);
711}
712
713void *
714thunk_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
728int
729thunk_munmap(void *addr, size_t len)
730{
731	return munmap(addr, len);
732}
733
734int
735thunk_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
744int
745thunk_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
754int
755thunk_posix_memalign(void **ptr, size_t alignment, size_t size)
756{
757	return posix_memalign(ptr, alignment, size);
758}
759
760char *
761thunk_getenv(const char *name)
762{
763	return getenv(name);
764}
765
766vaddr_t
767thunk_get_vm_min_address(void)
768{
769	return VM_MIN_ADDRESS;
770}
771
772int
773thunk_idle(void)
774{
775	sigset_t sigmask;
776
777	sigemptyset(&sigmask);
778
779	return sigsuspend(&sigmask);
780}
781
782int
783thunk_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;
800out:
801	*len = 0;
802	return -1;
803}
804
805int
806thunk_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
828int
829thunk_setown(int fd)
830{
831	return fcntl(fd, F_SETOWN, getpid());
832}
833
834int
835thunk_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
853int
854thunk_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
875int
876thunk_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 */
889int
890thunk_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
902int
903thunk_audio_open(const char *path)
904{
905	return open(path, O_RDWR);
906}
907
908int
909thunk_audio_close(int fd)
910{
911	return close(fd);
912}
913
914int
915thunk_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
939int
940thunk_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
953int
954thunk_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
967ssize_t
968thunk_audio_write(int fd, const void *buf, size_t buflen)
969{
970	return write(fd, buf, buflen);
971}
972
973ssize_t
974thunk_audio_read(int fd, void *buf, size_t buflen)
975{
976	return read(fd, buf, buflen);
977}
978
979int
980thunk_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
1017int
1018thunk_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
1054int
1055thunk_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
1077int
1078thunk_kgdb_getc(int fd, char *ch)
1079{
1080	return safe_recv(fd, ch, 1);
1081}
1082
1083int
1084thunk_kgdb_putc(int fd, char ch)
1085{
1086	return safe_send(fd, &ch, 1);
1087}
1088
1089static ssize_t
1090safe_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
1111static ssize_t
1112safe_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
1132static ssize_t
1133thunk_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
1160static int
1161thunk_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
1200static void
1201thunk_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
1309disco:
1310	fprintf(stdout, "rfb: client disconnected: %s\n", strerror(errno));
1311	close(rfb->clientfd);
1312	rfb->clientfd = -1;
1313	rfb->connected = false;
1314}
1315
1316int
1317thunk_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
1505discon:
1506	//printf("rfb: safe_recv failed: %s\n", strerror(errno));
1507	close(rfb->clientfd);
1508	rfb->clientfd = -1;
1509
1510	return -1;
1511}
1512
1513void
1514thunk_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
1544void
1545thunk_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
1553void
1554thunk_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
1581void
1582thunk_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