merge: branch 'wireguard-platform' of https://github.com/jbeta/NetworkManager
https://github.com/NetworkManager/NetworkManager/pull/143
This commit is contained in:
@@ -31,6 +31,31 @@ typedef struct {
|
||||
guint32 to;
|
||||
} NMVlanQosMapping;
|
||||
|
||||
typedef struct {
|
||||
NMIPAddr ip;
|
||||
guint8 family;
|
||||
guint8 mask;
|
||||
} NMWireguardAllowedIP;
|
||||
|
||||
#define NM_WG_PUBLIC_KEY_LEN 32
|
||||
#define NM_WG_SYMMETRIC_KEY_LEN 32
|
||||
|
||||
typedef struct {
|
||||
guint8 public_key[NM_WG_PUBLIC_KEY_LEN];
|
||||
guint8 preshared_key[NM_WG_SYMMETRIC_KEY_LEN];
|
||||
union {
|
||||
struct sockaddr addr;
|
||||
struct sockaddr_in addr4;
|
||||
struct sockaddr_in6 addr6;
|
||||
} endpoint;
|
||||
guint16 persistent_keepalive_interval;
|
||||
struct timespec last_handshake_time;
|
||||
guint64 rx_bytes, tx_bytes;
|
||||
|
||||
gsize allowedips_len;
|
||||
NMWireguardAllowedIP *allowedips;
|
||||
} NMWireguardPeer;
|
||||
|
||||
#define _NM_IP_TUNNEL_FLAG_ALL_IP6TNL \
|
||||
( NM_IP_TUNNEL_FLAG_IP6_IGN_ENCAP_LIMIT \
|
||||
| NM_IP_TUNNEL_FLAG_IP6_USE_ORIG_TCLASS \
|
||||
|
@@ -174,6 +174,7 @@ typedef enum {
|
||||
NM_LINK_TYPE_VETH,
|
||||
NM_LINK_TYPE_VLAN,
|
||||
NM_LINK_TYPE_VXLAN,
|
||||
NM_LINK_TYPE_WIREGUARD,
|
||||
|
||||
/* Software types with slaves */
|
||||
NM_LINK_TYPE_BRIDGE = 0x10000 | 0x20000,
|
||||
@@ -209,6 +210,7 @@ typedef enum {
|
||||
NMP_OBJECT_TYPE_LNK_TUN,
|
||||
NMP_OBJECT_TYPE_LNK_VLAN,
|
||||
NMP_OBJECT_TYPE_LNK_VXLAN,
|
||||
NMP_OBJECT_TYPE_LNK_WIREGUARD,
|
||||
|
||||
__NMP_OBJECT_TYPE_LAST,
|
||||
NMP_OBJECT_TYPE_MAX = __NMP_OBJECT_TYPE_LAST - 1,
|
||||
|
@@ -181,6 +181,40 @@ G_STATIC_ASSERT (RTA_MAX == (__RTA_MAX - 1));
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#define WG_CMD_GET_DEVICE 0
|
||||
#define WG_CMD_SET_DEVICE 1
|
||||
|
||||
#define WGDEVICE_A_UNSPEC 0
|
||||
#define WGDEVICE_A_IFINDEX 1
|
||||
#define WGDEVICE_A_IFNAME 2
|
||||
#define WGDEVICE_A_PRIVATE_KEY 3
|
||||
#define WGDEVICE_A_PUBLIC_KEY 4
|
||||
#define WGDEVICE_A_FLAGS 5
|
||||
#define WGDEVICE_A_LISTEN_PORT 6
|
||||
#define WGDEVICE_A_FWMARK 7
|
||||
#define WGDEVICE_A_PEERS 8
|
||||
#define WGDEVICE_A_MAX 8
|
||||
|
||||
#define WGPEER_A_UNSPEC 0
|
||||
#define WGPEER_A_PUBLIC_KEY 1
|
||||
#define WGPEER_A_PRESHARED_KEY 2
|
||||
#define WGPEER_A_FLAGS 3
|
||||
#define WGPEER_A_ENDPOINT 4
|
||||
#define WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL 5
|
||||
#define WGPEER_A_LAST_HANDSHAKE_TIME 6
|
||||
#define WGPEER_A_RX_BYTES 7
|
||||
#define WGPEER_A_TX_BYTES 8
|
||||
#define WGPEER_A_ALLOWEDIPS 9
|
||||
#define WGPEER_A_MAX 9
|
||||
|
||||
#define WGALLOWEDIP_A_UNSPEC 0
|
||||
#define WGALLOWEDIP_A_FAMILY 1
|
||||
#define WGALLOWEDIP_A_IPADDR 2
|
||||
#define WGALLOWEDIP_A_CIDR_MASK 3
|
||||
#define WGALLOWEDIP_A_MAX 3
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#define _NMLOG_PREFIX_NAME "platform-linux"
|
||||
#define _NMLOG_DOMAIN LOGD_PLATFORM
|
||||
#define _NMLOG2_DOMAIN LOGD_PLATFORM
|
||||
@@ -482,6 +516,18 @@ _support_rta_pref_get (void)
|
||||
return _support_rta_pref >= 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Support Generic Netlink family
|
||||
*****************************************************************************/
|
||||
|
||||
static int
|
||||
_support_genl_family (struct nl_sock *genl, const char *name)
|
||||
{
|
||||
int family_id = genl_ctrl_resolve (genl, name);
|
||||
_LOG2D ("kernel-support: genetlink: %s: %s", name, family_id ? "detected" : "not detected");
|
||||
return family_id;
|
||||
}
|
||||
|
||||
/******************************************************************
|
||||
* Various utilities
|
||||
******************************************************************/
|
||||
@@ -563,6 +609,7 @@ static const LinkDesc linktypes[] = {
|
||||
{ NM_LINK_TYPE_VETH, "veth", "veth", NULL },
|
||||
{ NM_LINK_TYPE_VLAN, "vlan", "vlan", "vlan" },
|
||||
{ NM_LINK_TYPE_VXLAN, "vxlan", "vxlan", "vxlan" },
|
||||
{ NM_LINK_TYPE_WIREGUARD, "wireguard", "wireguard", "wireguard" },
|
||||
|
||||
{ NM_LINK_TYPE_BRIDGE, "bridge", "bridge", "bridge" },
|
||||
{ NM_LINK_TYPE_BOND, "bond", "bond", "bond" },
|
||||
@@ -1760,6 +1807,197 @@ _parse_lnk_vxlan (const char *kind, struct nlattr *info_data)
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/* Context to build a NMPObjectLnkWireguard instance.
|
||||
* GArray wrappers are discarded after processing all netlink messages. */
|
||||
struct _wireguard_device_buf {
|
||||
NMPObject *obj;
|
||||
GArray *peers;
|
||||
GArray *allowedips;
|
||||
};
|
||||
|
||||
static int
|
||||
_wireguard_update_from_allowedips_nla (struct _wireguard_device_buf *buf,
|
||||
struct nlattr *allowedip_attr)
|
||||
{
|
||||
static const struct nla_policy allowedip_policy[WGALLOWEDIP_A_MAX + 1] = {
|
||||
[WGALLOWEDIP_A_FAMILY] = { .type = NLA_U16 },
|
||||
[WGALLOWEDIP_A_IPADDR] = { .minlen = sizeof (struct in_addr) },
|
||||
[WGALLOWEDIP_A_CIDR_MASK] = { .type = NLA_U8 },
|
||||
};
|
||||
struct nlattr *tba[WGALLOWEDIP_A_MAX + 1];
|
||||
NMWireguardPeer *peer = &g_array_index (buf->peers, NMWireguardPeer, buf->peers->len - 1);
|
||||
NMWireguardAllowedIP *allowedip;
|
||||
NMWireguardAllowedIP new_allowedip = {0};
|
||||
int addr_len;
|
||||
int ret;
|
||||
|
||||
ret = nla_parse_nested (tba, WGALLOWEDIP_A_MAX, allowedip_attr, allowedip_policy);
|
||||
if (ret)
|
||||
goto errout;
|
||||
|
||||
g_array_append_val (buf->allowedips, new_allowedip);
|
||||
allowedip = &g_array_index (buf->allowedips, NMWireguardAllowedIP, buf->allowedips->len - 1);
|
||||
peer->allowedips_len++;
|
||||
|
||||
if (tba[WGALLOWEDIP_A_FAMILY])
|
||||
allowedip->family = nla_get_u16 (tba[WGALLOWEDIP_A_FAMILY]);
|
||||
|
||||
if (allowedip->family == AF_INET)
|
||||
addr_len = sizeof (in_addr_t);
|
||||
else if (allowedip->family == AF_INET6)
|
||||
addr_len = sizeof (struct in6_addr);
|
||||
else {
|
||||
ret = -EAFNOSUPPORT;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
ret = -EMSGSIZE;
|
||||
_check_addr_or_errout (tba, WGALLOWEDIP_A_IPADDR, addr_len);
|
||||
if (tba[WGALLOWEDIP_A_IPADDR])
|
||||
nla_memcpy (&allowedip->ip, tba[WGALLOWEDIP_A_IPADDR], addr_len);
|
||||
|
||||
if (tba[WGALLOWEDIP_A_CIDR_MASK])
|
||||
allowedip->mask = nla_get_u8 (tba[WGALLOWEDIP_A_CIDR_MASK]);
|
||||
|
||||
ret = 0;
|
||||
errout:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
_wireguard_update_from_peers_nla (struct _wireguard_device_buf *buf,
|
||||
struct nlattr *peer_attr)
|
||||
{
|
||||
static const struct nla_policy peer_policy[WGPEER_A_MAX + 1] = {
|
||||
[WGPEER_A_PUBLIC_KEY] = { .minlen = NM_WG_PUBLIC_KEY_LEN },
|
||||
[WGPEER_A_PRESHARED_KEY] = { },
|
||||
[WGPEER_A_FLAGS] = { .type = NLA_U32 },
|
||||
[WGPEER_A_ENDPOINT] = { },
|
||||
[WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL] = { .type = NLA_U16 },
|
||||
[WGPEER_A_LAST_HANDSHAKE_TIME] = { },
|
||||
[WGPEER_A_RX_BYTES] = { .type = NLA_U64 },
|
||||
[WGPEER_A_TX_BYTES] = { .type = NLA_U64 },
|
||||
[WGPEER_A_ALLOWEDIPS] = { .type = NLA_NESTED },
|
||||
};
|
||||
struct nlattr *tbp[WGPEER_A_MAX + 1];
|
||||
NMWireguardPeer * const last = buf->peers->len ? &g_array_index (buf->peers, NMWireguardPeer, buf->peers->len - 1) : NULL;
|
||||
NMWireguardPeer *peer;
|
||||
NMWireguardPeer new_peer = {0};
|
||||
int ret;
|
||||
|
||||
if (nla_parse_nested (tbp, WGPEER_A_MAX, peer_attr, peer_policy)) {
|
||||
ret = -EBADMSG;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
if (!tbp[WGPEER_A_PUBLIC_KEY]) {
|
||||
ret = -EBADMSG;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* a peer with the same public key as last peer is just a continuation for extra AllowedIPs */
|
||||
if (last && !memcmp (nla_data (tbp[WGPEER_A_PUBLIC_KEY]), last->public_key, sizeof (last->public_key))) {
|
||||
peer = last;
|
||||
goto add_allowedips;
|
||||
}
|
||||
|
||||
/* otherwise, start a new peer */
|
||||
g_array_append_val (buf->peers, new_peer);
|
||||
peer = &g_array_index (buf->peers, NMWireguardPeer, buf->peers->len - 1);
|
||||
|
||||
nla_memcpy (&peer->public_key, tbp[WGPEER_A_PUBLIC_KEY], sizeof (peer->public_key));
|
||||
|
||||
if (tbp[WGPEER_A_PRESHARED_KEY])
|
||||
nla_memcpy (&peer->preshared_key, tbp[WGPEER_A_PRESHARED_KEY], sizeof (peer->preshared_key));
|
||||
if (tbp[WGPEER_A_ENDPOINT]) {
|
||||
struct sockaddr *addr = nla_data (tbp[WGPEER_A_ENDPOINT]);
|
||||
if (addr->sa_family == AF_INET)
|
||||
nla_memcpy (&peer->endpoint.addr4, tbp[WGPEER_A_ENDPOINT], sizeof (peer->endpoint.addr4));
|
||||
else if (addr->sa_family == AF_INET6)
|
||||
nla_memcpy (&peer->endpoint.addr6, tbp[WGPEER_A_ENDPOINT], sizeof (peer->endpoint.addr6));
|
||||
}
|
||||
if (tbp[WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL])
|
||||
peer->persistent_keepalive_interval = nla_get_u64 (tbp[WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL]);
|
||||
if (tbp[WGPEER_A_LAST_HANDSHAKE_TIME])
|
||||
nla_memcpy (&peer->last_handshake_time, tbp[WGPEER_A_LAST_HANDSHAKE_TIME], sizeof (peer->last_handshake_time));
|
||||
if (tbp[WGPEER_A_RX_BYTES])
|
||||
peer->rx_bytes = nla_get_u64 (tbp[WGPEER_A_RX_BYTES]);
|
||||
if (tbp[WGPEER_A_TX_BYTES])
|
||||
peer->tx_bytes = nla_get_u64 (tbp[WGPEER_A_TX_BYTES]);
|
||||
|
||||
peer->allowedips = NULL;
|
||||
peer->allowedips_len = 0;
|
||||
|
||||
add_allowedips:
|
||||
if (tbp[WGPEER_A_ALLOWEDIPS]) {
|
||||
struct nlattr *attr;
|
||||
int rem;
|
||||
|
||||
nla_for_each_nested (attr, tbp[WGPEER_A_ALLOWEDIPS], rem) {
|
||||
ret = _wireguard_update_from_allowedips_nla (buf, attr);
|
||||
if (ret)
|
||||
goto errout;
|
||||
}
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
errout:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
_wireguard_get_device_cb (struct nl_msg *msg, void *arg)
|
||||
{
|
||||
static const struct nla_policy device_policy[WGDEVICE_A_MAX + 1] = {
|
||||
[WGDEVICE_A_IFINDEX] = { .type = NLA_U32 },
|
||||
[WGDEVICE_A_IFNAME] = { .type = NLA_NUL_STRING, .maxlen = IFNAMSIZ },
|
||||
[WGDEVICE_A_PRIVATE_KEY] = { },
|
||||
[WGDEVICE_A_PUBLIC_KEY] = { },
|
||||
[WGDEVICE_A_FLAGS] = { .type = NLA_U32 },
|
||||
[WGDEVICE_A_LISTEN_PORT] = { .type = NLA_U16 },
|
||||
[WGDEVICE_A_FWMARK] = { .type = NLA_U32 },
|
||||
[WGDEVICE_A_PEERS] = { .type = NLA_NESTED },
|
||||
};
|
||||
struct _wireguard_device_buf *buf = arg;
|
||||
struct nlattr *tbd[WGDEVICE_A_MAX + 1];
|
||||
NMPlatformLnkWireguard *props = &buf->obj->lnk_wireguard;
|
||||
struct nlmsghdr *nlh = nlmsg_hdr (msg);
|
||||
int ret;
|
||||
|
||||
ret = genlmsg_parse (nlh, 0, tbd, WGDEVICE_A_MAX, device_policy);
|
||||
if (ret)
|
||||
goto errout;
|
||||
|
||||
if (tbd[WGDEVICE_A_PRIVATE_KEY])
|
||||
nla_memcpy (props->private_key, tbd[WGDEVICE_A_PRIVATE_KEY], sizeof (props->private_key));
|
||||
if (tbd[WGDEVICE_A_PUBLIC_KEY])
|
||||
nla_memcpy (props->public_key, tbd[WGDEVICE_A_PUBLIC_KEY], sizeof (props->public_key));
|
||||
if (tbd[WGDEVICE_A_LISTEN_PORT])
|
||||
props->listen_port = nla_get_u16 (tbd[WGDEVICE_A_LISTEN_PORT]);
|
||||
if (tbd[WGDEVICE_A_FWMARK])
|
||||
props->fwmark = nla_get_u32 (tbd[WGDEVICE_A_FWMARK]);
|
||||
|
||||
if (tbd[WGDEVICE_A_PEERS]) {
|
||||
struct nlattr *attr;
|
||||
int rem;
|
||||
|
||||
nla_for_each_nested (attr, tbd[WGDEVICE_A_PEERS], rem) {
|
||||
ret = _wireguard_update_from_peers_nla (buf, attr);
|
||||
if (ret)
|
||||
goto errout;
|
||||
}
|
||||
}
|
||||
|
||||
return NL_OK;
|
||||
errout:
|
||||
return NL_SKIP;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_wireguard_get_link_properties (NMPlatform *platform, const NMPlatformLink *link, NMPObject *obj);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/* Copied and heavily modified from libnl3's link_msg_parser(). */
|
||||
static NMPObject *
|
||||
_new_from_nl_link (NMPlatform *platform, const NMPCache *cache, struct nlmsghdr *nlh, gboolean id_only)
|
||||
@@ -1977,6 +2215,8 @@ _new_from_nl_link (NMPlatform *platform, const NMPCache *cache, struct nlmsghdr
|
||||
need_ext_data = TRUE;
|
||||
lnk_data_complete_from_cache = FALSE;
|
||||
break;
|
||||
case NM_LINK_TYPE_WIREGUARD:
|
||||
break;
|
||||
default:
|
||||
lnk_data_complete_from_cache = FALSE;
|
||||
break;
|
||||
@@ -2027,6 +2267,26 @@ _new_from_nl_link (NMPlatform *platform, const NMPCache *cache, struct nlmsghdr
|
||||
}
|
||||
}
|
||||
|
||||
if (obj->link.type == NM_LINK_TYPE_WIREGUARD) {
|
||||
nm_auto_nmpobj NMPObject *lnk_data_now;
|
||||
|
||||
/* The WireGuard kernel module does not yet send link update
|
||||
* notifications, so we don't actually update the cache. For
|
||||
* now, always refetch link data here. */
|
||||
lnk_data_now = nmp_object_new (NMP_OBJECT_TYPE_LNK_WIREGUARD, NULL);
|
||||
if (!_wireguard_get_link_properties (platform, &obj->link, lnk_data_now)) {
|
||||
_LOGE ("wireguard: %d %s: failed to get properties",
|
||||
obj->link.ifindex,
|
||||
obj->link.name ?: "");
|
||||
}
|
||||
|
||||
if (lnk_data && nmp_object_cmp (lnk_data, lnk_data_now))
|
||||
nmp_object_unref (g_steal_pointer (&lnk_data));
|
||||
|
||||
if (!lnk_data)
|
||||
lnk_data = (NMPObject *) nmp_object_ref (lnk_data_now);
|
||||
}
|
||||
|
||||
obj->_link.netlink.lnk = lnk_data;
|
||||
|
||||
if (need_ext_data && obj->_link.ext_data == NULL) {
|
||||
@@ -3143,6 +3403,8 @@ typedef struct {
|
||||
|
||||
gint is_handling;
|
||||
} delayed_action;
|
||||
|
||||
int wireguard_family_id;
|
||||
} NMLinuxPlatformPrivate;
|
||||
|
||||
struct _NMLinuxPlatform {
|
||||
@@ -6088,6 +6350,69 @@ link_release (NMPlatform *platform, int master, int slave)
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static gboolean
|
||||
_wireguard_get_link_properties (NMPlatform *platform, const NMPlatformLink *link, NMPObject *obj)
|
||||
{
|
||||
NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform);
|
||||
nm_auto_nlmsg struct nl_msg *msg = NULL;
|
||||
struct _wireguard_device_buf buf = {
|
||||
.obj = obj,
|
||||
.peers = g_array_new (FALSE, FALSE, sizeof (NMWireguardPeer)),
|
||||
.allowedips = g_array_new (FALSE, FALSE, sizeof (NMWireguardAllowedIP)),
|
||||
};
|
||||
struct nl_cb cb = {
|
||||
.valid_cb = _wireguard_get_device_cb,
|
||||
.valid_arg = &buf,
|
||||
};
|
||||
guint i, j;
|
||||
|
||||
if (!priv->wireguard_family_id)
|
||||
priv->wireguard_family_id = _support_genl_family (priv->genl, "wireguard");
|
||||
|
||||
if (!priv->wireguard_family_id) {
|
||||
_LOG2W ("kernel support not available for wireguard link %s", link->name);
|
||||
goto err;
|
||||
}
|
||||
|
||||
msg = nlmsg_alloc ();
|
||||
if (!msg)
|
||||
goto err;
|
||||
|
||||
if (!genlmsg_put (msg, NL_AUTO_PORT, NL_AUTO_SEQ, priv->wireguard_family_id,
|
||||
0, NLM_F_DUMP, WG_CMD_GET_DEVICE, 1))
|
||||
goto err;
|
||||
|
||||
NLA_PUT_U32 (msg, WGDEVICE_A_IFINDEX, link->ifindex);
|
||||
|
||||
if (nl_send_auto (priv->genl, msg) < 0)
|
||||
goto err;
|
||||
|
||||
if (nl_recvmsgs (priv->genl, &cb) < 0)
|
||||
goto err;
|
||||
|
||||
/* have each peer point to its own chunk of the allowedips buffer */
|
||||
for (i = 0, j = 0; i < buf.peers->len; i++) {
|
||||
NMWireguardPeer *p = &g_array_index (buf.peers, NMWireguardPeer, i);
|
||||
p->allowedips = &g_array_index (buf.allowedips, NMWireguardAllowedIP, j);
|
||||
j += p->allowedips_len;
|
||||
}
|
||||
/* drop the wrapper (but also the buffer if no peer points to it) */
|
||||
g_array_free (buf.allowedips, buf.peers->len ? FALSE : TRUE);
|
||||
|
||||
obj->_lnk_wireguard.peers_len = buf.peers->len;
|
||||
obj->_lnk_wireguard.peers = (NMWireguardPeer *) g_array_free (buf.peers, FALSE);
|
||||
|
||||
return TRUE;
|
||||
|
||||
err:
|
||||
nla_put_failure:
|
||||
g_array_free (buf.peers, TRUE);
|
||||
g_array_free (buf.allowedips, TRUE);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static gboolean
|
||||
_infiniband_partition_action (NMPlatform *platform,
|
||||
InfinibandAction action,
|
||||
|
@@ -27,6 +27,8 @@
|
||||
#include <unistd.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netdb.h>
|
||||
#include <string.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/if_tun.h>
|
||||
@@ -1932,6 +1934,12 @@ nm_platform_link_get_lnk_vxlan (NMPlatform *self, int ifindex, const NMPlatformL
|
||||
return _link_get_lnk (self, ifindex, NM_LINK_TYPE_VXLAN, out_link);
|
||||
}
|
||||
|
||||
const NMPlatformLnkWireguard *
|
||||
nm_platform_link_get_lnk_wireguard (NMPlatform *self, int ifindex, const NMPlatformLink **out_link)
|
||||
{
|
||||
return _link_get_lnk (self, ifindex, NM_LINK_TYPE_WIREGUARD, out_link);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
@@ -5463,6 +5471,100 @@ nm_platform_lnk_vxlan_to_string (const NMPlatformLnkVxlan *lnk, char *buf, gsize
|
||||
return buf;
|
||||
}
|
||||
|
||||
const char *
|
||||
nm_platform_wireguard_peer_to_string (const NMWireguardPeer *peer, char *buf, gsize len)
|
||||
{
|
||||
gs_free char *public_b64 = NULL;
|
||||
char s_address[INET6_ADDRSTRLEN] = {0};
|
||||
char s_endpoint[INET6_ADDRSTRLEN + NI_MAXSERV + sizeof("endpoint []:") + 1] = {0};
|
||||
guint8 nonzero_key = 0;
|
||||
gsize i;
|
||||
|
||||
nm_utils_to_string_buffer_init (&buf, &len);
|
||||
|
||||
if (peer->endpoint.addr.sa_family == AF_INET || peer->endpoint.addr.sa_family == AF_INET6) {
|
||||
char s_service[NI_MAXSERV];
|
||||
socklen_t addr_len = 0;
|
||||
|
||||
if (peer->endpoint.addr.sa_family == AF_INET)
|
||||
addr_len = sizeof (struct sockaddr_in);
|
||||
else if (peer->endpoint.addr.sa_family == AF_INET6)
|
||||
addr_len = sizeof (struct sockaddr_in6);
|
||||
if (!getnameinfo (&peer->endpoint.addr, addr_len, s_address, sizeof(s_address), s_service, sizeof(s_service), NI_DGRAM | NI_NUMERICSERV | NI_NUMERICHOST)) {
|
||||
if (peer->endpoint.addr.sa_family == AF_INET6 && strchr (s_address, ':'))
|
||||
g_snprintf(s_endpoint, sizeof (s_endpoint), "endpoint [%s]:%s ", s_address, s_service);
|
||||
else
|
||||
g_snprintf(s_endpoint, sizeof (s_endpoint), "endpoint %s:%s ", s_address, s_service);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (i = 0; i < sizeof (peer->preshared_key); i++)
|
||||
nonzero_key |= peer->preshared_key[i];
|
||||
|
||||
public_b64 = g_base64_encode (peer->public_key, sizeof (peer->public_key));
|
||||
|
||||
nm_utils_strbuf_append (&buf, &len,
|
||||
"{ "
|
||||
"public_key %s "
|
||||
"%s" /* preshared key indicator */
|
||||
"%s" /* endpoint */
|
||||
"rx %"G_GUINT64_FORMAT" "
|
||||
"tx %"G_GUINT64_FORMAT" "
|
||||
"allowedips (%"G_GSIZE_FORMAT") {",
|
||||
public_b64,
|
||||
nonzero_key ? "preshared_key (hidden) " : "",
|
||||
s_endpoint,
|
||||
peer->rx_bytes,
|
||||
peer->tx_bytes,
|
||||
peer->allowedips_len);
|
||||
|
||||
|
||||
for (i = 0; i < peer->allowedips_len; i++) {
|
||||
NMWireguardAllowedIP *allowedip = &peer->allowedips[i];
|
||||
const char *ret;
|
||||
|
||||
ret = inet_ntop (allowedip->family, &allowedip->ip, s_address, sizeof(s_address));
|
||||
|
||||
nm_utils_strbuf_append (&buf, &len,
|
||||
" %s/%u",
|
||||
ret ? s_address : "<EAFNOSUPPORT>",
|
||||
allowedip->mask);
|
||||
}
|
||||
|
||||
nm_utils_strbuf_append_str (&buf, &len, " } }");
|
||||
return buf;
|
||||
}
|
||||
|
||||
const char *
|
||||
nm_platform_lnk_wireguard_to_string (const NMPlatformLnkWireguard *lnk, char *buf, gsize len)
|
||||
{
|
||||
gs_free char *public_b64 = NULL;
|
||||
guint8 nonzero_key = 0;
|
||||
gsize i;
|
||||
|
||||
if (!nm_utils_to_string_buffer_init_null (lnk, &buf, &len))
|
||||
return buf;
|
||||
|
||||
public_b64 = g_base64_encode (lnk->public_key, sizeof (lnk->public_key));
|
||||
|
||||
for (i = 0; i < sizeof (lnk->private_key); i++)
|
||||
nonzero_key |= lnk->private_key[i];
|
||||
|
||||
g_snprintf (buf, len,
|
||||
"wireguard "
|
||||
"public_key %s "
|
||||
"%s" /* private key indicator */
|
||||
"listen_port %u "
|
||||
"fwmark 0x%x",
|
||||
public_b64,
|
||||
nonzero_key ? "private_key (hidden) " : "",
|
||||
lnk->listen_port,
|
||||
lnk->fwmark);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
/**
|
||||
* nm_platform_ip4_address_to_string:
|
||||
* @route: pointer to NMPlatformIP4Address address structure
|
||||
@@ -6302,6 +6404,27 @@ nm_platform_lnk_vxlan_cmp (const NMPlatformLnkVxlan *a, const NMPlatformLnkVxlan
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
nm_platform_lnk_wireguard_hash_update (const NMPlatformLnkWireguard *obj, NMHashState *h)
|
||||
{
|
||||
nm_hash_update_vals (h,
|
||||
obj->listen_port,
|
||||
obj->fwmark);
|
||||
nm_hash_update (h, obj->private_key, sizeof (obj->private_key));
|
||||
nm_hash_update (h, obj->public_key, sizeof (obj->public_key));
|
||||
}
|
||||
|
||||
int
|
||||
nm_platform_lnk_wireguard_cmp (const NMPlatformLnkWireguard *a, const NMPlatformLnkWireguard *b)
|
||||
{
|
||||
NM_CMP_SELF (a, b);
|
||||
NM_CMP_FIELD (a, b, listen_port);
|
||||
NM_CMP_FIELD (a, b, fwmark);
|
||||
NM_CMP_FIELD_MEMCMP (a, b, private_key);
|
||||
NM_CMP_FIELD_MEMCMP (a, b, public_key);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
nm_platform_ip4_address_hash_update (const NMPlatformIP4Address *obj, NMHashState *h)
|
||||
{
|
||||
|
@@ -732,6 +732,13 @@ typedef struct {
|
||||
bool l3miss:1;
|
||||
} NMPlatformLnkVxlan;
|
||||
|
||||
typedef struct {
|
||||
guint8 private_key[NM_WG_PUBLIC_KEY_LEN];
|
||||
guint8 public_key[NM_WG_PUBLIC_KEY_LEN];
|
||||
guint16 listen_port;
|
||||
guint32 fwmark;
|
||||
} NMPlatformLnkWireguard;
|
||||
|
||||
typedef enum {
|
||||
NM_PLATFORM_LINK_DUPLEX_UNKNOWN,
|
||||
NM_PLATFORM_LINK_DUPLEX_HALF,
|
||||
@@ -1225,6 +1232,7 @@ const NMPlatformLnkSit *nm_platform_link_get_lnk_sit (NMPlatform *self, int ifin
|
||||
const NMPlatformLnkTun *nm_platform_link_get_lnk_tun (NMPlatform *self, int ifindex, const NMPlatformLink **out_link);
|
||||
const NMPlatformLnkVlan *nm_platform_link_get_lnk_vlan (NMPlatform *self, int ifindex, const NMPlatformLink **out_link);
|
||||
const NMPlatformLnkVxlan *nm_platform_link_get_lnk_vxlan (NMPlatform *self, int ifindex, const NMPlatformLink **out_link);
|
||||
const NMPlatformLnkWireguard *nm_platform_link_get_lnk_wireguard (NMPlatform *self, int ifindex, const NMPlatformLink **out_link);
|
||||
|
||||
NMPlatformError nm_platform_link_vlan_add (NMPlatform *self,
|
||||
const char *name,
|
||||
@@ -1419,6 +1427,7 @@ const char *nm_platform_lnk_sit_to_string (const NMPlatformLnkSit *lnk, char *bu
|
||||
const char *nm_platform_lnk_tun_to_string (const NMPlatformLnkTun *lnk, char *buf, gsize len);
|
||||
const char *nm_platform_lnk_vlan_to_string (const NMPlatformLnkVlan *lnk, char *buf, gsize len);
|
||||
const char *nm_platform_lnk_vxlan_to_string (const NMPlatformLnkVxlan *lnk, char *buf, gsize len);
|
||||
const char *nm_platform_lnk_wireguard_to_string (const NMPlatformLnkWireguard *lnk, char *buf, gsize len);
|
||||
const char *nm_platform_ip4_address_to_string (const NMPlatformIP4Address *address, char *buf, gsize len);
|
||||
const char *nm_platform_ip6_address_to_string (const NMPlatformIP6Address *address, char *buf, gsize len);
|
||||
const char *nm_platform_ip4_route_to_string (const NMPlatformIP4Route *route, char *buf, gsize len);
|
||||
@@ -1432,6 +1441,10 @@ const char *nm_platform_vlan_qos_mapping_to_string (const char *name,
|
||||
char *buf,
|
||||
gsize len);
|
||||
|
||||
const char *nm_platform_wireguard_peer_to_string (const NMWireguardPeer *peer,
|
||||
char *buf,
|
||||
gsize len);
|
||||
|
||||
int nm_platform_link_cmp (const NMPlatformLink *a, const NMPlatformLink *b);
|
||||
int nm_platform_lnk_gre_cmp (const NMPlatformLnkGre *a, const NMPlatformLnkGre *b);
|
||||
int nm_platform_lnk_infiniband_cmp (const NMPlatformLnkInfiniband *a, const NMPlatformLnkInfiniband *b);
|
||||
@@ -1443,6 +1456,7 @@ int nm_platform_lnk_sit_cmp (const NMPlatformLnkSit *a, const NMPlatformLnkSit *
|
||||
int nm_platform_lnk_tun_cmp (const NMPlatformLnkTun *a, const NMPlatformLnkTun *b);
|
||||
int nm_platform_lnk_vlan_cmp (const NMPlatformLnkVlan *a, const NMPlatformLnkVlan *b);
|
||||
int nm_platform_lnk_vxlan_cmp (const NMPlatformLnkVxlan *a, const NMPlatformLnkVxlan *b);
|
||||
int nm_platform_lnk_wireguard_cmp (const NMPlatformLnkWireguard *a, const NMPlatformLnkWireguard *b);
|
||||
int nm_platform_ip4_address_cmp (const NMPlatformIP4Address *a, const NMPlatformIP4Address *b);
|
||||
int nm_platform_ip6_address_cmp (const NMPlatformIP6Address *a, const NMPlatformIP6Address *b);
|
||||
|
||||
@@ -1479,6 +1493,7 @@ void nm_platform_lnk_sit_hash_update (const NMPlatformLnkSit *obj, NMHashState *
|
||||
void nm_platform_lnk_tun_hash_update (const NMPlatformLnkTun *obj, NMHashState *h);
|
||||
void nm_platform_lnk_vlan_hash_update (const NMPlatformLnkVlan *obj, NMHashState *h);
|
||||
void nm_platform_lnk_vxlan_hash_update (const NMPlatformLnkVxlan *obj, NMHashState *h);
|
||||
void nm_platform_lnk_wireguard_hash_update (const NMPlatformLnkWireguard *obj, NMHashState *h);
|
||||
|
||||
void nm_platform_qdisc_hash_update (const NMPlatformQdisc *obj, NMHashState *h);
|
||||
void nm_platform_tfilter_hash_update (const NMPlatformTfilter *obj, NMHashState *h);
|
||||
|
@@ -346,6 +346,122 @@ _vlan_xgress_qos_mappings_cpy (guint *dst_n_map,
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
_wireguard_peers_hash_update (gsize n_peers,
|
||||
const NMWireguardPeer *peers,
|
||||
NMHashState *h)
|
||||
{
|
||||
gsize i, j;
|
||||
|
||||
nm_hash_update_val (h, n_peers);
|
||||
for (i = 0; i < n_peers; i++) {
|
||||
const NMWireguardPeer *p = &peers[i];
|
||||
|
||||
nm_hash_update (h, p->public_key, sizeof (p->public_key));
|
||||
nm_hash_update (h, p->preshared_key, sizeof (p->preshared_key));
|
||||
nm_hash_update_vals (h,
|
||||
p->persistent_keepalive_interval,
|
||||
p->allowedips_len,
|
||||
p->rx_bytes,
|
||||
p->tx_bytes,
|
||||
p->last_handshake_time.tv_sec,
|
||||
p->last_handshake_time.tv_nsec,
|
||||
p->endpoint.addr.sa_family);
|
||||
|
||||
if (p->endpoint.addr.sa_family == AF_INET)
|
||||
nm_hash_update_val (h, p->endpoint.addr4);
|
||||
else if (p->endpoint.addr.sa_family == AF_INET6)
|
||||
nm_hash_update_val (h, p->endpoint.addr6);
|
||||
else if (p->endpoint.addr.sa_family != AF_UNSPEC)
|
||||
g_assert_not_reached ();
|
||||
|
||||
for (j = 0; j < p->allowedips_len; j++) {
|
||||
const NMWireguardAllowedIP *ip = &p->allowedips[j];
|
||||
|
||||
nm_hash_update_vals (h, ip->family, ip->mask);
|
||||
|
||||
if (ip->family == AF_INET)
|
||||
nm_hash_update_val (h, ip->ip.addr4);
|
||||
else if (ip->family == AF_INET6)
|
||||
nm_hash_update_val (h, ip->ip.addr6);
|
||||
else if (ip->family != AF_UNSPEC)
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
_wireguard_peers_cmp (gsize n_peers,
|
||||
const NMWireguardPeer *p1,
|
||||
const NMWireguardPeer *p2)
|
||||
{
|
||||
gsize i, j;
|
||||
|
||||
for (i = 0; i < n_peers; i++) {
|
||||
const NMWireguardPeer *a = &p1[i];
|
||||
const NMWireguardPeer *b = &p2[i];
|
||||
|
||||
NM_CMP_FIELD (a, b, last_handshake_time.tv_sec);
|
||||
NM_CMP_FIELD (a, b, last_handshake_time.tv_nsec);
|
||||
NM_CMP_FIELD (a, b, rx_bytes);
|
||||
NM_CMP_FIELD (a, b, tx_bytes);
|
||||
NM_CMP_FIELD (a, b, allowedips_len);
|
||||
NM_CMP_FIELD (a, b, persistent_keepalive_interval);
|
||||
NM_CMP_FIELD (a, b, endpoint.addr.sa_family);
|
||||
NM_CMP_FIELD_MEMCMP (a, b, public_key);
|
||||
NM_CMP_FIELD_MEMCMP (a, b, preshared_key);
|
||||
|
||||
if (a->endpoint.addr.sa_family == AF_INET)
|
||||
NM_CMP_FIELD_MEMCMP (a, b, endpoint.addr4);
|
||||
else if (a->endpoint.addr.sa_family == AF_INET6)
|
||||
NM_CMP_FIELD_MEMCMP (a, b, endpoint.addr6);
|
||||
else if (a->endpoint.addr.sa_family != AF_UNSPEC)
|
||||
g_assert_not_reached ();
|
||||
|
||||
for (j = 0; j < a->allowedips_len; j++) {
|
||||
const NMWireguardAllowedIP *aip = &a->allowedips[j];
|
||||
const NMWireguardAllowedIP *bip = &b->allowedips[j];
|
||||
|
||||
NM_CMP_FIELD (aip, bip, family);
|
||||
NM_CMP_FIELD (aip, bip, mask);
|
||||
|
||||
if (aip->family == AF_INET)
|
||||
NM_CMP_FIELD_MEMCMP (&aip->ip, &bip->ip, addr4);
|
||||
else if (aip->family == AF_INET6)
|
||||
NM_CMP_FIELD_MEMCMP (&aip->ip, &bip->ip, addr6);
|
||||
else if (aip->family != AF_UNSPEC)
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
_wireguard_peers_cpy (gsize *dst_n_peers,
|
||||
NMWireguardPeer **dst_peers,
|
||||
gsize src_n_peers,
|
||||
const NMWireguardPeer *src_peers)
|
||||
{
|
||||
if (src_n_peers == 0) {
|
||||
g_clear_pointer (dst_peers, g_free);
|
||||
*dst_n_peers = 0;
|
||||
} else if ( src_n_peers != *dst_n_peers
|
||||
|| _wireguard_peers_cmp (src_n_peers, *dst_peers, src_peers) != 0) {
|
||||
gsize i;
|
||||
g_clear_pointer (dst_peers, g_free);
|
||||
*dst_n_peers = src_n_peers;
|
||||
if (src_n_peers > 0)
|
||||
*dst_peers = g_memdup (src_peers, sizeof (*src_peers) * src_n_peers);
|
||||
for (i = 0; i < src_n_peers; i++) {
|
||||
dst_peers[i]->allowedips = g_memdup (src_peers[i].allowedips, sizeof (src_peers[i].allowedips) * src_peers[i].allowedips_len);
|
||||
dst_peers[i]->allowedips_len = src_peers[i].allowedips_len;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static const char *
|
||||
_link_get_driver (struct udev_device *udevice, const char *kind, int ifindex)
|
||||
{
|
||||
@@ -470,6 +586,15 @@ _vt_cmd_obj_dispose_lnk_vlan (NMPObject *obj)
|
||||
g_free ((gpointer) obj->_lnk_vlan.egress_qos_map);
|
||||
}
|
||||
|
||||
static void
|
||||
_vt_cmd_obj_dispose_lnk_wireguard (NMPObject *obj)
|
||||
{
|
||||
if (obj->_lnk_wireguard.peers_len)
|
||||
g_free (obj->_lnk_wireguard.peers[0].allowedips);
|
||||
|
||||
g_free (obj->_lnk_wireguard.peers);
|
||||
}
|
||||
|
||||
static NMPObject *
|
||||
_nmp_object_new_from_class (const NMPClass *klass)
|
||||
{
|
||||
@@ -724,6 +849,52 @@ _vt_cmd_obj_to_string_lnk_vlan (const NMPObject *obj, NMPObjectToStringMode to_s
|
||||
}
|
||||
}
|
||||
|
||||
static const char *
|
||||
_vt_cmd_obj_to_string_lnk_wireguard (const NMPObject *obj, NMPObjectToStringMode to_string_mode, char *buf, gsize buf_size)
|
||||
{
|
||||
const NMPClass *klass;
|
||||
char buf2[sizeof (_nm_utils_to_string_buffer)];
|
||||
char *b;
|
||||
gsize i, l;
|
||||
|
||||
klass = NMP_OBJECT_GET_CLASS (obj);
|
||||
|
||||
switch (to_string_mode) {
|
||||
case NMP_OBJECT_TO_STRING_ID:
|
||||
g_snprintf (buf, buf_size, "%p", obj);
|
||||
return buf;
|
||||
case NMP_OBJECT_TO_STRING_ALL:
|
||||
b = buf;
|
||||
|
||||
nm_utils_strbuf_append (&b, &buf_size,
|
||||
"[%s,%p,%u,%calive,%cvisible; %s "
|
||||
"peers (%" G_GSIZE_FORMAT ") {",
|
||||
klass->obj_type_name, obj, obj->parent._ref_count,
|
||||
nmp_object_is_alive (obj) ? '+' : '-',
|
||||
nmp_object_is_visible (obj) ? '+' : '-',
|
||||
nmp_object_to_string (obj, NMP_OBJECT_TO_STRING_PUBLIC, buf2, sizeof (buf2)),
|
||||
obj->_lnk_wireguard.peers_len);
|
||||
|
||||
for (i = 0; i < obj->_lnk_wireguard.peers_len; i++) {
|
||||
const NMWireguardPeer *peer = &obj->_lnk_wireguard.peers[i];
|
||||
nm_platform_wireguard_peer_to_string (peer, b, buf_size);
|
||||
l = strlen (b);
|
||||
b += l;
|
||||
buf_size -= l;
|
||||
}
|
||||
|
||||
nm_utils_strbuf_append_str (&b, &buf_size, " }");
|
||||
|
||||
return buf;
|
||||
case NMP_OBJECT_TO_STRING_PUBLIC:
|
||||
NMP_OBJECT_GET_CLASS (obj)->cmd_plobj_to_string (&obj->object, buf, buf_size);
|
||||
|
||||
return buf;
|
||||
default:
|
||||
g_return_val_if_reached ("ERROR");
|
||||
}
|
||||
}
|
||||
|
||||
#define _vt_cmd_plobj_to_string_id(type, plat_type, ...) \
|
||||
static const char * \
|
||||
_vt_cmd_plobj_to_string_id_##type (const NMPlatformObject *_obj, char *buf, gsize buf_len) \
|
||||
@@ -791,6 +962,15 @@ _vt_cmd_obj_hash_update_lnk_vlan (const NMPObject *obj, NMHashState *h)
|
||||
h);
|
||||
}
|
||||
|
||||
static void
|
||||
_vt_cmd_obj_hash_update_lnk_wireguard (const NMPObject *obj, NMHashState *h)
|
||||
{
|
||||
nm_assert (NMP_OBJECT_GET_TYPE (obj) == NMP_OBJECT_TYPE_LNK_WIREGUARD);
|
||||
|
||||
nm_platform_lnk_wireguard_hash_update (&obj->lnk_wireguard, h);
|
||||
_wireguard_peers_hash_update (obj->_lnk_wireguard.peers_len, obj->_lnk_wireguard.peers, h);
|
||||
}
|
||||
|
||||
int
|
||||
nmp_object_cmp (const NMPObject *obj1, const NMPObject *obj2)
|
||||
{
|
||||
@@ -869,6 +1049,21 @@ _vt_cmd_obj_cmp_lnk_vlan (const NMPObject *obj1, const NMPObject *obj2)
|
||||
return c;
|
||||
}
|
||||
|
||||
static int
|
||||
_vt_cmd_obj_cmp_lnk_wireguard (const NMPObject *obj1, const NMPObject *obj2)
|
||||
{
|
||||
int c;
|
||||
|
||||
c = nm_platform_lnk_wireguard_cmp (&obj1->lnk_wireguard, &obj2->lnk_wireguard);
|
||||
if (c)
|
||||
return c;
|
||||
|
||||
if (obj1->_lnk_wireguard.peers_len != obj2->_lnk_wireguard.peers_len)
|
||||
return obj1->_lnk_wireguard.peers_len < obj2->_lnk_wireguard.peers_len ? -1 : 1;
|
||||
|
||||
return _wireguard_peers_cmp(obj1->_lnk_wireguard.peers_len, obj1->_lnk_wireguard.peers, obj2->_lnk_wireguard.peers);
|
||||
}
|
||||
|
||||
/* @src is a const object, which is not entirely correct for link types, where
|
||||
* we increase the ref count for src->_link.udev.device.
|
||||
* Hence, nmp_object_copy() can violate the const promise of @src.
|
||||
@@ -935,6 +1130,14 @@ _vt_cmd_obj_copy_lnk_vlan (NMPObject *dst, const NMPObject *src)
|
||||
src->_lnk_vlan.egress_qos_map);
|
||||
}
|
||||
|
||||
static void
|
||||
_vt_cmd_obj_copy_lnk_wireguard (NMPObject *dst, const NMPObject *src)
|
||||
{
|
||||
dst->lnk_wireguard = src->lnk_wireguard;
|
||||
_wireguard_peers_cpy (&dst->_lnk_wireguard.peers_len, &dst->_lnk_wireguard.peers,
|
||||
src->_lnk_wireguard.peers_len, src->_lnk_wireguard.peers);
|
||||
}
|
||||
|
||||
#define _vt_cmd_plobj_id_copy(type, plat_type, cmd) \
|
||||
static void \
|
||||
_vt_cmd_plobj_id_copy_##type (NMPlatformObject *_dst, const NMPlatformObject *_src) \
|
||||
@@ -2860,5 +3063,21 @@ const NMPClass _nmp_classes[NMP_OBJECT_TYPE_MAX] = {
|
||||
.cmd_plobj_hash_update = (void (*) (const NMPlatformObject *obj, NMHashState *h)) nm_platform_lnk_vxlan_hash_update,
|
||||
.cmd_plobj_cmp = (int (*) (const NMPlatformObject *obj1, const NMPlatformObject *obj2)) nm_platform_lnk_vxlan_cmp,
|
||||
},
|
||||
[NMP_OBJECT_TYPE_LNK_WIREGUARD - 1] = {
|
||||
.parent = DEDUP_MULTI_OBJ_CLASS_INIT(),
|
||||
.obj_type = NMP_OBJECT_TYPE_LNK_WIREGUARD,
|
||||
.sizeof_data = sizeof (NMPObjectLnkWireguard),
|
||||
.sizeof_public = sizeof (NMPlatformLnkWireguard),
|
||||
.obj_type_name = "wireguard",
|
||||
.lnk_link_type = NM_LINK_TYPE_WIREGUARD,
|
||||
.cmd_obj_hash_update = _vt_cmd_obj_hash_update_lnk_wireguard,
|
||||
.cmd_obj_cmp = _vt_cmd_obj_cmp_lnk_wireguard,
|
||||
.cmd_obj_copy = _vt_cmd_obj_copy_lnk_wireguard,
|
||||
.cmd_obj_dispose = _vt_cmd_obj_dispose_lnk_wireguard,
|
||||
.cmd_obj_to_string = _vt_cmd_obj_to_string_lnk_wireguard,
|
||||
.cmd_plobj_to_string = (const char *(*) (const NMPlatformObject *obj, char *buf, gsize len)) nm_platform_lnk_wireguard_to_string,
|
||||
.cmd_plobj_hash_update = (void (*) (const NMPlatformObject *obj, NMHashState *h)) nm_platform_lnk_vlan_hash_update,
|
||||
.cmd_plobj_cmp = (int (*) (const NMPlatformObject *obj1, const NMPlatformObject *obj2)) nm_platform_lnk_vlan_cmp,
|
||||
},
|
||||
};
|
||||
|
||||
|
@@ -216,6 +216,13 @@ typedef struct {
|
||||
NMPlatformLnkVxlan _public;
|
||||
} NMPObjectLnkVxlan;
|
||||
|
||||
typedef struct {
|
||||
NMPlatformLnkWireguard _public;
|
||||
|
||||
gsize peers_len;
|
||||
NMWireguardPeer *peers;
|
||||
} NMPObjectLnkWireguard;
|
||||
|
||||
typedef struct {
|
||||
NMPlatformIP4Address _public;
|
||||
} NMPObjectIP4Address;
|
||||
@@ -281,6 +288,9 @@ struct _NMPObject {
|
||||
NMPlatformLnkVxlan lnk_vxlan;
|
||||
NMPObjectLnkVxlan _lnk_vxlan;
|
||||
|
||||
NMPlatformLnkWireguard lnk_wireguard;
|
||||
NMPObjectLnkWireguard _lnk_wireguard;
|
||||
|
||||
NMPlatformIPAddress ip_address;
|
||||
NMPlatformIPXAddress ipx_address;
|
||||
NMPlatformIP4Address ip4_address;
|
||||
|
Reference in New Issue
Block a user