On Wed, 2018-03-14 at 00:03 +0000, Javier Arteaga wrote:
Add support for a new wireguard link type to the platform code. For now this only covers querying existing links via Generic Netlink and parsing them into platform objects. --- src/nm-types.h | 5 + src/platform/nm-linux-platform.c | 250 +++++++++++++++++++++++++++++++++++++++ src/platform/nm-platform.c | 97 +++++++++++++++ src/platform/nm-platform.h | 44 +++++++ src/platform/nmp-object.c | 25 ++++ src/platform/nmp-object.h | 21 ++++ 6 files changed, 442 insertions(+) diff --git a/src/nm-types.h b/src/nm-types.h index 239202cf4..d44cd0047 100644 --- a/src/nm-types.h +++ b/src/nm-types.h @@ -162,6 +162,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, @@ -193,6 +194,10 @@ typedef enum { NMP_OBJECT_TYPE_LNK_SIT, NMP_OBJECT_TYPE_LNK_VLAN, NMP_OBJECT_TYPE_LNK_VXLAN, + NMP_OBJECT_TYPE_LNK_WIREGUARD, + + NMP_OBJECT_TYPE_WIREGUARD_PEER, + NMP_OBJECT_TYPE_WIREGUARD_ALLOWEDIP,
You ask whether peer/allowed-ip should be their own NMPObject implementations. Maybe, but it's not stringend. For example, NMPObjectLnkVlan embeds a pointer to the egress-qos-map, and these map items are not individual "objects", they are just structs in an C-array. -- note that NMVlanQosMapping is not really more complex then NMPlatformWireguardAllowedIP. E.g. https://cgit.freedesktop.org/NetworkManager/NetworkManager/tree/src/platform/nm-linux-platform.c?id=167e42a87e97ed7fb26a4263c22f1774716ac51b#n1475 Note that most NMPObject implementations are plain struct. The fact that NMObjectLnkVlan is not, requires it to implement a special clone/destroy function and special equal/hash. https://cgit.freedesktop.org/NetworkManager/NetworkManager/tree/src/platform/nmp-object.c?id=167e42a87e97ed7fb26a4263c22f1774716ac51b#n2783 I think having them a separate object makes sense if you need things like: - compare/hash individual instances - to-string individual instances - share one instance (in general, NMPObject instances are supposed not to be changed after being created and shared (immutable) by taking references. Since NMPlatformWireguardAllowedIP and NMPlatformWireguardPeer embed a CList item, they cannot be really shared either. I tend to think they should not be own objects. If they are their own NMPObject instances, they maybe should not be linked via an embedded CList, beause it means they cannot be shared, which is a bit unusual for these objects. When receiving these objects, you also commonly get them all in one go, like for the VLAN egress-qos-map. That is another reason why it doesn't make much sense to have them individual objects. You can just allocate one large array and put all the parsed structs inside.
__NMP_OBJECT_TYPE_LAST, NMP_OBJECT_TYPE_MAX = __NMP_OBJECT_TYPE_LAST - 1, diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm- linux-platform.c index f29ee03e6..eb73858bd 100644 --- a/src/platform/nm-linux-platform.c +++ b/src/platform/nm-linux-platform.c @@ -161,6 +161,40 @@ G_STATIC_ASSERT (RTA_MAX == (__RTA_MAX - 1)); /******************************************************************* **********/ +#define WG_CMD_GET_DEVICE 0 +#define WG_CMD_SET_DEVICE 1 + +#define IFLA_WG_DEVICE_UNSPEC 0 +#define IFLA_WG_DEVICE_IFINDEX 1 +#define IFLA_WG_DEVICE_IFNAME 2 +#define IFLA_WG_DEVICE_PRIVATE_KEY 3 +#define IFLA_WG_DEVICE_PUBLIC_KEY 4 +#define IFLA_WG_DEVICE_FLAGS 5 +#define IFLA_WG_DEVICE_LISTEN_PORT 6 +#define IFLA_WG_DEVICE_FWMARK 7 +#define IFLA_WG_DEVICE_PEERS 8 +#define __IFLA_WG_DEVICE_MAX 9 + +#define IFLA_WG_PEER_UNSPEC 0 +#define IFLA_WG_PEER_PUBLIC_KEY 1 +#define IFLA_WG_PEER_PRESHARED_KEY 2 +#define IFLA_WG_PEER_FLAGS 3 +#define IFLA_WG_PEER_ENDPOINT 4 +#define IFLA_WG_PEER_PERSISTENT_KEEPALIVE_INTERVAL 5 +#define IFLA_WG_PEER_LAST_HANDSHAKE_TIME 6 +#define IFLA_WG_PEER_RX_BYTES 7 +#define IFLA_WG_PEER_TX_BYTES 8 +#define IFLA_WG_PEER_ALLOWEDIPS 9 +#define __IFLA_WG_PEER_MAX 10 + +#define IFLA_WG_ALLOWEDIP_UNSPEC 0 +#define IFLA_WG_ALLOWEDIP_FAMILY 1 +#define IFLA_WG_ALLOWEDIP_IPADDR 2 +#define IFLA_WG_ALLOWEDIP_CIDR_MASK 3 +#define __IFLA_WG_ALLOWEDIP_MAX 4 + +/******************************************************************* **********/ + #define _NMLOG_PREFIX_NAME "platform-linux" #define _NMLOG_DOMAIN LOGD_PLATFORM #define _NMLOG2_DOMAIN LOGD_PLATFORM @@ -543,6 +577,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" }, @@ -1377,6 +1412,218 @@ _parse_lnk_sit (const char *kind, struct nlattr *info_data) /******************************************************************* **********/ +static int +_wireguard_parse_allowedip (struct nlattr *allowedip_attr, CList *list_head) +{ + static const struct nla_policy allowedip_policy[__IFLA_WG_ALLOWEDIP_MAX] = { + [IFLA_WG_ALLOWEDIP_FAMILY] = { .type = NLA_U16 }, + [IFLA_WG_ALLOWEDIP_IPADDR] = { .minlen = sizeof (struct in_addr) }, + [IFLA_WG_ALLOWEDIP_CIDR_MASK] = { .type = NLA_U8 }, + }; + struct nlattr *tba[__IFLA_WG_ALLOWEDIP_MAX]; + NMPObject *obj; + NMPlatformWireguardAllowedIP *allowedip; + int addr_len; + int ret; + + ret = nla_parse_nested (tba, __IFLA_WG_ALLOWEDIP_MAX, allowedip_attr, allowedip_policy); + if (ret) + goto errout; + + obj = nmp_object_new (NMP_OBJECT_TYPE_WIREGUARD_ALLOWEDIP, NULL); + allowedip = &obj->wireguard_allowedip; + + allowedip->family = tba[IFLA_WG_ALLOWEDIP_FAMILY] ? nla_get_u16 (tba[IFLA_WG_ALLOWEDIP_FAMILY]) : 0; + + addr_len = (allowedip->family == AF_INET)
check that the family is at least AF_INET6, otherwise error out.
+ ? sizeof (in_addr_t) + : sizeof (struct in6_addr); + + ret = -NLE_ATTRSIZE; + _check_addr_or_errout (tba, IFLA_WG_ALLOWEDIP_IPADDR, addr_len); + if (tba[IFLA_WG_ALLOWEDIP_IPADDR]) + memcpy (&allowedip->ip, nla_data (tba[IFLA_WG_ALLOWEDIP_IPADDR]), addr_len); + + allowedip->cidr = tba[IFLA_WG_ALLOWEDIP_CIDR_MASK] ? nla_get_u8 (tba[IFLA_WG_ALLOWEDIP_CIDR_MASK]) : 0; + + c_list_link_tail (list_head, &allowedip->allowedips_lst); + + ret = 0; +errout: + return ret; +} + +static int +_wireguard_parse_peer (struct nlattr *peer_attr, CList *list_head) +{ + static const struct nla_policy peer_policy[__IFLA_WG_PEER_MAX] = { + [IFLA_WG_PEER_PUBLIC_KEY] = { .minlen = NM_WG_PUBLIC_KEY_LEN }, + [IFLA_WG_PEER_PRESHARED_KEY] = { .minlen = NM_WG_SYMMETRIC_KEY_LEN }, + [IFLA_WG_PEER_FLAGS] = { .type = NLA_U32 }, + [IFLA_WG_PEER_ENDPOINT] = { .minlen = sizeof (struct sockaddr) }, + [IFLA_WG_PEER_PERSISTENT_KEEPALIVE_INTERVAL] = { .type = NLA_U16 }, + [IFLA_WG_PEER_LAST_HANDSHAKE_TIME] = { .minlen = sizeof (struct timespec) }, + [IFLA_WG_PEER_RX_BYTES] = { .type = NLA_U64 }, + [IFLA_WG_PEER_TX_BYTES] = { .type = NLA_U64 }, + [IFLA_WG_PEER_ALLOWEDIPS] = { .type = NLA_NESTED }, + }; + struct nlattr *tbp[__IFLA_WG_PEER_MAX]; + NMPObject *obj; + NMPlatformWireguardPeer *peer; + int ret; + + ret = nla_parse_nested (tbp, __IFLA_WG_PEER_MAX, peer_attr, peer_policy); + if (ret) + goto errout; + + obj = nmp_object_new (NMP_OBJECT_TYPE_WIREGUARD_PEER, NULL); + peer = &obj->wireguard_peer; + + if (tbp[IFLA_WG_PEER_PUBLIC_KEY]) + memcpy (&peer->public_key, nla_data (tbp[IFLA_WG_PEER_PUBLIC_KEY]), sizeof (peer->public_key)); + + if (tbp[IFLA_WG_PEER_PRESHARED_KEY]) + memcpy (&peer->preshared_key, nla_data (tbp[IFLA_WG_PEER_PRESHARED_KEY]), sizeof (peer->preshared_key)); + + if (tbp[IFLA_WG_PEER_ENDPOINT]) + memcpy (&peer->endpoint, nla_data (tbp[IFLA_WG_PEER_ENDPOINT]), sizeof (peer->endpoint)); + + peer->persistent_keepalive_interval = tbp[IFLA_WG_PEER_PERSISTENT_KEEPALIVE_INTERVAL] ? nla_get_u64 (tbp[IFLA_WG_PEER_PERSISTENT_KEEPALIVE_INTERVAL]) : 0; + + if (tbp[IFLA_WG_PEER_LAST_HANDSHAKE_TIME]) + memcpy (&peer->last_handshake_time, nla_data (tbp[IFLA_WG_PEER_LAST_HANDSHAKE_TIME]), sizeof (peer-last_handshake_time));+ + peer->rx_bytes = tbp[IFLA_WG_PEER_RX_BYTES] ? nla_get_u64 (tbp[IFLA_WG_PEER_RX_BYTES]) : 0; + peer->tx_bytes = tbp[IFLA_WG_PEER_TX_BYTES] ? nla_get_u64 (tbp[IFLA_WG_PEER_TX_BYTES]) : 0; + + c_list_init (&peer->allowedips_lst_head); + if (tbp[IFLA_WG_PEER_ALLOWEDIPS]) { + struct nlattr *allowedip_attr; + int remaining_allowedips; + nla_for_each_nested (allowedip_attr, tbp[IFLA_WG_PEER_ALLOWEDIPS], remaining_allowedips) { + ret = _wireguard_parse_allowedip (allowedip_attr, &peer->allowedips_lst_head); + if (ret) + goto errout; + } + } + + c_list_link_tail (list_head, &peer->peers_lst); + + ret = 0; +errout: + return ret; +} + +static int +_wireguard_parse_getdevice (struct nl_msg *msg, void *arg) +{ + static const struct nla_policy device_policy[__IFLA_WG_DEVICE_MAX] = { + [IFLA_WG_DEVICE_IFINDEX] = { .type = NLA_U32 }, + [IFLA_WG_DEVICE_IFNAME] = { .type = NLA_NUL_STRING, .maxlen = IFNAMSIZ - 1 }, + [IFLA_WG_DEVICE_PRIVATE_KEY] = { .minlen = NM_WG_PUBLIC_KEY_LEN }, + [IFLA_WG_DEVICE_PUBLIC_KEY] = { .minlen = NM_WG_PUBLIC_KEY_LEN }, + [IFLA_WG_DEVICE_FLAGS] = { .type = NLA_U32 }, + [IFLA_WG_DEVICE_LISTEN_PORT] = { .type = NLA_U16 }, + [IFLA_WG_DEVICE_FWMARK] = { .type = NLA_U32 }, + [IFLA_WG_DEVICE_PEERS] = { .type = NLA_NESTED }, + }; + struct nlattr *tbd[__IFLA_WG_DEVICE_MAX]; + NMPObject *obj = * (NMPObject **) arg; + NMPlatformLnkWireguard *props; + struct nlmsghdr *nlh = nlmsg_hdr (msg); + int ret; + + ret = genlmsg_parse (nlh, 0, tbd, __IFLA_WG_DEVICE_MAX - 1, device_policy); + if (ret) + goto errout; + + props = &obj->lnk_wireguard; + + props->listen_port = tbd[IFLA_WG_DEVICE_LISTEN_PORT] ? nla_get_u16 (tbd[IFLA_WG_DEVICE_LISTEN_PORT]) : 0; + props->fwmark = tbd[IFLA_WG_DEVICE_FWMARK] ? nla_get_u32 (tbd[IFLA_WG_DEVICE_FWMARK]) : 0; + + if (tbd[IFLA_WG_DEVICE_PRIVATE_KEY]) + nla_memcpy (props->private_key, tbd[IFLA_WG_DEVICE_PRIVATE_KEY], sizeof (props->private_key)); + else + memset (props->private_key, 0, sizeof (props-private_key));+ + if (tbd[IFLA_WG_DEVICE_PUBLIC_KEY]) + nla_memcpy (props->public_key, tbd[IFLA_WG_DEVICE_PUBLIC_KEY], sizeof (props->public_key)); + else + memset (props->public_key, 0, sizeof (props-public_key));+ + c_list_init (&props->peers_lst_head); + if (tbd[IFLA_WG_DEVICE_PEERS]) { + struct nlattr *peer_attr; + int remaining_peers; + nla_for_each_nested (peer_attr, tbd[IFLA_WG_DEVICE_PEERS], remaining_peers) { + ret = _wireguard_parse_peer (peer_attr, &props->peers_lst_head); + if (ret) + goto errout; + } + } + + return NL_STOP; +errout: + return NL_SKIP; +} + +static NMPObject * +_parse_lnk_wireguard (const char *kind, const char *ifname) +{ + nm_auto_nmpobj NMPObject *obj = NULL; + NMPObject *obj_result = NULL; + struct nl_sock *sock; + nm_auto_nlmsg struct nl_msg *msg = NULL; + struct nl_cb cb = { + .valid_cb = _wireguard_parse_getdevice, + }; + static int family_id; + + if (!nm_streq0 (kind, "wireguard")) + goto err; + + sock = nl_socket_alloc (); + if (!sock) + goto err; + + if (nl_connect (sock, NETLINK_GENERIC))
I think the genl socket should be cached and re-used by NMLinuxPlatform. Likewise, family_id should be cached in NMLinuxPlatformPrivate.
+ goto err_socket;
It's a bit odd that _parse_lnk_wireguard() opens a genl socket to request additional data. Commonly the entire parsing of _new_from_nl_link() is only supposed to get information that is present in the netlink message. They only thing that they might do, is look into the platform cache, and re-use information from there, for example at https://cgit.freedesktop.org/NetworkManager/NetworkManager/tree/src/platform/nm-linux-platform.c?id=167e42a87e97ed7fb26a4263c22f1774716ac51b#n785 https://cgit.freedesktop.org/NetworkManager/NetworkManager/tree/src/platform/nm-linux-platform.c?id=167e42a87e97ed7fb26a4263c22f1774716ac51b#n1833 Basically, for every RTM_NEWLINK event, it re-fetches all wireguard information from genetlink. That seems a bit heavy. Do we get a notification on (ge)netlink when something about this interface changes? Otherwise, you could just look into the platform cache, see that the information is already, and re-use it from there.
+ + if (!family_id) + family_id = genl_ctrl_resolve (sock, "wireguard"); + if (family_id <= 0) + goto err_socket; + + msg = nlmsg_alloc (); + + if (!genlmsg_put (msg, NL_AUTO_PORT, NL_AUTO_SEQ, family_id, + 0, NLM_F_DUMP, WG_CMD_GET_DEVICE, 1)) + goto err_socket; + + if (nla_put_string (msg, IFLA_WG_DEVICE_IFNAME, ifname) < 0)
can we avoid lookup by ifname? The ifname can be changed, only ifindex is the unchangable, unique ID (mostly, not really either :( )
+ goto err_socket; + + if (nl_send_auto (sock, msg) < 0) + goto err_socket; + + obj = nmp_object_new (NMP_OBJECT_TYPE_LNK_WIREGUARD, NULL); + cb.valid_arg = &obj; + + if (nl_recvmsgs (sock, &cb) < 0) + goto err_socket; + + obj_result = obj; + obj = NULL; + +err_socket: + nl_socket_free (sock); +err: + return obj_result; +} + +/******************************************************************* **********/ + static gboolean _vlan_qos_mapping_from_nla (struct nlattr *nlattr, const NMVlanQosMapping **out_map, @@ -1814,6 +2061,9 @@ _new_from_nl_link (NMPlatform *platform, const NMPCache *cache, struct nlmsghdr case NM_LINK_TYPE_VXLAN: lnk_data = _parse_lnk_vxlan (nl_info_kind, nl_info_data); break; + case NM_LINK_TYPE_WIREGUARD: + lnk_data = _parse_lnk_wireguard (nl_info_kind, obj-link.name);+ break; default: lnk_data_complete_from_cache = FALSE; break; diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c index 7e2f27ced..2d631c7ca 100644 --- a/src/platform/nm-platform.c +++ b/src/platform/nm-platform.c @@ -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> @@ -1906,6 +1908,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); +} + /******************************************************************* **********/ /** @@ -4994,6 +5002,95 @@ nm_platform_lnk_sit_to_string (const NMPlatformLnkSit *lnk, char *buf, gsize len return buf; } +const char * +nm_platform_lnk_wireguard_to_string (const NMPlatformLnkWireguard *lnk, char *buf, gsize len) +{ + gchar *public_b64; + 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));+ + g_snprintf (buf, len, + "wireguard " + "public_key %s " + "private_key (hidden) " + "listen_port %u " + "fwmark 0x%x", + public_b64, + lnk->listen_port, + lnk->fwmark); + + g_free (public_b64);
don't explicitly free. Use one of the gs_* or nm_auto_* macros. In this case, gs_free. Commonly, the to-string methods should print *all* aspects of the object. It's right to hide the private-key, I am talking about the Peers/AllowedIPs. The sole purpose of the to-string methods if for debugging. Currently, the peers/allowed-ips are never printed, maybe they should. Note also that nmp_object_to_string() has an arguemnt to_string_mode, for printing common fields (NMP_OBJECT_TO_STRING_PUBLIC) vs. all (NMP_OBJECT_TO_STRING_ALL). I think at least for NMP_OBJECT_TO_STRING_ALL, NMPObjectLnkWireguard should print all peers/allowed-ips. This means to implement "cmd_obj_to_string". See https://cgit.freedesktop.org/NetworkManager/NetworkManager/tree/src/platform/nmp-object.c?id=167e42a87e97ed7fb26a4263c22f1774716ac51b#n666
+ + return buf; +} + +const char * +nm_platform_wireguard_peer_to_string (const NMPlatformWireguardPeer *peer, char *buf, gsize len) +{ + gchar *public_b64; + char s_endpoint[NI_MAXHOST + NI_MAXSERV + sizeof("endpoint []:") + 1]; + + if (!nm_utils_to_string_buffer_init_null (peer, &buf, &len)) + return buf; + + if (peer->endpoint.addr.sa_family == AF_INET || peer-endpoint.addr.sa_family == AF_INET6) {+ char host[NI_MAXHOST]; + char 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, host, sizeof(host), service, sizeof(service), NI_DGRAM | NI_NUMERICSERV | NI_NUMERICHOST)) {
I don't think we should resolve the addresses just for logging. Just convert them to string with nm_utils_inet_ntop().
+ if (peer->endpoint.addr.sa_family == AF_INET6 && strchr (host, ':')) + g_snprintf(s_endpoint, sizeof (s_endpoint), "endpoint [%s]:%s ", host, service); + else + g_snprintf(s_endpoint, sizeof (s_endpoint), "endpoint %s:%s ", host, service); + } + } else { + s_endpoint[0] = '\0'; + } + + public_b64 = g_base64_encode (peer->public_key, sizeof (peer->public_key)); + + g_snprintf (buf, len, + "wgpeer " + "public_key %s " + "preshared_key (hidden) " + "%s" /* endpoint */ + "rx %"G_GUINT64_FORMAT" " + "tx %"G_GUINT64_FORMAT"", + public_b64, + s_endpoint, + peer->rx_bytes, + peer->tx_bytes); + + g_free (public_b64); + + return buf; +} + +const char * +nm_platform_wireguard_allowedip_to_string (const NMPlatformWireguardAllowedIP *allowedip, char *buf, gsize len) +{ + char s_address[INET_ADDRSTRLEN]; + + if (!nm_utils_to_string_buffer_init_null (allowedip, &buf, &len)) + return buf; + + inet_ntop (allowedip->family, &allowedip->ip, s_address, sizeof(s_address)); + + g_snprintf (buf, len, + "wgallowedip %s/%u", + s_address, + allowedip->cidr); + + return buf; +} + const char * nm_platform_lnk_vlan_to_string (const NMPlatformLnkVlan *lnk, char *buf, gsize len) { diff --git a/src/platform/nm-platform.h b/src/platform/nm-platform.h index 53b2975bf..a8cf7bfd4 100644 --- a/src/platform/nm-platform.h +++ b/src/platform/nm-platform.h @@ -30,6 +30,7 @@ #include "nm-dbus-interface.h" #include "nm-core-types-internal.h" +#include "nm-utils/c-list.h" #include "nm-core-utils.h" #include "nm-setting-vlan.h" #include "nm-setting-wired.h" @@ -80,6 +81,9 @@ typedef gboolean (*NMPObjectPredicateFunc) (const NMPObject *obj, /* Redefine this in host's endianness */ #define NM_GRE_KEY 0x2000 +#define NM_WG_PUBLIC_KEY_LEN 32 +#define NM_WG_SYMMETRIC_KEY_LEN 32 + typedef enum { /* use our own platform enum for the nlmsg-flags. Otherwise, we'd have * to include <linux/netlink.h> */ @@ -682,6 +686,42 @@ typedef struct { bool l3miss:1; } NMPlatformLnkVxlan; +typedef struct { + guint16 family; + union { + struct in_addr ip4; + struct in6_addr ip6; + } ip; + guint8 cidr; + + CList allowedips_lst; +} NMPlatformWireguardAllowedIP; + +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; + struct timespec last_handshake_time; + guint64 rx_bytes, tx_bytes; + guint16 persistent_keepalive_interval; + + CList peers_lst; + CList allowedips_lst_head; +} NMPlatformWireguardPeer; + +typedef struct { + guint8 private_key[NM_WG_PUBLIC_KEY_LEN]; + guint8 public_key[NM_WG_PUBLIC_KEY_LEN]; + guint16 listen_port; + guint32 fwmark; + + CList peers_lst_head;
The public part of the NMPObjects (NMPlatformLnkWireguard vs. NMPObjectLnkWireguard) is supposed to be copyable directly. That means, it cannot have pointers (except for example NMPlatformLink.kind, which is however a static string, so it's safe to copy). This means, the CList part must go into NMPObjectLnkWireguard. Together with I said above about nm_platform_lnk_wireguard_to_string() to print all fields, it means, the list of peers/allowed-ips is not accessible to NMPlatformLnkWireguard, so there is nothing to print. But it certainly should implement cmd_obj_to_string().
+} NMPlatformLnkWireguard; + typedef struct { gint64 owner; gint64 group; @@ -1161,6 +1201,7 @@ const NMPlatformLnkMacvtap *nm_platform_link_get_lnk_macvtap (NMPlatform *self, const NMPlatformLnkSit *nm_platform_link_get_lnk_sit (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, @@ -1339,6 +1380,9 @@ const char *nm_platform_lnk_macvlan_to_string (const NMPlatformLnkMacvlan *lnk, const char *nm_platform_lnk_sit_to_string (const NMPlatformLnkSit *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_wireguard_peer_to_string (const NMPlatformWireguardPeer *peer, char *buf, gsize len); +const char *nm_platform_wireguard_allowedip_to_string (const NMPlatformWireguardAllowedIP *peer, 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); diff --git a/src/platform/nmp-object.c b/src/platform/nmp-object.c index 4df64e608..06883c57b 100644 --- a/src/platform/nmp-object.c +++ b/src/platform/nmp-object.c @@ -2807,5 +2807,30 @@ 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_plobj_to_string = (const char *(*) (const NMPlatformObject *obj, char *buf, gsize len))
the types that are put inside the platform cache (like NMPObjectLnkWireguard), they must implement equality/hash operators. NMPObjectLnkWireguard is not unlike NMPObjectLnkVlan. See what functions are implemented there.
nm_platform_lnk_wireguard_to_string, + }, + [NMP_OBJECT_TYPE_WIREGUARD_PEER - 1] = { + .parent = DEDUP_MULTI_OBJ_CLASS_INIT(), + .obj_type = NMP_OBJECT_TYPE_WIREGUARD_PEER, + .sizeof_data = sizeof (NMPObjectWireguardPeer), + .sizeof_public = sizeof (NMPlatformWireguardPeer), + .obj_type_name = "wireguard- peer", + .cmd_plobj_to_string = (const char *(*) (const NMPlatformObject *obj, char *buf, gsize len)) nm_platform_wireguard_peer_to_string, + }, + [NMP_OBJECT_TYPE_WIREGUARD_ALLOWEDIP - 1] = { + .parent = DEDUP_MULTI_OBJ_CLASS_INIT(), + .obj_type = NMP_OBJECT_TYPE_WIREGUARD_ALLOWEDIP, + .sizeof_data = sizeof (NMPObjectWireguardAllowedIP), + .sizeof_public = sizeof (NMPlatformWireguardAllowedIP), + .obj_type_name = "wireguard- allowedip", + .cmd_plobj_to_string = (const char *(*) (const NMPlatformObject *obj, char *buf, gsize len)) nm_platform_wireguard_allowedip_to_string, + }, }; diff --git a/src/platform/nmp-object.h b/src/platform/nmp-object.h index 8c36e2e3d..afa504f9c 100644 --- a/src/platform/nmp-object.h +++ b/src/platform/nmp-object.h @@ -209,6 +209,18 @@ typedef struct { NMPlatformLnkVxlan _public; } NMPObjectLnkVxlan; +typedef struct { + NMPlatformLnkWireguard _public; +} NMPObjectLnkWireguard; + +typedef struct { + NMPlatformWireguardPeer _public; +} NMPObjectWireguardPeer; + +typedef struct { + NMPlatformWireguardAllowedIP _public; +} NMPObjectWireguardAllowedIP; + typedef struct { NMPlatformIP4Address _public; } NMPObjectIP4Address; @@ -271,6 +283,15 @@ struct _NMPObject { NMPlatformLnkVxlan lnk_vxlan; NMPObjectLnkVxlan _lnk_vxlan; + NMPlatformLnkWireguard lnk_wireguard; + NMPObjectLnkWireguard _lnk_wireguard; + + NMPlatformWireguardPeer wireguard_peer; + NMPObjectWireguardPeer _wireguard_peer; + + NMPlatformWireguardAllowedIP wireguard_allowedip; + NMPObjectWireguardAllowedIP _wireguard_allowedip; + NMPlatformIPAddress ip_address; NMPlatformIPXAddress ipx_address; NMPlatformIP4Address ip4_address;
Attachment:
signature.asc
Description: This is a digitally signed message part