Introduction of a new setting ipv4.link-local, which enables
link-local IP addresses concurrently with other IP address assignment
implementations such as dhcp or manually.
No way is implemented to obtain a link-local address as a fallback when
dhcp does not respond (as dhcpd does, for example). This could be be
added later.
To maintain backward compatibility with ipv4.method ipv4.link-local has
lower priority than ipv4.method. This results in:
* method=link-local overrules link-local=disabled
* method=disabled overrules link-local=enabled
Furthermore, link-local=auto means that method defines whether
link-local is enabled or disabled:
* method=link-local --> link-local=enabled
* else --> link-local=disabled
The upside is, that this implementation requires no normalization.
Normalization is confusing to implement, because to get it really
right, we probably should support normalizing link-local based on
method, but also vice versa. And since the method affects how other
properties validate/normalize, it's hard to normalize that one, so that
the result makes sense. Normalization is also often not great to the
user, because it basically means to modify the profile based on other
settings.
The downside is that the auto flag becomes API and exists because
we need backward compatibility with ipv4.method.
We would never add this flag, if we would redesign "ipv4.method"
(by replacing by per-method-specific settings).
Defining a default setting for ipv4.link-local in the global
configuration is also supported.
The default setting for the new property can be "default", since old
users upgrading to a new version that supports ipv4.link-local will not
have configured the global default in NetworkManager.conf. Therefore,
they will always use the expected "auto" default unless they change
their configuration.
Co-Authored-By: Thomas Haller <thaller@redhat.com>
During the deactivation of ovs interfaces, ovsdb receives the command to
remove the interface but for OVS system ports the device won't
disappear.
When reconnecting, ovsdb will update first the status and it will notice
that the OVS system interface was removed and it will set the status as
DEACTIVATING. This is incorrect if the status is already DEACTIVATING,
DISCONNECTED, UNMANAGED or UNAVAILABLE because it will block the
activation of the interface.
https://bugzilla.redhat.com/show_bug.cgi?id=2080236
On m68k we get a static assertion, that NMPlatformIP4Address.address
is not at the same offset as NMPlatformIPAddress.address_ptr.
On most architectures, the bitfields fits in a gap between the fields,
but not on m68k, where integers are 2-byte aligned.
As almost always, there is a point in keeping IPv4 and IPv6 implementations
similar. Behave different where there is an actual difference, at the bottom
of the stack.
Technically, g_warn_if_reached() may not be an assertion, according to
glib. However, there is G_DEBUG=fatal-warnings and we want to run with
that.
So this is an assertion to us. Also, logging to stderr/stdout is not a
useful thing to the daemon. Don't do this. Especially, since it depends
on user provided (untrusted) input.
Optimally we want stateless, pure code. Obviously, NMDhcpClient needs to
keep state to know what it's doing. However, we should well encapsulate
the state inside NMDhcpClient, and only accept events/notifications that
mutate the internal state according to certain rules.
Having a function public set_state(self, new_state) means that other
components (subclasses of NMDhcpClient) can directly mangle the state.
That means, you no longer need to only reason about the internal state
of NMDhcpClient (and the events/notifications/state-changes that it
implements). You also need to reason that other components take part of
maintaining that internal state.
Rename nm_dhcp_client_set_state() to nm_dhcp_client_notify(). Also, add
a new enum NMDhcpClientEventType with notification/event types.
In practice, this is only renaming. But naming is important, because it
suggests the reader how to think about the code.
The "noop" state is almost unused, however, nm_dhcp_set_state()
has a check "if (new_state >= NM_DHCP_STATE_TIMEOUT)", so the order
of the NOOP state matters.
Fix that by reordering.
Also, just return right away from NOOP.
NMDhcpState is very tied to events from dhclient. But most of these
states we don't care about, and NMDhcpClient definitely should abstract
and hide them.
We should repurpose NMDhcpState to simpler state. For that, first drop
the state from nm_dhcp_client_handle_event().
This is only the first step (which arguably makes the code more
complicated, because reason_to_state() gets spread out and the logic
happens more than once). That will be addressed next.
- return early to avoid nested block.
- use NM_STR_HAS_PREFIX() over g_str_has_prefix(), because that
can be inlined and only accepts a C literal as prefix argument.
- the code comment was unclear/wrong. If something comes from an environment
variables it is *NOT* UTF-8 safe. Also, we convert all non-ASCII characters,
not only non UTF-8 characters.
- as we already convert the string to ASCII, the check whether it's UTF-8
is bogus.
- using GString is unnecessary.
- use NM_IN_STRSET_ASCII_CASE().
- don't use else block after we return.
- don't accept the "iface" argument just for logging. The caller
can do the logging, if they wish.
Log messages when invalid DHCP options are found. For example:
<info> dhcp4 (eth0): error parsing DHCP option 6 (domain_name_servers): address 0.0.0.0 is ignored
<info> dhcp4 (eth0): error parsing DHCP option 12 (host_name): '.example.com' is not a valid DNS domain
<info> dhcp4 (eth0): error parsing DHCP option 26 (interface_mtu): value 60 is smaller than 68
https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/1225
audit_encode_nv_string() is documented that it might fail. Handle
the error.
Also, the returned string was allocated with malloc(). We must free
that with free()/nm_auto_free, not g_free()/gs_free.
Currently nm_setting_bond_get_option_normalized() and
nm_setting_bond_get_option_or_default() are identical functions. As the
first one is exposed as public API and has a better name, let's drop the
second one.
IPv6 temporary addresses are configured by kernel, with the
"ipv6.ip6-privacy" setting ("use_tempaddr" sysctl) and the
IFA_F_MANAGETEMPADDR flag.
As such, the idea was that during reapply we would not remove them.
However, that is wrong.
The only case when we want to keep those addresses, is if during reapply
we are going to configure the same primary address (with mngtmpaddr
flag) again. Otherwise, theses addresses must always go away.
This is quite serious. This not only affects Reapply. Also during disconnect
we clear IP configuration via l3cfg.
Have an ethernet profile active with "ipv6.ip6-privacy". Unplug
the cable, the device disconnects but the temporary IPv6 address is not
cleared. As such, nm_device_generate_connection() will now generate
an external profile (with "ipv6.method=disabled" and no manual IP addresses).
The result is, that the device cannot properly autoconnect again,
once you replug the cable.
This is serious for disconnect. But I could not actually reproduce the
problem using reapply. That is, because during reapply we usually
toggle ipv6_disable sysctl, which drops all IPv6 addresses. I still
went through the effort of trying to preserve addresses that we still
want to have, because I am not sure whether there are cases where we
don't toggle ipv6_disable. Also, doing ipv6_disable during reapply is
bad anyway, and we might want to avoid that in the future.
Fixes: 58287cbcc0 ('core: rework IP configuration in NetworkManager using layer 3 configuration')
NM_STR_BUF_INIT() and nm_str_buf_init() were pretty much redundant. Drop one of
them.
Usually our pattern is that we don't have functions that return structs.
But NM_STR_BUF_INIT() returns a struct, because it's convenient to use
with
nm_auto_str_buf NMStrBuf strbuf = NM_STR_BUF_INIT(...);
So use that variant instead.
For some device types the attach-port operation doesn't complete
immediately. NMDevice needs to wait that the operation completes
before proceeding (for example, before starting stage3 for the port).
Change attach_port() so that it can return TERNARY_DEFAULT to indicate
that the operation will complete asynchronously. Most of devices are
not affected by this and can continue returning TRUE/FALSE as before
without callback.
DHCP leases for a given interface are already exported on D-Bus
through DHCP4Config and DHCP6Config objects. It is useful to have the
same information also available on the filesystem so that it can be
easily used by scripts.
NM already saves some information about DHCP leases in /var, however
that directory can only be accessed by root, for good reasons.
Append lease options to the existing state file
/run/NetworkManager/devices/$ifindex. Contrary to /var this directory
is not persistent, but it seems more correct to expose the lease only
when it is active and not after it expired or after a reboot.
Since the file is in keyfile format, we add new [dhcp4] and [dhcp6]
sections; however, since some options have the same name for DHCPv4
and DHCPv6, we add a "dhcp4." or "dhcp6." prefix to make the parsing
by scripts (e.g. via "grep") easier.
The option name is the same we use on D-Bus. Since some DHCPv6 options
also have a "dhcp6_" prefix, the key name can contain "dhcp6" twice.
The new sections look like this:
[dhcp4]
dhcp4.broadcast_address=172.25.1.255
dhcp4.dhcp_lease_time=120
dhcp4.dhcp_server_identifier=172.25.1.4
dhcp4.domain_name_servers=172.25.1.4
dhcp4.domain_search=example.com
dhcp4.expiry=1641214444
dhcp4.ip_address=172.25.1.182
dhcp4.next_server=172.25.1.4
dhcp4.routers=172.25.1.4
dhcp4.subnet_mask=255.255.255.0
[dhcp6]
dhcp6.dhcp6_name_servers=fd01::1
dhcp6.dhcp6_ntp_servers=ntp.example.com
dhcp6.ip6_address=fd01::1aa
Instead of logging the event-id, which is composed from options that
are already visible in the log, it's more interesting to log that the
lease was merged.
In practice there is little difference.
Previously, "strbuf" would own the string until the end of the function,
when the "nm_auto_str_buf" cleanup attribute destroys it. In the
meantime, we would pass it on to _fw_nft_call_sync(), which in fact
won't access the string after returning.
Instead, we can just transfer ownership to the GBytes instance. That seems
more logical and safer than aliasing the buffer owned by NMStrBuf with
a g_bytes_new_static(). That way, we don't add a non-obvious restriction
on the lifetime of the string. The lifetime is now guarded by the GBytes
instance, which, could be referenced and kept alive longer.
There is also no runtime/memory overhead in doing this.