When the default leasefile location got moved from distro-specific
dhclient locations to a single NM-specific location, that apparently
broke scripts and external tools that depended on the old location,
like dract netbooting.
During a netboot, DHCP is started from the initramfs and gets a
lease, and the leasefile lives in the initramfs. When the real
system is started, and the rootfs switches from the initramfs to
the actual rootfs, something needs to copy the leasefiles over to
where NetworkManager can find them. For dracut at least, various
dracut scripts were doing this, and copying to the old location
in /var/lib/dhclient or /var/lib/dhcp. Which means NM can no
longer find them, and proceeds to acquire a new DHCP lease when
taking over the existing connection, rather than renewing the
existing lease. This can lead to loss of network connectivity
and thus the netboot process fails.
If no leasefile for the connection in the new location exists,
look in the old locations and copy that leasefile over to the new
location.
Not all systems have machine-id in /etc, some still have it in /var/lib/dbus/
especially if they aren't using systemd. Furthermore, if we don't have
any machine-id file (like in the future, if we don't have a messaebus
daemon running) fall back to a random DUID as a last resort.
The config file can specify a dhclient script, which gets used instead
of what NM passes on the command-line. Make sure that script gets
ignored in the final dhclient config, because the script NM passes
is the script that needs to be used to pass data back to NM. People
may have old dhclient.conf files lying around that get picked up and
we don't want any script specified there to interfere.
The original used uuid_parse() but that function did not
work properly since the format of the machine-id is
not compatable with a real uuid. This patch adds a new
machine_id_parse() routine to correctly convert the
character string of hex digits to a 16 byte binary string.
g_malloc(), etc, never return NULL, by API contract. Likewise, by
extension, no other glib function ever returns NULL due to lack of
memory. So remove lots of unnecessary checks (the vast majority of
which would have immediately crashed had they ever run anyway, since
g_set_error(), g_warning(), and nm_log_*() all need to allocate
memory).
https://bugzilla.gnome.org/show_bug.cgi?id=693678
DHCPv6 RFCs require the DUID to be constant over time and to
be used as a permanent identifiers of the machine. This precludes
using a network interface MAC address since the MAC address may
change, and there may be more than one network interface installed.
Storing the DUID causes problems when an OS image is cloned between
virtual or physical machines because then the saved DUID is no longer
unique.
To fix all these issues, generate the DUID from the machine's hashed
machine-id, which is already a unique identifier of the machine and
will always be present because dbus requires it, and NM requires
dbus. It is assumed administrators will change the machine-id when
cloning an OS image; thus they only have to update one file, not
two (machine-id and the stored DUID).
Administrators may still override the machine-id-derived DUID by
setting a DUID in the default dhclient config file or the
interface-specific dhclient config files.
dhclient no longer saves a generated DUID to the config files,
because the default DUID will always be regenerated from
the machine-id on startup and thus always stable.
The DUID is supposed to be machine-wide, so if we're writing a new
leasefile, save the default DUID to it. If we haven't saved a
persistent DUID yet, do that to.
Add infrastructure for generating DUID-LLT from a given device MAC and
passing it around to the DHCP client implementations.
Thanks to Mathieu Trudel-Lapierre for bug fixes in the
unescaping code, which were merged into this commit.
For the default wired connection (or any connection that doesn't have an IPv4
setting, which means "auto"), the hostname should always be sent to the DHCP
server to register in DNS.
This patch makes DHCPv6 support more or less equivalent to that
one of IPv4 DHCP.
(dcbw: fix some formatting, rearrange code so it's less convoluted,
fix up writing hostname to ifcfg files)
For NetworkManager, dhclient is a runtime dependency. Distribution dhclient
configuration is either put directly into /etc or in /etc/dhcp. It is much
safer to check this at runtime than to guess the location from distribution
name.
Additionally, the distribution dhclient configuration files can be overriden
by a configuration file in /etc/NetworkManager.
TODO: Functions get_dhclient_config() and merge_dhclient_config() should
be also used for IPv6.
DHCP lease file names are built by NetworkManager and contain connection UUID
which makes them NM-specific. Their new location belongs to NetworkManager and
doesn't have to be guessed. With no guessing, we don't need distribution-specific
conditionals.
Note: This change may require modifications to the selinux policy. But after all
these files actually belong to NetworkManager as well as the instance of dhclient
that uses them.
Use --enable-doc and --enable-tests instead of --with-docs and
--with-tests. This is consistent with other features and with
--enable-gtk-doc option. Support current variants as fallback.
Don't build tests unless --enable-tests is specified.
Use autoconf/automake variables for NetworkManager paths. Use
NetworkManager subdirectory where appropriate.
Files in /var/run (or /run on some distros) are moved into a separate
directory as is usual with other daemons. It makes the filesystem
more readable and file prefixing unnecessary.
/var/run/NetworkManager.pid -> /var/run/NetworkManager/NetworkManager.pid
/var/run/nm-dns-dnsmasq.pid -> /var/run/NetworkManager/dnsmasq.pid
/var/run/nm-dns-dnsmasq.conf -> /var/run/NetworkManager/dnsmasq.conf
The /var/run/NetworkManager directory is created at runtime, if it doesn't
exist.
Note: Path-based security policies like SELinux and AppArmor may need to
be adapted.
This functionality is (mostly) obsoleted by the newer
GLIB_VERSION_MIN_REQUIRED and GLIB_VERSION_MAX_ALLOWED defines. With
this, your build doesn't all of a sudden blow up if we deprecate
something in GLib - you have to explicitly opt-in to the newer
version.
G_DISABLE_DEPRECATED does still apply for macros and things that can't
take __attribute__((deprecated)), but it's not really worth the pain
and cargo culting around just for that.
The idea was copied from gtk, but it's only used there in cases where
the method's wrapper function and default implementation would
otherwise have the same name, which never happens in NM because our
method implementations aren't prefixed with the type name, so it's
just noise here.
The ctype macros (eg, isalnum(), tolower()) are locale-dependent. Use
glib's ASCII-only versions instead.
Also, replace isascii() with g_ascii_isprint(), since isascii()
accepts control characters, which isn't what the code wanted in any of
the places where it was using it.
WiMAX failed distcheck if the iwmxsdk devel files were installed but
--enable-wimax=no was used, since the distcheck configure bits found
the iwmxsdk headers, defaulted WiMAX support to 'on', and then proceeded
to use the generated headers from the top srcdir, where of course
wimax was turned off (due to --enable-wimax=no). Instead, everything
should use the headers from the builddir, which reflects the options
that 'make distcheck' actually selects.
At the same time, re-order various includes everywhere to ensure that
the builddir paths come before the srcdir paths to prevent this from
happening in the future.
DHCPv6 IA_NA assignments do not contain a prefix length, they are for a
single address (/128) only. However, the ISC DHCPv6 client incorrectly
assumes IA_NA assignments come with a implicit prefix length of /64, and
passes this incorrect information on to NetworkManager, which adds this
prefix as a on-link route. This will cause communication failures in
certain networks, for example NBMA networks, and in organisations using
longer prefix lengths than /64 for their LANs. For more discussion
regarding this problem, see RFC 5942 section 5.
This patch makes NM ignore the false prefix length attribute provided by
the ISC DHCPv6 client, instead setting it to a /128 (single address) in
all cases. Note that this does not preclude an on-link prefix from being
added by NM if it is being advertised in the correct way, i.e., by
including a Prefix Information Option with the L flag set in an ICMPv6
Router Advertisement.
For what it's worth I've also sent a patch to ISC to change the hard-
coded implicit prefix length value from /64 to /128 in [ISC-Bugs #29468].
If there was an existing dhclient config file, don't leak it when
merging to the new configuration.
Found by Mathieu Trudel-Lapierre <mathieu@canonical.com>
Commit 217c5bf6ac fixed processing of unix
signals: signals are blocked in all threads and a dedicated thread handles the
signals using sigwait().
However, the commit forgot that child processes inherit signal mask as well.
That is why we have to unblock signals for child processes we spawn from NM, so
that they can receive signals.
The DHCP code usually ignores dhclient state transitions to the
same state it's currently in. This turns out to be wrong, since
dhclient will use the same reason code (which NM uses for the
state value) for operations like RENEW and REBIND. i.e. you'll
see states like this:
BOUND
RENEW (first renew)
RENEW (second renew)
RENEW (third renew)
etc
Therefore to ensure we trigger dispatcher scripts and internal
housekeeping code for renewals we need to make sure we process
these events even though they use the same state as the previous
event.
The DHCP code usually ignores dhclient state transitions to the
same state it's currently in. This turns out to be wrong, since
dhclient will use the same reason code (which NM uses for the
state value) for operations like RENEW and REBIND. i.e. you'll
see states like this:
BOUND
RENEW (first renew)
RENEW (second renew)
RENEW (third renew)
etc
Therefore to ensure we trigger dispatcher scripts and internal
housekeeping code for renewals we need to make sure we process
these events even though they use the same state as the previous
event.
When NM was registering all of its enum types by hand, it was using
NamesLikeThis rather than the default names-like-this for the "nick"
values. When we switched to using glib-mkenums, this resulted in
dbus-glib using different strings for the D-Bus error names, causing
compatibility problems.
Fix this by using glib-mkenums annotations to manually fix all the
enum values back to what they were before. (This can't be done in a
more automated way, because the old names aren't 100% consistent. Eg,
"UNKNOWN" frequently becomes "UnknownError" rather than just
"Unknown".)
Rather than generating enum classes by hand (and complaining in each
file that "this should really be standard"), use glib-mkenums.
Unfortunately, we need a very new version of glib-mkenums in order to
deal with NM's naming conventions and to fix a few other bugs, so just
import that into the source tree temporarily.
Also, to simplify the use of glib-mkenums, import Makefile.glib from
https://bugzilla.gnome.org/654395.
To avoid having to run glib-mkenums for every subdirectory of src/,
add a new "generated" directory, and put the generated enums files
there.
Finally, use Makefile.glib for marshallers too, and generate separate
ones for libnm-glib and NetworkManager.
So that dhclient will, in turn, pass it to the action script
(the action script tries to send a DBus signal to NetworkManager
over the system bus).
Dhclient "execve"s the action script with a hand-constructed environment
that only includes specific variables, plus whatever is passed to
dhclient with "-e".
As far as I know, dhcpcd has no option equivalent to dhclient's "-e".