NMSetting internally already tracked a list of all proper GObject properties
and D-Bus-only properties.
Rework the tracking of the list, so that:
- instead of attaching the data to the GType of the setting via
g_type_set_qdata(), it is tracked in a static array indexed by
NMMetaSettingType. This allows to find the setting-data by simple
pointer arithmetic, instead of taking a look and iterating (like
g_type_set_qdata() does).
Note, that this is still thread safe, because the static table entry is
initialized in the class-init function with _nm_setting_class_commit().
And it only accessed by following a NMSettingClass instance, thus
the class constructor already ran (maybe not for all setting classes,
but for the particular one that we look up).
I think this makes initialization of the metadata simpler to
understand.
Previously, in a first phase each class would attach the metadata
to the GType as setting_property_overrides_quark(). Then during
nm_setting_class_ensure_properties() it would merge them and
set as setting_properties_quark(). Now, during the first phase,
we only incrementally build a properties_override GArray, which
we finally hand over during nm_setting_class_commit().
- sort the property infos by name and do binary search.
Also expose this meta data types as internal API in nm-setting-private.h.
While not accessed yet, it can prove beneficial, to have direct (internal)
access to these structures.
Also, rename NMSettingProperty to NMSettInfoProperty to use a distinct
naming scheme. We already have 40+ subclasses of NMSetting that are called
NMSetting*. Likewise, NMMetaSetting* is heavily used already. So, choose a
new, distinct name.
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.
- Don't use @parent_class name. This local variable (and @object_class) is
the class instance up-cast to the pointer types of the parents. The point
here is not that it is the direct parent. The point is, that it's the
NMSettingClass type.
Also, it can only be used inconsistently, in face of NMSettingIP4Config,
who's parent type is NMSettingIPConfig. Clearly, inside
nm-setting-ip4-config.c we wouldn't want to use the "parent_class"
name. Consistently rename @parent_class to @setting_class.
- Also rename the pointer to the own class to @klass. "setting_class" is also the
wrong name for that, because the right name would be something like
"setting_6lowpan_class".
However, "klass" is preferred over the latter, because we commonly create new
GObject implementations by copying an existing one. Generic names like "klass"
and "self" inside a type implementation make that simpler.
- drop useless comments like
/* virtual functions */
/* Properties */
It's better to logically and visually structure the code, and avoid trival
remarks about that. They only end up being used inconsistently. If you
even need a stronger visual separator, then an 80 char /****/ line
should be preferred.
constructor functions are ugly, because code is running before
main() starts. Instead, as the registration code for NMSetting types
is insid the GType constructor, we just need to ensure at the
right place, that the GType was created.
The right place here is _register_settings_ensure_inited(), because
that is called before we need the registration information.
Usecase: when connecting to a public Wi-Fi with MAC address randomization
("wifi.cloned-mac-address=random") you get on every re-connect a new
IP address due to the changing MAC address.
"wifi.cloned-mac-address=stable" is the solution for that. But that
means, every time when reconnecting to this network, the same ID will
be reused. We want an ID that is stable for a while, but at a later
point a new ID should e generated when revisiting the Wi-Fi network.
Extend the stable-id to become dynamic and support templates/substitutions.
Currently supported is "${CONNECTION}", "${BOOT}" and "${RANDOM}".
Any unrecognized pattern is treated verbaim/untranslated.
"$$" is treated special to allow escaping the '$' character. This allows
the user to still embed verbatim '$' characters with the guarantee that
future versions of NetworkManager will still generate the same ID.
Of course, a user could just avoid '$' in the stable-id unless using
it for dynamic substitutions.
Later we might want to add more recognized substitutions. For example, it
could be useful to generate new IDs based on the current time. The ${} syntax
is extendable to support arguments like "${PERIODIC:weekly}".
Also allow "connection.stable-id" to be set as global default value.
Previously that made no sense because the stable-id was static
and is anyway strongly tied to the identity of the connection profile.
Now, with dynamic stable-ids it gets much more useful to specify
a global default.
Note that pre-existing stable-ids don't change and still generate
the same addresses -- unless they contain one of the new ${} patterns.
Long ago before commit 1b49f94, NetworkManager did not touch the
MAC address at all. Since 0.8.2 NetworkManager would modify the
MAC address, and eventually it would reset the permanent MAC address
of the device.
This prevents a user from externally setting the MAC address via tools
like macchanger and rely on NetworkManager not to reset it to the
permanent MAC address. This is considered a security regression in
bgo#708820.
This only changed with commit 9a354cd and 1.4.0. Since then it is possible
to configure "cloned-mac-address=preserve", which instead uses the "initial"
MAC address when the device activates.
That also changed that the "initial" MAC address is the address which was
externally configured on the device as last. In other words, the
"initial" MAC address is picked up from external changes, unless it
was NetworkManager itself who configured the address when activating a
connection.
However, in absence of an explicit configuration the default for
"cloned-mac-address" is still "permanent". Meaning, the user has to
explicitly configure that NetworkManager should not touch the MAC address.
It makes sense to change the upstream default to "preserve". Although this
is a change in behavior since 0.8.2, it seems a better default.
This change has the drastic effect that all the existing connections
out there with "cloned-mac-address=$(nil)" change behavior after upgrade.
I think most users won't notice, because their devices have the permanent
address set by default anyway. I would think that there are few users
who intentionally configured "cloned-mac-address=" to have NetworkManager
restore the permanent address.
https://bugzilla.gnome.org/show_bug.cgi?id=770611
For the per-connection settings "ethernet.cloned-mac-address"
and "wifi.cloned-mac-address", and for the per-device setting
"wifi.scan-rand-mac-address", we may generate MAC addresses using
either the "random" or "stable" algorithm.
Add new properties "generate-mac-address-mask" that allow to configure
which bits of the MAC address will be scrambled.
By default, the "random" and "stable" algorithms scamble all bits
of the MAC address, including the OUI part and generate a locally-
administered, unicast address.
By specifying a MAC address mask, we can now configure to perserve
parts of the current MAC address of the device. For example, setting
"FF:FF:FF:00:00:00" will preserve the first 3 octects of the current
MAC address.
One can also explicitly specify a MAC address to use instead of the
current MAC address. For example, "FF:FF:FF:00:00:00 68:F7:28:00:00:00"
sets the OUI part of the MAC address to "68:F7:28" while scrambling
the last 3 octects.
Similarly, "02:00:00:00:00:00 00:00:00:00:00:00" will scamble
all bits of the MAC address, except clearing the second-least
significant bit. Thus, creating a burned-in address, globally
administered.
One can also supply a list of MAC addresses like
"FF:FF:FF:00:00:00 68:F7:28:00:00:00 00:0C:29:00:00:00 ..." in which
case a MAC address is choosen randomly.
To fully scamble the MAC address one can configure
"02:00:00:00:00:00 00:00:00:00:00:00 02:00:00:00:00:00".
which also randomly creates either a locally or globally administered
address.
With this, the following macchanger options can be implemented:
`macchanger --random`
This is the default if no mask is configured.
-> ""
while is the same as:
-> "00:00:00:00:00:00"
-> "02:00:00:00:00:00 02:00:00:00:00:00"
`macchanger --random --bia`
-> "02:00:00:00:00:00 00:00:00:00:00:00"
`macchanger --ending`
This option cannot be fully implemented, because macchanger
uses the current MAC address but also implies --bia.
-> "FF:FF:FF:00:00:00"
This would yields the same result only if the current MAC address
is already a burned-in address too. Otherwise, it has not the same
effect as --ending.
-> "FF:FF:FF:00:00:00 <MAC_ADDR>"
Alternatively, instead of using the current MAC address,
spell the OUI part out. But again, that is not really the
same as macchanger does because you explictly have to name
the OUI part to use.
`machanger --another`
`machanger --another_any`
-> "FF:FF:FF:00:00:00 <MAC_ADDR> <MAC_ADDR> ..."
"$(printf "FF:FF:FF:00:00:00 %s\n" "$(sed -n 's/^\([0-9a-fA-F][0-9a-fA-F]\) \([0-9a-fA-F][0-9a-fA-F]\) \([0-9a-fA-F][0-9a-fA-F]\) .*/\1:\2:\3:00:00:00/p' /usr/share/macchanger/wireless.list | xargs)")"
Extend the "ethernet.cloned-mac-address" and "wifi.cloned-mac-address"
settings. Instead of specifying an explicit MAC address, the additional
special values "permanent", "preserve", "random", "random-bia", "stable" and
"stable-bia" are supported.
"permanent" means to use the permanent hardware address. Previously that
was the default if no explict cloned-mac-address was set. The default is
thus still "permanent", but it can be overwritten by global
configuration.
"preserve" means not to configure the MAC address when activating the
device. That was actually the default behavior before introducing MAC
address handling with commit 1b49f941a6.
"random" and "random-bia" use a randomized MAC address for each
connection. "stable" and "stable-bia" use a generated, stable
address based on some token. The "bia" suffix says to generate a
burned-in address. The stable method by default uses as token the
connection UUID, but the token can be explicitly choosen via
"stable:<TOKEN>" and "stable-bia:<TOKEN>".
On a D-Bus level, the "cloned-mac-address" is a bytestring and thus
cannot express the new forms. It is replaced by the new
"assigned-mac-address" field. For the GObject property, libnm's API,
nmcli, keyfile, etc. the old name "cloned-mac-address" is still used.
Deprecating the old field seems more complicated then just extending
the use of the existing "cloned-mac-address" field, although the name
doesn't match well with the extended meaning.
There is some overlap with the "wifi.mac-address-randomization" setting.
https://bugzilla.gnome.org/show_bug.cgi?id=705545https://bugzilla.gnome.org/show_bug.cgi?id=708820https://bugzilla.gnome.org/show_bug.cgi?id=758301
- All internal source files (except "examples", which are not internal)
should include "config.h" first. As also all internal source
files should include "nm-default.h", let "config.h" be included
by "nm-default.h" and include "nm-default.h" as first in every
source file.
We already wanted to include "nm-default.h" before other headers
because it might contains some fixes (like "nm-glib.h" compatibility)
that is required first.
- After including "nm-default.h", we optinally allow for including the
corresponding header file for the source file at hand. The idea
is to ensure that each header file is self contained.
- Don't include "config.h" or "nm-default.h" in any header file
(except "nm-sd-adapt.h"). Public headers anyway must not include
these headers, and internal headers are never included after
"nm-default.h", as of the first previous point.
- Include all internal headers with quotes instead of angle brackets.
In practice it doesn't matter, because in our public headers we must
include other headers with angle brackets. As we use our public
headers also to compile our interal source files, effectively the
result must be the same. Still do it for consistency.
- Except for <config.h> itself. Include it with angle brackets as suggested by
https://www.gnu.org/software/autoconf/manual/autoconf.html#Configuration-Headers
Some drivers (or things outside NM like 'powertop') may turn powersave
on, so don't touch it unless explicitly configured by user.
To achieve this, add new 'default' and 'ignore' options; the former
can be used to fall back to a globally configured setting, while the
latter tells NM not to touch the current setting.
When 'default' is specified, a missing global default configuration is
equivalent to 'ignore'.
It is possible to enable Wi-Fi power saving for all connections by
dropping a file in /etc/NetworkManager/conf.d with the following
content:
[connection]
wifi.powersave=3
https://bugzilla.gnome.org/show_bug.cgi?id=760125
Old init-scripts that did not yet understand this key will have
mac-address-randomization explicitly disabled. This is to ensure
that old connections don't change behavior.
Thus, the writer must always write the value explicitly.
Downside is, if somebody creates a quick ifcfg-file, the feature
is disabled by default.
We want "nm-dbus-interface.h" to have no dependancy on libnm and glib.
That way, it is usable for example in the QT examples without dragging
in dependencies to glib.
Also drop all the unneccessary include to "nm-dbus-interface.h", which
we already get by directly or indirectly including "nm-core-types.h".
The localization headers are now included via "nm-default.h".
Also fixes several places, where we wrongly included <glib/gi18n-lib.h>
instead of <glib/gi18n.h>. For example under "clients/" directory.
Add "---dbus---" sections to the NMSetting property docs, in the same
style as the plugin docs, parse them out into a file
"nm-setting-docs-overrides.xml", and use them to override the GObject
property docs in nm-setting-docs.xml.
This lets us put more D-Bus-specific information in the setting docs,
without cluttering up the property docs, and it also lets us document
dbus-only properties.
Each GBytes-valued property was using
_nm_setting_class_transform_property() to register a GBytes<->'ay'
transform. So just build that rule into the generic machinery in
nm-setting.c.
Move the settings/plugins doc generation from libnm-util to
libnm-core, since libnm-util isn't being updated for all new
properties.
With this commit, the keyfile and ifcfg-rh documentation is basically
unchanged, except that deprecated properties are now gone, and new
properties have been added, and the sections are in a different order.
(generate-plugin-docs.pl just outputs the settings in Makefile order,
and they were unsorted in libnm-util, but are sorted in libnm-core).
The settings documentation used for nm-settings.5, the D-Bus API docs,
and the nmcli help is changed a bit more at this point, and mostly for
the worse, since the libnm-core setting properties don't match up with
the D-Bus API as well as the libnm-util ones do. To be fixed...
(I also removed the "plugins docs" line in each plugin docs comment
block while moving them, since those blocks will be used for more than
just plugins soon, and it's sort of obvious anyway.)
All the old "const GByteArray" methods got changed to return a GBytes
instead, but since they aren't declared "const" any more, we need to
explicitly annotate them "(transfer none)".
Also, the scanner apparently doesn't recognize that an (out)
"const char **" is "(transfer none)", so annotate that in two places
too
Libraries need to include <gi18n-lib.h>, not <gi18n.h>, so that _()
will get defined to "dgettext (GETTEXT_DOMAIN, string)" rather than
"gettext (string)" (which will use the program's default domain, which
works fine for programs in the NetworkManager tree, but not for
external users). Likewise, we need to call bindtextdomain() so that
gettext can find the translations if the library is installed in a
different prefix from the program using it (and
bind_textdomain_codeset(), so it will know the translations are in
UTF-8 even if the locale isn't).
(The fact that no one noticed this was broken before is because the
libraries didn't really start returning useful translated strings much
until 0.9.10, and none of the out-of-tree clients have been updated to
actually show those strings to users yet.)
config.h should be included from every .c file, and it should be
included before any other include. Fix that.
(As a side effect of how I did this, this also changes us to
consistently use "config.h" rather than <config.h>. To the extent that
it matters [which is not much], quotes are more correct anyway, since
we're talking about a file in our own build tree, not a system
include.)
nm_setting_verify() took a GSList of other NMSettings, but really it
would just be simpler all around to pass the NMConnection instead...
This means that several formerly NMSetting-branded functions that
operated on lists-of-settings now get replaced with
NMConnection-branded functions instead.
Each setting type was defining its own error type, but most of them
had exactly the same three errors ("unknown", "missing property", and
"invalid property"), and none of the other values was of much use
programmatically anyway.
So, this commit merges NMSettingError, NMSettingAdslError, etc, all
into NMConnectionError. (The reason for merging into NMConnectionError
rather than NMSettingError is that we also already have
"NMSettingsError", for errors related to the settings service, so
"NMConnectionError" is a less-confusable name for settings/connection
errors than "NMSettingError".)
Also, make sure that all of the affected error messages are localized,
and (where appropriate) prefix them with the relevant property name.
Renamed error codes:
NM_SETTING_ERROR_PROPERTY_NOT_FOUND -> NM_CONNECTION_ERROR_PROPERTY_NOT_FOUND
NM_SETTING_ERROR_PROPERTY_NOT_SECRET -> NM_CONNECTION_ERROR_PROPERTY_NOT_SECRET
Remapped error codes:
NM_SETTING_*_ERROR_MISSING_PROPERTY -> NM_CONNECTION_ERROR_MISSING_PROPERTY
NM_SETTING_*_ERROR_INVALID_PROPERTY -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_ERROR_PROPERTY_TYPE_MISMATCH -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_BLUETOOTH_ERROR_TYPE_SETTING_NOT_FOUND -> NM_CONNECTION_ERROR_INVALID_SETTING
NM_SETTING_BOND_ERROR_INVALID_OPTION -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_BOND_ERROR_MISSING_OPTION -> NM_CONNECTION_ERROR_MISSING_PROPERTY
NM_SETTING_CONNECTION_ERROR_TYPE_SETTING_NOT_FOUND -> NM_CONNECTION_ERROR_MISSING_SETTING
NM_SETTING_CONNECTION_ERROR_SLAVE_SETTING_NOT_FOUND -> NM_CONNECTION_ERROR_MISSING_SETTING
NM_SETTING_IP4_CONFIG_ERROR_NOT_ALLOWED_FOR_METHOD -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_IP6_CONFIG_ERROR_NOT_ALLOWED_FOR_METHOD -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_VLAN_ERROR_INVALID_PARENT -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_WIRELESS_SECURITY_ERROR_MISSING_802_1X_SETTING -> NM_CONNECTION_ERROR_MISSING_SETTING
NM_SETTING_WIRELESS_SECURITY_ERROR_LEAP_REQUIRES_802_1X -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_WIRELESS_SECURITY_ERROR_LEAP_REQUIRES_USERNAME -> NM_CONNECTION_ERROR_MISSING_PROPERTY
NM_SETTING_WIRELESS_SECURITY_ERROR_SHARED_KEY_REQUIRES_WEP -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_WIRELESS_ERROR_CHANNEL_REQUIRES_BAND -> NM_CONNECTION_ERROR_MISSING_PROPERTY
Dropped error codes (were previously defined but unused):
NM_SETTING_CDMA_ERROR_MISSING_SERIAL_SETTING
NM_SETTING_CONNECTION_ERROR_IP_CONFIG_NOT_ALLOWED
NM_SETTING_GSM_ERROR_MISSING_SERIAL_SETTING
NM_SETTING_PPP_ERROR_REQUIRE_MPPE_NOT_ALLOWED
NM_SETTING_PPPOE_ERROR_MISSING_PPP_SETTING
NM_SETTING_SERIAL_ERROR_MISSING_PPP_SETTING
NM_SETTING_WIRELESS_ERROR_MISSING_SECURITY_SETTING
In preparation for porting to GDBus, make nm_connection_to_dbus(),
etc, represent connections as GVariants of type 'a{sa{sv}}' rather
than as GHashTables-of-GHashTables-of-GValues.
This means we're constantly converting back and forth internally, but
this is just a stepping stone on the way to the full GDBus port, and
all of that code will go away again later.
Change all DBUS_TYPE_G_UCHAR_ARRAY properties to G_TYPE_BYTES, and
update corresponding APIs. Notably, this means they are now refcounted
rather than being copied.
Update the rest of NM for the changes. The daemon still converts SSIDs
to GByteArrays internally, because changing it to use GBytes has lots
of trickle-down effects. It can possibly be changed later.
Change all DBUS_TYPE_G_LIST_OF_STRING and DBUS_TYPE_G_ARRAY_OF_STRING
properties to G_TYPE_STRV, and update everything accordingly.
(This doesn't actually require using
_nm_setting_class_transform_property(); dbus-glib is happy to transform
between 'as' and G_TYPE_STRV.)
Make all mac-address properties (including NMSettingBluetooth:bdaddr,
NMSettingOlpcMesh:dhcp-anycast-addr, and NMSettingWireless:bssid) be
strings, using _nm_setting_class_transform_property() to handle
translating to/from binary form when dealing with D-Bus.
Update everything accordingly for the change, and also add a test for
transformed setting properties to test-general.
NMParamSpecSpecialized existed basically to provide a version of
GParamSpecBoxed that could compare dbus-glib-valued properties
correctly.
However, g_param_values_cmp() was only used by NM directly in one
place (NMSetting's compare_property()), and we don't actually need to
indirect through GParamSpec there; we could just call
NMParamSpecSpecialized's value-comparison function directly.
So, change all NMParamSpecSpecialized properties to GParamSpecBoxed,
rename the _gvalues_compare() function it used to
"nm_property_compare()", and use that from NMSetting.
(g_param_values_cmp() also gets used internally by
g_param_value_defaults(), but all NMParamSpecSpecialized properties
have a default value of NULL, so GParamSpecBoxed's pointer-equality
check will do the job just fine there.)
Simplify the use of _nm_register_setting() by having it splice
together various symbol names itself rather than requiring them to be
specified explicitly, and extend it to also ensure that the type's
corresponding error type is registered (allowing one to find it via
g_type_from_name() if necessary).
Drop the NMSetting properties that were marked deprecated in
libnm-util in 0.9.10, but use nm_setting_class_add_dbus_property() to
deal with them appropriately when serializing/deserializing.