nmc_read_connection_properties() iterates over the input arguments, and
completes the connection.
Initially, the type is not yet known, in that case, we should not wrongly
assume that this is a generic connection. Later, when the type is specified,
con_settings() will return the correct settings.
Previously, this would wrongly add a [generic] section:
$ nmcli connection add type ethernet ifname eth1 con-name ethie autoconnect no ipv4.method auto ethernet.cloned-mac-address random
With the fix, it still works to specify the type later:
$ nmcli connection add ifname eth1 con-name ethie autoconnect no ipv4.method auto type ethernet
but it doesn't work, to specify the type after type-specific options:
$ nmcli connection add ifname eth1 con-name ethie autoconnect no ipv4.method auto ethernet.cloned-mac-address random type ethernet
Error: invalid or not allowed setting 'ethernet': 'ethernet' not among [connection, ipv4, ipv6, proxy].
The patch doesn't change the latter limitation.
Fixes: c5324ed285
shared/nm-utils/nm-hash-utils.c:110:3: error: right shift count >= width of type [-Werror]
h = h ^ ((guint) (((uintptr_t) ptr) >> 32)) ^ ((guint) ((uintptr_t) ptr));
^
Even if the branch is not reached on 32-bit architectures, the
compiler still emits a warning for the 32-bit right shift.
Fixes: ee76b0979f
Previously, nm_setting_diff() would return !(*results), that means,
if the caller passed in a hash table (empty or not), the return value
would always be FALSE, indicating a difference.
That is not documented, and makes no sense.
The return value, should solely indicate whether some difference was
found. The only convenience is, if nm_setting_diff() created a hash
table internally and no difference was found, it would destroy
it again, without returning it to the caller.
NMSettingGeneric has no properties at all. Hence, nm_connection_diff() would report that
a connection A with a generic setting and a connection B without a generic setting are
equal.
They are not. For empty settings, let nm_setting_diff() return also empty difference
hash.
Before commit 3ecb57fdc4 ("settings: get rid of callback arguments
for nm_settings_connection_delete()") audit logging was done in the
callback, which was run by nm_settings_connection_delete() with a
reference to the connection to keep it alive. Now we have to keep an
extra reference to ensure it doesn't go away.
Fixes: 3ecb57fdc4
Add dhclient and iptables packages to build dependencies to satisfy
rpmbuild complaints:
```
error: Failed build dependencies:
dhclient is needed by NetworkManager-1:1.9.2-18653.43dba57439.fc28.x86_64
iptables is needed by NetworkManager-1:1.9.2-18653.43dba57439.fc28.x86_64
ERROR: rpmbuild FAILED
```
https://github.com/NetworkManager/NetworkManager/pull/33
Eventually, we want to fully implement policy routing and
handle rules as well. When that happens, we will use the
route-table setting to tell NetworkManager to handle the
rule file as well.
Since we currently don't yet support that, we should reject
configuring a non-zero routing table combined with a rule file,
because later we will change behavior in that case.
We should support an arbitrary number of routes and addresses.
Arguably, our accessors for shvarFile are O(n), hence with
large ifcfg files, we will have a performance problem. The
fix for that would be to index the files.
The only implementation of can_commit() was ifcfg-rh, which
bails out with complex routes.
Note that the only caller of can_commit() (update_auth_cb()),
immidiately afterwards called nm_settings_connection_commit_changes(),
which, a few layers down in nms_ifcfg_rh_writer_write_connection()
as first thing errors out in presence of complex routes.
The check was redundant.
In general, a can_commit() function before a commit_changes() makes
no sense, because commit_changes() can just fail with error.
write_ip4_aliases() does not collect internal in-memory state, instead
it writes state to disk and deletes extraneous alias files.
It should be done after we completed our pre-run checks to generated
the data we want to write.
Instead of having set_secret() for each call open the file,
mangle it, and write it back, collect all secrets and process
them at the end once.
Also, previously set_secrets() ignored failures to write a secret and
added the secret in plain to the ifcfg file. Let's not do that.
Also, purge all other entires form the secrets file. Not only
the once that we explicitly touch.
Eventually, we should generate all configuration in-memory
first, and only after validating everything write to disk.
That avoids that we start touching files, and later encounter
a fatal error that let's us abort writing the connection.
Also, previously, we would not purge the route file if
write_ip6_setting() returns early for slave types.
- we now safe all routes we have, not limited to 256.
- we use svUnsetAll() to delete the existing keys. This is
faster then probing them one-by-one, and not limited to
256 keys (which we were checking before).
Note that we always try to load an existing file and
drop the unneeded keys. We do that, so that unrelated
entries and comments don't get the deleted. Also, so
that the order of the variables is not changed.
When calling svOpenFileInternal() with @create, we don't care about
potential errors reading the file. We shouldn't return NULL in such
case, but always create a shvarFile instance.
They are basically the same, with a minor difference where the @filename
argument determines whether to write a new file or do an update.
Also, rename them, to give them a nms_* prefix in the header file.
As writing a connection to disk might modify it, we re-read
it back and use what we actually found on disk.
For example, if you have a connection with ipv6.method=ignore,
ifcfg-rh writer will not persist the ipv6.route-metric. That
is likely a bug in the writer. Before this patch, changing
the route metric would seemingly succeed, but on the next reload
from this, the changes are lost.
We should fix such bugs. Regardless, it's better to pick up
what we wrote to disk, instead of later.
Previously, we would first call replace_settings(), followed by
commit_changes(). There are two problems with that:
- commit_changes() might fail easily, for example if the settings
plugin cannot handle the connection. In that case, we fail the operation,
but still we already replaced the settings in memory. We should
first write to disk, and only when that succeeded, replace our
settings.
Also, note that replace_settings() cannot really fail at that
point, because we already validate the setting previously
(everything else would be a bug).
- commit_changes() might modify the connection while writing it.
We re-read it and replace the settings. If we already replaced
it before, we replcace the settings twice -- needlessly.
During write, it can regularly happen that the connection gets modified.
For example, keyfile never writes blobs as-is, it always writes the
blob to an external file, and replaces the certificate property with
a path.
Other reasons could be just bugs, where the reader and writer are not doing
a proper round trip (these cases should be fixed).
Refactor commit_changes(), to return the re-read connection to
the settings-connection class, and handle replacing the settings
there.
Also, prepare for another change. Sometimes we first call replace_settings()
followed by commit_changes(). It would be better to instead call commit_changes()
first, and only on success proceed with replace_settings(). Hence, commit_changes()
gets a new argument new_connection, that can be used to write another
connection to disk.
Don't delegate so much to the virtual function commit_changes().
Calling the callback is not the task of the virtual function,
because every implementation must do that.
There are some minor changes in behavior for ifnet, where we now
first setup the monitors and reload the parsers, before invoking
the callback.
The virtual function replace_and_commit() had only one implementation: ifcfg-rh.
Refactor the code, to delegate less. That is, the main part of
replace-and-commit is not delegated to a virtual function.
Now, the virtual function is only a pre-check hook, so that
the ifcfg-rh implementation can abort the function.
There are no functional changes.
Also, need to avoid danling pointers in clear_monitor().
This was not really a problem, because we would always call
cancel() before setup(). Still, it's fragile.