New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
core,libnm: introduce NMDeviceWireguard #162
Conversation
NM CI: Please confirm test execution over this PR. Comment .ok\W+to\W+test. to confirm and/or .add\W+to\W+whitelist. to add the PR author in whitelist for future. |
f510352
to
980e0cc
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you, this looks rather reasonable.
I've suggested some changes, mostly nitpicks.
Also, please split the commit into the server part and the libnm part. The introspection/ should either go into the server part or a separate commit.
The brand new checkpatch.pl seems rather happy too, with two OCD warnings.
<property name="ListenPort" type="u" access="read"/> | ||
|
||
<!-- | ||
Fwmark: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wouldn't "FirewallMark" be a better name?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe. fwmark
is what wg(8)
and WG APIs use, however - I'd like to stick to the upstream naming where possible.
<!-- | ||
Fwmark: | ||
|
||
Firewall mark. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add a sentence or two explaining what a Firewall mark is.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thought I had added it somewhere actually! Will do.
|
||
32-byte private WireGuard key. | ||
--> | ||
<property name="PrivateKey" type="v" access="read"/> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"v" signature ? Wouldn't "ay" make more sense for a byte array?
Also, the PrivateKey probably shouldn't be visible on the D-Bus API, since it has not access control and is visible to all local users. Is it necessary to have this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, right now keys are shown as base64 strings when queried via D-Bus. The purpose is to play nice with wg
config files and commandline, with both take base64 strings.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, it still doesn't have to be base64 on D-Bus API -- it may make more sense to encode it in nmcli and possibly the keyfile plugin. @thom311, what do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I also would think that the private key is either a binary array (ay) or a string (s).
Maybe string is nicer, because then we can have there the base64 key directly. And if we some day in the future a different format (but why would we?), then we possibly could even extend the string with a "prefix:" (since ':' cannot be in plain base64).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we settle on base64, then it the documentation comment should state that it's base64-encoded.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we settle on base64, then it the documentation comment should state that it's base64-encoded.
That's fine.
Also, I hadn't looked into the access control for the D-Bus API yet. If indeed it's readable by all non-root users then of course we can't have the private key there :)
libnm/libnm.ver
Outdated
@@ -1383,6 +1383,11 @@ global: | |||
nm_connection_get_setting_6lowpan; | |||
nm_connection_get_setting_wpan; | |||
nm_device_6lowpan_get_type; | |||
nm_device_wireguard_get_public_key; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please keep this sorted alphabetically.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will fix.
libnm/nm-device-wireguard.c
Outdated
const guchar* | ||
nm_device_wireguard_get_private_key (NMDeviceWireguard *device) | ||
{ | ||
g_return_val_if_fail (NM_IS_DEVICE_WIREGUARD (device), 0); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You probably meant NULL instead of 0.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed. Thanks!
libnm/nm-device-wireguard.h
Outdated
/** | ||
* NMDeviceWireguard: | ||
*/ | ||
struct _NMDeviceWireguard { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For new devices, we like to keep these in the .c file, be cause they don't need to be part of the public API. See (nm-device-wpan for an example).
Also, when the object structure itself is not public, there's no need for the NMDeviceWireguardPrivate structure, since all NMDeviceWireguard fields would be private. (This is left for your consideration -- you may still want to keep the private structure for clarity.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Understood. NMDeviceWireguardPrivate
I was using while playing around with a PROP_PEERS
implementation - but yeah I can drop it for now.
src/devices/nm-device-wireguard.c
Outdated
* This program is free software; you can redistribute it and/or modify | ||
* it under the terms of the GNU General Public License as published by | ||
* the Free Software Foundation; either version 2 of the License, or | ||
* (at your option) any later version. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm wondering if I could ask you to license this under LGPL, the same as the libnm part? We sometimes move things around between libnm and core, and the inconsistent licensing has caused us trouble.
This also applies to some other GPL-licensed files.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah - don't worry, it's just a case of lazy copy-paste licensing. Happy to mirror the licenses for similar files.
--> | ||
<property name="PublicKey" type="v" access="read"/> | ||
|
||
<!-- |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please just drop this, none of your properties emit the legacy signal.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK.
32-byte public WireGuard key. | ||
--> | ||
<property name="PublicKey" type="v" access="read"/> | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please include a "Parent" property too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a question I meant to ask too - what is the purpose of the parent device?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On the second thought -- I have no idea if this is relevant for Wireguard. Maybe not.
Links that are associated with some other interface have this. E.g. VLANs, Tunneling devices or Veth pairs. In general it mirrors the IFLA_LINK property of the rtnetlink link. (In other words, if it says "link1@link0:" in "ip link", then link0 is the parent device.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In that case, I don't think it's relevant, no. Wireguard is layer 3, it doesn't care about another particular link.
src/devices/nm-device-wireguard.h
Outdated
#define NM_IS_DEVICE_WIREGUARD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DEVICE_WIREGUARD)) | ||
#define NM_DEVICE_WIREGUARD_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_WIREGUARD, NMDeviceWireguardClass)) | ||
|
||
/* defined in the parent class, but exposed on D-Bus by the subclass. */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, actually not exposed. But I guess it should be.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
True. I'll drop this too.
082c37d
to
647c478
Compare
libnm/nm-device-wireguard.c
Outdated
* @device: a #NMDeviceWireguard | ||
* | ||
* Gets the private key for this interface | ||
* |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please document that it's a base64-encoded here too. I still find it somewhat odd.
Also, the "32-byte" length might be somewhat impractical -- it would be better if it was NUL terminated. g_base64_encode() doesn't actually guarantee any particular length, since base64 allows using whitespace pretty arbitrarily.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please document that it's a base64-encoded here too.
Well, for this particular function it isn't shouldn't have been base64-encoded - whoops. I'll update this PR.
Also, the "32-byte" length might be somewhat impractical -- it would be better if it was NUL terminated. g_base64_encode() doesn't actually guarantee any particular length, since base64 allows using whitespace pretty arbitrarily.
I probably didn't make this clear - WG keys are fixed-size 32-byte binary data (NULs allowed). base64 is only used to portably move them around and we're not really interested in the length of the base64 strings at this level.
My intention was to use base64 only in interfaces that are expected to be directly visible to end-users, as this is the standard across WG utilities. This includes NM logs (e.g. nm_platform_lnk_wireguard_to_string
), and any CLI components. Honestly I'm not sure about the D-Bus interface, maybe it doesn't fall under this category in which case I agree base64 would be odd.
For all the other internal and external APIs we simply need to pass around fixed-size 32-byte buffers that can hold arbitrary data.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My intention was to use base64 only in interfaces that are expected to be directly visible to end-users, as this is the standard across WG utilities. This includes NM logs (e.g. nm_platform_lnk_wireguard_to_string), and any CLI components. Honestly I'm not sure about the D-Bus interface, maybe it doesn't fall under this category in which case I agree base64 would be odd.
That makes sense. D-Bus is an API that's not exposed to the user, and I believe it shouldn't use base48. Agreed that logs/cli should.
I'll update this PR.
Looking forward. I think this already looks pretty well and almost ready to e merged.
ok to test |
Makefile.am
Outdated
@@ -234,6 +234,8 @@ introspection_sources = \ | |||
introspection/org.freedesktop.NetworkManager.Device.Vlan.h \ | |||
introspection/org.freedesktop.NetworkManager.Device.Vxlan.c \ | |||
introspection/org.freedesktop.NetworkManager.Device.Vxlan.h \ | |||
introspection/org.freedesktop.NetworkManager.Device.Wireguard.c \ | |||
introspection/org.freedesktop.NetworkManager.Device.Wireguard.h \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wireguard -> WireGuard
(similar to WiMax.h below)
docs/api/Makefile.am
Outdated
@@ -74,6 +74,7 @@ content_files = \ | |||
dbus-org.freedesktop.NetworkManager.Device.Veth.xml \ | |||
dbus-org.freedesktop.NetworkManager.Settings.xml \ | |||
dbus-org.freedesktop.NetworkManager.Device.Wired.xml \ | |||
dbus-org.freedesktop.NetworkManager.Device.Wireguard.xml \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
WireGuard
docs/api/network-manager-docs.xml
Outdated
@@ -203,8 +203,10 @@ | |||
<xi:include href="dbus-org.freedesktop.NetworkManager.Device.Veth.xml"/> | |||
<xi:include href="dbus-org.freedesktop.NetworkManager.Device.Vlan.xml"/> | |||
<xi:include href="dbus-org.freedesktop.NetworkManager.Device.Vxlan.xml"/> | |||
<xi:include href="dbus-org.freedesktop.NetworkManager.Device.Wireguard.xml"/> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
WireGuard
introspection/meson.build
Outdated
@@ -34,6 +34,7 @@ ifaces = [ | |||
'org.freedesktop.NetworkManager.Device.Wpan', | |||
'org.freedesktop.NetworkManager.Device.Wired', | |||
'org.freedesktop.NetworkManager.Device.Wireless', | |||
'org.freedesktop.NetworkManager.Device.Wireguard', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wireguard -> WireGuard
<?xml version="1.0" encoding="UTF-8"?> | ||
<node name="/"> | ||
<!-- | ||
org.freedesktop.NetworkManager.Device.Wireguard: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wireguard -> WireGuard
@short_description: WireGuard Device | ||
|
||
--> | ||
<interface name="org.freedesktop.NetworkManager.Device.Wireguard"> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wireguard -> WireGuard
libnm-core/nm-dbus-interface.h
Outdated
@@ -73,6 +73,7 @@ | |||
#define NM_DBUS_INTERFACE_DEVICE_MACVLAN NM_DBUS_INTERFACE_DEVICE ".Macvlan" | |||
#define NM_DBUS_INTERFACE_DEVICE_PPP NM_DBUS_INTERFACE_DEVICE ".Ppp" | |||
#define NM_DBUS_INTERFACE_DEVICE_VXLAN NM_DBUS_INTERFACE_DEVICE ".Vxlan" | |||
#define NM_DBUS_INTERFACE_DEVICE_WIREGUARD NM_DBUS_INTERFACE_DEVICE ".Wireguard" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wireguard -> WireGuard
libnm/nm-device-wireguard.c
Outdated
NMDeviceClass parent; | ||
} NMDeviceWireguardClass; | ||
|
||
G_DEFINE_TYPE (NMDeviceWireguard, nm_device_wireguard, NM_TYPE_DEVICE) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wireguard -> WireGuard
libnm/nm-device-wireguard.c
Outdated
|
||
typedef struct { | ||
NMDeviceClass parent; | ||
} NMDeviceWireguardClass; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wireguard -> WireGuard
@zx2c4 if the spelling is "WireGuard" with camel-case, then our style requires a separator at non-camel-case places. For example
|
I wasn't available this week, sorry for the delay. Would you consider fixup commits from branch https://github.com/NetworkManager/NetworkManager/tree/th/review/pr/162 for inclusion? If you happen to agree, just squash the patches. Thanks. After that, it looks good to me. The last remaining question is the naming. |
Oh, ugh, no, please no. That will cause way more confusion and hurt obvious source searches and really isn't nice. That doesn't make sense for so many reasons. WiMax is |
I am aware of that. WiMax is also deprecated. The older the code, the less it conforms to our current style (which, slightly adjusts over time). Anyway, I think it doesn't have so strict, and
is fine with me. @lkundrak WDYT? |
No worries - this week it was my turn :)
Thanks for this. Most fixups I agree with and I'll update the PR with them. However taking into account the above feedback from @lkundrak, I think the public key should also become an array on both libnm and D-Bus APIs.
That looks sane to me. |
Hi, I don't fully understand this reply. My suggestion (the fixup commits) do not affect that the public key is exposed on libnm and D-Bus API. It however removes unused API for the private key. I agree with how the public key is treated. |
Respect WireGuard canonical capitalization on identifiers. As per discussion on: NetworkManager#162
For now, the device only exposes partial link status (not including peers). It cannot create new links.
647c478
to
c5a93fc
Compare
Correct. I was just pointing out that as per previous discussion with @lkundrak we should also remove base64 from the non-user-visible APIs. That's done now. Updated the PR with:
|
Hi,
I personally don't think this change was a good idea, because a base64 string is easier to work with. Anyway, the change is fine with me. However, const char *
nm_device_wireguard_get_public_key (NMDeviceWireguard *device)
{
g_return_val_if_fail (NM_IS_DEVICE_WIREGUARD (device), NULL);
return NM_DEVICE_WIREGUARD_GET_PRIVATE (device)->public_key;
} public_key is no longer a NUL terminated string. You cannot expose it with such an API. It must be instead something like: const guint8 *nm_device_wireguard_get_public_key (NMDeviceWireguard *device, guint *out_length); or better: GBytes *nm_device_wireguard_get_public_key (NMDeviceWireguard *device); Also, static GVariant *
get_public_key_as_variant (NMDeviceWireGuard *device)
{
NMDeviceWireGuardPrivate *priv;
g_return_val_if_fail (NM_IS_DEVICE_WIREGUARD (device), NULL);
priv = NM_DEVICE_WIREGUARD_GET_PRIVATE (device);
return g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE,
priv->public_key, sizeof (priv->public_key), 1);
} is wrong. Also, in libnm's NMDeviceWireGuard, I think that PROP_PUBLIC_KEY should be of type |
Hopefully it's the other way around and we save consumers of these APIs a base64 decoding step. I'm OK with this being reverted later if turns out not to be the case.
The key size is always 32 bytes, so in practice you can. But I'll follow your advice and use GBytes.
True. Thanks for spotting this.
Ah, I didn't realize that was an option. That's easier then. Thanks again for reviewing! |
See
Maybe "ay" + GBytes is indeed better. In the end, there are pros+cons. Leave it as "ay", ok?
I think it's better to not commit the API to this. Also, I think the previous API could not be nicely exposed via GObject introspection (for example, the Python bindings wouldn't be correct). |
c5a93fc
to
37b12b3
Compare
Switched to GBytes + boxed param for libnm now. |
Looks good to me. Let's merge this so @jbeta can move onto part 3? |
merged to master. Thanks Javier!! |
For now, the device only exposes partial link status (not including
peers). It cannot create new links.
This PR is mostly sanity check / request for comments. I'm also looking for guidance on how to model Peers/AllowedIPs on the D-Bus interface: would these be object paths to separate instances, a complex
a(ss...qta(...))
D-Bus signature that maps to aNMWireguardPeer
array, neither...?