NMSettingEthtool is implemented using "gendata", meaning a hash
of GVariant. This is different from most other settings that have
properties implemented as GObject properties. There are two reasons
for this approach:
- The setting is transferred via D-Bus as "a{sv}" dictionary.
By unpacking the dictionary into GObject properties, the setting
cannot handle unknown properties. To be forward compatible (and
due to sloppy programming), unknown dictionary keys are silently
ignored when parsing a NMSetting. That is error prone and also
prevents settings to be treated loss-less.
Instead, we should at first accept all values from the dictionary.
Only in a second step, nm_connection_verify() rejects invalid settings
with an error reason. This way, the user can create a NMSetting,
but in a separate step handle if the setting doesn't verify.
"gendata" solves this by tracking the full GVariant dictionary.
This is still not entirely lossless, because multiple keys are
combined.
This is for example interesting if an libnm client fetches a connection
from a newer NetworkManager version. Now the user can modify the
properties that she knows about, while leaving all unknown
properties (from newer versions) in place.
- the approach aims to reduce the necessary boiler plate to create
GObject properties. Adding a new property should require less new code.
This approach was always be intended to be suitable for all settings, not only
NMSettingEthtool. We should not once again try to add API like
nm_setting_ethtool_set_feature(), nm_setting_ethtool_set_coalesce(), etc.
Note that the option name already fully encodes whether it is a feature,
a coalesce option, or whatever. We should not have
"nm_setting_set_$SUB_GROUP (setting, $ONE_NAME_FROM_GROUP)" API, but
simply "nm_setting_option_set (setting, $OPTION)" accessors.
Also, when parsing a NMSettingEthtool from a GVariant, then a feature
option can be any kind of variant. Only nm_setting_verify() rejects
variants of the wrong type. As such, nm_setting_option_set*() also
doesn't validate whether the variant type matches the option. Of course,
if you set a value of wrong type, verify() will reject the setting.
Add new general purpose API for this and expose it for NMSetting.
When parsing user input if is often convenient to allow stripping whitespace.
Especially with escaped strings, the user could still escape the whitespace,
if the space should be taken literally.
Add support for that to nm_utils_buf_utf8safe_unescape().
Note that this is not the same as calling g_strstrip() before/after
unescape. That is, because nm_utils_buf_utf8safe_unescape() correctly
preserves escaped whitespace. If you call g_strstrip() before/after
the unescape, you don't know whether the whitespace is escaped.
Reported by coverity:
>>> CID 210230: Control flow issues (UNREACHABLE)
>>> This code cannot be reached: "i = 0;".
Fixes: 09e17888f7 ('libnm: add mapping functions between string and NMClientPermission enum')
Reported by coverity:
>>> CID 210228: Null pointer dereferences (REVERSE_INULL)
>>> Null-checking "dbobj" suggests that it may be null, but it has
already been dereferenced on all paths leading to the check.
Fixes: ce0e898fb4 ('libnm: refactor caching of D-Bus objects in NMClient')
Add a new "driver" match option to nm-settings. It allows to disable a
network connection configuration if a pattern is found or is not found
in the device driver name.
Add a new "kernel-command-line" match option to nm-settings. It allows
to disable a network connection configuration if a pattern is found or
is not found in /proc/cmdline.
env -i starts with an empty environment, which is undesired when the build
environment needs certain environment variables to function.
One such example is a custom PYTHONPATH, which gets dropped by env -i and
results in the nm-settings-docs.xml generator not finding the gi Python module.
https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/478
g_clear_pointer() would always cast the destroy notify function
pointer to GDestroyNotify. That means, it lost some type safety, like
GPtrArray *ptr_arr = ...
g_clear_pointer (&ptr_arr, g_array_unref);
Since glib 2.58 ([1]), g_clear_pointer() is also more type safe. But
this is not used by NetworkManager, because we don't set
GLIB_VERSION_MIN_REQUIRED to 2.58.
[1] f9a9902aac
We have nm_clear_pointer() to avoid this issue for a long time (pre
1.12.0). Possibly we should redefine in our source tree g_clear_pointer()
as nm_clear_pointer(). However, I don't like to patch glib functions
with our own variant. Arguably, we do patch g_clear_error() in
such a manner. But there the point is to make the function inlinable.
Also, nm_clear_pointer() returns a boolean that indicates whether
anything was cleared. That is sometimes useful. I think we should
just consistently use nm_clear_pointer() instead, which does always
the preferable thing.
Replace:
sed 's/\<g_clear_pointer *(\([^;]*\), *\([a-z_A-Z0-9]\+\) *)/nm_clear_pointer (\1, \2)/g' $(git grep -l g_clear_pointer) -i
I think it's preferable to use nm_clear_g_free() instead of
g_clear_pointer(, g_free). The reasons are not very strong,
but I think it is overall preferable to have a shorthand for this
frequently used functionality.
sed 's/\<g_clear_pointer *(\([^;]*\), *\(g_free\) *)/nm_clear_g_free (\1)/g' $(git grep -l g_clear_pointer) -i
With 1.22, various synchronous functions for invoking D-Bus methods were
deprecated. The reason was that D-Bus is fundamentally asynchronous, and
providing synchronous API in NMClient is inherently wrong. That is
because NMClient essentially is a cache of the D-Bus API, and invoking
g_dbus_connection_call_sync() messes up the order of events from D-Bus.
In particular, when the synchronous function completes, the content of
the cache does not yet reflect the change.
Since they got deprecated, the question is with what to replace them.
Instead of adding a (e.g.) nm_client_networking_set_enabled_async()
for nm_client_networking_set_enabled(), just expect the user to call
D-Bus directly.
D-Bus itself defines a reasonable API, and with GDBusConnection it
is fine (and convenient) to just call D-Bus operations directly.
Often libraries try to abstract D-Bus by providing convenience
wrappers around D-Bus API. I think that often is wrong and unnecessary.
Note that libnm's NMClient does a lot more than just wrapping simple
D-Bus calls. It provides a complete client-side cache of the D-Bus
interface. As such, what libnm's NMClient does is more than simple
wrappers around D-Bus. NMClient is a reasonable thing to do.
However, it is unnecessary to add API like nm_client_networking_set_enabled_async()
that only calls g_dbus_connection_call(). Don't pretend that we would need such
trivial wrappers in libnm.
Instead, recommend to use g_dbus_connection_call(). Or alternatively,
the convenience wrappers nm_client_dbus_call() and
nm_client_dbus_set_property().
Similar to nm_client_dbus_call(), but useful for setting a D-Bus
property on NetworkManager's D-Bus interface.
Note that we currently have various synchronous API for setting D-Bus
properties (like nm_client_networking_set_enabled()). Synchronous
API does not play well with the content of NMClient's cache, and was
thus deprecated. However, until now no async variant exists.
Instead of adding multiple async operations, I think it should be
sufficient to only add one nm_client_dbus_set_property() property.
It's still reasonably convenient to use for setting a property.
Add an API for calling D-Bus methods arbitrary objects of
NetworkManager's API.
Of course, this is basically just a call to g_dbus_connection_call(),
using the current name owner, nm_client_get_dbus_connection() and
nm_client_get_main_context().
All of this could also be achieved without this new API. However,
nm_client_dbus_call() also gracefully handles if the current name
owner is %NULL.
It's a valid concern whether such API is useful, as the users already
have all pieces to do it themself. I think it is.
Add 'nm_setting_bond_get_option_normalized()', the purpose of this API
is to retrieve a bond option normalized value which is the option that
NetworkManager will actually apply to the bond when activating the
connection, this takes into account default values for some options that
NM assumes.
For example, if you create a connection:
$ nmcli c add type bond con-name nm-bond ifname bond0 bond.options mode=0
Calling 'nm_setting_bond_get_option_normalized(s_bond, "miimon")' would
return "100" as even if not specified NetworkManager enables miimon for
bond connections.
Another example:
$ nmcli c add type bond con-name nm-bond ifname bond0 bond.options mode=0,arp_interval=100
Calling 'nm_setting_bond_get_option_normalized(s_bond, "miimon")' would
return NULL in this case because NetworkManager disables miimon if
'arp_interval' is set explicitly but 'miimon' is not.
nm_setting_ip6_config_get_ra_timeout() was backported to nm-1-22 branch, and
will be released as 1.22.8. As such, on the stable branch the symbol will be
placed in a separate symbol version ("libnm_1_22_8").
To support the upgrade path from 1.22.8+ to 1.23+, we want this symbol
also present on master.
At that point, we don't need to duplicate the symbol. Just add the same linker
symbol version also to master.