diff options
| author | Mikhail Osipov <mike.osipov@gmail.com> | 2019-10-18 20:46:58 +0300 |
|---|---|---|
| committer | Mikhail Osipov <mike.osipov@gmail.com> | 2019-10-18 21:14:24 +0300 |
| commit | 8142854950bc510b8c21a210538d14a301dbcf63 (patch) | |
| tree | db4ecc964090218f50f1e9c4a8797544f9d45879 | |
| parent | 3b00c7be0e8834402ed93eb42b3a93302076c5ff (diff) | |
skel update
| -rw-r--r-- | Makefile | 6 | ||||
| -rw-r--r-- | daemon.c | 91 | ||||
| -rw-r--r-- | macro.h | 43 | ||||
| -rw-r--r-- | main.c | 44 | ||||
| -rw-r--r-- | tunnel.c | 120 | ||||
| -rw-r--r-- | tunnel.h | 7 | ||||
| -rw-r--r-- | utils.c | 14 | ||||
| -rw-r--r-- | utils.h | 8 |
8 files changed, 262 insertions, 71 deletions
@@ -1,6 +1,6 @@ PROGNAME = tunnel -CFLAGS = -Wall -Wextra +CFLAGS = -Wall -Wextra -Werror LDFLAGS = include libevent.mk @@ -9,10 +9,10 @@ SOURCES = $(wildcard *.c) OBJECTS = $(patsubst %.c,%.o,$(SOURCES)) $(PROGNAME): $(OBJECTS) - gcc $(LDFLAGS) -o $@ $^ + gcc -o $@ $^ $(LDFLAGS) %.o: %.c - gcc $(CFLAGS) -c -o $@ $< + gcc -c -o $@ $< $(CFLAGS) clean: @echo cleaning... @@ -3,44 +3,109 @@ #include <signal.h> #include <unistd.h> #include <stdio.h> +#include <time.h> #include <err.h> #include "tunnel.h" #include "macro.h" +#include "utils.h" -static void sighandler(int signo __unused) +static time_t since; + +static void tunnel_daemon_atexit(void) { unlink(TUNNEL_SOCK_PATH); +} + +static void sighandler(int signo __unused) +{ exit(EXIT_FAILURE); } +static char **parse_args(char *buf, int len) +{ + char **args = NULL; + + while (len) { + addv(&args, buf); + + char *p = memchr(buf, '\0', len); + if (!p) + break; + + len -= p - buf + 1; + buf = p + 1; + } + + return args; +} + +static void echo(FILE *fp, char **args) +{ + for (int n = 0; args[n]; n++) + fprintf(fp, "%s%s", n ? " " : "", args[n]); +} + static void tunnel_daemon_loop(int sock) { - for (;;) { + bool alive = true; + + while (alive) { + char msg[1024]; + int len; + 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); + len = read(fd, msg, sizeof(msg) - 1); + if (len < 0) { + warn("read"); + close(fd); + continue; + } + + if (! len) { + close(fd); + continue; + } + + msg[len] = '\0'; + + char **args = parse_args(msg, len); + + let (fp, fdopen(fd, "w"), fclose) { + char *cmd = *args; + + if (strequal(cmd, "echo")) + echo(fp, args + 1); + else if (strequal(cmd, "hello")) + fprintf(fp, "hello from %d", getpid()); + else if (strequal(cmd, "alive")) + fprintf(fp, "since %s", ctime(&since)); + else if (strequal(cmd, "stop")) { + fprintf(fp, "ok"); + alive = false; + } else + fprintf(fp, "what do you want?"); } + + free(args); } } -int tunnel_daemon(int sock) +bool tunnel_daemon(int sock) { switch (fork()) { case -1: warn("fork"); - return -1; + return false; case 0: break; default: - return 0; + return true; } if (setsid() < 0) @@ -68,7 +133,13 @@ int tunnel_daemon(int sock) close(fd); #endif + time(&since); + + atexit(tunnel_daemon_atexit); + tunnel_daemon_loop(sock); - return 0; + exit(EXIT_SUCCESS); + + return true; } @@ -4,7 +4,7 @@ #include <stdlib.h> #include <string.h> -#define _new(t) memset(malloc(sizeof(t)), 0, sizeof(t)) +#define _new(T, ...) ({ T __v = { __VA_ARGS__ }; _copy(&__v); }) #define _copy(p, ...) _copy_(p, ## __VA_ARGS__, sizeof(*p)) #define _copy_(p, n, ...) memcpy(malloc(n), p, n) @@ -22,4 +22,45 @@ int UNIQ(defer_var) __cleanup(UNIQ(defer_func)); \ void UNIQ(defer_func)(int *p __unused) +static __unused void __let_nothing(void) +{ +} + +#define let(p, e, ...) let_(p, e, ## __VA_ARGS__, __let_nothing) +#define let_(p, e, f, ...) \ + for (int step = 1; step; ) \ + for (typeof(e) p = e; step; f(p), step = 0) + +static inline int lenv(void **pp) +{ + int count = 0; + + if (pp) { + for (; *pp; pp++) + count++; + } + + return count; +} + +#define lenv(v) lenv((void **) v) + +static inline void **addv(void ***v, void *p) +{ + if (! v) { + *v = calloc(2, sizeof(*v)); + **v = p; + } else { + int len = lenv(*v); + + *v = realloc(*v, sizeof(*v) * (len + 2)); + (*v)[len] = p; + (*v)[len + 1] = NULL; + } + + return *v; +} + +#define addv(v, p) addv((void ***) v, p) + #endif @@ -5,25 +5,51 @@ #include "tunnel.h" #include "macro.h" +#include "utils.h" -int main(int argc __unused, char *argv[] __unused) +static void sendcmd(int sock, int argc, char *argv[]) { -#if 0 - if (geteuid() != 0) - errx(EXIT_FAILURE, "running as root required"); -#endif + char *buf = NULL; + size_t len = 0; + + let (fp, open_memstream(&buf, &len), fclose) { + for (int n = 0; n < argc; n++) { + if (n) + fputc('\0', fp); + + fprintf(fp, "%s", argv[n]); + } + } + + if (write(sock, buf, len) < 0) + err(EXIT_FAILURE, "write"); + + free(buf); +} + +int main(int argc, char *argv[]) +{ + char reply[1024]; + + if (argc == 1) + errx(EXIT_FAILURE, "bad usage"); int sock = tunnel_client(); if (sock < 0) - errx(EXIT_FAILURE, "tunnel_connect failed"); + errx(EXIT_FAILURE, "tunnel_client failed"); - char buf[512]; + sendcmd(sock, argc - 1, argv + 1); - int n = read(sock, buf, sizeof(buf)); + int n = read(sock, reply, sizeof(reply)); if (n < 0) err(EXIT_FAILURE, "read"); - printf("%.*s\n", n, buf); + if (n) { + if (reply[n - 1] == '\n') + printf("%.*s", n, reply); + else + printf("%.*s\n", n, reply); + } close(sock); @@ -2,6 +2,7 @@ #include <sys/stat.h> #include <sys/un.h> +#include <stdbool.h> #include <stddef.h> #include <unistd.h> #include <errno.h> @@ -12,12 +13,45 @@ #include "tunnel.h" #include "macro.h" -int tunnel_socket(struct sockaddr **sa, socklen_t *salen) +struct socket { + int fd; + struct sockaddr *sa; + socklen_t salen; +}; + +static bool socket_connect(struct socket *sock) +{ + if (connect(sock->fd, sock->sa, sock->salen) < 0) + return false; + + return true; +} + +static void socket_free(struct socket *sock) +{ + if (sock) { + if (sock->fd >= 0) + close(sock->fd); + free(sock->sa); + free(sock); + } +} + +static int socket_detach_fd(struct socket *sock) +{ + int fd = sock->fd; + + sock->fd = -1; + + return fd; +} + +struct socket *tunnel_socket(void) { - int sock = socket(AF_UNIX, SOCK_SEQPACKET, 0); - if (sock < 0) { + int fd = socket(AF_UNIX, SOCK_SEQPACKET, 0); + if (fd < 0) { warn("socket"); - return -1; + return NULL; } struct sockaddr_un sun = { @@ -31,86 +65,78 @@ int tunnel_socket(struct sockaddr **sa, socklen_t *salen) if (len > sizeof(sun)) { warnx("too large unix path"); - close(sock); - return -1; + close(fd); + return NULL; } - *sa = _copy(&sun, len); - *salen = len; + struct socket *sock = _new(struct socket, + .fd = fd, + .salen = len, + .sa = _copy(&sun, len), + ); return sock; } -int tunnel_listen(int sock, struct sockaddr *sa, socklen_t salen) +bool tunnel_listen(struct socket *sock) { - if (bind(sock, sa, salen) < 0) { + if (bind(sock->fd, sock->sa, sock->salen) < 0) { warn("bind"); - return -1; + return false; } - if (listen(sock, 0) < 0) { + if (listen(sock->fd, 0) < 0) { warn("listen"); - return -1; + return false; } - return 0; + return true; } -int tunnel_server(void) +bool tunnel_server(void) { - struct sockaddr *sa = NULL; - socklen_t salen = 0; + struct socket *sock = tunnel_socket(); + if (!sock) + return false; - int sock = tunnel_socket(&sa, &salen); - if (sock < 0) - return -1; + defer { socket_free(sock); } - defer { - close(sock); - free(sa); - } + if (! tunnel_listen(sock)) + return false; - if (tunnel_listen(sock, sa, salen) < 0) - return -1; - - if (tunnel_daemon(sock) < 0) - return -1; + if (! tunnel_daemon(sock->fd)) + return false; - return 0; + return true; } -int tunnel_connect(int sock, struct sockaddr *sa, socklen_t salen) +bool tunnel_connect(struct socket *sock) { - if (connect(sock, sa, salen) < 0) { + if (! socket_connect(sock)) { if (errno == ENOENT) { - if (tunnel_server() < 0) - return -1; + if (! tunnel_server()) + return false; } - if (errno != ENOENT || connect(sock, sa, salen) < 0) { + if (errno != ENOENT || ! socket_connect(sock)) { warn("connect"); - return -1; + return false; } } - return 0; + return true; } int tunnel_client(void) { - struct sockaddr *sa = NULL; - socklen_t salen = 0; - - int sock = tunnel_socket(&sa, &salen); - if (sock < 0) + struct socket *sock = tunnel_socket(); + if (! sock) return -1; - defer { free(sa); } + defer { socket_free(sock); } - if (tunnel_connect(sock, sa, salen) < 0) { - close(sock); + if (! tunnel_connect(sock)) return -1; - } - return sock; + return socket_detach_fd(sock); } @@ -1,9 +1,14 @@ #ifndef __TUNNEL_H__ #define __TUNNEL_H__ +#include <stdbool.h> + #define TUNNEL_SOCK_PATH "/tmp/tunnel.sock" +bool tunnel_alive(bool *alive); + int tunnel_client(void); -int tunnel_daemon(int sock); + +bool tunnel_daemon(int sock); #endif @@ -0,0 +1,14 @@ +#include <string.h> + +#include "utils.h" + +bool strequal(const char *a, const char *b) +{ + if (!a && !b) + return true; + + if (!a || !b) + return false; + + return !strcmp(a, b); +} @@ -0,0 +1,8 @@ +#ifndef __TUNNEL_UTILS_H__ +#define __TUNNEL_UTILS_H__ + +#include <stdbool.h> + +bool strequal(const char *a, const char *b); + +#endif |
