#if 0 /* -*- mode: c; c-file-style: "stroustrup"; tab-width: 8; -*- # Hack to hook FS-UAE to TAP device. Execute sh tap4-fs-uae.c for more info. set -euf case ${1-} in t) test=true; trg=${0##*?/}; trg=${trg%.c} ;; m) test=false; trg=qemu-uae.so ;; *) printf '\nUsage: sh %s m | t -- module or test\n\n' "$0" exec sed '1,/\/[*]i/d; /[*]\//{g;q;}' "$0"; exit not reached esac WARN="-Wall -Wstrict-prototypes -Winit-self -Wformat=2" # -pedantic WARN="$WARN -Wcast-align -Wpointer-arith " # -Wfloat-equal #-Werror WARN="$WARN -Wextra -Wwrite-strings -Wcast-qual -Wshadow" # -Wconversion WARN="$WARN -Wmissing-include-dirs -Wundef -Wbad-function-cast -Wlogical-op" WARN="$WARN -Waggregate-return -Wold-style-definition" WARN="$WARN -Wmissing-prototypes -Wmissing-declarations -Wredundant-decls" WARN="$WARN -Wnested-externs -Winline -Wvla -Woverlength-strings -Wpadded" x_exec () { printf %s\\n "$*" >&2; exec "$@"; } if $test then x_exec gcc -std=c99 -o $trg "$0" $WARN -DTEST=1 -pthread else x_exec gcc -std=c99 -shared -fPIC -o $trg "$0" $WARN -ldl -pthread fi exit not reached */ #endif /* * $ sh tap4-fs-uae.c $ * * Author: Tomi Ollila -- too ät iki piste fi * * Copyright (c) 2017 Tomi Ollila * All rights reserved * * Created: Sun 28 May 2017 16:39:18 +0300 too * Last modified: Sun 28 May 2017 23:48:32 +0300 too */ // License: 2-Clause (Simplified) BSD. // References GPLv2+ code via dynamic loading/binding -- commented below. /*i The above command line (using the 'm' option, 't' does not even work now) will compile qemu-uae.so to current directory. It is to be copied to $HOME/Documents/FS-UAE/Plugins/ for FS-UAE to use it -- remember to backup previous $HOME/Documents/FS-UAE/Plugins/qemu-uae.so away, if any. This module requires tap4 "device" to exist. Create it with: $ sudo ip tuntap add dev tap4 mode tap user $USER $ sudo ip link set tap4 up Now you can add ip to this tap4 device and communicate with it from UAE. Or you can add tap4 to some bridge using `brctl` command. Iptables may interfere; One (bad?) option is to clear all rules... Note that this replaces proper qemu-uae.so (and exits uae if tap4 is unusable) -- nothing else than packet IO between UAE and TAP device are implemented. */ #if 0 } // for emacs indentation #endif #include #include #include #include #include #include #include // needed for linux/if.h -- FIXME "correct" include #include #include #include #include #if ! defined(TEST) #define TEST 0 #endif // gplv2+ code via dynamic loading/binding... void (*uae_slirp_output)(const uint8_t * pkt, int pkt_len) = NULL; // ditto void (*uae_log)(const char * format, ...) = NULL; // printf attribute todo ? void qemu_uae_version(int * major, int * minor, int * revision); void qemu_uae_version(int * major, int * minor, int * revision) { // qemu-uae-main.c 2017-05-28 (Sun) <- gplv2... *major = 3; *minor = 8; *revision = 2; } void qemu_uae_init(void); void qemu_uae_init(void) { } int tap_fd; unsigned char input_buf[65536]; static void * tap_read_thread(void * arg); // open tap device instead... void qemu_uae_slirp_init(void); void qemu_uae_slirp_init(void) { uae_log("TAP: Initializing\n"); #if 1 if ((tap_fd = open("/dev/net/tun", O_RDWR)) < 0) { perror("Opening /dev/net/tun"); exit(1); } struct ifreq ifr = { .ifr_flags = IFF_TAP | IFF_NO_PI }; strncpy(ifr.ifr_name, "tap4", IFNAMSIZ); if (ioctl(tap_fd, TUNSETIFF, (void *)&ifr) < 0) { perror("ioctl(TUNSETIFF)"); close(tap_fd); exit(2); } //strcpy(dev, ifr.ifr_name); #else tap_fd = 0; #endif pthread_attr_t attr; pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); pthread_t t; if (pthread_create(&t, &attr, tap_read_thread, NULL) != 0) { perror("pthread create"); exit(3); } pthread_attr_destroy(&attr); } void qemu_uae_slirp_input(const uint8_t *pkt, int pkt_len); void qemu_uae_slirp_input(const uint8_t *pkt, int pkt_len) { uae_log("TAP: data from uae: pkt_len %d\n", pkt_len); // opportunistic write (void)write(tap_fd, pkt, pkt_len); } static void * tap_read_thread(void * arg) { uae_log("TAP: read thread started\n"); for(;;) { int len = read(tap_fd, input_buf, sizeof input_buf); uae_log("TAP (thread): read %d bytes\n", len); if (len <= 0) { sleep(2); continue; } uae_slirp_output(input_buf, len); } return arg; } #if TEST int main(void) { test_code_not_done return 0; } #endif // TEST