summaryrefslogtreecommitdiff
path: root/yocto/esp32tun/esp32tun.c
diff options
context:
space:
mode:
Diffstat (limited to 'yocto/esp32tun/esp32tun.c')
-rwxr-xr-xyocto/esp32tun/esp32tun.c173
1 files changed, 173 insertions, 0 deletions
diff --git a/yocto/esp32tun/esp32tun.c b/yocto/esp32tun/esp32tun.c
new file mode 100755
index 0000000..8f9e3bd
--- /dev/null
+++ b/yocto/esp32tun/esp32tun.c
@@ -0,0 +1,173 @@
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <assert.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+
+#include <linux/if.h>
+#include <linux/if_tun.h>
+
+#include <pthread.h>
+
+#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);
+}