From 7861a52adf92a083bb2aed4c35f98d8035dce032 Mon Sep 17 00:00:00 2001 From: Xavier Del Campo Romero Date: Mon, 7 Jul 2025 13:22:53 +0200 Subject: Setup project skeleton --- tools/tun2tcp/CMakeLists.txt | 21 ++++++ tools/tun2tcp/README.md | 13 ++++ tools/tun2tcp/tun2tcp.c | 160 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 194 insertions(+) create mode 100644 tools/tun2tcp/CMakeLists.txt create mode 100644 tools/tun2tcp/README.md create mode 100644 tools/tun2tcp/tun2tcp.c (limited to 'tools/tun2tcp') diff --git a/tools/tun2tcp/CMakeLists.txt b/tools/tun2tcp/CMakeLists.txt new file mode 100644 index 0000000..674aef6 --- /dev/null +++ b/tools/tun2tcp/CMakeLists.txt @@ -0,0 +1,21 @@ +# wnix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . + +cmake_minimum_required(VERSION 3.13) +project(tun2tcp C) +add_executable(${PROJECT_NAME} tun2tcp.c) +target_compile_options(${PROJECT_NAME} PUBLIC ${cflags}) +install(TARGETS ${PROJECT_NAME} DESTINATION bin) diff --git a/tools/tun2tcp/README.md b/tools/tun2tcp/README.md new file mode 100644 index 0000000..9fcc641 --- /dev/null +++ b/tools/tun2tcp/README.md @@ -0,0 +1,13 @@ +# tun2serial + +```sh +# setcap cap_net_admin+ep ./tun2serial +# sudo ip addr add 10.0.0.1/24 dev tun0 +# sudo ip link set tun0 up +# socat TCP-L:6699 /dev/ttyUSB0,rawer,b1200 +``` + +## Thanks + +- https://backreference.org/2010/03/26/tuntap-interface-tutorial/index.html +- https://blog.mbedded.ninja/programming/operating-systems/linux/linux-serial-ports-using-c-cpp/ diff --git a/tools/tun2tcp/tun2tcp.c b/tools/tun2tcp/tun2tcp.c new file mode 100644 index 0000000..4b6615f --- /dev/null +++ b/tools/tun2tcp/tun2tcp.c @@ -0,0 +1,160 @@ + +/* + * wnix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static int getport(const char *const s, unsigned short *const port) +{ + char *end; + unsigned long v; + + errno = 0; + v = strtoull(s, &end, 10); + + if (errno || *end || v > USHRT_MAX) + return -1; + + *port = v; + return 0; +} + +int main(int argc, char *argv[]) +{ + static const char path[] = "/dev/net/tun"; + char *s = NULL; + int ret = EXIT_FAILURE, cfd = -1, tfd = -1; + unsigned short port; + + if (argc != 2) + { + fprintf(stderr, "%s \n", *argv); + goto end; + } + else if (getport(argv[1], &port)) + { + fprintf(stderr, "invalid port: %s\n", argv[1]); + goto end; + } + else if ((cfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) + { + perror("socket(2)"); + goto end; + } + + const struct sockaddr_in addr = + { + .sin_family = AF_INET, + .sin_addr.s_addr = inet_addr("127.0.0.1"), + .sin_port = htons(port) + }; + + const struct ifreq ifr = {.ifr_flags = IFF_TUN | IFF_NO_PI}; + + if (connect(cfd, (const struct sockaddr *)&addr, sizeof addr)) + { + perror("connect(2)"); + goto end; + } + else if ((tfd = open(path, O_RDWR)) < 0) + { + fprintf(stderr, "open(2) %s: %s\n", path, strerror(errno)); + goto end; + } + else if (ioctl(tfd, TUNSETIFF, &ifr) < 0) + { + perror("ioctl(2)"); + goto end; + } + else if (!(s = strdup(ifr.ifr_name))) + { + perror("strdup(3)"); + goto end; + } + + fprintf(stderr, "set up TUN device %s\n", s); + unsigned long long total = 0; + + for (;;) + { + char b[1500]; + ssize_t n = read(tfd, &b, sizeof b); + + if (n < 0) + { + perror("read(2)"); + goto end; + } + + fprintf(stderr, "read %zu bytes\n", n); + + size_t rem = n; + + while (rem) + { + const void *p = b; + + fprintf(stderr, "sending %zu bytes\n", rem); + + if ((n = write(cfd, p, rem)) < 0) + { + perror("write(2)"); + goto end; + } + + fprintf(stderr, "sent %zu bytes, total: %llu\n", n, total += n); + + p = (const char *)p + n; + rem -= n; + } + } + + ret = EXIT_SUCCESS; + +end: + + if (cfd >= 0 && close(cfd)) + { + ret = EXIT_FAILURE; + perror("close(2)"); + } + + if (tfd >= 0 && close(tfd)) + { + ret = EXIT_FAILURE; + fprintf(stderr, "close(2) %s: %s\n", path, strerror(errno)); + } + + free(s); + return ret; +} -- cgit v1.2.3