The connection.mdns setting is a per-connection setting,
so one might expect that one activated device can only have
one MDNS setting at a time.
However, with certain VPN plugins (those that don't have their
own IP interface, like libreswan), the VPN configuration is merged
into the configuration of the device. So, in this case, there
might be multiple settings for one device that must be merged.
We already have a mechanism for that. It's NMIP4Config. Let NMIP4Config
track this piece of information. Although, stricitly speaking this
is not tied to IPv4, the alternative would be to introduce a new
object to track such data, which would be a tremendous effort
and more complicated then this.
Luckily, NMDnsManager and NMDnsPlugin are already equipped to
handle multiple NMIPConfig instances per device (IPv4 vs. IPv6,
and Device vs. VPN).
Also make "connection.mdns" configurable via global defaults in
NetworkManager.conf.
Don't track the per-device configuration in NMDnsManager by
the ifname, but by the ifindex. We should consistently treat
the ifindex as the ID of a link, like kernel does.
At the few places where we actually need the ifname, resolve
it by looking into the platform cache. That is not necessarily
the same as the ifname that is currently tracked by NMDevice,
because netdev interfaces can be renamed, and NMDevice updates
it's link properties delayed. However, the platform cache has
the most recent notion of the correct interface name for an
ifindex, so if we ever hit a race here, we do it now more
correctly.
This also temporarily drops support for mdns. Will be re-added next,
but differently.
We had two separate queues, one for "SetLinkDNS" and one for
"SetLinkDomains". Merge them into one, and track the operation
as part of the new RequestItem structure.
A visible change to before is that we now would make all requests
per-interface first. Prevously, we would first make all SetLinkDNS
requests (for all interfaces) and then all SetLinkDomains requests.
It feels more correct to order the requests this way, not by
type.
The reason to merge is, that we will next get another operation
and in the current scheme we would need 3 GQueue instances.
While at it, refactor the code to use CList. We now anyway would
need a new struct to track the operation, requiring to allocate
and free it. Previously, we would only track the GVariant argument
as data of the GQueue.
Use a GHashTable instead of a GArray to construct the list of
@interfaces. Also, use NMCListElem instead of GList. With this,
the runtime is O(n*log(n)) instead of O(n^2).
I belive, we should take care that all our code has a reasonable
runtime complexity, even in common use-cases the number of elements
is small. This is not about performace, because likely we expect few
entries anyway, and the direct GArray implementation is likely faster
in those cases. It's about using the data structure that best suits the
access pattern.
The log(n) part comes from sorting the keys. I also believe we should
always aim for a stable behavior. When sending the D-Bus request to
resolved, the order of elements should be in ~some~ defined order.
"UNKNOWN" is not a good name. If you don't set the property
in the connection explicitly, it should be "DEFAULT".
Also, make "DEFAULT" -1. For one, that ensures that the enum's
underlying integer type is signed. Otherwise, it's cumbersome
to test "if (mdns >= DEFAULT)" because in case of unsigned types,
the compiler will warn about the check always being true.
Also, it allows for "NO" to be zero. These are no strong reasons,
but I tend to think this is better.
Also, don't make the property of NMSettingConnection a CONSTRUCT property.
Initialize the default manually in the init function.
Also, order the numeric values so that DEFAULT < NO < RESOLVE < YES with
YES being largest because it enables *the most*.
Update nm-policy.c and nm-dns-manager.c so that the connection-specific
settings get propagated to DNS manger. Currently the only such value is
the mDNS status.
Add update_mdns() function to DNS plugin interface. If a DNS plugin
supports mDNS, it can set an interface with a given index to support
mDNS resolving or also register the current hostname.
The mDNS support is currently added only to systemd-resolved DNS plugin.
The compiler warns when we ignore the return value from write().
And assigning it to an unused variable, causes another warning.
Make some use of it, at least to handle EINTR. All other errors
are still ignored.
While at it, rework the write code to first write to a buffer
in memory.
src/dns/nm-dns-manager.c: In function ‘write_to_netconfig’:
src/dns/nm-dns-manager.c:387:8: error: ignoring return value of ‘write’, declared with attribute warn_unused_result [-Werror=unused-result]
write (fd, str, strlen (str));
^
src/settings/plugins/ifnet/nms-ifnet-connection-parser.c: In function ‘ifnet_update_parsers_by_connection’:
src/settings/plugins/ifnet/nms-ifnet-connection-parser.c:2600:26: error: variable ‘pppoe’ set but not used [-Werror=unused-but-set-variable]
gboolean wired = FALSE, pppoe = TRUE;
^~~~~
While at it, don't log line breaks in ifnet_update_parsers_by_connection().
Fixes: e912b36d95
Fix resolved detection, the symlink target is usually relative to the
root, such that in chroots the file points to a file inside the
chroot. But keep absolute targets too, as these may have been in use
with older version of systemd. Add support for stub-resolv.conf
detection.
https://bugzilla.gnome.org/show_bug.cgi?id=790446
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.
Default-routes are for the most part like regular routes. Add support to
track them like regular routes in NMIP4Config/NMIP6Config.
One thing is, sometimes we need to figure out whether an ip-config
instance has a default-route. For that, keep track of the best
default-route (there might be multiple) and expose it. That is
the most complicated part of this patch, because there are so many
places where the list of routes gets modified (replace, intersect,
subtract, merge, add), and they all need to take care of updating
the best default-route.
In a next patch, NMDefaultRouteManager will be dropped and default-routes
will be tracked by NMIP4Config/NMIP6Config.
Reasons:
- it adds an O(1) lookup index for accessing NMIPxConfig's addresses.
Hence, operations like merge/intersect have now runtime O(n) instead
of O(n^2).
Arguably, we expect low numbers of addresses in general. For low
numbers, the O(n^2) doesn't matter and quite likely in those cases
the previous implementation was just fine -- maybe even faster.
But the simple case works fine either way. It's important to scale
well in the exceptional case.
- the tracked objects can be shared between the various NMPI4Config,
NMIP6Config instances with NMPlatform and everybody else.
- the NMPObject can be treated generically, meaning it enables code to
handle both IPv4 and IPv6, or addresses and routes. See for example
_nm_ip_config_add_obj().
- I want core to evolve to somewhere where we don't keep copies of
NMPlatformIP4Address, et al. instances. Instead they shall all be
shared. I hope this will reduce memory consumption (although tracking a
reference consumes some memory too). Also, it shortcuts nmp_object_equal()
when comparing the same object. Calling nmp_object_equal() on the
identical objects would be a common case after the hash function
pre-evaluates equality.
The DNS manager drops from the search list domains that are public
suffixes to prevent a possible domain hijack when using two-labels
hostnames [1].
This is a problem now that every single-label domain can be a TLD
since this means that such domains can't be used in the search list.
While it's useful to apply such restriction to the domain
automatically derived from the system hostname, it seems wrong to drop
domains specified by users in the configuration or provided by DHCP.
This commit keeps the public-suffix check only for the
hostname-derived domain
[1] https://bugzilla.redhat.com/show_bug.cgi?id=812394https://bugzilla.redhat.com/show_bug.cgi?id=1404350
Eventually, every NMPlatformIP4Route, NMPlatformIP6Route,
NMPlatformIP4Address and NMPlatformIP6Address should be shared
an deduplicated via the global NMDedupMultiIndex instance.
As first proof of concept, refactor NMIP4Config to track
IPv4 routes via the shared multi_idx. There is later potential
for improvement, when we pass (deduplicated) NMPObject instances
around instead of plain NMPlatformIP4Route, which needs still
a lot of comparing and cloning.
No need to clone the list anymore. Unfortunately, GPtrArray is not NULL
terminated (without extra effort), so we have to pass on the GPtrArray
instance for the length.
A negative ipv4.dns-priority and ipv6.dns-priority has the meaning to configure
the DNS information of the connection exclusively. With systemd-resolved, that means
we must explicitly unset the configuration from other interfaces.
https://bugzilla.gnome.org/show_bug.cgi?id=783569
The code was correct previously, but it was confusing to me,
because
- once @skip gets set to TRUE, it stays TRUE for the rest
of the loop.
- in each additional skipped iteration, it would still set
plugin_confs[i] to NULL. Which is not wrong, but confusing.
- it would set "prev_prio = prio;" in each iteration.
After @skip is set to TRUE, that doesn't matter anymore,
but is confusing. Before @skip is set to TRUE it also
doesn't really matter to set it more then once, because
we only care about the very first priority.
- @skip sounded to me like the current iteration would
be skipped. But really all remaining will be skipped too.
We autodetect systemd-resolved based on whether /etc/resolv.conf points
to one of the well known files of systemd-resolved.
Extend the check by also
- follow symlinks and compare the absolute link target
- open the file and compare the inodes for hard-linking
Note that when NetworkManager starts, systemd-resolved might not
have started yet. So, while comparing the inode is the best check,
we also compare symlinks (g_file_read_link() and realpath()).
Based-on-patch-by: Sam Morris <sam@robots.org.uk>
https://github.com/NetworkManager/NetworkManager/pull/16https://bugzilla.gnome.org/show_bug.cgi?id=779269
When rc-manager=file other services may overwrite resolv.conf at any
time. We don't support merging configurations in resolv.conf but we can
be more tolerant avoiding updating resolv.conf when not strictly needed.
In this case, if the last write of resolv.conf had no nameservers (nor
options), reset the "dns_touched" flag in order to avoid resetting
resolv.conf when quitting (so, potentially overwriting some other
service configuration there).
https://bugzilla.redhat.com/show_bug.cgi?id=1426748
When hostname changes, resolv.conf should be rewritten to update the
"search" option with the new domain parameters. If no device is
active nor going to activate, skip triggering resolv.conf update.
The DNS configuration for VPN connections is associated to the VPN
device (tun, ppp, etc.) and that device can be unmanaged by NM: don't
ignore such configuration. We do the same for other DNS plugins.
https://bugzilla.gnome.org/show_bug.cgi?id=779087
The purpose of "rc-manager=symlink" is so that the administrator can point
the "/etc/resolv.conf" as a symlink to a certain file, and thus indicating
that a certain component is responsible to manage resolv.conf, while others
should stay away from it.
For example, systemd-resolved never touches "/etc/resolv.conf", but
expects the admin to setup the symlink appropriately. It also recognizes
whether the symlink points to it's own resolv.conf in /run or to another
component.
Previously, "rc-manager=symlink" would always replace a regular file
with a symlink to "/var/run/NetworkManager/resolv.conf". Only if
"/etc/resolv.conf" is already a symlink somewhere else, NM would not
touch it. This with the exception that if "/etc/resolv.conf" points to
"/var/run/NetworkManager/resolv.conf", it would replace the symlink
with the same link to raise inotify events.
Change behavior so if "/etc/resolv.conf" is already a regular file, keep
it as file.
This means, if you have multiple components that don't care, everybody
can write the "/etc/resolv.conf" (as file) and there is no clear
expressed responsibility.
It was wrong that NetworkManager would convert the file to a symlink,
this should be reserved to the admin. Instead, NetworkManager should
accept that the intent is unspecified and preserve the regular file.
It's up to the admin to replace the symlink to somewhere else (to keep
NM off), or to point it to "/var/run/NetworkManager/resolv.conf", to show
the explicit intent.
The wrong behavior causes dangling symlinks when somebody disables
NetworkManager for good.
https://bugzilla.redhat.com/show_bug.cgi?id=1367551
The DNS manager and other singletons have the problem that
they are not properly destroyed on exit, that is, we leak
most of the instances. That should be eventually fixed and
all resources/memory should be released.
Anyway, fix the shutdown procedure by adding an explict command
nm_dns_manager_shutdown(). We should not rely on cleanup actions
to take place when the last reference is dropped, because then
we get complex interactions where we must ensure that everybody
drops the references at the right pointer.
Since the previous shutdown action was effectively never performed,
it is not quite clear what we actually want to do on shutdown.
For now, move the code to nm_dns_manager_stop(). We will see if
that is the desired behavior.
The -Wimplicit-fallthrough=3 warning is quite flexible of accepting
a fall-through warning.
Some comments were missing or not detected correctly.
Thereby, also change all other comments to follow the exact
same pattern.
nm_spawn_process() only sets error if the g_spawn_sync() itself fails,
not when the program ran returns a non-zero code.
<debug> [148 059915.1567] dns-mgr: update-dns: updating resolv.conf
<info> [148 059915.1568] dns-mgr: Removing DNS information from /usr/bin/resolvconf
No resolv.conf for interface NetworkManager
Thread 1 "NetworkManager" received signal SIGSEGV, Segmentation fault.
0x0000555555 7c325 in nm_dns_manager_end_updates
1532 _LOGW ("could not commit DNS changes: %s", error->message);
(gdb) bt full
#0 0x0000555555 7c325 in nm_dns_manager_end_updates
error = 0x0