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.
Since commit 5c299454b4 we can configure
multiple default-routes.
That is especially useful with IPv6 to configure multiple routers.
It will also be useful, once we allow configuring manual default-routes,
like regular static routes.
However the problem is, that the default-route for the manual gateway
and the gateway from DHCP both get the same metric. So it's undefined
which route is used. To avoid that problem, and to restore previous
behavior, don't accept any default-routes if a gateway is set.
Fixes: 5c299454b4
After commit 5c299454b4 ("core: rework tracking of
gateway/default-route in ip-config") NM set a default route for VPNs
only based on the "never-default" option reported by the plugin. It
should also consider the connection setting.
Fixes: 5c299454b4https://bugzilla.redhat.com/show_bug.cgi?id=1505886
Setting the MTU might fail when the underlying device's MTU
is not set.
Detect that case, and log a better warning message.
Unfortunately, it's tricky to detect whether this is a complete
failure, or whether we will later try again to change the MTU.
So, we log a failure, altough later we might fix it. It would
be better not to warn about non-errors.
and nm_utils_ip6_property_path(). The API with static buffers
looks a bit nicer. But I think they are dangerous, because
we tend to pass the buffer down several layers of the stack, and
it's not immediately clear, that we don't overwrite the static
buffer again (which we probably did not, but it's hard to verify
that there is no bug there).
Setting the MTU failes under regular conditions, for example when
setting the MTU of a master larger then the MTU of the slaves.
Logging a warning it too alarming.
Kernel does not allow setting the MTU of a VLAN larger
then the MTU of the underlying device. Hence, we might
initially fail to set a large MTU of the VLAN, but we
have to retry when the MTU of the parent changes.
https://bugzilla.redhat.com/show_bug.cgi?id=1414901