device: add ipv4.link-local=fallback (IPv4LL set iff no other IPv4 set)
When a connection with ipv4.method=auto (DHCP) is configured with ipv4.link-local=enable we were leaving the link-local address forever, but this is not correct according to RFC3927[1] which says: a host SHOULD NOT have both an operable routable address and an IPv4 Link-Local address configured on the same interface. This adds a new mode that is more compliant, which only sets an IPv4 link-local address if no other address is set (through either DHCP lease or ivp4.addresses setting) Closes #1562 Link: https://github.com/systemd/systemd/issues/13316 Link: https://datatracker.ietf.org/doc/html/rfc3927#section-1.9 [1]
This commit is contained in:

committed by
Beniamino Galvani

parent
b3d2902ad4
commit
c575293f1b
2
NEWS
2
NEWS
@@ -26,6 +26,8 @@ USE AT YOUR OWN RISK. NOT RECOMMENDED FOR PRODUCTION USE!
|
||||
* Support reapplying the VLANs on bridge ports.
|
||||
* Fix crash caused by malformed LLDP package if debug log is enabled
|
||||
* Retry hostname resolution when it fails
|
||||
* Add new ipv4.link-local=fallback to set an IPv4 link-local address
|
||||
when no other IPv4 is set.
|
||||
|
||||
=============================================
|
||||
NetworkManager-1.48
|
||||
|
@@ -276,6 +276,7 @@ typedef struct {
|
||||
NML3IPv4LL *ipv4ll;
|
||||
NML3IPv4LLRegistration *ipv4ll_registation;
|
||||
GSource *timeout_source;
|
||||
NMSettingIP4LinkLocal mode;
|
||||
} v4;
|
||||
struct {
|
||||
NML3IPv6LL *ipv6ll;
|
||||
@@ -830,6 +831,7 @@ static void _set_mtu(NMDevice *self, guint32 mtu);
|
||||
static void _commit_mtu(NMDevice *self);
|
||||
static void _cancel_activation(NMDevice *self);
|
||||
|
||||
static void _dev_ipll4_check_fallback(NMDevice *self, const NML3ConfigData *l3cd_new);
|
||||
static void _dev_ipll4_notify_event(NMDevice *self);
|
||||
|
||||
static void _dev_ip_state_check(NMDevice *self, int addr_family);
|
||||
@@ -1596,6 +1598,7 @@ _prop_get_ipv4_link_local(NMDevice *self)
|
||||
{
|
||||
NMSettingIP4Config *s_ip4;
|
||||
NMSettingIP4LinkLocal link_local;
|
||||
const char *method;
|
||||
|
||||
s_ip4 = nm_device_get_applied_setting(self, NM_TYPE_SETTING_IP4_CONFIG);
|
||||
if (!s_ip4)
|
||||
@@ -1604,6 +1607,8 @@ _prop_get_ipv4_link_local(NMDevice *self)
|
||||
if (NM_IS_DEVICE_LOOPBACK(self))
|
||||
return NM_SETTING_IP4_LL_DISABLED;
|
||||
|
||||
method = nm_setting_ip_config_get_method((NMSettingIPConfig *) s_ip4);
|
||||
|
||||
link_local = nm_setting_ip4_config_get_link_local(s_ip4);
|
||||
|
||||
if (link_local == NM_SETTING_IP4_LL_DEFAULT) {
|
||||
@@ -1613,30 +1618,44 @@ _prop_get_ipv4_link_local(NMDevice *self)
|
||||
NM_CON_DEFAULT("ipv4.link-local"),
|
||||
self,
|
||||
NM_SETTING_IP4_LL_AUTO,
|
||||
NM_SETTING_IP4_LL_ENABLED,
|
||||
NM_SETTING_IP4_LL_FALLBACK,
|
||||
NM_SETTING_IP4_LL_DEFAULT);
|
||||
if (link_local == NM_SETTING_IP4_LL_DEFAULT) {
|
||||
/* If there is no global configuration for ipv4.link-local assume auto */
|
||||
link_local = NM_SETTING_IP4_LL_AUTO;
|
||||
} else if (link_local == NM_SETTING_IP4_LL_ENABLED
|
||||
&& nm_streq(nm_setting_ip_config_get_method((NMSettingIPConfig *) s_ip4),
|
||||
NM_SETTING_IP4_CONFIG_METHOD_DISABLED)) {
|
||||
/* ipv4.method=disabled has higher priority than the global ipv4.link-local=enabled */
|
||||
} else if (NM_IN_SET(link_local, NM_SETTING_IP4_LL_ENABLED, NM_SETTING_IP4_LL_FALLBACK)
|
||||
&& nm_streq(method, NM_SETTING_IP4_CONFIG_METHOD_DISABLED)) {
|
||||
/* ipv4.method=disabled has higher priority than the global
|
||||
* ipv4.link-local=enabled / ipv4.link-local=fallback */
|
||||
link_local = NM_SETTING_IP4_LL_DISABLED;
|
||||
} else if (link_local == NM_SETTING_IP4_LL_DISABLED
|
||||
&& nm_streq(nm_setting_ip_config_get_method((NMSettingIPConfig *) s_ip4),
|
||||
NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL)) {
|
||||
&& nm_streq(method, NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL)) {
|
||||
/* ipv4.method=link-local has higher priority than the global ipv4.link-local=disabled */
|
||||
link_local = NM_SETTING_IP4_LL_ENABLED;
|
||||
}
|
||||
}
|
||||
|
||||
if (link_local == NM_SETTING_IP4_LL_AUTO) {
|
||||
link_local = nm_streq(nm_setting_ip_config_get_method((NMSettingIPConfig *) s_ip4),
|
||||
NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL)
|
||||
? NM_SETTING_IP4_LL_ENABLED
|
||||
: NM_SETTING_IP4_LL_DISABLED;
|
||||
/* ipv4.link-local=auto means enabled for ipv4.method=link-local,
|
||||
* and disabled for anything else */
|
||||
if (nm_streq(method, NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL)) {
|
||||
link_local = NM_SETTING_IP4_LL_ENABLED;
|
||||
} else {
|
||||
link_local = NM_SETTING_IP4_LL_DISABLED;
|
||||
}
|
||||
}
|
||||
|
||||
if (link_local == NM_SETTING_IP4_LL_FALLBACK
|
||||
&& nm_streq(method, NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL)) {
|
||||
/* ipv4.link-local=fallback with ipv4.method=link-local will
|
||||
* always be on anyway, simplify logic */
|
||||
link_local = NM_SETTING_IP4_LL_ENABLED;
|
||||
}
|
||||
|
||||
nm_assert(NM_IN_SET(link_local,
|
||||
NM_SETTING_IP4_LL_DISABLED,
|
||||
NM_SETTING_IP4_LL_ENABLED,
|
||||
NM_SETTING_IP4_LL_FALLBACK));
|
||||
|
||||
return link_local;
|
||||
}
|
||||
@@ -4639,13 +4658,14 @@ _dev_l3_cfg_notify_cb(NML3Cfg *l3cfg, const NML3ConfigNotifyData *notify_data, N
|
||||
const NML3ConfigData *l3cd;
|
||||
NMDeviceState state = nm_device_get_state(self);
|
||||
|
||||
l3cd = nm_l3cfg_get_combined_l3cd(l3cfg, TRUE);
|
||||
if (state >= NM_DEVICE_STATE_IP_CONFIG && state < NM_DEVICE_STATE_DEACTIVATING) {
|
||||
/* FIXME(l3cfg): MTU handling should be moved to l3cfg. */
|
||||
l3cd = nm_l3cfg_get_combined_l3cd(l3cfg, TRUE);
|
||||
if (l3cd)
|
||||
priv->ip6_mtu = nm_l3_config_data_get_ip6_mtu(l3cd);
|
||||
_commit_mtu(self);
|
||||
}
|
||||
_dev_ipll4_check_fallback(self, l3cd);
|
||||
return;
|
||||
}
|
||||
case NM_L3_CONFIG_NOTIFY_TYPE_POST_COMMIT:
|
||||
@@ -10648,6 +10668,25 @@ _dev_ipll4_start(NMDevice *self)
|
||||
nm_l3_ipv4ll_register_new(priv->ipll_data_4.v4.ipv4ll, timeout_msec);
|
||||
}
|
||||
|
||||
static void
|
||||
_dev_ipll4_check_fallback(NMDevice *self, const NML3ConfigData *l3cd_new)
|
||||
{
|
||||
gboolean has_non_ll;
|
||||
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
|
||||
|
||||
if (!l3cd_new || priv->ipll_data_4.v4.mode != NM_SETTING_IP4_LL_FALLBACK) {
|
||||
return;
|
||||
}
|
||||
|
||||
has_non_ll = nm_l3_config_data_get_flags(l3cd_new) & NM_L3_CONFIG_DAT_FLAGS_HAS_IPV4_NON_LL;
|
||||
_LOGT_ipll(AF_INET, "%s fallback", has_non_ll ? "cleanup" : "start");
|
||||
if (has_non_ll) {
|
||||
_dev_ipllx_cleanup(self, AF_INET);
|
||||
} else {
|
||||
_dev_ipll4_start(self);
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static const char *
|
||||
@@ -12747,7 +12786,8 @@ activate_stage3_ip_config_for_addr_family(NMDevice *self, int addr_family, const
|
||||
goto out_devip;
|
||||
|
||||
if (IS_IPv4) {
|
||||
if (_prop_get_ipv4_link_local(self) == NM_SETTING_IP4_LL_ENABLED)
|
||||
priv->ipll_data_4.v4.mode = _prop_get_ipv4_link_local(self);
|
||||
if (priv->ipll_data_4.v4.mode == NM_SETTING_IP4_LL_ENABLED)
|
||||
_dev_ipll4_start(self);
|
||||
|
||||
if (nm_streq(method, NM_SETTING_IP4_CONFIG_METHOD_AUTO))
|
||||
@@ -13495,8 +13535,11 @@ _cleanup_ip_pre(NMDevice *self, int addr_family, CleanupType cleanup_type, gbool
|
||||
|
||||
_dev_ipdhcpx_cleanup(self, addr_family, !preserve_dhcp || !keep_reapply, FALSE);
|
||||
|
||||
if (!IS_IPv4)
|
||||
if (IS_IPv4) {
|
||||
priv->ipll_data_4.v4.mode = NM_SETTING_IP4_LL_DISABLED;
|
||||
} else {
|
||||
_dev_ipac6_cleanup(self);
|
||||
}
|
||||
|
||||
_dev_ipllx_cleanup(self, addr_family);
|
||||
|
||||
|
@@ -241,7 +241,8 @@ verify(NMSetting *setting, NMConnection *connection, GError **error)
|
||||
NM_SETTING_IP4_LL_AUTO,
|
||||
NM_SETTING_IP4_LL_DEFAULT,
|
||||
NM_SETTING_IP4_LL_DISABLED,
|
||||
NM_SETTING_IP4_LL_ENABLED)) {
|
||||
NM_SETTING_IP4_LL_ENABLED,
|
||||
NM_SETTING_IP4_LL_FALLBACK)) {
|
||||
g_set_error(error,
|
||||
NM_CONNECTION_ERROR,
|
||||
NM_CONNECTION_ERROR_INVALID_PROPERTY,
|
||||
@@ -252,7 +253,7 @@ verify(NMSetting *setting, NMConnection *connection, GError **error)
|
||||
NM_SETTING_IP4_CONFIG_LINK_LOCAL);
|
||||
return FALSE;
|
||||
}
|
||||
if (priv->link_local == NM_SETTING_IP4_LL_ENABLED
|
||||
if (NM_IN_SET(priv->link_local, NM_SETTING_IP4_LL_ENABLED, NM_SETTING_IP4_LL_FALLBACK)
|
||||
&& nm_streq(method, NM_SETTING_IP4_CONFIG_METHOD_DISABLED)) {
|
||||
g_set_error_literal(error,
|
||||
NM_CONNECTION_ERROR,
|
||||
@@ -1016,6 +1017,8 @@ nm_setting_ip4_config_class_init(NMSettingIP4ConfigClass *klass)
|
||||
* When set to "default", it honors the global connection default, before
|
||||
* falling back to "auto". Note that if "ipv4.method" is "disabled", then
|
||||
* link local addressing is always disabled too. The default is "default".
|
||||
* Since 1.50, when set to "fallback", a link-local address is obtained
|
||||
* if no other IPv4 address is set.
|
||||
*
|
||||
* Since: 1.40
|
||||
*/
|
||||
|
@@ -88,6 +88,8 @@ G_BEGIN_DECLS
|
||||
* @NM_SETTING_IP4_LL_DISABLED: Disable IPv4 link-local protocol.
|
||||
* @NM_SETTING_IP4_LL_ENABLED: Enable the IPv4 link-local protocol regardless what other protocols
|
||||
* such as DHCP or manually assigned IP addresses might be active.
|
||||
* @NM_SETTING_IP4_LL_FALLBACK: Since 1.50. This sets an IPv4 link-local address if no other IPv4
|
||||
* address is set, dynamically removing/re-adding it depending on DHCP leases.
|
||||
*
|
||||
* #NMSettingIP4LinkLocal values indicate whether IPv4 link-local address protocol should be enabled.
|
||||
*
|
||||
@@ -98,6 +100,7 @@ typedef enum {
|
||||
NM_SETTING_IP4_LL_AUTO = 1,
|
||||
NM_SETTING_IP4_LL_DISABLED = 2,
|
||||
NM_SETTING_IP4_LL_ENABLED = 3,
|
||||
NM_SETTING_IP4_LL_FALLBACK = 4,
|
||||
} NMSettingIP4LinkLocal;
|
||||
|
||||
typedef struct _NMSettingIP4ConfigClass NMSettingIP4ConfigClass;
|
||||
|
@@ -185,7 +185,7 @@
|
||||
#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_GATEWAY N_("The gateway associated with this configuration. This is only meaningful if \"addresses\" is also set. Setting the gateway causes NetworkManager to configure a standard default route with the gateway as next hop. This is ignored if \"never-default\" is set. An alternative is to configure the default route explicitly with a manual route and /0 as prefix length. Note that the gateway usually conflicts with routing that NetworkManager configures for WireGuard interfaces, so usually it should not be set in that case. See \"ip4-auto-default-route\".")
|
||||
#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_IGNORE_AUTO_DNS N_("When \"method\" is set to \"auto\" and this property to TRUE, automatically configured name servers and search domains are ignored and only name servers and search domains specified in the \"dns\" and \"dns-search\" properties, if any, are used.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_IGNORE_AUTO_ROUTES N_("When \"method\" is set to \"auto\" and this property to TRUE, automatically configured routes are ignored and only routes specified in the \"routes\" property, if any, are used.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_LINK_LOCAL N_("Enable and disable the IPv4 link-local configuration independently of the ipv4.method configuration. This allows a link-local address (169.254.x.y/16) to be obtained in addition to other addresses, such as those manually configured or obtained from a DHCP server. When set to \"auto\", the value is dependent on \"ipv4.method\". When set to \"default\", it honors the global connection default, before falling back to \"auto\". Note that if \"ipv4.method\" is \"disabled\", then link local addressing is always disabled too. The default is \"default\".")
|
||||
#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_LINK_LOCAL N_("Enable and disable the IPv4 link-local configuration independently of the ipv4.method configuration. This allows a link-local address (169.254.x.y/16) to be obtained in addition to other addresses, such as those manually configured or obtained from a DHCP server. When set to \"auto\", the value is dependent on \"ipv4.method\". When set to \"default\", it honors the global connection default, before falling back to \"auto\". Note that if \"ipv4.method\" is \"disabled\", then link local addressing is always disabled too. The default is \"default\". Since 1.50, when set to \"fallback\", a link-local address is obtained if no other IPv4 address is set.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_MAY_FAIL N_("If TRUE, allow overall network configuration to proceed even if the configuration specified by this property times out. Note that at least one IP configuration must succeed or overall network configuration will still fail. For example, in IPv6-only networks, setting this property to TRUE on the NMSettingIP4Config allows the overall network configuration to succeed if IPv4 configuration fails but IPv6 configuration completes successfully.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_METHOD N_("The IPv4 connection method.")
|
||||
#define DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_NEVER_DEFAULT N_("If TRUE, this connection will never be the default connection for this IP type, meaning it will never be assigned the default route by NetworkManager.")
|
||||
|
@@ -1377,9 +1377,9 @@
|
||||
nmcli-description="The Vendor Class Identifier DHCP option (60). Special characters in the data string may be escaped using C-style escapes, nevertheless this property cannot contain nul bytes. If the per-profile value is unspecified (the default), a global connection default gets consulted. If still unspecified, the DHCP option is not sent to the server."
|
||||
format="string" />
|
||||
<property name="link-local"
|
||||
nmcli-description="Enable and disable the IPv4 link-local configuration independently of the ipv4.method configuration. This allows a link-local address (169.254.x.y/16) to be obtained in addition to other addresses, such as those manually configured or obtained from a DHCP server. When set to "auto", the value is dependent on "ipv4.method". When set to "default", it honors the global connection default, before falling back to "auto". Note that if "ipv4.method" is "disabled", then link local addressing is always disabled too. The default is "default"."
|
||||
nmcli-description="Enable and disable the IPv4 link-local configuration independently of the ipv4.method configuration. This allows a link-local address (169.254.x.y/16) to be obtained in addition to other addresses, such as those manually configured or obtained from a DHCP server. When set to "auto", the value is dependent on "ipv4.method". When set to "default", it honors the global connection default, before falling back to "auto". Note that if "ipv4.method" is "disabled", then link local addressing is always disabled too. The default is "default". Since 1.50, when set to "fallback", a link-local address is obtained if no other IPv4 address is set."
|
||||
format="choice (NMSettingIP4LinkLocal)"
|
||||
values="default (0), auto (1), disabled (2), enabled (3)" />
|
||||
values="default (0), auto (1), disabled (2), enabled (3), fallback (4)" />
|
||||
<property name="dhcp-reject-servers"
|
||||
nmcli-description="Array of servers from which DHCP offers must be rejected. This property is useful to avoid getting a lease from misconfigured or rogue servers. For DHCPv4, each element must be an IPv4 address, optionally followed by a slash and a prefix length (e.g. "192.168.122.0/24"). This property is currently not implemented for DHCPv6."
|
||||
format="list of IPv4 addresses" />
|
||||
|
Reference in New Issue
Block a user