complete initial implementation

Never tested. Let's see how many bugs we find.
master
BodgeMaster 2025-02-05 23:06:16 +01:00
parent da6461ad47
commit 77542aa220
1 changed files with 94 additions and 15 deletions

View File

@ -2,12 +2,14 @@
#include <fcntl.h> #include <fcntl.h>
#include <linux/if.h> #include <linux/if.h>
#include <linux/if_tun.h> #include <linux/if_tun.h>
#include <signal.h>
#include <stdbool.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <unistd.h> #include <unistd.h>
#define DEVICE_NODE_TUN /dev/net/tun #define DEVICE_NODE_TUN "/dev/net/tun"
#define BUFFER_SIZE 0x1000 #define BUFFER_SIZE 0x1000
#define EXIT_SUCCESS 0 #define EXIT_SUCCESS 0
@ -17,6 +19,27 @@
int file_descriptor; int file_descriptor;
char buffer[BUFFER_SIZE]; char buffer[BUFFER_SIZE];
struct ifreq ifr; struct ifreq ifr;
bool stop_now = false;
ssize_t read_size;
ssize_t write_size;
bool just_created_dup;
int stdin_dup;
void stop() {
stop_now = true;
}
void yeet(int fd) {
if (fcntl(fd, F_GETFD) != -1) {
close(fd);
}
}
void recreate_dup() {
just_created_dup = true;
yeet(stdin_dup);
stdin_dup = dup(fileno(stdin));
}
int main(int argc, char** argv) { int main(int argc, char** argv) {
if (argc != 2) { if (argc != 2) {
@ -27,32 +50,88 @@ int main(int argc, char** argv) {
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }
if (freopen(NULL, "rb", stdin) == NULL) {
fprintf(stderr, "Failed to set stdin to binary mode: %i\n", errno);
return EXIT_RUNTIME;
}
stdin_dup = dup(fileno(stdin));
if (stdin_dup == -1) {
fprintf(stderr, "Failed to dup() stdin: %i\n", errno);
}
if (freopen(NULL, "wb", stdout) == NULL) {
fprintf(stderr, "Failed to set stdout to binary mode: %i\n", errno);
return EXIT_RUNTIME;
}
file_descriptor = open(DEVICE_NODE_TUN, O_RDWR | O_NONBLOCK);
if (file_descriptor == -1) {
fprintf(stderr, "Failed to open %s: %i\n", DEVICE_NODE_TUN, errno);
return EXIT_RUNTIME;
}
memset(&ifr, 0, sizeof(ifr)); memset(&ifr, 0, sizeof(ifr));
ifr.ifr_flags = IFF_TAP | IFF_NO_PI; ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
strncpy(ifr.ifr_name, argv[1], IFNAMSIZ); strncpy(ifr.ifr_name, argv[1], IFNAMSIZ);
file_descriptor = open("/dev/net/tun", O_RDWR);
if (file_descriptor == -1) {
fprintf(stderr, "An error occurred while trying to open DEVICE_NODE_TUN: %i\n", errno);
return EXIT_RUNTIME;
}
if (ioctl(file_descriptor, TUNSETIFF, &ifr) == -1) { if (ioctl(file_descriptor, TUNSETIFF, &ifr) == -1) {
fprintf(stderr, "An error occurred while trying to ioctl: %i\n", errno); fprintf(stderr, "An error occurred while trying to ioctl: %i\n", errno);
close(file_descriptor); close(file_descriptor);
return EXIT_RUNTIME; return EXIT_RUNTIME;
} }
//TODO: signal(SIGINT, stop);
// while input not EOF signal(SIGTERM, stop);
// and the tap is still a valid device (it might go away) signal(SIGALRM, recreate_dup);
// read from tap to stdout
// read from stdin to tap
//TODO: signal handler for SIGINT (and SIGHUP? maybe others?) ualarm(500000, 500000);
if (fcntl(fd, F_GETFD) != -1 || errno != EBADF) { while (fcntl(file_descriptor, F_GETFD) != -1 && !stop_now) {
close(file_descriptor); read_size = read(file_descriptor, buffer, BUFFER_SIZE);
if (read_size == -1) {
fprintf(stderr, "Failed to read from tap: %i\n", errno);
yeet(file_descriptor);
return EXIT_RUNTIME;
}
for (
write_size = 0;
read_size > 0 && !stop_now;
read_size = read_size - write_size
) {
// using read_size as the amount of remaining bytes
write_size = write(fileno(stdout), buffer, read_size);
if (write_size == -1) {
fprintf(stderr, "Failed to write stdout: %i\n", errno);
yeet(file_descriptor);
return EXIT_RUNTIME;
}
}
just_created_dup = false;
read_size = read(stdin_dup, buffer, BUFFER_SIZE);
if (read_size == -1) {
fprintf(stderr, "Failed to read from stdin: %i\n", errno);
yeet(file_descriptor);
return EXIT_RUNTIME;
}
if (read_size == 0 && !just_created_dup) {
// probably EOF
break;
}
for (
write_size = 0;
read_size > 0 && !stop_now;
read_size = read_size - write_size
) {
write_size = write(file_descriptor, buffer, read_size);
if (write_size == -1) {
fprintf(stderr, "Failed to write stdout: %i\n", errno);
yeet(file_descriptor);
return EXIT_RUNTIME;
}
}
} }
yeet(file_descriptor);
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }