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
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).
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
By using a macro, we don't cast all the types to guint. Instead,
we use their native types directly. Hence, we don't need
nm_hash_update_uint64() nor nm_hash_update_ptr().
Also, for types smaller then guint like char, we save hashing
the all zero bytes.
siphash24() is wildly used by projects nowadays.
It's certainly slower then our djb hashing that we used before.
But quite likely it's fast enough for us, given how wildly it is
used. I think it would be hard to profile NetworkManager to show
that the performance of hash tables is the issue, be it with
djb or siphash24.
Certainly with siphash24() it's much harder to exploit the hashing
algorithm to cause worst case hash operations (provided that the
seed is kept private). Does this better resistance against a denial
of service matter for us? Probably not, but let's better be safe then
sorry.
Note that systemd's implementation uses a different seed for each hash
table (at least, after the hash table grows to a certain size).
We don't do that and use only one global seed.
Replace the usage of g_str_hash() with our own nm_str_hash().
GLib's g_str_hash() uses djb2 hashing function, just like we
do at the moment. The only difference is, that we use a diffrent
seed value.
Note, that we initialize the hash seed with random data (by calling
getrandom() or reading /dev/urandom). That is a change compared to
before.
This change of the hashing function and accessing the random pool
might be undesired for libnm/libnm-core. Hence, the change is not
done there as it possibly changes behavior for public API. Maybe
we should do that later though.
At this point, there isn't much of a change. This patch becomes
interesting, if we decide to use a different hashing algorithm.
The privious NM_HASH_* macros directly operated on a guint value
and were thus close to the actual implementation.
Replace them by adding a NMHashState struct and accessors to
update the hash state. This hides the implementation better
and would allow us to carry more state. For example, we could
switch to siphash24() transparently.
For now, we still do a form basically djb2 hashing, albeit with
differing start seed.
Also add nm_hash_str() and nm_str_hash():
- nm_hash_str() is our own string hashing implementation
- nm_str_hash() is our own string implementation, but with a
GHashFunc signature, suitable to pass it to g_hash_table_new().
Also, it has this name in order to remind you of g_str_hash(),
which it is replacing.
Introduce a NM_HASH_INIT() function. It makes the places
where we initialize a hash with a certain seed visually clear.
Also, move them from "shared/nm-utils/nm-shared-utils.h" to
"shared/nm-utils/nm-macros-internal.h". We might want to
have NM_HASH_INIT() non-inline (hence, define it in the
source file).
For routes and the default-route from NDisc, set the router preference
RTA_PREF.
Also, previously, we would only configure one IPv6 default-route. That by itself
was not really a problem, as long as NetworkManager would always make sure that
it configured the route to the ~best~ router.
Actually, NM should have done that already. It keeps the list of gateways
sorted, and prefers them according to their preference. But maybe
it didn't, so we have bug rh#1445417 (??).
Change that by configuring a default-route for all gateways, with
appropriate router prefrence. In case, kernel doesn't support RTA_PREF
yet, only configure all routes that share the same maxiumum preference.
https://bugzilla.redhat.com/show_bug.cgi?id=1445417
Instead of having 3 properties @gateway, @never_default and @has_gateway
on NMIP4Config/NMIP6Config that determine the default-route, track the
default-route as a regular route.
The gateway setting is the configuration knob for the default-route.
Since an NMIP4Config/NMIP6Config instance only has one gateway property,
it cannot track more then one default-routes (see related bug rh#1445417).
Especially with policy routing, it might be interesting to configure a
default-route in multiple tables.
Also, later it might be interesting to allow adding default-routes as
regular static routes in a connection, so that the user can configure additional
route parameters for the default-route or add default-routes in multiple tables.
With this patch, default-routes now have a rt_source property according to their
origin.
Also, the previous commits of this branch broke handling of the
default-route :) . That should be working now again.
The MSS is only set for VPN connections (by merging it in the respective
NMIP4Config/NMIP6Config).
It is also only used when setting the MSS of the default route.
Don't track that property in NMIP4Config/NMIP6Config, instead, set the
mss of the route directly in nm_vpn_connection_ip4_config_get() and
nm_vpn_connection_ip6_config_get().
There is a potential change in behavior here: NMDevice also consisdered
the MSS for the default route, but that would only be set if the MSS
gets merged from an vpn-ip-config. Which at most is the case for
iterface-less VPN types (libreswan). But even in that case, it doesn't
seem right to me to use the VPN's MSS for the device's default-route.
We added "ipv4.route-table-sync" and "ipv6.route-table-sync" to not change
behavior for users that configured policy routing outside of NetworkManager,
for example, via a dispatcher script. Users had to explicitly opt-in
for NetworkManager to fully manage all routing tables.
These settings were awkward. Replace them with new settings "ipv4.route-table"
and "ipv6.route-table". Note that this commit breaks API/ABI on the unstable
development branch by removing recently added API.
As before, a connection will have no route-table set by default. This
has the meaning that policy-routing is not enabled and only the main table
will be fully synced. Once the user sets a table, we recognize that and
NetworkManager manages all routing tables.
The new route-table setting has other important uses: analog to
"ipv4.route-metric", it is the default that applies to all routes.
Currently it only works for static routes, not DHCP, SLAAC,
default-route, etc. That will be implemented later.
For static routes, each route still can explicitly set a table, and
overwrite the per-connection setting in "ipv4.route-table" and
"ipv6.route-table".
The line
device (wlan0): state change: ip-config -> ip-check (reason none, internal state managed)
prints the sys-iface-state, which is at other places logged with
device[0x55914506ed70] (wlan0): sys-iface-state: external -> managed
For consistency, name the same parameter the same.
The name nm_device_get_priority() is misleading. Nowadays it's only used
for the default route metric, and nothing else.
Rename it, and make it static.
One might already question the existance of nm_utils_parse_inaddr_bin(),
because it only wraps inet_pton(), which by itself isn't terrible API.
The reason nm_utils_parse_inaddr_bin() exists, is to mirror to nm_utils_parse_inaddr()
function, which has additional functionality on top of inet_pton().
But we shouldn't have more then one wrapper for inet_pton().
For some logging lines this changes the domain
from LOGD_PPP or LOGD_MB|LOGD_IP4 to LOGD_MB.
Also, it changes the format of the prefix, and
adds a prefix for some logging lines that didn't
have one previously.
Found by clang warning:
src/devices/nm-device.c:11370:14: error: use of logical '||' with constant operand [-Werror,-Wconstant-logical-operand]
|| NM_UNMANAGED_USER_UDEV
^ ~~~~~~~~~~~~~~~~~~~~~~
Fixes: 5778bc6a34
If unrealize() failed we returned without thawing notify signals. Fix
this by moving g_object_freeze_notify() after the
unrealization/deletion but before the properties are reset in
unrealize_notify().
Fixes: a93807c288
- clearify in the manual page that setting retry to 1 means to try
once, without retry.
- log the initially set retry value in nm_settings_connection_get_autoconnect_retries().
- use nm_settings_connection_get_autoconnect_retries() in
nm_settings_connection_can_autoconnect().
- use nm_utils_addr_family_to_char(). It asserts that the input argument
is either AF_INET or AF_INET6.
- rename variable @family to @addr_family for consistency.
- when logging addr_family for activation-stage, use v4 or v6 instead
of numeric AF_INET/AF_INET6.
Move creating the logging output inside the logging macro, so it is
evaluated lazyly. Also, use a stack-allocated buffer.
Drop the redundant @inet4 variable.
Since commit 6845b9b80a ("device: delay
startup complete until device is initialized in platform", we also wait
for devices that are still initializing platform/UDEV.
Obviously, that only applies to realized devices.
Otherwise, an unrealized device is going to block startup complete.
Fixes: 6845b9b80a
Sometimes, when we have a platform object, we need to keep it
alive, because any subsequent platform operation might invalidate
the object.
Previously, we achieved that by copying the NMPlatformLink data.
For a while now, all platform object are immuable and recounted.
We should not copy the instance to a NMPlatformLink object, because
then the instance is no longer a full NMPObject. Instead, just take an
additional reference. Since the object must be immutable, that is
just as safe. But now callees down the stack get a proper NMPObject
instance, and might reference it too.
Distinguish between connections blocked from autoconnecting by user
request and connections blocked because they failed (and would fail
again).
Later, the reason will be used to unblock failed connection when some
conditions change.
We already have various ways to mark a device as unmanaged.
1) via udev-rule ENV{NM_UNMANAGED}. This can be overwritten via D-Bus
at runtime.
2) via settings plugin. That is NM_CONTROLLED=no for ifcfg-rh and
keyfile.unmanaged-devices in NetworkManager.conf.
3) at runtime, via D-Bus. This is persisted in the run state file
and persists restarts (but not reboot).
This adds another way via NetworkManager.conf file. Note that the
existing keyfile.unmanaged-devices (above 2) is also a configuration
optin in NetworkManager.conf. However it has various downsides:
- it cannot be overwritten at runtime (see commit
c210134bd5).
- you can only explicitly mark a device as unmanaged. That means,
you cannot use it to manage a device which is unmanaged due to
a udev rule.
- the name "keyfile.*" sounds like it's only relevant for the keyfile settings
plugin. Nowadays the keyfile plugin is always loaded, so the option applies
to NetworkManager in general.
https://github.com/NetworkManager/NetworkManager/pull/29
nm_device_match_parent() is called to check whether a device is
compatible with a given parent (UUID or interface). Accept any UUID If
there is no connection active on the device.
Without this, when there is a VLAN/MACVLAN connection with a parent
UUID the manager would create the device in
system_create_virtual_device(), realize it and then at the next call
of system_create_virtual_device() it would notice that the connection
is not compatible with the device because of the parent UUID;
therefore the manager would try to create again the same device,
failing.
https://mail.gnome.org/archives/networkmanager-list/2017-September/msg00034.html
Since commit a21b8882cc ("device: update
external configuration before commit"), we correctly re-sync the
external IP configuration before a merge, in case we notice that
there were some changes in platform.
Go a step further, and do the full update_ext_ip_config(). We should
have one way how to capture the external config, including intersect
and subtract. Otherwise, we end up with an @ext_ip4_config, which is
different from how it looks usually.
Refactor the code. There should be no changes in behavior at all.
The point is, to be able to reuse update_ext_ip_config() in the
next commit.
And also, I think it's an antipattern to have mirroring functions like
ip4_xyz() and ip6_xyz(). Instead, there should be one function, with
extra addr_family argument. That way, it'much clearer where two
implementations differ and where they are identical.
Basically, it moves the differentiation per the address family down
the call stack, closer to the place where the behavior is actually
different.