diff options
| -rw-r--r-- | .gitignore | 3 | ||||
| -rw-r--r-- | Makefile | 19 | ||||
| -rw-r--r-- | TODO | 12 | ||||
| -rw-r--r-- | daemon.c | 74 | ||||
| -rw-r--r-- | libevent.mk | 2 | ||||
| -rw-r--r-- | macro.h | 25 | ||||
| -rw-r--r-- | main.c | 31 | ||||
| -rw-r--r-- | tunnel.c | 116 | ||||
| -rw-r--r-- | tunnel.h | 9 |
9 files changed, 291 insertions, 0 deletions
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 *~ @@ -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 <sys/socket.h> +#include <stdlib.h> +#include <signal.h> +#include <unistd.h> +#include <stdio.h> +#include <err.h> + +#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) @@ -0,0 +1,25 @@ +#ifndef __TUNNEL_MACRO_H__ +#define __TUNNEL_MACRO_H__ + +#include <stdlib.h> +#include <string.h> + +#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 @@ -0,0 +1,31 @@ +#include <stdlib.h> +#include <unistd.h> +#include <stdio.h> +#include <err.h> + +#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 <sys/socket.h> +#include <sys/stat.h> +#include <sys/un.h> + +#include <stddef.h> +#include <unistd.h> +#include <errno.h> +#include <fcntl.h> +#include <stdio.h> +#include <err.h> + +#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 |
