platform: add peer_flags argument to nm_platform_link_wireguard_change()

This commit is contained in:
Thomas Haller 2019-02-11 11:07:06 +01:00
parent 1e1b03c089
commit 153b41fa97
4 changed files with 126 additions and 57 deletions

View file

@ -2371,6 +2371,7 @@ _wireguard_create_change_nlmsgs (NMPlatform *platform,
int wireguard_family_id,
const NMPlatformLnkWireGuard *lnk_wireguard,
const NMPWireGuardPeer *peers,
const NMPlatformWireGuardChangePeerFlags *peer_flags,
guint peers_len,
NMPlatformWireGuardChangeFlags change_flags,
GPtrArray **out_msgs)
@ -2384,6 +2385,7 @@ _wireguard_create_change_nlmsgs (NMPlatform *platform,
struct nlattr *nest_curr_peer;
struct nlattr *nest_allowed_ips;
struct nlattr *nest_curr_allowed_ip;
NMPlatformWireGuardChangePeerFlags p_flags = NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_DEFAULT;
#define _nla_nest_end(msg, nest_start) \
G_STMT_START { \
@ -2449,6 +2451,21 @@ again:
for (; idx_peer_curr < peers_len; idx_peer_curr++) {
const NMPWireGuardPeer *p = &peers[idx_peer_curr];
if (peer_flags) {
p_flags = peer_flags[idx_peer_curr];
if (!NM_FLAGS_ANY (p_flags, NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_REMOVE_ME
| NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_HAS_PRESHARED_KEY
| NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_HAS_KEEPALIVE_INTERVAL
| NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_HAS_ENDPOINT
| NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_HAS_ALLOWEDIPS
| NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_REPLACE_ALLOWEDIPS)) {
/* no flags set. We take that as indication to skip configuring the peer
* entirely. */
nm_assert (p_flags == NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_NONE);
continue;
}
}
nest_curr_peer = nla_nest_start (msg, 0);
if (!nest_curr_peer)
goto toobig_peers;
@ -2456,63 +2473,77 @@ again:
if (nla_put (msg, WGPEER_A_PUBLIC_KEY, NMP_WIREGUARD_PUBLIC_KEY_LEN, p->public_key) < 0)
goto toobig_peers;
if (idx_allowed_ips_curr == IDX_NIL) {
if (nla_put (msg, WGPEER_A_PRESHARED_KEY, sizeof (p->preshared_key), p->preshared_key) < 0)
if (NM_FLAGS_HAS (p_flags, NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_REMOVE_ME)) {
/* all other p_flags are silently ignored. */
if (nla_put_uint32 (msg, WGPEER_A_FLAGS, WGPEER_F_REMOVE_ME) < 0)
goto toobig_peers;
} else {
if (nla_put_uint16 (msg, WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL, p->persistent_keepalive_interval) < 0)
goto toobig_peers;
if (nla_put_uint32 (msg, WGPEER_A_FLAGS, WGPEER_F_REPLACE_ALLOWEDIPS) < 0)
goto toobig_peers;
if (NM_IN_SET (p->endpoint.sa.sa_family, AF_INET, AF_INET6)) {
if (nla_put (msg,
WGPEER_A_ENDPOINT,
p->endpoint.sa.sa_family == AF_INET
? sizeof (p->endpoint.in)
: sizeof (p->endpoint.in6),
&p->endpoint) < 0)
if (idx_allowed_ips_curr == IDX_NIL) {
if ( NM_FLAGS_HAS (p_flags, NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_HAS_PRESHARED_KEY)
&& nla_put (msg, WGPEER_A_PRESHARED_KEY, sizeof (p->preshared_key), p->preshared_key) < 0)
goto toobig_peers;
} else
nm_assert (p->endpoint.sa.sa_family == AF_UNSPEC);
}
if (p->allowed_ips_len > 0) {
if (idx_allowed_ips_curr == IDX_NIL)
idx_allowed_ips_curr = 0;
if ( NM_FLAGS_HAS (p_flags, NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_HAS_KEEPALIVE_INTERVAL)
&& nla_put_uint16 (msg, WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL, p->persistent_keepalive_interval) < 0)
goto toobig_peers;
nest_allowed_ips = nla_nest_start (msg, WGPEER_A_ALLOWEDIPS);
if (!nest_allowed_ips)
goto toobig_allowedips;
if ( NM_FLAGS_HAS (p_flags, NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_REPLACE_ALLOWEDIPS)
&& nla_put_uint32 (msg, WGPEER_A_FLAGS, WGPEER_F_REPLACE_ALLOWEDIPS) < 0)
goto toobig_peers;
for (; idx_allowed_ips_curr < p->allowed_ips_len; idx_allowed_ips_curr++) {
const NMPWireGuardAllowedIP *aip = &p->allowed_ips[idx_allowed_ips_curr];
nest_curr_allowed_ip = nla_nest_start (msg, 0);
if (!nest_curr_allowed_ip)
goto toobig_allowedips;
g_return_val_if_fail (NM_IN_SET (aip->family, AF_INET, AF_INET6), -NME_BUG);
if (nla_put_uint16 (msg, WGALLOWEDIP_A_FAMILY, aip->family) < 0)
goto toobig_allowedips;
if (nla_put (msg,
WGALLOWEDIP_A_IPADDR,
nm_utils_addr_family_to_size (aip->family),
&aip->addr) < 0)
goto toobig_allowedips;
if (nla_put_uint8 (msg, WGALLOWEDIP_A_CIDR_MASK, aip->mask) < 0)
goto toobig_allowedips;
_nla_nest_end (msg, nest_curr_allowed_ip);
nest_curr_allowed_ip = NULL;
if (NM_FLAGS_HAS (p_flags, NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_HAS_ENDPOINT)) {
if (NM_IN_SET (p->endpoint.sa.sa_family, AF_INET, AF_INET6)) {
if (nla_put (msg,
WGPEER_A_ENDPOINT,
p->endpoint.sa.sa_family == AF_INET
? sizeof (p->endpoint.in)
: sizeof (p->endpoint.in6),
&p->endpoint) < 0)
goto toobig_peers;
} else {
/* I think there is no way to clear an endpoint, though there shold be. */
nm_assert (p->endpoint.sa.sa_family == AF_UNSPEC);
}
}
}
idx_allowed_ips_curr = IDX_NIL;
_nla_nest_end (msg, nest_allowed_ips);
nest_allowed_ips = NULL;
if ( NM_FLAGS_HAS (p_flags, NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_HAS_ALLOWEDIPS)
&& p->allowed_ips_len > 0) {
if (idx_allowed_ips_curr == IDX_NIL)
idx_allowed_ips_curr = 0;
nest_allowed_ips = nla_nest_start (msg, WGPEER_A_ALLOWEDIPS);
if (!nest_allowed_ips)
goto toobig_allowedips;
for (; idx_allowed_ips_curr < p->allowed_ips_len; idx_allowed_ips_curr++) {
const NMPWireGuardAllowedIP *aip = &p->allowed_ips[idx_allowed_ips_curr];
nest_curr_allowed_ip = nla_nest_start (msg, 0);
if (!nest_curr_allowed_ip)
goto toobig_allowedips;
g_return_val_if_fail (NM_IN_SET (aip->family, AF_INET, AF_INET6), -NME_BUG);
if (nla_put_uint16 (msg, WGALLOWEDIP_A_FAMILY, aip->family) < 0)
goto toobig_allowedips;
if (nla_put (msg,
WGALLOWEDIP_A_IPADDR,
nm_utils_addr_family_to_size (aip->family),
&aip->addr) < 0)
goto toobig_allowedips;
if (nla_put_uint8 (msg, WGALLOWEDIP_A_CIDR_MASK, aip->mask) < 0)
goto toobig_allowedips;
_nla_nest_end (msg, nest_curr_allowed_ip);
nest_curr_allowed_ip = NULL;
}
idx_allowed_ips_curr = IDX_NIL;
_nla_nest_end (msg, nest_allowed_ips);
nest_allowed_ips = NULL;
}
}
_nla_nest_end (msg, nest_curr_peer);
@ -2560,6 +2591,7 @@ link_wireguard_change (NMPlatform *platform,
int ifindex,
const NMPlatformLnkWireGuard *lnk_wireguard,
const NMPWireGuardPeer *peers,
const NMPlatformWireGuardChangePeerFlags *peer_flags,
guint peers_len,
NMPlatformWireGuardChangeFlags change_flags)
{
@ -2578,6 +2610,7 @@ link_wireguard_change (NMPlatform *platform,
wireguard_family_id,
lnk_wireguard,
peers,
peer_flags,
peers_len,
change_flags,
&msgs);

View file

@ -1990,6 +1990,16 @@ NM_UTILS_FLAGS2STR_DEFINE_STATIC (_wireguard_change_flags_to_string, NMPlatformW
NM_UTILS_FLAGS2STR (NM_PLATFORM_WIREGUARD_CHANGE_FLAG_HAS_FWMARK, "has-fwmark"),
);
NM_UTILS_FLAGS2STR_DEFINE_STATIC (_wireguard_change_peer_flags_to_string, NMPlatformWireGuardChangePeerFlags,
NM_UTILS_FLAGS2STR (NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_NONE, "none"),
NM_UTILS_FLAGS2STR (NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_REMOVE_ME, "remove"),
NM_UTILS_FLAGS2STR (NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_HAS_PRESHARED_KEY, "psk"),
NM_UTILS_FLAGS2STR (NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_HAS_KEEPALIVE_INTERVAL, "ka"),
NM_UTILS_FLAGS2STR (NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_HAS_ENDPOINT, "ep"),
NM_UTILS_FLAGS2STR (NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_HAS_ALLOWEDIPS, "aips"),
NM_UTILS_FLAGS2STR (NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_REPLACE_ALLOWEDIPS, "remove-aips"),
);
int
nm_platform_link_wireguard_add (NMPlatform *self,
const char *name,
@ -2003,6 +2013,7 @@ nm_platform_link_wireguard_change (NMPlatform *self,
int ifindex,
const NMPlatformLnkWireGuard *lnk_wireguard,
const NMPWireGuardPeer *peers,
const NMPlatformWireGuardChangePeerFlags *peer_flags,
guint peers_len,
NMPlatformWireGuardChangeFlags change_flags)
{
@ -2026,6 +2037,11 @@ nm_platform_link_wireguard_change (NMPlatform *self,
nm_utils_strbuf_append_str (&b, &len, " { ");
nm_platform_wireguard_peer_to_string (&peers[i], b, len);
nm_utils_strbuf_seek_end (&b, &len);
if (peer_flags) {
nm_utils_strbuf_append (&b, &len,
" (%s)",
_wireguard_change_peer_flags_to_string (peer_flags[i], buf_change_flags, sizeof (buf_change_flags)));
}
nm_utils_strbuf_append_str (&b, &len, " } ");
}
nm_utils_strbuf_append_str (&b, &len, "}");
@ -2043,6 +2059,7 @@ nm_platform_link_wireguard_change (NMPlatform *self,
ifindex,
lnk_wireguard,
peers,
peer_flags,
peers_len,
change_flags);
}

View file

@ -748,19 +748,35 @@ typedef enum {
} NMPlatformLinkDuplexType;
typedef enum {
NM_PLATFORM_KERNEL_SUPPORT_EXTENDED_IFA_FLAGS = (1LL << 0),
NM_PLATFORM_KERNEL_SUPPORT_USER_IPV6LL = (1LL << 1),
NM_PLATFORM_KERNEL_SUPPORT_RTA_PREF = (1LL << 2),
NM_PLATFORM_KERNEL_SUPPORT_EXTENDED_IFA_FLAGS = (1LL << 0),
NM_PLATFORM_KERNEL_SUPPORT_USER_IPV6LL = (1LL << 1),
NM_PLATFORM_KERNEL_SUPPORT_RTA_PREF = (1LL << 2),
} NMPlatformKernelSupportFlags;
typedef enum {
NM_PLATFORM_WIREGUARD_CHANGE_FLAG_NONE = 0,
NM_PLATFORM_WIREGUARD_CHANGE_FLAG_REPLACE_PEERS = (1LL << 0),
NM_PLATFORM_WIREGUARD_CHANGE_FLAG_HAS_PRIVATE_KEY = (1LL << 1),
NM_PLATFORM_WIREGUARD_CHANGE_FLAG_HAS_LISTEN_PORT = (1LL << 2),
NM_PLATFORM_WIREGUARD_CHANGE_FLAG_HAS_FWMARK = (1LL << 3),
NM_PLATFORM_WIREGUARD_CHANGE_FLAG_NONE = 0,
NM_PLATFORM_WIREGUARD_CHANGE_FLAG_REPLACE_PEERS = (1LL << 0),
NM_PLATFORM_WIREGUARD_CHANGE_FLAG_HAS_PRIVATE_KEY = (1LL << 1),
NM_PLATFORM_WIREGUARD_CHANGE_FLAG_HAS_LISTEN_PORT = (1LL << 2),
NM_PLATFORM_WIREGUARD_CHANGE_FLAG_HAS_FWMARK = (1LL << 3),
} NMPlatformWireGuardChangeFlags;
typedef enum {
NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_NONE = 0,
NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_REMOVE_ME = (1LL << 0),
NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_HAS_PRESHARED_KEY = (1LL << 1),
NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_HAS_KEEPALIVE_INTERVAL = (1LL << 2),
NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_HAS_ENDPOINT = (1LL << 3),
NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_HAS_ALLOWEDIPS = (1LL << 4),
NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_REPLACE_ALLOWEDIPS = (1LL << 5),
NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_DEFAULT = NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_HAS_PRESHARED_KEY
| NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_HAS_KEEPALIVE_INTERVAL
| NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_HAS_ENDPOINT
| NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_HAS_ALLOWEDIPS,
} NMPlatformWireGuardChangePeerFlags;
/*****************************************************************************/
struct _NMPlatformPrivate;
@ -838,6 +854,7 @@ typedef struct {
int ifindex,
const NMPlatformLnkWireGuard *lnk_wireguard,
const struct _NMPWireGuardPeer *peers,
const NMPlatformWireGuardChangePeerFlags *peer_flags,
guint peers_len,
NMPlatformWireGuardChangeFlags change_flags);
@ -1401,6 +1418,7 @@ int nm_platform_link_wireguard_change (NMPlatform *self,
int ifindex,
const NMPlatformLnkWireGuard *lnk_wireguard,
const struct _NMPWireGuardPeer *peers,
const NMPlatformWireGuardChangePeerFlags *peer_flags,
guint peers_len,
NMPlatformWireGuardChangeFlags change_flags);

View file

@ -912,6 +912,7 @@ _test_wireguard_change (NMPlatform *platform,
ifindex,
&lnk_wireguard,
(const NMPWireGuardPeer *) peers->data,
NULL,
peers->len,
NM_PLATFORM_WIREGUARD_CHANGE_FLAG_HAS_PRIVATE_KEY
| NM_PLATFORM_WIREGUARD_CHANGE_FLAG_HAS_LISTEN_PORT