The parent device is just the device that happens to be the best device.
It does not mean, that its route metric should be inherited to the VPN
connection.
This also makes the resulting route metric for VPN connections much
more predictable: now it is either ipv4.route-metric from the connection,
or it falls back to NM_VPN_ROUTE_METRIC_DEFAULT (10).
Also read the command line argument as G_OPTION_ARG_INT64 type. Otherwise, on
32-bit integers, you could not enter any number larger then G_MAXINT32.
Signed-off-by: Thomas Haller <thaller@redhat.com>
For IPv4 addresses, the kernel automatically adds a route when
configuring an IP address. Unfortunately, there is no way to control
this behavior or to set the route metric.
Fix this, by adding our own route and removing the kernel provided
one.
Note that this adds a major change in that we no longer call
nm_ip4_config_commit() for assumed devices.
https://bugzilla.gnome.org/show_bug.cgi?id=723178
Signed-off-by: Thomas Haller <thaller@redhat.com>
NMIPRoute is used by NMSettingIPConfig, but also
NMIPConfig. In the former case, default routes are (still)
disallowed. But in the NMIPConfig use-case, it can make sense
to expose default routes as NMIPRoute instances.
Relax the restriction on the NMIPRoute API to allow this
future change.
No code actually supports having NMIPRoute instances with
prefix length zero (default routes). Up to now, all such uses
would be a bug.
https://bugzilla.gnome.org/show_bug.cgi?id=739969
Signed-off-by: Thomas Haller <thaller@redhat.com>
The previous nm-dhcp-systemd code for logging the lease expiry time,
and exporting that value to D-Bus was clamping the value to
G_MAXUINT32-1, but that's unnecessary on x86_64, and incorrect on x86
(since time_t is signed).
Correctly adding a value to the current time and not overflowing seems
to be more-or-less impossible without having separate cases for 4- and
8-byte time_t. Since this was basically just for logging purposes
anyway, just log the number of seconds rather than the timestamp, and
then we don't have to worry about sizeof(time_t).
We've previously been just watching for state changes into UNMANAGED state. No
state change is emitted upon removal of a device which is already unmanaged.
https://bugzilla.gnome.org/show_bug.cgi?id=737659
Before, we would only track a device in NMDefaultRouteManager
if it had a default route. Otherwise the entry for the device
was removed.
That was wrong, because having no entry meant that the interface
is assumed and hence we would not touch the interface. Instead we must
esplicitly track devices without default route to know when an interface
has no default route.
Signed-off-by: Thomas Haller <thaller@redhat.com>
It's better to add the more important routes first. Otherwise there
might be a short time when a lower priority route has precedence.
Signed-off-by: Thomas Haller <thaller@redhat.com>
The previous commit made NM enforce the default route on interfaces for
which NM manages a default route.
For interfaces that are configured never-default, NM will now pick up
any externally configured default route, as if it was managed by NM.
This is important, because NMDefaultRouteManager needs a notion of which
is the best device. Without this change, it was agnostic to default routes
on managed, never-default interfaces.
Signed-off-by: Thomas Haller <thaller@redhat.com>
Monitor default routes from platform, and resync the default routes
on changes.
For one, this fixes the following use-case: have an assumed device em1
with two routes of metric 20 and 21. Activate em2, which will get effective
metric 22.
When externally removing route em1/20, em2 would resync the effective metric to
20. This is correct and already worked before. However, when deleting em1/21,
nothing happened. With this change, em2 would resync to metric 21 to fill the gap.
However this commit has much bigger effects: whenever the user externally adds
a default route to an interface for which NM manages an default route, NM will
delete it.
Also, when deleting the default route (managed by NM), NM would readd
it. Effectivly, the user can no longer mess with the default route on
interfaces for which it manages the default route.
If the connection is configured never-default, the user still can add
default routes and NM will not touch them.
Obviously, this has no effect for assumed devices either and the user
can externally add and remove default routes as he wishes.
https://bugzilla.gnome.org/show_bug.cgi?id=735512
Signed-off-by: Thomas Haller <thaller@redhat.com>
Don't only consider the best route of assumed devices when syncing the route
metrics. This fixes the following scenario:
Have em1 assumed, with two default routes (metric 20 and 21).
When activating em2, NMDefaultRouteManager would have determined
21 as the effective metric, thus replacing the assumed route of em1.
Since we don't want to touch assumed interfaces, it is wrong to
replace their default routes.
Instead, keep track of all the assumed default routes and consider their
metrics when choosing effective_metric.
Signed-off-by: Thomas Haller <thaller@redhat.com>
When calling update_default_route(), NMDefaultRouteManager will look at the
source, and determine whether it has a default route or not. For example
for device sources, this means calling nm_device_get_ip4_default_route().
If the source indicates that it has no default route, the effect of
calling update_default_route() is the same as calling
remove_default_route() (hence, remove() can be replaced by update()).
If the source however still indicates a default route, the behavior
would be different. This case would be an undesired inconsistancy,
because source and NMDefaultRouteManager would disagree of whether
the source has a default route.
Source must always properly indicate whether it has a default route
or not, hence this situation does not arise.
Hence it is always better to call update().
Signed-off-by: Thomas Haller <thaller@redhat.com>
The case of having a metric MAXUINT32 is special, because in face of
multiple default routes with the same metric, NMDefaultRouteManager
cannot reduce the effective metric (because there is no lower priority
value).
This case works already correct, just when adding such a default route,
ensure that we add it to the *first* entry.
Signed-off-by: Thomas Haller <thaller@redhat.com>
NetworkManager[31624]: <warn> VPN service 'openvpn': could not launch the VPN service. error: (8) Failed to execute child process "/usr/local/libexec/nm-openvpn-service" (No such file or directory).
**
NetworkManager:ERROR:nm-manager.c:3094:_activation_auth_done: assertion failed: (error)
An sd_dhcp_lease will always have an associated address, netmask, and
lifetime, so we don't have to check for errors when fetching them.
(The systemd code will fill in a default netmask if the server didn't
provide one; nm-dhcp-systemd's code to do that itself was redundant
and unused.)
Also, log the expiration time and NTP servers, for consistency with
everything else.
If asked to read a file that doesn't exist, sd_dhcp_lease_load()
returns 0 (success) without setting the out lease argument. So we need
to check both the return status and the lease before proceeding.
Not invoking a callback when cancelling the operation is counter
intuitive.
Note that NMPolicy refs the device, cancelling the call would leave
the reference hanging. That was not an issue because the call was
never cancelled. But still the behavior of NMFirewallManager is
unexpected.
Signed-off-by: Thomas Haller <thaller@redhat.com>
The directory firewall-manager/ only contained one source and one
header file. Move them to the parent src/ directory.
Signed-off-by: Thomas Haller <thaller@redhat.com>
NMIP4Config/NMIP6Config have their own NMIPRoute->D-Bus conversion
code since the code in libnm-core is gdbus-specific. But they were
doing it wrong, resulting in clients seeing a next hop of 0.0.0.0/::
for all routes.
Left over from a previous version of the iface helper patches and was
never removed when NM_IFACE_HELPER was removed. Since NM_IFACE_HELPER
wasn't defined, this code was already always compiled.
The kernel does not terminate an ongoing IPv6LL address process when
the IPv6LL address generation mode is set to 'none' (indicating that
userspace wishes to handle IPv6LL). Next, NetworkManager does not
expose IPv6 addresses internally until they have completed DAD. This
means that the kernel may still be performing DAD for an IPv6LL
address when NetworkManager turns userspace IPv6LL on, and when
DAD is complete NetworkManager will finally pay attention to the
address. If the device is in the DISCONNECTED state, NetworkManager
will then generate and assume an IPv6LL-only connection on the device.
Unfortunately, that behavior happens if the following is true:
1) IPv6LL addressing takes a while (eg, dad_transmits is high or
the kernel takes a while for some reason)
2) the activated connection fails quickly (dhclient fails or some
other fatal error terminates the activation attempt)
3) the activated connection has ipv6.method=ignore
In this case, when the device was brought up and ipv6.method=ignore,
NetworkManager re-enabled kernel IPv6LL and reset the IPv6 sysctl
properties. The kernel then generated an IPv6LL address and began
DAD. dhclient failed quickly, and NM deactivated the device. NM
then turned off kernel IPv6LL when deactivating the device, but the
kernel does not terminate the ongoing DAD. Some time after the device
entered the DISCONNECTED state, the kernel finished DAD and that
allowed NetworkManager to internally see the address, which caused
NetworkManager to emit the 'recheck-assume' signal. This
generated a new IPv6LL-only connection which was then assumed.
Bouncing 'disable_ipv6' when re-enabling userspace IPv6LL during
device deactivation flushes the tentative kernel IPv6LL address,
thus preventing the address from being announced after userspace
IPv6LL is re-enabled. The other alternative is to expose
tentative addresses (eg those still doing DAD) in NMPlatform so
they would be flushed when the device deactivates, but that is a
larger & riskier set of changes.
Reproducer:
- ifconfig eth0 down
- prepare a DHCPv4 connection with ipv6.method=ignore
- set /proc/sys/net/ipv6/conf/all/dad_transmits to "15"
- ensure that DHCPv4 will fail (replace dhclient with a script
that exits after 2 seconds or something)
- run NetworkManager
- activate the DHCP connection and watch it immediately fail
- wait for the kernel to announce the IPv6LL address after DAD finishes
- watch NM "assume" the new IPv6LL connection
https://bugzilla.gnome.org/show_bug.cgi?id=740096
For ipv6.method=dhcp NM was not waiting for an IPv6LL address, which
caused the DHCP client to exit early because it had no local address
to bind to.
https://bugzilla.gnome.org/show_bug.cgi?id=740147
The upstream kernel added module aliases for nl80211 in commit
fb4e156886ce6e8309e912d8b370d192330d19d3, so querying nl80211
now auto-loads the module. Previously NM was doing this to
determine whether an ethernet-like device was a Wi-Fi device
that supported nl80211, but this leads to the nl80211 loading
on platforms that will never have or use Wi-Fi.
Since every nl80211-capable device will already have
DEVTYPE=wlan set (from /sys/class/net/wlan0/uevent), we can use
that as an indicator that the ethernet-like device is WiFi
instead of asking nl80211.
https://bugzilla.gnome.org/show_bug.cgi?id=740131