#include "common.h" #include #include #include #include #include #include #include #include #include #include #include #define GT_BUFFER_SIZE (256*1024) volatile sig_atomic_t running; static int gt_open_sock (char *host, char *port, int listener) { struct addrinfo hints = { .ai_family = AF_UNSPEC, .ai_socktype = SOCK_STREAM, .ai_protocol = IPPROTO_TCP, .ai_flags = AI_PASSIVE, }; struct addrinfo *ai, *res = NULL; if (getaddrinfo(host, port, &hints, &res)) { printf("host not found\n"); return -1; } int fd = -1; for (ai=res; ai; ai=ai->ai_next) { fd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); if (fd==-1) continue; int ret; if (listener) { ret = bind(fd, ai->ai_addr, ai->ai_addrlen); if (!ret) ret = listen(fd, 1); } else { ret = connect(fd, ai->ai_addr, ai->ai_addrlen); } if (!ret) break; if (errno) printf("socket: %m\n"); close(fd); fd = -1; } freeaddrinfo(res); return fd; } static int gt_open_tun (char *name) { int fd = open("/dev/net/tun", O_RDWR); if (fd<0) { printf("open /dev/net/tun: %m\n"); return -1; } struct ifreq ifr = { .ifr_flags = IFF_TUN|IFF_NO_PI, }; str_cpy(ifr.ifr_name, name, IFNAMSIZ-1); int ret = ioctl(fd, TUNSETIFF, &ifr); if (ret<0) { printf("ioctl TUNSETIFF: %m\n"); return -1; } printf("tun name: %s\n", ifr.ifr_name); return fd; } static void gt_sa_stop (int sig) { switch (sig) { case SIGINT: case SIGTERM: running = 0; } } static int gt_set_signal (void) { struct sigaction sa = {0}; running = 1; sa.sa_handler = gt_sa_stop; sigaction(SIGINT, &sa, NULL); sigaction(SIGTERM, &sa, NULL); sa.sa_handler = SIG_IGN; sigaction(SIGHUP, &sa, NULL); sigaction(SIGPIPE, &sa, NULL); } static inline int read_to_buffer (int fd, buffer_t *buffer) { buffer_shift(buffer); size_t size = buffer_write_size(buffer); if (!size) return -1; ssize_t ret = read(fd, buffer->write, size); if (ret==-1) { if (errno==EAGAIN || errno==EINTR) return -1; if (errno) printf("read: %m\n"); return 0; } buffer->write += ret; return 1; } static inline int write_from_buffer (int fd, buffer_t *buffer) { size_t size = buffer_read_size(buffer); if (!size) return -1; ssize_t ret = write(fd, buffer->read, size); if (ret==-1) { if (errno==EAGAIN || errno==EINTR) return -1; if (errno) printf("read: %m\n"); return 0; } buffer->read += ret; buffer_shift(buffer); return 1; } enum option_type { option_flag, option_string, }; struct option { char *name; void *data; enum option_type type; }; static void option (int argc, char **argv, int n, struct option *opt) { for (int i=0; i