g_steal_pointer() is marked as GLIB_AVAILABLE_STATIC_INLINE_IN_2_44,
that means we get a deprecated warning. Avoid that. We anyway
re-implement the macro so that we can use it before 2.44 and so
that it always does the typeof() cast.
(cherry picked from commit edfe9fa9a2)
(cherry picked from commit 6936a0613c)
The BPF filter takes the byte containing IP Flags and performs a
bitwise AND with "ntohs(IP_MF | IP_OFFMASK)".
On little-endian architectures the IP_MF flag (0x20) is ANDed with
0xFF3F and so the presence of the flag is correctly detected ignoring
other flags as IP_DF (0x40) or IP_RF (0x80).
On big-endian, "ntohs(IP_MF | IP_OFFMASK)" is 0x3FFF and so the filter
wrongly checks the presence of *any* flags. Therefore, a packet with
the DF flag set is dropped.
Instead, take the two bytes containing flags and offset:
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|Version| IHL |Type of Service| Total Length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Identification |Flags| Fragment Offset |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
and verify that IP_MF and the offset are zero.
Fixes: e43b1791a3 ('Merge commit 'e23b3c9c3ac86b065eef002fa5c4321cc4a87df2' as 'shared/n-dhcp4'')
https://bugzilla.redhat.com/show_bug.cgi?id=1861488https://github.com/nettools/n-dhcp4/pull/19
(cherry picked from commit 03d38e83e558802a82cb0e4847cb1f1ef75ccd16)
(cherry picked from commit 0024cef238)
(cherry picked from commit 80835f8f89)
(cherry picked from commit 4588e2e817)
Currently any error encountered in n_dhcp4_c_connection_dispatch_io()
causes a dispatch failure and interrupts the library state
machine. The recvmsg() on the socket can fail for different reasons;
one of these is for example that the UDP request previously sent got a
ICMP port-unreachable response. This can be reproduced in the
following way:
ip netns add ns1
ip link add veth0 type veth peer name veth1
ip link set veth1 netns ns1
ip link set veth0 up
cat > dhcpd.conf <<EOF
server-identifier 172.25.0.1;
max-lease-time 120;
default-lease-time 120;
subnet 172.25.0.0 netmask 255.255.255.0 {
range 172.25.0.100 172.25.0.200;
}
EOF
ip -n ns1 link set veth1 up
ip -n ns1 address add dev veth1 172.25.0.1/24
ip netns exec ns1 iptables -A INPUT -p udp --dport 67 -j REJECT
ip netns exec ns1 dhcpd -4 -cf dhcpd.conf -pf /tmp/dhcp-server.pid
If a client is started on veth0, it is able to obtain a lease despite
the firewall rule blocking DHCP, because dhcpd uses a packet
socket. Then it fails during the renewal because the recvmsg() fails:
dhcp4 (veth0): send REQUEST of 172.25.0.178 to 172.25.0.1
dhcp4 (veth0): error -111 dispatching events
dhcp4 (veth0): state changed bound -> fail
The client should consider such errors non fatal and keep running.
https://bugzilla.redhat.com/show_bug.cgi?id=1829178https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/486
(cherry picked from commit c5d1d4c498)
(cherry picked from commit bee01292f8)
Sometimes these function may set errno to unexpected values like EAGAIN.
This causes confusion. Avoid that by using our own wrappers that retry
in that case. For example, in rhbz#1797915 we have failures like:
errno = 0;
v = g_ascii_strtoll ("10", 0, &end);
if (errno != 0)
g_assert_not_reached ();
as g_ascii_strtoll() would return 10, but also set errno to EAGAIN.
Work around that by using wrapper functions that retry. This certainly
should be fixed in glib (or glibc), but the issues are severe enough to
warrant a workaround.
Note that our workarounds are very defensive. We only retry 2 times, if
we get an unexpected errno value. This is in the hope to recover from
a spurious EAGAIN. It won't recover from other errors.
https://bugzilla.redhat.com/show_bug.cgi?id=1797915
(cherry picked from commit 7e49f4a199)
NMTST_SWAP() used memcpy() for copying the value, while NM_SWAP() uses
a temporary variable with typeof(). I think the latter is preferable.
Also, the macro is essentially doing the same thing.
(cherry picked from commit 6f9a478b7d)
Currently if an error is encountered during a send() of a message, the
client fails and there is no possibility of recover, since no timers
are armed after a failed event dispatch. An easy way to reproduce a
failure is to add a firewall rule like:
iptables -A OUTPUT -p udp --dport 67 -j REJECT
which makes the send() fail with EPERM during the renew. In such case,
the client should continue (failing) until it reaches the rebind phase
at T2, when it will be able to renew the lease using the packet
socket.
In general, a failure to send a packet should not cause the failure of
the client.
https://gitlab.freedesktop.org/NetworkManager/NetworkManager/merge_requests/419https://bugzilla.redhat.com/show_bug.cgi?id=1806516
(cherry picked from commit 5a7b83ea0a)
The interface name might come from the command line or from a filename
(like during nm_vpn_wireguard_import()). It's not clear that this
is valid UTF-8. Asserting against that requires the caller to ensure
that the encoding is valid. That is cumbersome, especially since we anyway
check. Just report a regular error.
(cherry picked from commit 82fb8b00b4)
quoting 'man ovs-vswitchd.conf.db':
"The name must be alphanumeric and must not contain forward or backward
slashes."
OVS actually accepts a wider range of chars (all printable UTF-8 chars),
NetworkManager restricts this to ASCII char as it's a safer option for
now since OVS is not well documented on this matter.
https://bugzilla.redhat.com/show_bug.cgi?id=1788432
Fixes: e7d72a14f6 ('libnm-core: use different ifname validation function for OVS bridges, ports and interfaces')
(cherry picked from commit ed5a647ad1)
The only affected caller is nm_modem_manager_get_modems(), which
is used by NMDeviceBt for DUN connections. This is rather bad.
Fixes: 4154d9618c ('bluetooth: refactor BlueZ handling and let NMBluezManager cache ObjectManager data')
Fixes: e688e70b37 ('shared: add nm_utils_hash_values_to_array() helper')
(cherry picked from commit 037507f790)
Move the body of nm_utils_is_valid_iface_name() to
nm_utils_ifname_valid_kernel() so that it's shared between NM and
clients.
(cherry picked from commit 550f538564)
G_SOURCE_FUNC has attribute GLIB_AVAILABLE_MACRO_IN_2_58, which means
that the compiler will emit a warning when GLIB_VERSION_MAX_ALLOWED <
GLIB_VERSION_2_58. We currently define GLIB_VERSION_MAX_ALLOWED as
GLIB_VERSION_2_40. Redefine the macro to fix the following build error
when using glib >= 2.63.5 (the version in which the attribute was
added):
CC shared/nm-glib-aux/libnm_glib_aux_la-nm-shared-utils.lo
shared/nm-glib-aux/nm-shared-utils.c: In function ‘nm_g_unix_fd_source_new’:
shared/nm-glib-aux/nm-shared-utils.c:3679:13: error: Not available before [-Werror]
3679 | g_source_set_callback (source, G_SOURCE_FUNC (source_func), user_data, destroy_notify);
Fixes: 9c5741ccd2 ('shared/nm-glib: add compat implementation for G_SOURCE_FUNC()')
(cherry picked from commit 7f801685b2)
Properly initialize 'overload' when the space in the file section
ends.
shared/n-dhcp4/src/n-dhcp4-outgoing.c: In function ‘n_dhcp4_outgoing_append’:
shared/n-dhcp4/src/n-dhcp4-outgoing.c:198:17: error: ‘overload’ may be used uninitialized in this function [-Werror=maybe-uninitialized]
(cherry picked from commit b2620e798a)
Move back to INIT state after the lease expires, as per section 4.4.5
of RFC 2131. Previously the client just moved to EXPIRED, closed the
connection and cleared the probe, leaving to the caller of the library
the choice to create a new client instance and to start from
scratch. However, it seems more useful that the client, once
initialized, always tries to get a lease even after an expiration.
(cherry picked from commit 182a8021f3)
If the server sends a packet with multiple instances of the same
option, they are concatenated during n_dhcp4_incoming_linearize() and
evaluated as a single option as per section 7 of RFC 3396.
However, there are broken server implementations that send
self-contained options in multiple copies. They are reassembled to
form a single instance by the nettools client, which then fails to
parse them because they have a length greater than the expected one.
This problem can be reproduced by starting a server with:
dnsmasq --bind-interfaces --interface veth1 -d
--dhcp-range=172.25.1.100,172.25.1.200,1m
--dhcp-option=54,172.25.1.1
In this way dnsmasq sends a duplicate option 54 (server-id) when the
client requests it in the 'parameter request list' option, as
dhcp=systemd and dhcp=nettools currently do.
While this is a violation of the RFC by the server, both isc-dhcp and
systemd-networkd client implementations have mechanisms to deal with
this situation. dhclient simply takes the first bytes of the
aggregated option. systemd-networkd doesn't follow RFC 3396 and
doesn't aggregate multiple options; it considers only the last
occurrence of each option.
Change the parsing code to accept options that are longer than
necessary.
https://gitlab.freedesktop.org/NetworkManager/NetworkManager/issues/324
(cherry picked from commit 1cbf9d22a5)
The latter requires __auto_type which is not available in GCC versions
older than 4.9. Fix the following compile error on RHEL 7.8:
CC src/src_libNetworkManagerBase_la-NetworkManagerUtils.lo
shared/n-dhcp4/src/n-dhcp4-c-probe.c: In function 'n_dhcp4_client_probe_transition_nak':
shared/n-dhcp4/src/n-dhcp4-c-probe.c:1008:17: error: unknown type name '__auto_type'
probe->ns_nak_restart_delay = c_clamp(probe->ns_nak_restart_delay * 2,
^
shared/n-dhcp4/src/n-dhcp4-c-probe.c:1008:17: error: unknown type name '__auto_type'
shared/n-dhcp4/src/n-dhcp4-c-probe.c:1008:17: error: unknown type name '__auto_type'
Fixes: 218782a9a3 ('n-dhcp4: restart the transaction after a NAK')
(cherry picked from commit 3a9b069c41)
It is not enough to set the INIT state after a NAK; a timeout
(ns_deferred) must be set so that it is added to the event fd. The
client retries immediately the first time, so that in the successful
case it gets an address quickly. To avoid flooding the network in case
of servers always replying with NAKs, next attempts are done with
intervals from 2 seconds to 5 minutes using exponential backoff. See
also systemd commit [1].
[1] 1d1a3e0afbhttps://gitlab.freedesktop.org/NetworkManager/NetworkManager/issues/325
(cherry picked from commit 218782a9a3)
When the client enters the INIT state, it calls listen() on the
connection connection to create the packet socket. However, if the
client is coming from the REBOOTING state after a NAK, the connection
is already in the listening state; do nothing in such case.
(cherry picked from commit 4bcdc3c1eb)
Instead of terminating the program when the dispatch function returns
an invalid return code, log an error message and convert the error
code to a valid, generic one.
https://bugs.archlinux.org/task/64880
(cherry picked from commit 36f8822c9b)
After t1, the client tries to renew the lease by contacting via the
udp socket the server specified in the server-id option. If this
fails, after t2 it tries to contact any server using broadcast. For
this to work, the packet socket must be used.
(cherry picked from commit f860e929c0)
Currently the client always starts from the INIT state (i.e. sending a
discover message). If a requested-ip was specified by the caller, it
is added as an option in the discover.
It was reported that some DHCP servers don't respond to discover
messages with the requested-ip option set [1][2].
The RFC allows to skip the discover by entering the INIT-REBOOT state
and starting directly with a broadcast request message containing the
requested IP address. Implement that.
[1] https://bugzilla.redhat.com/show_bug.cgi?id=1781856
[2] https://gitlab.freedesktop.org/NetworkManager/NetworkManager/issues/310
(cherry picked from commit af03b77980)
Found by covscan:
NetworkManager-1.22.0/shared/nm-glib-aux/nm-dbus-aux.c:361:
missing_va_end: va_end was not called for "ap".
Fixes: ce36494c0a ('shared: add nm_dbus_error_is() helper')
(cherry picked from commit 0de4fd6ebc)
"nm-glib-aux/nm-logging-fwd.h" provides macros like _LOGD() to be reused
by various parts which implement logging (by defining _NMLOG() accordingly).
libnm also has logging, however it uses different logging levels
aside LOGD_DEBUG.
Instead, implement _LOGD() using a define _LOGL_DEBUG, so that libnm can
redefine thos _LOGL_DEBUG defines and use the _LOGD() macro.
(cherry picked from commit 1b00fd2fd2)
RHEL7 supports clock_gettime(CLOCK_BOOTIME), but it does not support
timerfd_create(CLOCK_BOOTIME). Creating a timerfd will fail with EINVAL.
Fallback to CLOCK_MONOTONIC.
Compare this to n-acd which also has compatibility code to fallback to
CLOCK_MONOTONIC. However when n-acd falls back to CLOCK_MONOTONIC, it uses
monotonic clock also for clock_gettime().
For n-dhcp4, the timestamps are also exposed in the public API
(n_dhcp4_client_lease_get_lifetime()). Hence, for timestamps n-dhcp4
still uses and requires clock_gettime(CLOCK_BOOTIME). Only the internal
timeout handling with the timerfd falls back to CLOCK_MONOTONIC.
https://github.com/nettools/n-dhcp4/pull/13https://gitlab.freedesktop.org/NetworkManager/NetworkManager/merge_requests/362
(cherry picked from commit a1771c738d)
Otherwise, other applications cannot bind to port 0.0.0.0:68 at the same time.
This is for example what dhclient wants to do. So even when running
dhclient on another, unrelated interface, it would fail to bind the UDP
socket and quit.
Note that also systemd-networkd's DHCPv4 client sets this socket option.
Presumably for the same reasons.
Signed-off-by: Thomas Haller <thaller@redhat.com>
https://github.com/nettools/n-dhcp4/pull/12
(cherry picked from commit 53b74bc614)
inet_aton() also supports IPv4 addresses in octal (with a leading '0')
or where not all 4 digits of the address are present.
Add nm_utils_parse_inaddr_bin_full() to optionally fallback to
parse the address with inet_aton().
Note taht inet_aton() also supports all crazy formats, including
ignoring trailing garbage after a whitespace. We don't want to accept
that in general.
Note that even in legacy format we:
- accept everything that inet_pton() would accept
- additionally, we also accept some forms which inet_aton() would
accept, but not all.
That means, the legacy format that we accept is a superset of
inet_pton() and a subset of inet_aton(). Which is desirable.
(cherry picked from commit 8fbf67d138)
Do another import, shortly before re-release.
There are no actual changes, but as always: to find out
that there are no changes requires large part of the work of
just doing the reimport.
Also, systemd import branch was rebased recently, that means
git-merge does not get this reimport right automatically (because
it thinks that the changes on master should be reverted). Hence,
this reimport required more care. Do it while there are few
changes.
We have our NM specific logging and log levels. Maybe we should
not have that, and instead only rely on syslog (like systemd)
or glog(). Anyway, currently we have one way and it makes sense
that this is also used outside from "src".
Move the helper function to parse log levels from string to
"nm-logging-base.h" so that we can use the same logging levels
outside of core.
This moves code that is currently GPL2+ licensed to
LGPL2.1+. However as far as I see, this code was entirely written
by Red Hat employees who would not object with this change. Also,
it's as obvious and trivial as it gets.