#include #include #include #include #include #include #include #include #include #include #define TUN_NAME "tun0" #define ESP32_MTU 1500 #define ESP32_FNAMSIZ 64 #define ESP32_DEVFN "/dev/esp32.?" #define ESP32_MTYPE_TUN 1 #define ESP32_MAX_MTYPE 8 static pthread_t tun_handler_thd, esp32_handler_thd; static int tun_fd, esp32_fd; static char tun_name[IFNAMSIZ]; /* Arguments taken by the function: * * char *dev: the name of an interface (or '\0'). MUST have enough * space to hold the interface name if '\0' is passed * int flags: interface flags (eg, IFF_TUN etc.) */ int tun_alloc(char *dev, int flags) { struct ifreq ifr; int fd, rv; char *clonedev = "/dev/net/tun"; fd = open(clonedev, O_RDWR); if (fd < 0) return fd; memset(&ifr, 0, sizeof(ifr)); ifr.ifr_flags = flags; /* IFF_TUN or IFF_TAP, plus maybe IFF_NO_PI */ if (*dev) { /* if a device name was specified, put it in the structure; otherwise, * the kernel will try to allocate the "next" device of the * specified type */ strncpy(ifr.ifr_name, dev, IFNAMSIZ); } /* try to create the device */ rv = ioctl(fd, TUNSETIFF, (void *) &ifr); if (rv < 0) { close(fd); return rv; } /* if the operation was successful, write back the name of the * interface to the variable "dev", so the caller can know * it. Note that the caller MUST reserve space in *dev (see calling * code below) */ strcpy(dev, ifr.ifr_name); /* this is the special file descriptor that the caller will use to talk * with the virtual interface */ return fd; } ssize_t tun_read(unsigned char *buffer, size_t buf_size) { return read(tun_fd, buffer, buf_size); } ssize_t tun_write(unsigned char *buffer, size_t buf_len) { return write(tun_fd, buffer, buf_len); } int tun_init(char *name) { if (strlen(name) + 1 > sizeof(tun_name)) return -1; strcpy(tun_name, name); tun_fd = tun_alloc(tun_name, IFF_TUN | IFF_NO_PI); if (tun_fd < 0) return tun_fd; return 0; } ssize_t esp32_read(unsigned char *buffer, size_t buf_size) { return read(esp32_fd, buffer, buf_size); } ssize_t esp32_write(unsigned char *buffer, size_t buf_len) { return write(esp32_fd, buffer, buf_len); } int esp32_fname(char *fname, int mtype) { if (mtype >= ESP32_MAX_MTYPE) return -1; strcpy(fname, ESP32_DEVFN); fname[strlen(fname) - 1] = '0' + mtype; return 0; } int esp32_init(void) { char fname[ESP32_FNAMSIZ]; int rv; rv = esp32_fname(fname, ESP32_MTYPE_TUN); if (rv) return rv; esp32_fd = open(fname, O_RDWR); if (esp32_fd < 0) return esp32_fd; return 0; } void *tun_handler(void *arg) { unsigned char buffer[ESP32_MTU]; ssize_t len, rv; while (1) { len = tun_read(buffer, ESP32_MTU); if (len < 0) { perror("tun read"); continue; } rv = esp32_write(buffer, len); if (rv < 0) { perror("esp32 write"); continue; } } return NULL; } void *esp32_handler(void *arg) { unsigned char buffer[ESP32_MTU]; ssize_t len, rv; while (1) { len = esp32_read(buffer, ESP32_MTU); if (len < 0) { perror("esp32 read"); continue; } rv = tun_write(buffer, len); if (rv < 0) { perror("tun write"); continue; } } return NULL; } int main(int argc, char *argv[]) { int rv; rv = tun_init(TUN_NAME); assert(rv == 0); rv = esp32_init(); assert(rv == 0); rv = pthread_create(&tun_handler_thd, NULL, tun_handler, NULL); assert(rv == 0); rv = pthread_create(&esp32_handler_thd, NULL, esp32_handler, NULL); assert(rv == 0); while(1); }