Most nm_platform_*() functions operate on the platform
singleton nm_platform_get(). That made sense because the
NMPlatform instance was mainly to hook fake platform for
testing.
While the implicit argument saved some typing, I think explicit is
better. Especially, because NMPlatform could become a more usable
object then just a hook for testing.
With this change, NMPlatform instances can be used individually, not
only as a singleton instance.
Before this change, the constructor of NMLinuxPlatform could not
call any nm_platform_*() functions because the singleton was not
yet initialized. We could only instantiate an incomplete instance,
register it via nm_platform_setup(), and then complete initialization
via singleton->setup().
With this change, we can create and fully initialize NMPlatform instances
before/without setting them up them as singleton.
Also, currently there is no clear distinction between functions
that operate on the NMPlatform instance, and functions that can
be used stand-alone (e.g. nm_platform_ip4_address_to_string()).
The latter can not be mocked for testing. With this change, the
distinction becomes obvious. That is also useful because it becomes
clearer which functions make use of the platform cache and which not.
Inside nm-linux-platform.c, continue the pattern that the
self instance is named @platform. That makes sense because
its type is NMPlatform, and not NMLinuxPlatform what we
would expect from a paramter named @self.
This is a major diff that causes some pain when rebasing. Try
to rebase to the parent commit of this commit as a first step.
Then rebase on top of this commit using merge-strategy "ours".
(cherry picked from commit c6529a9d74)
We trigger a new solicitation upon seeing the new token. Kernel triggers one
too, but that one is of no use to us, since the advertisement might arrive sooner
than we learn about the token change.
(cherry picked from commit 24e7ea7860)
A solicitation loop could result for two cases:
1) a router sent DNS information, then removed that information without
sending it with lifetime=0
2) two routers exist, one sending DNS information and the other not, and
the first router which sends DNS information disappears
In these cases a solicitation would be generated when the DNS information
reached 1/2 its lifetime. A router would then reply to the solicitation
without DNS information, which would then trigger another lifetime check,
which finds that the DNS info is still 1/2 lifetime. Which triggers
another solicitation, etc.
Fix this by ensuring that a solicitation is never sent less than
rtr_solicitation_interval seconds after the last one.
If a route or gateway's priority increased, the item would be added
to the array again without removing the older entry. At the same time
don't bother adding an item with a zero lifetime, since it will just
be removed again by the clean_* functions.
Instead of having it all in the Linux implementation, move all the
timeout logic and most of the processing logic into the NMRDisc
base class so that it can be used by NMFakeRDisc as well. This
will help increase testability since now we can test the timeout
and expiry logic from the fake plugin too.
ndp_close() does not do that -- it only closes the socket. It's safe to call
even if we didn't start solicitation as it has a NULL-check.
==7745== 80 (+80) bytes in 2 (+2) blocks are definitely lost in loss record 3,983 of 5,735
==7745== at 0x4C29BCF: malloc (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==7745== by 0x6F57A2D: ndp_msgrcv_handler_register (libndp.c:1697)
==7745== by 0x47572E: start (nm-lndp-rdisc.c:691)
==7745== by 0x44A457: addrconf6_start_with_link_ready (nm-device.c:4280)
==7745== by 0x44C1E7: linklocal6_complete (nm-device.c:3931)
==7745== by 0x44C1E7: update_ip_config (nm-device.c:6667)
==7745== by 0x44C2F8: queued_ip_config_change (nm-device.c:6688)
==7745== by 0x7F44AEA: g_main_dispatch (gmain.c:3111)
==7745== by 0x7F44AEA: g_main_context_dispatch (gmain.c:3710)
==7745== by 0x7F44E87: g_main_context_iterate.isra.29 (gmain.c:3781)
==7745== by 0x7F451B1: g_main_loop_run (gmain.c:3975)
==7745== by 0x432F74: main (main.c:460)
(cherry picked from commit 5d9f9febfb)
config.h should be included from every .c file, and it should be
included before any other include. Fix that.
(As a side effect of how I did this, this also changes us to
consistently use "config.h" rather than <config.h>. To the extent that
it matters [which is not much], quotes are more correct anyway, since
we're talking about a file in our own build tree, not a system
include.)
If the router sends an RA with an RDNSS or DNSSL lifetime of "0", that
means to immediately stop using the corresponding server/domain name.
NMLNDPRDisc knew this, but messed up its handling of it, and so if
this happened, it might end up sending out an RS to get new data every
0 seconds...
(Noticed while investigating bgo 735325, though it turned out to be
irrelevant there.)
Previously, src/nm-ip4-config.h, libnm/nm-ip4-config.h, and
libnm-glib/nm-ip4-config.h all used "NM_IP4_CONFIG_H" as an include
guard, which meant that nm-test-utils.h could not tell which of them
was being included (and so, eg, if you tried to include
nm-ip4-config.h in a libnm test, it would fail to compile because
nm-test-utils.h was referring to symbols in src/nm-ip4-config.h).
Fix this by changing the include guards in the non-API-stable parts of
the tree:
- libnm-glib/nm-ip4-config.h remains NM_IP4_CONFIG_H
- libnm/nm-ip4-config.h now uses __NM_IP4_CONFIG_H__
- src/nm-ip4-config.h now uses __NETWORKMANAGER_IP4_CONFIG_H__
And likewise for all other headers.
The two non-"nm"-prefixed headers, libnm/NetworkManager.h and
src/NetworkManagerUtils.h are now __NETWORKMANAGER_H__ and
__NETWORKMANAGER_UTILS_H__ respectively, which, while not entirely
consistent with the general scheme, do still mostly make sense in
isolation.
Add NetworkManager.h, which includes all of the other NM header, and
require all external users of libnm to use that rather than the
individual headers.
(An exception is made for nm-dbus-interface.h,
nm-vpn-dbus-interface.h, and nm-version.h, which can be included
separately.)
Since the API has not changed at this point, this is mostly just a
matter of updating Makefiles, and changing references to the library
name in comments.
NetworkManager cannot link to libnm due to the duplicated type/symbol
names. So it links to libnm-core.la directly, which means that
NetworkManager gets a separate copy of that code from libnm.so.
Everything else links to libnm.
Some subdirectories of src/ encapsulate large chunks of functionality,
but src/config/, src/logging/, and src/posix-signals/ are really only
separated out because they used to be built into separate
sub-libraries that were needed either for test programs, or to prevent
circular dependencies. Since this is no longer relevant, simplify
things by moving their files back into the main source directory.
Ethernet-like interfaces aren't the only type of interfaces that can
run IPv6 but the rdisc code only returns an address if the interface's
hardware address is 6 bytes.
Interface types like PPP (rfc5072) and IPoIB (rfc4391) have their own
specifications for constructing IPv6 addresses and we should honor
those.
So instead of expecting a MAC address, let each device subclass
generate an Interface Identifier and use that for rdisc instead.
We were linking libndp into the NetworkManager binary, but it ought to
be marked as a dependency of libNetworkManager, in case a test
exercises that code.
Clean up some of the cross-includes between headers (which made it so
that, eg, if you included NetworkManagerUtils.h in a test program, you
would need to build the test with -I$(top_srcdir)/src/platform, and if
you included nm-device.h you'd need $(POLKIT_CFLAGS)) by moving all
GObject struct definitions for src/ and src/settings/ into nm-types.h
(which already existed to solve the NMDevice/NMActRequest circular
references).
Update various .c files to explicitly include the headers they used to
get implicitly, and remove some now-unnecessary -I options from
Makefiles.
nm-version.h was getting disted, making srcdir!=builddir work for
tarball builds, but not for git builds.
Also, remove "-I${top_builddir}/include" from all Makefile.ams, since
there's nothing generated in include/ any more.
check_timestamps() was mixing up absolute and relative timestamps,
which meant that IPv6 expiration checks more-or-less stopped happening
after a while, allowing expired IPv6 routes, etc, to remain applied.
The IPv6 spec say that when performing SLAAC, you should sent at most
3 RSes, at least 4 seconds apart. We were previously continuing to
send RSes forever if we didn't get back a response. Fix that.
(Since the fix involves making nm-lndp-rdisc use NMPlatform, it was
necessary to rewrite the rdisc test program a bit, to not try to
include <net/if.h>, which is incompatible with <linux/if.h>.)
NetworkManager uses the sysctl value 'max_addresses' as the kernel does.
There is however a difference in what addresses are taken into account.
The kernel counts all addresses on the interface (including temporary,
private addresses and user configured ones).
NM instead only limits the number of public autoconf addresses to
'max_addresses'. This is because it is difficult for NM to count all
addresses (which can come from different sources) and it is not
necessarily a more logical behavior. Only be aware, that NM uses
the same config value as the kernel, but counts differently.
Especially, the kernel might reach the limit earlier then NM in the
presence of temporary addresses or addresses not from SLAAC.
Note, that the kernel uses 'max_addresses' only to limit public, autoconf
addresses. So this limit does not affect NM adding as many addresses as
it wants.
Signed-off-by: Thomas Haller <thaller@redhat.com>
If the command line or NetworkManager.conf mentions a non-existent
domain, just print a warning and ignore it. That way if you switch to
using an older NM that doesn't have that domain, it will still work.
A lifetime of 0 means that the domain or server should no longer
be used, so if we get an RA with a zero-lifetime DNS server or
domain that we haven't seen before, don't bother adding it to the
list.
DNS servers and domains that are already known and become zero
lifetime in the next RA are already correctly handled by
clean_dns_servers() and clean_domains().
The DNS server and domain timestamps and lifetimes weren't updated
when a new RA was received. When half the lifetime for either of
them had passed, clean_dns_servers() and clean_domains() request a
Router Solicitation to ensure the DNS information does not expire.
This obviously results in a new Router Advertisement, but since the
timestamps don't get updated, clean_dns_servers() and clean_domains()
simply request another solicitation because 'now' is still greater
than half the old lifetime. This casues another solicit request,
which causes another RA, which... etc.
https://bugzilla.redhat.com/show_bug.cgi?id=1044757https://bugzilla.gnome.org/show_bug.cgi?id=720760