diff options
author | Jason A. Donenfeld <Jason@zx2c4.com> | 2019-06-11 19:22:52 +0200 |
---|---|---|
committer | Jason A. Donenfeld <Jason@zx2c4.com> | 2019-06-11 19:41:02 +0200 |
commit | 096e54a8c05389a090ad4a25d892c4516c62591d (patch) | |
tree | 88939de0a4d828c74bb0299d05b6fb7e3e1cbe0a /src/tools | |
parent | blake2s: spacing (diff) | |
download | wireguard-monolithic-historical-jd/syncconf.tar.xz wireguard-monolithic-historical-jd/syncconf.zip |
tools: add syncconf commandjd/syncconf
Diffstat (limited to 'src/tools')
-rw-r--r-- | src/tools/setconf.c | 88 | ||||
-rw-r--r-- | src/tools/wg.c | 1 |
2 files changed, 89 insertions, 0 deletions
diff --git a/src/tools/setconf.c b/src/tools/setconf.c index 8211ebd..a244c07 100644 --- a/src/tools/setconf.c +++ b/src/tools/setconf.c @@ -13,6 +13,89 @@ #include "ipc.h" #include "subcommands.h" +struct pubkey_origin { + uint8_t *pubkey; + bool from_file; +}; + +static int pubkey_cmp(const void *first, const void *second) +{ + const struct pubkey_origin *a = first, *b = second; + int ret = memcmp(a->pubkey, b->pubkey, WG_KEY_LEN); + if (ret) + return ret; + return a->from_file - b->from_file; +} + +static bool sync_conf(struct wgdevice *file) +{ + struct wgdevice *runtime; + struct wgpeer *peer; + struct pubkey_origin *pubkeys; + size_t peer_count = 0, i = 0; + + if (!file->first_peer) + return true; + + for_each_wgpeer(file, peer) + ++peer_count; + + if (ipc_get_device(&runtime, file->name) != 0) { + perror("Unable to retrieve current interface configuration"); + return false; + } + + if (!runtime->first_peer) + return true; + + file->flags &= ~WGDEVICE_REPLACE_PEERS; + + for_each_wgpeer(runtime, peer) + ++peer_count; + + pubkeys = calloc(peer_count, sizeof(*pubkeys)); + if (!pubkeys) { + free_wgdevice(runtime); + perror("Public key allocation"); + return false; + } + + for_each_wgpeer(file, peer) { + pubkeys[i].pubkey = peer->public_key; + pubkeys[i].from_file = true; + ++i; + } + for_each_wgpeer(runtime, peer) { + pubkeys[i].pubkey = peer->public_key; + pubkeys[i].from_file = false; + ++i; + } + qsort(pubkeys, peer_count, sizeof(*pubkeys), pubkey_cmp); + + for (i = 0; i < peer_count; ++i) { + if (pubkeys[i].from_file) + continue; + if (i == peer_count - 1 || !pubkeys[i + 1].from_file || memcmp(pubkeys[i].pubkey, pubkeys[i + 1].pubkey, WG_KEY_LEN)) { + peer = calloc(1, sizeof(struct wgpeer)); + if (!peer) { + free_wgdevice(runtime); + free(pubkeys); + perror("Peer allocation"); + return false; + } + peer->flags = WGPEER_REMOVE_ME; + memcpy(peer->public_key, pubkeys[i].pubkey, WG_KEY_LEN); + peer->next_peer = file->first_peer; + file->first_peer = peer; + if (!file->last_peer) + file->last_peer = peer; + } + } + free_wgdevice(runtime); + free(pubkeys); + return true; +} + int setconf_main(int argc, char *argv[]) { struct wgdevice *device = NULL; @@ -50,6 +133,11 @@ int setconf_main(int argc, char *argv[]) strncpy(device->name, argv[1], IFNAMSIZ - 1); device->name[IFNAMSIZ - 1] = '\0'; + if (!strcmp(argv[0], "syncconf")) { + if (!sync_conf(device)) + goto cleanup; + } + if (ipc_set_device(device) != 0) { perror("Unable to modify interface"); goto cleanup; diff --git a/src/tools/wg.c b/src/tools/wg.c index 550d9b4..7b5d3af 100644 --- a/src/tools/wg.c +++ b/src/tools/wg.c @@ -21,6 +21,7 @@ static const struct { { "set", set_main, "Change the current configuration, add peers, remove peers, or change peers" }, { "setconf", setconf_main, "Applies a configuration file to a WireGuard interface" }, { "addconf", setconf_main, "Appends a configuration file to a WireGuard interface" }, + { "syncconf", setconf_main, "Synchronizes a configuration file to a WireGuard interface" }, { "genkey", genkey_main, "Generates a new private key and writes it to stdout" }, { "genpsk", genkey_main, "Generates a new preshared key and writes it to stdout" }, { "pubkey", pubkey_main, "Reads a private key from stdin and writes a public key to stdout" } |