aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--src/tools/peer_names.c139
-rw-r--r--src/tools/peer_names.h29
-rw-r--r--src/tools/show.c21
3 files changed, 185 insertions, 4 deletions
diff --git a/src/tools/peer_names.c b/src/tools/peer_names.c
new file mode 100644
index 0000000..37e122d
--- /dev/null
+++ b/src/tools/peer_names.c
@@ -0,0 +1,139 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2019 Luis Ressel <aranea@aixah.de>. All Rights Reserved.
+ */
+
+#include <errno.h>
+#include <limits.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "containers.h"
+#include "encoding.h"
+#include "peer_names.h"
+
+static bool parse_peer_name(char *line, struct wgpeer_name *slot)
+{
+ char *name;
+ size_t len;
+
+ name = strpbrk(line, " \t");
+ if (!name)
+ return false;
+ *name = '\0';
+
+ if (!key_from_base64(slot->public_key, line))
+ return false;
+
+ len = strlen(++name);
+ if (name[len - 1] == '\n')
+ name[len - 1] = '\0';
+ slot->name = strdup(name);
+ return !!slot->name;
+}
+
+static int peer_name_cmp(const void *a, const void *b)
+{
+ const struct wgpeer_name *x = a, *y = b;
+ return memcmp(x->public_key, y->public_key, WG_KEY_LEN);
+}
+
+bool peer_names_open(struct wgpeer_names *names, struct wgdevice *device)
+{
+ size_t max_peers = 1, peers = 0, buf_len = 0, path_len;
+ struct wgpeer_name *arr, *arr2;
+ char *buf = NULL, *path;
+ FILE *f;
+
+ path = getenv("WG_PEER_NAMES");
+ if (!path || !path[0]) {
+ errno = 0;
+ return false;
+ }
+
+ path_len = strlen(path);
+ if (path[path_len - 1] == '/') {
+ size_t dev_len = strlen(device->name);
+ char *path2 = malloc(path_len + dev_len + 1);
+
+ if (!path2)
+ return false;
+ memcpy(path2, path, path_len);
+ memcpy(path2 + path_len, device->name, dev_len + 1);
+ f = fopen(path2, "r");
+ free(path2);
+ } else
+ f = fopen(path, "r");
+ if (!f)
+ return false;
+
+ arr = malloc(sizeof(struct wgpeer_name));
+ if (!arr)
+ return false;
+
+ while (getline(&buf, &buf_len, f) >= 0) {
+ if (parse_peer_name(buf, &arr[peers]) && (++peers == max_peers)) {
+ // TODO: Pulled this overflow check out of my ass, gotta revisit it later
+ if (SIZE_MAX / (2 * sizeof(struct wgpeer_name)) < max_peers) {
+ errno = ENOMEM;
+ return false;
+ }
+ max_peers *= 2;
+
+ arr2 = realloc(arr, max_peers * sizeof(struct wgpeer_name));
+ if (!arr2) {
+ free(arr);
+ return false;
+ }
+ arr = arr2;
+ }
+ }
+ free(buf);
+
+ if (!peers)
+ free(arr);
+ if ((arr2 = realloc(arr, peers * sizeof(struct wgpeer_name))))
+ arr = arr2;
+
+ qsort(arr, peers, sizeof(struct wgpeer_name), peer_name_cmp);
+ names->len = peers;
+ names->arr = arr;
+ return true;
+}
+
+void peer_names_free(struct wgpeer_names *names)
+{
+ if (!names)
+ return;
+
+ for (size_t i = 0; i < names->len; ++i)
+ free(names->arr[i].name);
+ if (names->len)
+ free(names->arr);
+}
+
+char *peer_names_get(struct wgpeer_names *names, uint8_t key[static WG_KEY_LEN])
+{
+ size_t r, l = 0;
+
+ if (!names || !names->len)
+ return NULL;
+ r = names->len - 1;
+
+ while (l <= r) {
+ size_t m = l + (r - l) / 2;
+ int cmp = memcmp(key, names->arr[m].public_key, WG_KEY_LEN);
+ if (!cmp)
+ return names->arr[m].name;
+ else if (cmp > 0)
+ l = m + 1;
+ else if (!m)
+ break;
+ else
+ r = m - 1;
+ }
+ return NULL;
+}
diff --git a/src/tools/peer_names.h b/src/tools/peer_names.h
new file mode 100644
index 0000000..5ba73fe
--- /dev/null
+++ b/src/tools/peer_names.h
@@ -0,0 +1,29 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2019 Luis Ressel <aranea@aixah.de>. All Rights Reserved.
+ */
+
+#ifndef PEER_NAMES_H
+#define PEER_NAMES_H
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#include "containers.h"
+
+struct wgpeer_name {
+ char *name;
+ uint8_t public_key[WG_KEY_LEN];
+};
+
+struct wgpeer_names {
+ size_t len;
+ struct wgpeer_name *arr;
+};
+
+bool peer_names_open(struct wgpeer_names *names, struct wgdevice *device);
+void peer_names_free(struct wgpeer_names *names);
+char *peer_names_get(struct wgpeer_names *names, uint8_t key[static WG_KEY_LEN]);
+
+#endif // PEER_NAMES_H
diff --git a/src/tools/show.c b/src/tools/show.c
index ff0897d..ca26cc6 100644
--- a/src/tools/show.c
+++ b/src/tools/show.c
@@ -22,6 +22,7 @@
#include "ipc.h"
#include "terminal.h"
#include "encoding.h"
+#include "peer_names.h"
#include "subcommands.h"
static int peer_cmp(const void *first, const void *second)
@@ -205,8 +206,9 @@ static void show_usage(void)
fprintf(stderr, "Usage: %s %s { <interface> | all | interfaces } [public-key | private-key | listen-port | fwmark | peers | preshared-keys | endpoints | allowed-ips | latest-handshakes | transfer | persistent-keepalive | dump]\n", PROG_NAME, COMMAND_NAME);
}
-static void pretty_print(struct wgdevice *device)
+static void pretty_print(struct wgdevice *device, struct wgpeer_names *names)
{
+ char *name;
struct wgpeer *peer;
struct wgallowedip *allowedip;
@@ -226,6 +228,8 @@ static void pretty_print(struct wgdevice *device)
}
for_each_wgpeer(device, peer) {
terminal_printf(TERMINAL_FG_YELLOW TERMINAL_BOLD "peer" TERMINAL_RESET ": " TERMINAL_FG_YELLOW "%s" TERMINAL_RESET "\n", key(peer->public_key));
+ if ((name = peer_names_get(names, peer->public_key)))
+ terminal_printf(" " TERMINAL_BOLD "name" TERMINAL_RESET ": %s\n", name);
if (peer->flags & WGPEER_HAS_PRESHARED_KEY)
terminal_printf(" " TERMINAL_BOLD "preshared key" TERMINAL_RESET ": %s\n", masked_key(peer->preshared_key));
if (peer->endpoint.addr.sa_family == AF_INET || peer->endpoint.addr.sa_family == AF_INET6)
@@ -398,6 +402,7 @@ int show_main(int argc, char *argv[])
interface = interfaces;
for (size_t len = 0; (len = strlen(interface)); interface += len + 1) {
struct wgdevice *device = NULL;
+ struct wgpeer_names names;
if (ipc_get_device(&device, interface) < 0) {
fprintf(stderr, "Unable to access interface %s: %s\n", interface, strerror(errno));
@@ -410,9 +415,12 @@ int show_main(int argc, char *argv[])
break;
}
} else {
- pretty_print(device);
+ if (!peer_names_open(&names, device) && errno)
+ perror("peer_names_open");
+ pretty_print(device, &names);
if (strlen(interface + len + 1))
printf("\n");
+ peer_names_free(&names);
}
free_wgdevice(device);
ret = 0;
@@ -438,6 +446,7 @@ int show_main(int argc, char *argv[])
show_usage();
else {
struct wgdevice *device = NULL;
+ struct wgpeer_names names;
if (ipc_get_device(&device, argv[1]) < 0) {
perror("Unable to access interface");
@@ -446,8 +455,12 @@ int show_main(int argc, char *argv[])
if (argc == 3) {
if (!ugly_print(device, argv[2], false))
ret = 1;
- } else
- pretty_print(device);
+ } else {
+ if (!peer_names_open(&names, device) && errno)
+ perror("peer_names_open");
+ pretty_print(device, &names);
+ peer_names_free(&names);
+ }
free_wgdevice(device);
}
return ret;