And now rewrite half of it bc the previous approach didn't actually work...
parent
da8543510a
commit
d5547c3035
102
ethercat.c
102
ethercat.c
|
@ -2,6 +2,7 @@
|
||||||
#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 <poll.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
@ -10,20 +11,25 @@
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#define DEVICE_NODE_TUN "/dev/net/tun"
|
#define DEVICE_NODE_TUN "/dev/net/tun"
|
||||||
|
// This number mus be larger than the MTU.
|
||||||
#define BUFFER_SIZE 0x1000
|
#define BUFFER_SIZE 0x1000
|
||||||
|
#define NUMBER_OF_POLLED_FILES 2
|
||||||
|
#define POLL_TIMEOUT 100
|
||||||
|
|
||||||
#define EXIT_SUCCESS 0
|
#define EXIT_SUCCESS 0
|
||||||
#define EXIT_USAGE 1
|
#define EXIT_USAGE 1
|
||||||
#define EXIT_RUNTIME 2
|
#define EXIT_RUNTIME 2
|
||||||
|
|
||||||
int file_descriptor;
|
int file_descriptor;
|
||||||
|
int poll_result;
|
||||||
char buffer[BUFFER_SIZE];
|
char buffer[BUFFER_SIZE];
|
||||||
struct ifreq ifr;
|
struct ifreq ifr;
|
||||||
bool stop_now = false;
|
bool stop_now = false;
|
||||||
ssize_t read_size;
|
ssize_t read_size;
|
||||||
ssize_t write_size;
|
ssize_t write_size;
|
||||||
bool just_created_dup;
|
// 0 file_descriptor
|
||||||
int stdin_dup;
|
// 1 stdin
|
||||||
|
struct pollfd polls_pls[NUMBER_OF_POLLED_FILES];
|
||||||
|
|
||||||
void stop() {
|
void stop() {
|
||||||
stop_now = true;
|
stop_now = true;
|
||||||
|
@ -35,12 +41,6 @@ void yeet(int 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) {
|
||||||
fprintf(stderr, "Usage: %s TAP\n", argv[0]);
|
fprintf(stderr, "Usage: %s TAP\n", argv[0]);
|
||||||
|
@ -55,18 +55,15 @@ int main(int argc, char** argv) {
|
||||||
return EXIT_RUNTIME;
|
return EXIT_RUNTIME;
|
||||||
}
|
}
|
||||||
|
|
||||||
stdin_dup = dup(fileno(stdin));
|
polls_pls[1].fd = fileno(stdin);
|
||||||
if (stdin_dup == -1) {
|
polls_pls[1].events = POLLIN;
|
||||||
fprintf(stderr, "Failed to dup() stdin: %s\n", strerror(errno));
|
|
||||||
return EXIT_RUNTIME;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (freopen(NULL, "wb", stdout) == NULL) {
|
if (freopen(NULL, "wb", stdout) == NULL) {
|
||||||
fprintf(stderr, "Failed to set stdout to binary mode: %s\n", strerror(errno));
|
fprintf(stderr, "Failed to set stdout to binary mode: %s\n", strerror(errno));
|
||||||
return EXIT_RUNTIME;
|
return EXIT_RUNTIME;
|
||||||
}
|
}
|
||||||
|
|
||||||
file_descriptor = open(DEVICE_NODE_TUN, O_RDWR | O_NONBLOCK);
|
file_descriptor = open(DEVICE_NODE_TUN, O_RDWR);
|
||||||
if (file_descriptor == -1) {
|
if (file_descriptor == -1) {
|
||||||
fprintf(stderr, "Failed to open %s: %s\n", DEVICE_NODE_TUN, strerror(errno));
|
fprintf(stderr, "Failed to open %s: %s\n", DEVICE_NODE_TUN, strerror(errno));
|
||||||
return EXIT_RUNTIME;
|
return EXIT_RUNTIME;
|
||||||
|
@ -82,51 +79,64 @@ int main(int argc, char** argv) {
|
||||||
return EXIT_RUNTIME;
|
return EXIT_RUNTIME;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
polls_pls[0].fd = file_descriptor;
|
||||||
|
polls_pls[0].events = POLLIN;
|
||||||
|
|
||||||
signal(SIGINT, stop);
|
signal(SIGINT, stop);
|
||||||
signal(SIGTERM, stop);
|
signal(SIGTERM, stop);
|
||||||
signal(SIGALRM, recreate_dup);
|
|
||||||
|
|
||||||
ualarm(500000, 500000);
|
|
||||||
|
|
||||||
while (fcntl(file_descriptor, F_GETFD) != -1 && !stop_now) {
|
while (fcntl(file_descriptor, F_GETFD) != -1 && !stop_now) {
|
||||||
read_size = read(file_descriptor, buffer, BUFFER_SIZE);
|
poll_result = poll(polls_pls, NUMBER_OF_POLLED_FILES, POLL_TIMEOUT);
|
||||||
if (read_size == -1) {
|
if (poll_result == -1 && errno != EINTR) {
|
||||||
fprintf(stderr, "Failed to read from tap: %s\n", strerror(errno));
|
fprintf(stderr, "An error occurred while polling: %s\n", strerror(errno));
|
||||||
yeet(file_descriptor);
|
yeet(file_descriptor);
|
||||||
return EXIT_RUNTIME;
|
return EXIT_RUNTIME;
|
||||||
}
|
}
|
||||||
for (
|
if (poll_result == 0) {
|
||||||
write_size = 0;
|
continue;
|
||||||
read_size > 0 && !stop_now;
|
}
|
||||||
read_size = read_size - write_size
|
|
||||||
) {
|
if (polls_pls[0].revents & POLLIN) {
|
||||||
// using read_size as the amount of remaining bytes
|
read_size = read(file_descriptor, buffer, BUFFER_SIZE);
|
||||||
write_size = write(fileno(stdout), buffer, read_size);
|
if (read_size == -1) {
|
||||||
if (write_size == -1) {
|
fprintf(stderr, "Failed to read from tap: %s\n", strerror(errno));
|
||||||
fprintf(stderr, "Failed to write stdout: %s\n", strerror(errno));
|
|
||||||
yeet(file_descriptor);
|
yeet(file_descriptor);
|
||||||
return EXIT_RUNTIME;
|
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: %s\n", strerror(errno));
|
||||||
|
yeet(file_descriptor);
|
||||||
|
return EXIT_RUNTIME;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
just_created_dup = false;
|
|
||||||
read_size = read(stdin_dup, buffer, BUFFER_SIZE);
|
if (polls_pls[1].revents & POLLIN) {
|
||||||
if (read_size == -1) {
|
read_size = read(fileno(stdin), buffer, BUFFER_SIZE);
|
||||||
fprintf(stderr, "Failed to read from stdin: %s\n", strerror(errno));
|
if (read_size == -1) {
|
||||||
yeet(file_descriptor);
|
fprintf(stderr, "Failed to read from stdin: %s\n", strerror(errno));
|
||||||
return EXIT_RUNTIME;
|
yeet(file_descriptor);
|
||||||
}
|
return EXIT_RUNTIME;
|
||||||
if (read_size == 0 && !just_created_dup) {
|
}
|
||||||
// probably EOF
|
if (read_size == 0) {
|
||||||
break;
|
//TODO: is this still how to check for eof with poll?
|
||||||
}
|
// or is there another way?
|
||||||
for (
|
break;
|
||||||
write_size = 0;
|
}
|
||||||
read_size > 0 && !stop_now;
|
|
||||||
read_size = read_size - write_size
|
//TODO: How to properly deal with partial reads?
|
||||||
) {
|
|
||||||
|
// accepts exactly one complete packet (Ethernet Frame?) at a time
|
||||||
write_size = write(file_descriptor, buffer, read_size);
|
write_size = write(file_descriptor, buffer, read_size);
|
||||||
if (write_size == -1) {
|
if (write_size == -1) {
|
||||||
fprintf(stderr, "Failed to write stdout: %s\n", strerror(errno));
|
fprintf(stderr, "Failed to write tap: %s\n", strerror(errno));
|
||||||
yeet(file_descriptor);
|
yeet(file_descriptor);
|
||||||
return EXIT_RUNTIME;
|
return EXIT_RUNTIME;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue