From 54db1977b2501680eb0e407efbf0350c103ca7a0 Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Sat, 28 Sep 2019 20:04:17 +0200 Subject: netlink: allow preventing creation of new peers when updating This enables race-free updates for wg-dynamic and similar tools. Suggested-by: Thomas Gschwantner --- src/netlink.c | 7 +++---- src/uapi/wireguard.h | 14 +++++++++----- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/src/netlink.c b/src/netlink.c index 0805a26..190e405 100644 --- a/src/netlink.c +++ b/src/netlink.c @@ -389,10 +389,10 @@ static int set_peer(struct wg_device *wg, struct nlattr **attrs) peer = wg_pubkey_hashtable_lookup(wg->peer_hashtable, nla_data(attrs[WGPEER_A_PUBLIC_KEY])); + ret = 0; if (!peer) { /* Peer doesn't exist yet. Add a new one. */ - ret = -ENODEV; - if (flags & WGPEER_F_REMOVE_ME) - goto out; /* Tried to remove a non-existing peer. */ + if (flags & (WGPEER_F_REMOVE_ME | WGPEER_F_UPDATE_ONLY)) + goto out; /* The peer is new, so there aren't allowed IPs to remove. */ flags &= ~WGPEER_F_REPLACE_ALLOWEDIPS; @@ -429,7 +429,6 @@ static int set_peer(struct wg_device *wg, struct nlattr **attrs) wg_peer_get(peer); } - ret = 0; if (flags & WGPEER_F_REMOVE_ME) { wg_peer_remove(peer); goto out; diff --git a/src/uapi/wireguard.h b/src/uapi/wireguard.h index 5a3e5a7..dd8a47c 100644 --- a/src/uapi/wireguard.h +++ b/src/uapi/wireguard.h @@ -87,10 +87,12 @@ * 0: NLA_NESTED * WGPEER_A_PUBLIC_KEY: len WG_KEY_LEN * WGPEER_A_FLAGS: NLA_U32, 0 and/or WGPEER_F_REMOVE_ME if the - * specified peer should be removed rather than - * added/updated and/or WGPEER_F_REPLACE_ALLOWEDIPS - * if all current allowed IPs of this peer should be - * removed prior to adding the list below. + * specified peer should not exist at the end of the + * operation, rather than added/updated and/or + * WGPEER_F_REPLACE_ALLOWEDIPS if all current allowed + * IPs of this peer should be removed prior to adding + * the list below and/or WGPEER_F_UPDATE_ONLY if the + * peer should only be set if it already exists. * WGPEER_A_PRESHARED_KEY: len WG_KEY_LEN, all zeros to remove * WGPEER_A_ENDPOINT: struct sockaddr_in or struct sockaddr_in6 * WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL: NLA_U16, 0 to disable @@ -162,7 +164,9 @@ enum wgdevice_attribute { enum wgpeer_flag { WGPEER_F_REMOVE_ME = 1U << 0, WGPEER_F_REPLACE_ALLOWEDIPS = 1U << 1, - __WGPEER_F_ALL = WGPEER_F_REMOVE_ME | WGPEER_F_REPLACE_ALLOWEDIPS + WGPEER_F_UPDATE_ONLY = 1U << 2, + __WGPEER_F_ALL = WGPEER_F_REMOVE_ME | WGPEER_F_REPLACE_ALLOWEDIPS | + WGPEER_F_UPDATE_ONLY }; enum wgpeer_attribute { WGPEER_A_UNSPEC, -- cgit v1.2.3-59-g8ed1b