From 3c2423a38be51a42b85821a9a7158a180e1ec81d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adrien=20Gallou=C3=ABt?= Date: Mon, 12 Feb 2018 22:58:57 +0000 Subject: [PATCH] Add command show MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Adrien Gallouët --- Makefile.am | 1 + meson.build | 1 + src/bind.c | 26 +++++++++++--- src/ctl.c | 95 ++++++++++++++++++++++++++++++++++++-------------- src/ctl.h | 18 ++++++++-- src/main.c | 15 +------- src/path.c | 24 ++++++------- src/show.c | 99 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 8 files changed, 219 insertions(+), 60 deletions(-) create mode 100644 src/show.c diff --git a/Makefile.am b/Makefile.am index b6b03b5..a4b8204 100644 --- a/Makefile.am +++ b/Makefile.am @@ -21,6 +21,7 @@ glorytun_SOURCES = \ src/keygen.c \ src/main.c \ src/path.c \ + src/show.c \ src/str.h \ src/tun.c \ src/tun.h diff --git a/meson.build b/meson.build index 6a8c7db..1ef448d 100644 --- a/meson.build +++ b/meson.build @@ -28,6 +28,7 @@ executable('glorytun', install: true, 'src/keygen.c', 'src/main.c', 'src/path.c', + 'src/show.c', 'src/tun.c', ], dependencies: [ diff --git a/src/bind.c b/src/bind.c index 70ccc3e..50e59ae 100644 --- a/src/bind.c +++ b/src/bind.c @@ -199,8 +199,10 @@ gt_bind(int argc, char **argv) return 1; } - if (!chacha && mud_set_aes(mud)) + if (!chacha && mud_set_aes(mud)) { gt_log("AES is not available\n"); + chacha = 1; + } if (timeout && mud_set_send_timeout(mud, timeout)) { perror("timeout"); @@ -234,10 +236,10 @@ gt_bind(int argc, char **argv) gt_setup_mtu(mud, tun_name, &mtu); - int ctl_fd = ctl_init("/run/" PACKAGE_NAME, tun_name); + int ctl_fd = ctl_create("/run/" PACKAGE_NAME, tun_name); if (ctl_fd == -1) { - perror("ctl_init"); + perror("ctl_create"); return 1; } @@ -313,7 +315,21 @@ gt_bind(int argc, char **argv) perror("mud_del_path"); } break; - case CTL_PING: + case CTL_STATUS: + gt_log("[ctl status]\n"); + reply = (struct ctl_msg){ + .type = CTL_STATUS_REPLY, + .status = { + .mtu = mtu, + .mtu_auto = (icmp_fd != -1), + .chacha = chacha, + .port = port, + .bind_port = bind_port, + .ipv4 = ipv4, + .ipv6 = ipv6, + }, + }; + str_cpy(reply.status.addr, sizeof(reply.status.addr) - 1, host); break; default: reply = (struct ctl_msg){ @@ -423,5 +439,7 @@ gt_bind(int argc, char **argv) perror("tun_set_persist"); } + ctl_delete(ctl_fd); + return 0; } diff --git a/src/ctl.c b/src/ctl.c index e5bcf36..f559473 100644 --- a/src/ctl.c +++ b/src/ctl.c @@ -2,21 +2,15 @@ #include "ctl.h" #include "str.h" +#include +#include #include #include #include -int -ctl_init(const char *dir, const char *file) +static int +ctl_setsun(struct sockaddr_un *dst, const char *dir, const char *file) { - if (str_empty(dir) || str_empty(file)) { - errno = EINVAL; - return -1; - } - - if (mkdir(dir, 0700) == -1 && errno != EEXIST) - return -1; - struct sockaddr_un sun = { .sun_family = AF_UNIX, }; @@ -31,14 +25,74 @@ ctl_init(const char *dir, const char *file) } } + *dst = sun; + + return 0; +} + +static int +ctl_bind(int fd, const char *dir, const char *file) +{ + char tmp[32]; + struct sockaddr_un sun; + + if (str_empty(file)) { + for (int i = 0; i < 64; i++) { + if (snprintf(tmp, sizeof(tmp), ".%i", i) >= sizeof(tmp)) + return -1; + + if (ctl_setsun(&sun, dir, tmp)) + return -1; + + if (!bind(fd, (struct sockaddr *)&sun, sizeof(sun))) + return 0; + } + } else { + if (ctl_setsun(&sun, dir, file)) + return -1; + + unlink(sun.sun_path); + + if (!bind(fd, (struct sockaddr *)&sun, sizeof(sun))) + return 0; + } + + return -1; +} + +void +ctl_delete(int fd) +{ + if (fd == -1) + return; + + struct sockaddr_storage ss; + socklen_t sslen = sizeof(ss); + + if ((getsockname(fd, (struct sockaddr *)&ss, &sslen) == 0) && + (ss.ss_family == AF_UNIX)) + unlink(((struct sockaddr_un *)&ss)->sun_path); + + close(fd); +} + +int +ctl_create(const char *dir, const char *file) +{ + if (str_empty(dir)) { + errno = EINVAL; + return -1; + } + + if (mkdir(dir, 0700) == -1 && errno != EEXIST) + return -1; + int fd = socket(AF_UNIX, SOCK_DGRAM, 0); if (fd == -1) return -1; - unlink(sun.sun_path); - - if (bind(fd, (struct sockaddr *)&sun, sizeof(sun)) == -1) { + if (ctl_bind(fd, dir, file)) { int err = errno; close(fd); errno = err; @@ -56,19 +110,10 @@ ctl_connect(int fd, const char *dir, const char *file) return -1; } - struct sockaddr_un sun = { - .sun_family = AF_UNIX, - }; + struct sockaddr_un sun; - const char *path[] = {dir, "/", file}; - const size_t len = sizeof(sun.sun_path) - 1; - - if (str_cat(sun.sun_path, len, path, COUNT(path)) == len) { - if (str_cat(NULL, len + 1, path, COUNT(path)) > len) { - errno = EINVAL; - return -1; - } - } + if (ctl_setsun(&sun, dir, file)) + return -1; return connect(fd, (struct sockaddr *)&sun, sizeof(sun)); } diff --git a/src/ctl.h b/src/ctl.h index c3a4ad5..777bd86 100644 --- a/src/ctl.h +++ b/src/ctl.h @@ -4,7 +4,8 @@ enum ctl_type { CTL_UNKNOWN, CTL_PATH_ADD, CTL_PATH_DEL, - CTL_PING, + CTL_STATUS, + CTL_STATUS_REPLY, CTL_REPLY, }; @@ -19,9 +20,20 @@ struct ctl_msg { char addr[256]; } add, del; } path; + struct { + size_t mtu; + int mtu_auto; + int chacha; + char addr[256]; + unsigned short port; + unsigned short bind_port; + int ipv4; + int ipv6; + } status; int reply; }; }; -int ctl_init (const char *, const char *); -int ctl_connect (int, const char *, const char *); +int ctl_create (const char *, const char *); +int ctl_connect (int, const char *, const char *); +void ctl_delete (int); diff --git a/src/main.c b/src/main.c index 3ce4f7f..f4d3a09 100644 --- a/src/main.c +++ b/src/main.c @@ -50,20 +50,7 @@ gt_version(int argc, char **argv) return 0; } -int -gt_show(int argc, char **argv) -{ - printf("show (todo)\n"); - return 0; -} - -int -gt_key(int argc, char **argv) -{ - printf("key (todo)\n"); - return 0; -} - +int gt_show(int, char **); int gt_bind(int, char **); int gt_path(int, char **); int gt_keygen(int, char **); diff --git a/src/path.c b/src/path.c index bf8dd73..63ee05f 100644 --- a/src/path.c +++ b/src/path.c @@ -28,13 +28,11 @@ gt_path(int argc, char **argv) struct ctl_msg msg; if (argz_is_set(pathz, "up")) { - gt_log("up\n"); msg = (struct ctl_msg){ .type = CTL_PATH_ADD, }; str_cpy(msg.path.add.addr, sizeof(msg.path.add.addr) - 1, addr); } else if (argz_is_set(pathz, "down")) { - gt_log("down\n"); msg = (struct ctl_msg){ .type = CTL_PATH_DEL, }; @@ -44,27 +42,25 @@ gt_path(int argc, char **argv) return 0; } - int ctl_fd = ctl_init("/run/" PACKAGE_NAME, "client"); + int fd = ctl_create("/run/" PACKAGE_NAME, NULL); - if (ctl_fd == -1) { - perror("ctl_init"); + if (fd == -1) { + perror("ctl_create"); return 1; } - if (ctl_connect(ctl_fd, "/run/" PACKAGE_NAME, dev) == -1) { + if (ctl_connect(fd, "/run/" PACKAGE_NAME, dev) == -1) { gt_log("couldn't connect to %s\n", dev); - return 1; - } - - if (send(ctl_fd, &msg, sizeof(msg), 0) == -1) { - perror("send"); + ctl_delete(fd); return 1; } struct ctl_msg reply; - if (recv(ctl_fd, &reply, sizeof(reply), 0) == -1) { - perror("recv"); + if ((send(fd, &msg, sizeof(msg), 0) == -1) || + (recv(fd, &reply, sizeof(reply), 0) == -1)) { + perror("send/recv"); + ctl_delete(fd); return 1; } @@ -82,7 +78,7 @@ gt_path(int argc, char **argv) gt_log("bad reply from server: %i\n", reply.type); } - close(ctl_fd); + ctl_delete(fd); return 0; } diff --git a/src/show.c b/src/show.c new file mode 100644 index 0000000..33f8c62 --- /dev/null +++ b/src/show.c @@ -0,0 +1,99 @@ +#include "common.h" +#include "ctl.h" +#include "str.h" + +#include +#include +#include +#include + +static int +gt_show_tunnel(int fd, const char *dev) +{ + if (ctl_connect(fd, "/run/" PACKAGE_NAME, dev) == -1) { + perror("connect"); + return -1; + } + + struct ctl_msg reply, msg = { + .type = CTL_STATUS, + }; + + if ((send(fd, &msg, sizeof(msg), 0) == -1) || + (recv(fd, &reply, sizeof(reply), 0) == -1)) { + perror("send/recv"); + return -1; + } + + if (reply.type != CTL_STATUS_REPLY) + return -1; + + if (str_empty(reply.status.addr)) { + printf("server %s:\n" + " mtu: %zu\n" + " auto mtu: %s\n" + " bind port: %hu\n" + " cipher: %s\n" + " ipv4: %s\n" + " ipv6: %s\n", + dev, + reply.status.mtu, + reply.status.mtu_auto ? "enabled" : "disabled", + reply.status.bind_port, + reply.status.chacha ? "chacha20poly1305" : "aes256gcm", + reply.status.ipv4 ? "enabled" : "disabled", + reply.status.ipv6 ? "enabled" : "disabled"); + } else { + printf("client %s:\n" + " host: %s\n" + " port: %hu\n" + " mtu: %zu\n" + " auto mtu: %s\n" + " bind port: %hu\n" + " cipher: %s\n" + " ipv4: %s\n" + " ipv6: %s\n", + dev, + reply.status.addr, reply.status.port, + reply.status.mtu, + reply.status.mtu_auto ? "enabled" : "disabled", + reply.status.bind_port, + reply.status.chacha ? "chacha20poly1305" : "aes256gcm", + reply.status.ipv4 ? "enabled" : "disabled", + reply.status.ipv6 ? "enabled" : "disabled"); + } + + return 0; +} + +int +gt_show(int argc, char **argv) +{ + DIR *dp = opendir("/run/" PACKAGE_NAME); + + if (!dp) { + perror("opendir"); + return 1; + } + + struct dirent *d = NULL; + + while (d = readdir(dp), d) { + if (d->d_name[0] == '.') + continue; + + int fd = ctl_create("/run/" PACKAGE_NAME, NULL); + + if (fd == -1) { + perror("ctl_create"); + return 1; + } + + gt_show_tunnel(fd, d->d_name); + ctl_delete(fd); + } + + closedir(dp); + + return 0; +}