Ok, I changed my mind.
The new behavior seems to make more sense to me. Not that it matters,
because we always use nm_utils_strbuf*() API with buffers that we expect
to be large enough to contain the result. And when truncation occurs,
we usually don't care much about it. That is, there is no code that
uses nm_utils_strbuf*() API and handles string truncation in particular.
- previously, parsing wireguard genl data resulted in memory corruption:
- _wireguard_update_from_allowedips_nla() takes pointers to
allowedip = &g_array_index (buf->allowedips, NMWireGuardAllowedIP, buf->allowedips->len - 1);
but resizing the GArray will invalidate this pointer. This happens
when there are multiple allowed-ips to parse.
- there was some confusion who owned the allowedips pointers.
_wireguard_peers_cpy() and _vt_cmd_obj_dispose_lnk_wireguard()
assumed each peer owned their own chunk, but _wireguard_get_link_properties()
would not duplicate the memory properly.
- rework memory handling for allowed_ips. Now, the NMPObjectLnkWireGuard
keeps a pointer _allowed_ips_buf. This buffer contains the instances for
all peers.
The parsing of the netlink message is the complicated part, because
we don't know upfront how many peers/allowed-ips we receive. During
construction, the tracking of peers/allowed-ips is complicated,
via a CList/GArray. At the end of that, we prettify the data
representation and put everything into two buffers. That is more
efficient and simpler for user afterwards. This moves complexity
to the way how the object is created, vs. how it is used later.
- ensure that we nm_explicit_bzero() private-key and preshared-key. However,
that only works to a certain point, because our netlink library does not
ensure that no data is leaked.
- don't use a "struct sockaddr" union for the peer's endpoint. Instead,
use a combintation of endpoint_family, endpoint_port, and
endpoint_addr.
- a lot of refactoring.
I think g_memdup() is dangerous for integer overflow. There
is no need for accepting this danger, just use our own nm_memdup()
which does not have this flaw.
PROP_0 is how we commonly name this property when we don't use
NM_GOBJECT_PROPERTIES_DEFINE(). Rename it.
Also, allow to skip PROP_0 in nm_gobject_notify_together(), that
is handy to optionally invoke a notification, like
nm_gobject_notify_together (obj,
PROP_SOMETHING,
changed ? PROP_OTHER : PROP_0);
We already had nm_free_secret() to clear the secret out
of a NUL terminated string. That works well for secrets
which are strings, it can be used with a cleanup attribute
(nm_auto_free_secret) and as a cleanup function for a
GBytes.
However, it does not work for secrets which are binary.
For those, we must also track the length of the allocated
data and clear it.
Add two new structs NMSecretPtr and NMSecretBuf to help
with that.
Internally, GByteArray is actually a GArray, so it would be safe to
use "gs_unref_array" macro. However, that is rather ugly, and means
to rely on an internal implementation detail of GByteArray.
Instead, add a cleanup macro for GByteArray.
We already have nm_utils_str_utf8safe_escape() to convert a
NUL termianted string to an UTF-8 string. nm_utils_str_utf8safe_escape()
operates under the assumption, that the input strig is already valid UTF-8
and returns the input string verbatim. That way, in the common expected
cases, the string just looks like a regular UTF-8 string.
However, in case there are invalid UTF-8 sequences (or a backslash
escape characters), the function will use backslash escaping to encode
the input string as a valid UTF-8 sequence. Note that the escaped
sequence, can be reverted to the original non-UTF-8 string via
unescape.
An example, where this is useful are file names or interface names.
Which are not in a defined encoding, but NUL terminated and commonly ASCII or
UTF-8 encoded.
Extend this, to also handle not NUL terminated buffers. The same
applies, except that the process cannot be reverted via g_strcompress()
-- because the NUL character cannot be unescaped.
This will be useful to escape a Wi-Fi SSID. Commonly we expect the SSID
to be in UTF-8/ASCII encoding and we want to print it verbatim. Only
if that is not the case, we fallback to backslash escaping. However, the
orginal value can be fully recovered via unescape(). The difference
between an SSID and a filename is, that the former can contain '\0'
bytes.
Add a new 'match' setting containing properties to match a connection
to devices. At the moment only the interface-name property is present
and, contrary to connection.interface-name, it allows the use of
wildcards.
As of upstream kernel v4.18-rc8.
Note that we name the features like they are called in ethtool's
ioctl API ETH_SS_FEATURES.
Except, for features like "tx-gro", which ethtool utility aliases
as "gro". So, for those features where ethtool has a built-in,
alternative name, we prefer the alias.
And again, note that a few aliases of ethtool utility ("sg", "tso", "tx")
actually affect more than one underlying kernel feature.
Note that 3 kernel features which are announced via ETH_SS_FEATURES are
explicitly exluded because kernel marks them as "never_changed":
#define NETIF_F_NEVER_CHANGE (NETIF_F_VLAN_CHALLENGED | \
NETIF_F_LLTX | NETIF_F_NETNS_LOCAL)
Also, add two more features "tx-tcp-segmentation" and
"tx-tcp6-segmentation". There are two reasons for that:
- systemd-networkd supports setting these two features,
so lets support them too (apparently they are important
enough for networkd).
- these two features are already implicitly covered by "tso".
Like for the "ethtool" program, "tso" is an alias for several
actual features. By adding two features that are already
also covered by an alias (which sets multiple kernel names
at once), we showcase how aliases for the same feature can
coexist. In particular, note how setting
"tso on tx-tcp6-segmentation off" will behave as one would
expect: all 4 tso features covered by the alias are enabled,
except that particular one.
Note that in NetworkManager API (D-Bus, libnm, and nmcli),
the features are called "feature-xyz". The "feature-" prefix
is used, because NMSettingEthtool possibly will gain support
for options that are not only -K|--offload|--features, for
example -C|--coalesce.
The "xzy" suffix is either how ethtool utility calls the feature
("tso", "rx"). Or, if ethtool utility specifies no alias for that
feature, it's the name from kernel's ETH_SS_FEATURES ("tx-tcp6-segmentation").
If possible, we prefer ethtool utility's naming.
Also note, how the features "feature-sg", "feature-tso", and
"feature-tx" actually refer to multiple underlying kernel features
at once. This too follows what ethtool utility does.
The functionality is not yet implemented server-side.
nm_meta_setting_infos_by_name() did a naive search by name by
iterating over all 42 setting types.
Reorder nm_meta_setting_infos array, and use binary search instead.
Previously, each (non abstract) NMSetting class had to register
its name and priority via _nm_register_setting().
Note, that libnm-core.la already links against "nm-meta-setting.c",
which also redundantly keeps track of the settings name and gtype
as well.
Re-use NMMetaSettingInfo also in libnm-core.la, to track this meta
data.
The goal is to get rid of private data structures that track
meta data about NMSetting classes. In this case, "registered_settings"
hash. Instead, we should have one place where all this meta data
is tracked. This was, it is also accessible as internal API,
which can be useful (for keyfile).
Note that NMSettingClass has some overlap with NMMetaSettingInfo.
One difference is, that NMMetaSettingInfo is const, while NMSettingClass
is only initialized during the class_init() method. Appart from that,
it's mostly a matter of taste, whether we attach meta data to
NMSettingClass, to NMMetaSettingInfo, or to a static-array indexed
by NMMetaSettingType.
Note, that previously, _nm_register_setting() was private API. That
means, no user could subclass a functioning NMSetting instance. The same
is still true: NMMetaSettingInfo is internal API and users cannot access
it to create their own NMSetting subclasses. But that is almost desired.
libnm is not designed, to be extensible via subclassing, nor is it
clear why that would be a useful thing to do. One day, we should remove
the NMSetting and NMSettingClass definitions from public headers. Their
only use is subclassing the types, which however does not work.
While libnm-core was linking already against nm-meta-setting.c,
nm_meta_setting_infos was unreferenced. So, this change increases
the binary size of libnm and NetworkManager (1032 bytes). Note however
that roughly the same information was previously allocated at runtime.
NM_GOBJECT_PROPERTIES_DEFINE() defines a helper function
_notify() to emit a GObject property changed notification.
Add another helper function to emit multiple notifications
together, and freeze/thaw the notification before.
This is particularly useful, because our D-Bus glue in
"nm-dbus-object.c" hooks into dispatch_properties_changed(),
to emit a combined PropertiesChanged signal for multiple
properties. By carefully freezing/thawing the notifications,
the exported objects can combine changes of multiple properties
in one D-Bus signal.
This helper is here to make that simpler.
Note that the compiler still has no problem to inline _notify()
entirey. So, in a non-debug build, there is little difference in
the generated code. It can even nicely inline calls like
nm_gobject_notify_together (self, PROP_ADDRESS_DATA,
PROP_ADDRESSES);
We only have a certain granularity of how our headers in "shared/nm-utils"
can be used independently.
For example, it's not supported to use "nm-macros-internal.h" without
"gsystem-local-alloc.h". Likewise, you cannot use "nm-glib.h" directly,
you always get it together with "nm-macros-internal.h".
This is, we don't support to use certain headers entirely independently,
because usually you anyway want to use them together.
As such, no longer support "gsystem-local-alloc.h", but merge the
remainder into "nm-macros-internal.h". There is really no reason
to support arbitrary flexibility of including individual bits. You
want cleanup-macros? Include "nm-macros-internal.h".
Merge the headers.
These cleanup macros are unused by NetworkManager code. Note that
since "shared/nm-utils" is used by applet and VPN plugins, theoretically,
they could be used there. I didn't check that, but breaking API of
"shared/nm-utils" is fine (as long as we catch it with a compilation
error).
Historically, we use libgsystem's gsystem-local-alloc header and their
"gs_*" macros. However, they are not really our style and don't have
a nm-prefix (like the rest of our code). We keep the gs_ names, because
they are wildly used and because we wanted to keep gsystem-local-alloc
in sync with upstream (which is no longer the case).
Our own cleanup macros are always called "nm_auto_*". So, at least
for the unused "gs_*" macros, rename them to "nm_auto_*".
Don't drop them, despite they being unused. The reason is, that we should
make use of cleanup functions more eagerly. Dropping them now -- because
they are momentarily unused -- hampers using them in the future. We
often don't use the cleanup macros at places where I think we should,
so by dropping them, we hamper future use.
Drop unused "gs_fd_close" macro, now that we no longer care about keeping
"gsystem-local-alloc.h" header in sync with (unmaintained) upstream.
Also, our own "nm_auto_close" macro should be preferred, because
- it preserves errno
- it uses nm_close(), which asserts against EBADF.