From 3b00c7be0e8834402ed93eb42b3a93302076c5ff Mon Sep 17 00:00:00 2001 From: Mikhail Osipov Date: Fri, 18 Oct 2019 17:43:38 +0300 Subject: skel --- .gitignore | 3 ++ Makefile | 19 ++++++++++ TODO | 12 +++++++ daemon.c | 74 ++++++++++++++++++++++++++++++++++++++ libevent.mk | 2 ++ macro.h | 25 +++++++++++++ main.c | 31 ++++++++++++++++ tunnel.c | 116 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ tunnel.h | 9 +++++ 9 files changed, 291 insertions(+) create mode 100644 .gitignore create mode 100644 Makefile create mode 100644 daemon.c create mode 100644 libevent.mk create mode 100644 macro.h create mode 100644 main.c create mode 100644 tunnel.c create mode 100644 tunnel.h diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..350c6e0 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +tunnel +*.o +*~ diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..365d550 --- /dev/null +++ b/Makefile @@ -0,0 +1,19 @@ +PROGNAME = tunnel + +CFLAGS = -Wall -Wextra +LDFLAGS = + +include libevent.mk + +SOURCES = $(wildcard *.c) +OBJECTS = $(patsubst %.c,%.o,$(SOURCES)) + +$(PROGNAME): $(OBJECTS) + gcc $(LDFLAGS) -o $@ $^ + +%.o: %.c + gcc $(CFLAGS) -c -o $@ $< + +clean: + @echo cleaning... + @rm -f *.o *~ diff --git a/TODO b/TODO index 511a63b..663f2ab 100644 --- a/TODO +++ b/TODO @@ -5,3 +5,15 @@ Usage: tunnel route del ip[/mask] tunnel route show tunnel show + + tunnel create http host port name proxy + tunnel route add port 80 via proxy + tunnel route del port 80 via proxy + tunnel route drop via proxy + + tunnel add proxy httpconnect host port + tunnel route add proxy port 80 + tunnel route add proxy port 22 + tunnel show proxy + tunnel del proxy + tunnel list diff --git a/daemon.c b/daemon.c new file mode 100644 index 0000000..305755d --- /dev/null +++ b/daemon.c @@ -0,0 +1,74 @@ +#include +#include +#include +#include +#include +#include + +#include "tunnel.h" +#include "macro.h" + +static void sighandler(int signo __unused) +{ + unlink(TUNNEL_SOCK_PATH); + exit(EXIT_FAILURE); +} + +static void tunnel_daemon_loop(int sock) +{ + for (;;) { + int fd = accept(sock, NULL, NULL); + if (fd < 0) { + warn("accept"); + continue; + } + + FILE *fp = fdopen(fd, "w"); + if (fp) { + fprintf(fp, "hello from %d", getpid()); + fclose(fp); + } + } +} + +int tunnel_daemon(int sock) +{ + switch (fork()) { + case -1: + warn("fork"); + return -1; + case 0: + break; + default: + return 0; + } + + if (setsid() < 0) + err(EXIT_FAILURE, "setsid"); + + chdir("/"); + + struct sigaction sa = { + .sa_handler = sighandler + }; + + sigaction(SIGTERM, &sa, NULL); + sigaction(SIGINT, &sa, NULL); + +#if 0 + int fd = open("/dev/null", O_RDWR); + if (fd < 0) + err(EXIT_FAILURE, "open /dev/null"); + + dup2(fd, STDIN_FILENO); + dup2(fd, STDOUT_FILENO); + dup2(fd, STDERR_FILENO); + + if (fd > 2) + close(fd); +#endif + + tunnel_daemon_loop(sock); + + return 0; +} diff --git a/libevent.mk b/libevent.mk new file mode 100644 index 0000000..194a525 --- /dev/null +++ b/libevent.mk @@ -0,0 +1,2 @@ +CFLAGS += $(shell pkg-config --cflags libevent) +LDFLAGS += $(shell pkg-config --libs libevent) diff --git a/macro.h b/macro.h new file mode 100644 index 0000000..c91b8cf --- /dev/null +++ b/macro.h @@ -0,0 +1,25 @@ +#ifndef __TUNNEL_MACRO_H__ +#define __TUNNEL_MACRO_H__ + +#include +#include + +#define _new(t) memset(malloc(sizeof(t)), 0, sizeof(t)) + +#define _copy(p, ...) _copy_(p, ## __VA_ARGS__, sizeof(*p)) +#define _copy_(p, n, ...) memcpy(malloc(n), p, n) + +#define __unused __attribute__((unused)) +#define __cleanup(f) __attribute__((cleanup(f))) + +#define CAT(a, b) CAT_(a, b) +#define CAT_(a, b) a ## b + +#define UNIQ(name) CAT(name, __LINE__) + +#define defer \ + auto void UNIQ(defer_func)(int *); \ + int UNIQ(defer_var) __cleanup(UNIQ(defer_func)); \ + void UNIQ(defer_func)(int *p __unused) + +#endif diff --git a/main.c b/main.c new file mode 100644 index 0000000..5a43f51 --- /dev/null +++ b/main.c @@ -0,0 +1,31 @@ +#include +#include +#include +#include + +#include "tunnel.h" +#include "macro.h" + +int main(int argc __unused, char *argv[] __unused) +{ +#if 0 + if (geteuid() != 0) + errx(EXIT_FAILURE, "running as root required"); +#endif + + int sock = tunnel_client(); + if (sock < 0) + errx(EXIT_FAILURE, "tunnel_connect failed"); + + char buf[512]; + + int n = read(sock, buf, sizeof(buf)); + if (n < 0) + err(EXIT_FAILURE, "read"); + + printf("%.*s\n", n, buf); + + close(sock); + + return 0; +} diff --git a/tunnel.c b/tunnel.c new file mode 100644 index 0000000..56bdcdd --- /dev/null +++ b/tunnel.c @@ -0,0 +1,116 @@ +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "tunnel.h" +#include "macro.h" + +int tunnel_socket(struct sockaddr **sa, socklen_t *salen) +{ + int sock = socket(AF_UNIX, SOCK_SEQPACKET, 0); + if (sock < 0) { + warn("socket"); + return -1; + } + + struct sockaddr_un sun = { + .sun_family = AF_UNIX + }; + + const char *path = TUNNEL_SOCK_PATH; + + int n = snprintf(sun.sun_path, sizeof(sun.sun_path), "%s", path); + socklen_t len = offsetof(struct sockaddr_un, sun_path) + n + 1; + + if (len > sizeof(sun)) { + warnx("too large unix path"); + close(sock); + return -1; + } + + *sa = _copy(&sun, len); + *salen = len; + + return sock; +} + +int tunnel_listen(int sock, struct sockaddr *sa, socklen_t salen) +{ + if (bind(sock, sa, salen) < 0) { + warn("bind"); + return -1; + } + + if (listen(sock, 0) < 0) { + warn("listen"); + return -1; + } + + return 0; +} + +int tunnel_server(void) +{ + struct sockaddr *sa = NULL; + socklen_t salen = 0; + + int sock = tunnel_socket(&sa, &salen); + if (sock < 0) + return -1; + + defer { + close(sock); + free(sa); + } + + if (tunnel_listen(sock, sa, salen) < 0) + return -1; + + if (tunnel_daemon(sock) < 0) + return -1; + + return 0; +} + +int tunnel_connect(int sock, struct sockaddr *sa, socklen_t salen) +{ + if (connect(sock, sa, salen) < 0) { + if (errno == ENOENT) { + if (tunnel_server() < 0) + return -1; + } + + if (errno != ENOENT || connect(sock, sa, salen) < 0) { + warn("connect"); + return -1; + } + } + + return 0; +} + +int tunnel_client(void) +{ + struct sockaddr *sa = NULL; + socklen_t salen = 0; + + int sock = tunnel_socket(&sa, &salen); + if (sock < 0) + return -1; + + defer { free(sa); } + + if (tunnel_connect(sock, sa, salen) < 0) { + close(sock); + return -1; + } + + return sock; +} diff --git a/tunnel.h b/tunnel.h new file mode 100644 index 0000000..d04bde5 --- /dev/null +++ b/tunnel.h @@ -0,0 +1,9 @@ +#ifndef __TUNNEL_H__ +#define __TUNNEL_H__ + +#define TUNNEL_SOCK_PATH "/tmp/tunnel.sock" + +int tunnel_client(void); +int tunnel_daemon(int sock); + +#endif -- cgit v1.2.3-70-g09d2