diff options
Diffstat (limited to 'src')
36 files changed, 681 insertions, 168 deletions
diff --git a/src/NetworkManagerUtils.c b/src/NetworkManagerUtils.c index 1773405d..c33f36ec 100644 --- a/src/NetworkManagerUtils.c +++ b/src/NetworkManagerUtils.c @@ -359,11 +359,12 @@ check_ip6_method (NMConnection *orig, */ allow = TRUE; } else if ( NM_IN_STRSET (orig_ip6_method, NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL, + NM_SETTING_IP6_CONFIG_METHOD_DISABLED, NM_SETTING_IP6_CONFIG_METHOD_AUTO) && nm_streq0 (candidate_ip6_method, NM_SETTING_IP6_CONFIG_METHOD_IGNORE)) { - /* If the generated connection method is 'link-local' or 'auto' and the candidate - * method is 'ignore' we can take the connection, because NM didn't simply take care - * of IPv6. + /* If the generated connection method is 'link-local', disabled' or 'auto' and + * the candidate method is 'ignore' we can take the connection, because NM didn't + * simply take care of IPv6. */ allow = TRUE; } diff --git a/src/devices/nm-device-ethernet.c b/src/devices/nm-device-ethernet.c index 8571e526..b2b05883 100644 --- a/src/devices/nm-device-ethernet.c +++ b/src/devices/nm-device-ethernet.c @@ -87,6 +87,7 @@ typedef enum { typedef struct _NMDeviceEthernetPrivate { guint32 speed; + gulong carrier_id; Supplicant supplicant; guint supplicant_timeout_id; @@ -948,7 +949,7 @@ act_stage1_prepare (NMDevice *device, NMDeviceStateReason *out_failure_reason) } static NMActStageReturn -nm_8021x_stage2_config (NMDeviceEthernet *self, NMDeviceStateReason *out_failure_reason) +supplicant_check_secrets_needed (NMDeviceEthernet *self, NMDeviceStateReason *out_failure_reason) { NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); NMConnection *connection; @@ -957,7 +958,6 @@ nm_8021x_stage2_config (NMDeviceEthernet *self, NMDeviceStateReason *out_failure NMActStageReturn ret = NM_ACT_STAGE_RETURN_FAILURE; connection = nm_device_get_applied_connection (NM_DEVICE (self)); - g_return_val_if_fail (connection, NM_ACT_STAGE_RETURN_FAILURE); security = nm_connection_get_setting_802_1x (connection); @@ -996,6 +996,44 @@ nm_8021x_stage2_config (NMDeviceEthernet *self, NMDeviceStateReason *out_failure return ret; } +static void +carrier_changed (NMSupplicantInterface *iface, + GParamSpec *pspec, + NMDeviceEthernet *self) +{ + NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); + NMDeviceStateReason reason; + NMActStageReturn ret; + + if (nm_device_has_carrier (NM_DEVICE (self))) { + _LOGD (LOGD_DEVICE | LOGD_ETHER, "got carrier, initializing supplicant"); + nm_clear_g_signal_handler (self, &priv->carrier_id); + ret = supplicant_check_secrets_needed (self, &reason); + if (ret == NM_ACT_STAGE_RETURN_FAILURE) { + nm_device_state_changed (NM_DEVICE (self), + NM_DEVICE_STATE_FAILED, + reason); + } + } +} + +static NMActStageReturn +nm_8021x_stage2_config (NMDeviceEthernet *self, NMDeviceStateReason *out_failure_reason) +{ + NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); + + if (!nm_device_has_carrier (NM_DEVICE (self))) { + _LOGD (LOGD_DEVICE | LOGD_ETHER, "delay supplicant initialization until carrier goes up"); + priv->carrier_id = g_signal_connect (self, + "notify::" NM_DEVICE_CARRIER, + G_CALLBACK (carrier_changed), + self); + return NM_ACT_STAGE_RETURN_POSTPONE; + } + + return supplicant_check_secrets_needed (self, out_failure_reason); +} + /*****************************************************************************/ /* PPPoE */ @@ -1393,13 +1431,15 @@ act_stage3_ip_config_start (NMDevice *device, } static guint32 -get_configured_mtu (NMDevice *device, NMDeviceMtuSource *out_source) +get_configured_mtu (NMDevice *device, + NMDeviceMtuSource *out_source, + gboolean *out_force) { /* MTU only set for plain ethernet */ if (NM_DEVICE_ETHERNET_GET_PRIVATE ((NMDeviceEthernet *) device)->ppp_manager) return 0; - return nm_device_get_configured_mtu_for_wired (device, out_source); + return nm_device_get_configured_mtu_for_wired (device, out_source, out_force); } static void @@ -1411,6 +1451,7 @@ deactivate (NMDevice *device) GError *error = NULL; nm_clear_g_source (&priv->pppoe_wait_id); + nm_clear_g_signal_handler (self, &priv->carrier_id); if (priv->ppp_manager) { nm_ppp_manager_stop (priv->ppp_manager, NULL, NULL, NULL); @@ -1727,6 +1768,8 @@ dispose (GObject *object) nm_clear_g_source (&priv->dcb_timeout_id); + nm_clear_g_signal_handler (self, &priv->carrier_id); + G_OBJECT_CLASS (nm_device_ethernet_parent_class)->dispose (object); } diff --git a/src/devices/nm-device-infiniband.c b/src/devices/nm-device-infiniband.c index 89db2af2..e39329a9 100644 --- a/src/devices/nm-device-infiniband.c +++ b/src/devices/nm-device-infiniband.c @@ -116,7 +116,9 @@ act_stage1_prepare (NMDevice *device, NMDeviceStateReason *out_failure_reason) } static guint32 -get_configured_mtu (NMDevice *device, NMDeviceMtuSource *out_source) +get_configured_mtu (NMDevice *device, + NMDeviceMtuSource *out_source, + gboolean *out_force) { return nm_device_get_configured_mtu_from_connection (device, NM_TYPE_SETTING_INFINIBAND, diff --git a/src/devices/nm-device-ip-tunnel.c b/src/devices/nm-device-ip-tunnel.c index ede4487e..f070dd5f 100644 --- a/src/devices/nm-device-ip-tunnel.c +++ b/src/devices/nm-device-ip-tunnel.c @@ -854,7 +854,9 @@ create_and_realize (NMDevice *device, } static guint32 -get_configured_mtu (NMDevice *device, NMDeviceMtuSource *out_source) +get_configured_mtu (NMDevice *device, + NMDeviceMtuSource *out_source, + gboolean *out_force) { return nm_device_get_configured_mtu_from_connection (device, NM_TYPE_SETTING_IP_TUNNEL, diff --git a/src/devices/nm-device-macsec.c b/src/devices/nm-device-macsec.c index e3e3a895..13798f5e 100644 --- a/src/devices/nm-device-macsec.c +++ b/src/devices/nm-device-macsec.c @@ -66,6 +66,7 @@ NM_GOBJECT_PROPERTIES_DEFINE (NMDeviceMacsec, typedef struct { NMPlatformLnkMacsec props; gulong parent_state_id; + gulong parent_mtu_id; Supplicant supplicant; guint supplicant_timeout_id; NMActRequestGetSecretsCallId *macsec_secrets_id; @@ -114,6 +115,17 @@ parent_state_changed (NMDevice *parent, } static void +parent_mtu_maybe_changed (NMDevice *parent, + GParamSpec *pspec, + gpointer user_data) +{ + /* the MTU of a MACsec device is limited by the parent's MTU. + * + * When the parent's MTU changes, try to re-set the MTU. */ + nm_device_commit_mtu (user_data); +} + +static void parent_changed_notify (NMDevice *device, int old_ifindex, NMDevice *old_parent, @@ -133,12 +145,16 @@ parent_changed_notify (NMDevice *device, * because NMDevice's dispose() will unset the parent, which in turn calls * parent_changed_notify(). */ nm_clear_g_signal_handler (old_parent, &priv->parent_state_id); + nm_clear_g_signal_handler (old_parent, &priv->parent_mtu_id); if (new_parent) { priv->parent_state_id = g_signal_connect (new_parent, NM_DEVICE_STATE_CHANGED, G_CALLBACK (parent_state_changed), device); + priv->parent_mtu_id = g_signal_connect (new_parent, "notify::" NM_DEVICE_MTU, + G_CALLBACK (parent_mtu_maybe_changed), device); + /* Set parent-dependent unmanaged flag */ nm_device_set_unmanaged_by_flags (device, @@ -791,11 +807,15 @@ static void dispose (GObject *object) { NMDeviceMacsec *self = NM_DEVICE_MACSEC (object); + NMDeviceMacsecPrivate *priv = NM_DEVICE_MACSEC_GET_PRIVATE (self); macsec_secrets_cancel (self); supplicant_interface_release (self); G_OBJECT_CLASS (nm_device_macsec_parent_class)->dispose (object); + + nm_assert (priv->parent_state_id == 0); + nm_assert (priv->parent_mtu_id == 0); } static const NMDBusInterfaceInfoExtended interface_info_device_macsec = { @@ -838,6 +858,7 @@ nm_device_macsec_class_init (NMDeviceMacsecClass *klass) device_class->connection_type_supported = NM_SETTING_MACSEC_SETTING_NAME; device_class->connection_type_check_compatible = NM_SETTING_MACSEC_SETTING_NAME; device_class->link_types = NM_DEVICE_DEFINE_LINK_TYPES (NM_LINK_TYPE_MACSEC); + device_class->mtu_parent_delta = 32; device_class->act_stage2_config = act_stage2_config; device_class->create_and_realize = create_and_realize; @@ -847,7 +868,7 @@ nm_device_macsec_class_init (NMDeviceMacsecClass *klass) device_class->is_available = is_available; device_class->parent_changed_notify = parent_changed_notify; device_class->state_changed = device_state_changed; - device_class->get_configured_mtu = nm_device_get_configured_mtu_for_wired; + device_class->get_configured_mtu = nm_device_get_configured_mtu_wired_parent; obj_properties[PROP_SCI] = g_param_spec_uint64 (NM_DEVICE_MACSEC_SCI, "", "", diff --git a/src/devices/nm-device-macvlan.c b/src/devices/nm-device-macvlan.c index ee8b9974..964e0f61 100644 --- a/src/devices/nm-device-macvlan.c +++ b/src/devices/nm-device-macvlan.c @@ -48,6 +48,7 @@ NM_GOBJECT_PROPERTIES_DEFINE (NMDeviceMacvlan, typedef struct { gulong parent_state_id; + gulong parent_mtu_id; NMPlatformLnkMacvlan props; } NMDeviceMacvlanPrivate; @@ -135,6 +136,17 @@ parent_state_changed (NMDevice *parent, } static void +parent_mtu_maybe_changed (NMDevice *parent, + GParamSpec *pspec, + gpointer user_data) +{ + /* the MTU of a macvlan/macvtap device is limited by the parent's MTU. + * + * When the parent's MTU changes, try to re-set the MTU. */ + nm_device_commit_mtu (user_data); +} + +static void parent_changed_notify (NMDevice *device, int old_ifindex, NMDevice *old_parent, @@ -150,12 +162,15 @@ parent_changed_notify (NMDevice *device, * because NMDevice's dispose() will unset the parent, which in turn calls * parent_changed_notify(). */ nm_clear_g_signal_handler (old_parent, &priv->parent_state_id); + nm_clear_g_signal_handler (old_parent, &priv->parent_mtu_id); if (new_parent) { priv->parent_state_id = g_signal_connect (new_parent, NM_DEVICE_STATE_CHANGED, G_CALLBACK (parent_state_changed), device); + priv->parent_mtu_id = g_signal_connect (new_parent, "notify::" NM_DEVICE_MTU, + G_CALLBACK (parent_mtu_maybe_changed), device); /* Set parent-dependent unmanaged flag */ nm_device_set_unmanaged_by_flags (device, @@ -476,6 +491,17 @@ nm_device_macvlan_init (NMDeviceMacvlan *self) { } +static void +dispose (GObject *object) +{ + NMDeviceMacvlanPrivate *priv = NM_DEVICE_MACVLAN_GET_PRIVATE (object); + + G_OBJECT_CLASS (nm_device_macvlan_parent_class)->dispose (object); + + nm_assert (priv->parent_state_id == 0); + nm_assert (priv->parent_mtu_id == 0); +} + static const NMDBusInterfaceInfoExtended interface_info_device_macvlan = { .parent = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT ( NM_DBUS_INTERFACE_DEVICE_MACVLAN, @@ -499,6 +525,7 @@ nm_device_macvlan_class_init (NMDeviceMacvlanClass *klass) NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS (klass); NMDeviceClass *device_class = NM_DEVICE_CLASS (klass); + object_class->dispose = dispose; object_class->get_property = get_property; object_class->set_property = set_property; @@ -507,13 +534,14 @@ nm_device_macvlan_class_init (NMDeviceMacvlanClass *klass) device_class->connection_type_supported = NM_SETTING_MACVLAN_SETTING_NAME; device_class->connection_type_check_compatible = NM_SETTING_MACVLAN_SETTING_NAME; device_class->link_types = NM_DEVICE_DEFINE_LINK_TYPES (NM_LINK_TYPE_MACVLAN, NM_LINK_TYPE_MACVTAP); + device_class->mtu_parent_delta = 0; device_class->act_stage1_prepare = act_stage1_prepare; device_class->check_connection_compatible = check_connection_compatible; device_class->complete_connection = complete_connection; device_class->create_and_realize = create_and_realize; device_class->get_generic_capabilities = get_generic_capabilities; - device_class->get_configured_mtu = nm_device_get_configured_mtu_for_wired; + device_class->get_configured_mtu = nm_device_get_configured_mtu_wired_parent; device_class->is_available = is_available; device_class->link_changed = link_changed; device_class->parent_changed_notify = parent_changed_notify; diff --git a/src/devices/nm-device-private.h b/src/devices/nm-device-private.h index 0a414af9..83feb130 100644 --- a/src/devices/nm-device-private.h +++ b/src/devices/nm-device-private.h @@ -174,7 +174,11 @@ guint32 nm_device_get_configured_mtu_from_connection (NMDevice *device, GType setting_type, NMDeviceMtuSource *out_source); -guint32 nm_device_get_configured_mtu_for_wired (NMDevice *self, NMDeviceMtuSource *out_source); +guint32 nm_device_get_configured_mtu_for_wired (NMDevice *self, NMDeviceMtuSource *out_source, gboolean *out_force); + +guint32 nm_device_get_configured_mtu_wired_parent (NMDevice *self, + NMDeviceMtuSource *out_source, + gboolean *out_force); void nm_device_commit_mtu (NMDevice *self); diff --git a/src/devices/nm-device-vlan.c b/src/devices/nm-device-vlan.c index 0467a6e4..f8f6a597 100644 --- a/src/devices/nm-device-vlan.c +++ b/src/devices/nm-device-vlan.c @@ -523,26 +523,6 @@ act_stage1_prepare (NMDevice *device, NMDeviceStateReason *out_failure_reason) return ret; } -static guint32 -get_configured_mtu (NMDevice *self, NMDeviceMtuSource *out_source) -{ - guint32 mtu = 0; - int ifindex; - - mtu = nm_device_get_configured_mtu_for_wired (self, out_source); - if (*out_source != NM_DEVICE_MTU_SOURCE_NONE) - return mtu; - - /* Inherit the MTU from parent device, if any */ - ifindex = nm_device_parent_get_ifindex (self); - if (ifindex > 0) { - mtu = nm_platform_link_get_mtu (nm_device_get_platform (NM_DEVICE (self)), ifindex); - *out_source = NM_DEVICE_MTU_SOURCE_PARENT; - } - - return mtu; -} - /*****************************************************************************/ static void @@ -598,13 +578,14 @@ nm_device_vlan_class_init (NMDeviceVlanClass *klass) device_class->connection_type_supported = NM_SETTING_VLAN_SETTING_NAME; device_class->connection_type_check_compatible = NM_SETTING_VLAN_SETTING_NAME; device_class->link_types = NM_DEVICE_DEFINE_LINK_TYPES (NM_LINK_TYPE_VLAN); + device_class->mtu_parent_delta = 0; /* VLANs can have the same MTU of parent */ device_class->create_and_realize = create_and_realize; device_class->link_changed = link_changed; device_class->unrealize_notify = unrealize_notify; device_class->get_generic_capabilities = get_generic_capabilities; device_class->act_stage1_prepare = act_stage1_prepare; - device_class->get_configured_mtu = get_configured_mtu; + device_class->get_configured_mtu = nm_device_get_configured_mtu_wired_parent; device_class->is_available = is_available; device_class->parent_changed_notify = parent_changed_notify; diff --git a/src/devices/nm-device-wireguard.c b/src/devices/nm-device-wireguard.c index e3b8e8b4..5d640b62 100644 --- a/src/devices/nm-device-wireguard.c +++ b/src/devices/nm-device-wireguard.c @@ -1714,7 +1714,7 @@ act_stage3_ip_config_start (NMDevice *device, } static guint32 -get_configured_mtu (NMDevice *device, NMDeviceMtuSource *out_source) +get_configured_mtu (NMDevice *device, NMDeviceMtuSource *out_source, gboolean *out_force) { /* When "MTU" for `wg-quick up` is unset, it calls `ip route get` for * each configured endpoint, to determine the suitable MTU how to reach diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index 67e23b8f..b3d97af7 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -9274,13 +9274,59 @@ nm_device_get_configured_mtu_from_connection (NMDevice *self, } guint32 -nm_device_get_configured_mtu_for_wired (NMDevice *self, NMDeviceMtuSource *out_source) +nm_device_get_configured_mtu_for_wired (NMDevice *self, + NMDeviceMtuSource *out_source, + gboolean *out_force) { return nm_device_get_configured_mtu_from_connection (self, NM_TYPE_SETTING_WIRED, out_source); } +guint32 +nm_device_get_configured_mtu_wired_parent (NMDevice *self, + NMDeviceMtuSource *out_source, + gboolean *out_force) +{ + guint32 mtu = 0; + guint32 parent_mtu = 0; + int ifindex; + + ifindex = nm_device_parent_get_ifindex (self); + if (ifindex > 0) { + parent_mtu = nm_platform_link_get_mtu (nm_device_get_platform (self), ifindex); + if (parent_mtu >= NM_DEVICE_GET_CLASS (self)->mtu_parent_delta) + parent_mtu -= NM_DEVICE_GET_CLASS (self)->mtu_parent_delta; + else + parent_mtu = 0; + } + + mtu = nm_device_get_configured_mtu_for_wired (self, out_source, NULL); + + if (parent_mtu && mtu > parent_mtu) { + /* Trying to set a MTU that is out of range from configuration: + * fall back to the parent MTU and set force flag so that it + * overrides an MTU with higher priority already configured. + */ + *out_source = NM_DEVICE_MTU_SOURCE_PARENT; + *out_force = TRUE; + return parent_mtu; + } + + if (*out_source != NM_DEVICE_MTU_SOURCE_NONE) { + nm_assert (mtu > 0); + return mtu; + } + + /* Inherit the MTU from parent device, if any */ + if (parent_mtu) { + mtu = parent_mtu; + *out_source = NM_DEVICE_MTU_SOURCE_PARENT; + } + + return mtu; +} + /*****************************************************************************/ static void @@ -9332,15 +9378,34 @@ _commit_mtu (NMDevice *self, const NMIP4Config *config) { guint32 mtu = 0; + gboolean force = FALSE; - /* preferably, get the MTU from explicit user-configuration. - * Only if that fails, look at the current @config (which contains - * MTUs from DHCP/PPP) or maybe fallback to a device-specific MTU. */ + /* We take the MTU from various sources: (in order of increasing + * priority) parent link, IP configuration (which contains the + * MTU from DHCP/PPP), connection profile. + * + * We could just compare it with the platform MTU and apply it + * when different, but this would revert at random times manual + * changes done by the user with the MTU from the connection. + * + * Instead, we remember the source of the currently configured + * MTU and apply the new one only when the new source has a + * higher priority, so that we don't set a MTU from same source + * multiple times. An exception to this is for the PARENT + * source, since we need to keep tracking the parent MTU when it + * changes. + * + * The subclass can set the @force argument to TRUE to signal that the + * returned MTU should be applied even if it has a lower priority. This + * is useful when the value from a lower source should + * preempt the one from higher ones. + */ if (NM_DEVICE_GET_CLASS (self)->get_configured_mtu) - mtu = NM_DEVICE_GET_CLASS (self)->get_configured_mtu (self, &source); + mtu = NM_DEVICE_GET_CLASS (self)->get_configured_mtu (self, &source, &force); if ( config + && !force && source < NM_DEVICE_MTU_SOURCE_IP_CONFIG && nm_ip4_config_get_mtu (config)) { mtu = nm_ip4_config_get_mtu (config); @@ -9349,14 +9414,16 @@ _commit_mtu (NMDevice *self, const NMIP4Config *config) if (mtu != 0) { _LOGT (LOGD_DEVICE, - "mtu: value %u from source '%s' (%u), current source '%s' (%u)", + "mtu: value %u from source '%s' (%u), current source '%s' (%u)%s", (guint) mtu, mtu_source_to_str (source), (guint) source, - mtu_source_to_str (priv->mtu_source), (guint) priv->mtu_source); + mtu_source_to_str (priv->mtu_source), (guint) priv->mtu_source, + force ? " (forced)" : ""); } if ( mtu != 0 - && ( source > priv->mtu_source + && ( force + || source > priv->mtu_source || (priv->mtu_source == NM_DEVICE_MTU_SOURCE_PARENT && source == priv->mtu_source))) mtu_desired = mtu; else { @@ -9600,6 +9667,18 @@ ndisc_config_changed (NMNDisc *ndisc, const NMNDiscData *rdata, guint changed_in if (changed & NM_NDISC_CONFIG_HOP_LIMIT) nm_platform_sysctl_ip_conf_set_ipv6_hop_limit_safe (nm_device_get_platform (self), nm_device_get_ip_iface (self), rdata->hop_limit); + if (changed & NM_NDISC_CONFIG_REACHABLE_TIME) { + nm_platform_sysctl_ip_neigh_set_ipv6_reachable_time (nm_device_get_platform (self), + nm_device_get_ip_iface (self), + rdata->reachable_time_ms); + } + + if (changed & NM_NDISC_CONFIG_RETRANS_TIMER) { + nm_platform_sysctl_ip_neigh_set_ipv6_retrans_time (nm_device_get_platform (self), + nm_device_get_ip_iface (self), + rdata->retrans_timer_ms); + } + if (changed & NM_NDISC_CONFIG_MTU) { if (priv->ip6_mtu != rdata->mtu) { _LOGD (LOGD_DEVICE, "mtu: set IPv6 MTU to %u", (guint) rdata->mtu); @@ -9661,24 +9740,11 @@ addrconf6_start_with_link_ready (NMDevice *self) if (!ip_config_merge_and_apply (self, AF_INET6, TRUE)) _LOGW (LOGD_IP6, "failed to apply manual IPv6 configuration"); - /* FIXME: These sysctls would probably be better set by the lndp ndisc itself. */ - switch (nm_ndisc_get_node_type (priv->ndisc)) { - case NM_NDISC_NODE_TYPE_HOST: - /* Accepting prefixes from discovered routers. */ - nm_device_sysctl_ip_conf_set (self, AF_INET6, "accept_ra", "1"); - nm_device_sysctl_ip_conf_set (self, AF_INET6, "accept_ra_defrtr", "0"); - nm_device_sysctl_ip_conf_set (self, AF_INET6, "accept_ra_pinfo", "0"); - nm_device_sysctl_ip_conf_set (self, AF_INET6, "accept_ra_rtr_pref", "0"); - break; - case NM_NDISC_NODE_TYPE_ROUTER: - /* We're the router. */ + if (nm_ndisc_get_node_type (priv->ndisc) == NM_NDISC_NODE_TYPE_ROUTER) { nm_device_sysctl_ip_conf_set (self, AF_INET6, "forwarding", "1"); nm_device_activate_schedule_ip_config_result (self, AF_INET6, NULL); priv->needs_ip6_subnet = TRUE; g_signal_emit (self, signals[IP6_SUBNET_NEEDED], 0); - break; - default: - g_assert_not_reached (); } priv->ndisc_changed_id = g_signal_connect (priv->ndisc, @@ -9789,9 +9855,6 @@ save_ip6_properties (NMDevice *self) { static const char *const ip6_properties_to_save[] = { "accept_ra", - "accept_ra_defrtr", - "accept_ra_pinfo", - "accept_ra_rtr_pref", "forwarding", "disable_ipv6", "hop_limit", @@ -10116,6 +10179,7 @@ act_stage3_ip_config_start (NMDevice *self, set_nm_ipv6ll (self, TRUE); /* Re-enable IPv6 on the interface */ + nm_device_sysctl_ip_conf_set (self, AF_INET6, "accept_ra", "0"); set_disable_ipv6 (self, "0"); /* Synchronize external IPv6 configuration with kernel, since @@ -12123,7 +12187,7 @@ _carrier_wait_check_queued_act_request (NMDevice *self) _LOGD (LOGD_DEVICE, "Cancel queued activation request as we have no carrier after timeout"); _clear_queued_act_request (priv, NM_ACTIVE_CONNECTION_STATE_REASON_DEVICE_DISCONNECTED); - } else { + } else if (priv->state == NM_DEVICE_STATE_DISCONNECTED) { gs_unref_object NMActRequest *queued_req = NULL; _LOGD (LOGD_DEVICE, "Activate queued activation request as we now have carrier"); @@ -14744,7 +14808,6 @@ nm_device_cleanup (NMDevice *self, NMDeviceStateReason reason, CleanupType clean /* Turn off kernel IPv6 */ if (cleanup_type == CLEANUP_TYPE_DECONFIGURE) { set_disable_ipv6 (self, "1"); - nm_device_sysctl_ip_conf_set (self, AF_INET6, "accept_ra", "0"); nm_device_sysctl_ip_conf_set (self, AF_INET6, "use_tempaddr", "0"); } @@ -14802,6 +14865,7 @@ nm_device_cleanup (NMDevice *self, NMDeviceStateReason reason, CleanupType clean } priv->mtu_source = NM_DEVICE_MTU_SOURCE_NONE; + priv->ip6_mtu = 0; if (priv->mtu_initial || priv->ip6_mtu_initial) { ifindex = nm_device_get_ip_ifindex (self); @@ -15035,9 +15099,7 @@ ip6_managed_setup (NMDevice *self) { set_nm_ipv6ll (self, TRUE); set_disable_ipv6 (self, "1"); - nm_device_sysctl_ip_conf_set (self, AF_INET6, "accept_ra_defrtr", "0"); - nm_device_sysctl_ip_conf_set (self, AF_INET6, "accept_ra_pinfo", "0"); - nm_device_sysctl_ip_conf_set (self, AF_INET6, "accept_ra_rtr_pref", "0"); + nm_device_sysctl_ip_conf_set (self, AF_INET6, "accept_ra", "0"); nm_device_sysctl_ip_conf_set (self, AF_INET6, "use_tempaddr", "0"); nm_device_sysctl_ip_conf_set (self, AF_INET6, "forwarding", "0"); } diff --git a/src/devices/nm-device.h b/src/devices/nm-device.h index ae6aab39..412a57a0 100644 --- a/src/devices/nm-device.h +++ b/src/devices/nm-device.h @@ -239,6 +239,10 @@ typedef struct _NMDeviceClass { const NMLinkType *link_types; + /* if the device MTU is set based on parent's one, this specifies + * a delta in the MTU allowed value due the encapsulation overhead */ + guint16 mtu_parent_delta; + /* Whether the device type is a master-type. This depends purely on the * type (NMDeviceClass), not the actual device instance. */ bool is_master:1; @@ -335,7 +339,9 @@ typedef struct _NMDeviceClass { NMSettingsConnection *sett_conn, char **specific_object); - guint32 (*get_configured_mtu) (NMDevice *self, NMDeviceMtuSource *out_source); + guint32 (*get_configured_mtu) (NMDevice *self, + NMDeviceMtuSource *out_source, + gboolean *out_force); /* allow the subclass to overwrite the routing table. This is mainly useful * to change from partial mode (route-table=0) to full-sync mode (route-table=254). */ diff --git a/src/devices/ovs/nm-device-ovs-port.c b/src/devices/ovs/nm-device-ovs-port.c index 8a93a5a9..39e64b3f 100644 --- a/src/devices/ovs/nm-device-ovs-port.c +++ b/src/devices/ovs/nm-device-ovs-port.c @@ -102,6 +102,7 @@ enslave_slave (NMDevice *device, NMDevice *slave, NMConnection *connection, gboo { NMActiveConnection *ac_port = NULL; NMActiveConnection *ac_bridge = NULL; + NMDevice *bridge_device; if (!configure) return TRUE; @@ -111,10 +112,14 @@ enslave_slave (NMDevice *device, NMDevice *slave, NMConnection *connection, gboo if (!ac_bridge) ac_bridge = ac_port; + bridge_device = nm_active_connection_get_device (ac_bridge); + nm_ovsdb_add_interface (nm_ovsdb_get (), nm_active_connection_get_applied_connection (ac_bridge), nm_device_get_applied_connection (device), nm_device_get_applied_connection (slave), + bridge_device, + slave, add_iface_cb, g_object_ref (slave)); return TRUE; diff --git a/src/devices/ovs/nm-ovsdb.c b/src/devices/ovs/nm-ovsdb.c index e5de466c..c0e68db3 100644 --- a/src/devices/ovs/nm-ovsdb.c +++ b/src/devices/ovs/nm-ovsdb.c @@ -27,6 +27,7 @@ #include "nm-glib-aux/nm-jansson.h" #include "nm-core-utils.h" #include "nm-core-internal.h" +#include "devices/nm-device.h" /*****************************************************************************/ @@ -130,6 +131,8 @@ typedef struct { NMConnection *bridge; NMConnection *port; NMConnection *interface; + NMDevice *bridge_device; + NMDevice *interface_device; }; }; } OvsdbMethodCall; @@ -182,6 +185,7 @@ static void ovsdb_call_method (NMOvsdb *self, OvsdbCommand command, const char *ifname, NMConnection *bridge, NMConnection *port, NMConnection *interface, + NMDevice *bridge_device, NMDevice *interface_device, OvsdbMethodCallback callback, gpointer user_data) { NMOvsdbPrivate *priv = NM_OVSDB_GET_PRIVATE (self); @@ -204,6 +208,8 @@ ovsdb_call_method (NMOvsdb *self, OvsdbCommand command, call->bridge = nm_simple_connection_new_clone (bridge); call->port = nm_simple_connection_new_clone (port); call->interface = nm_simple_connection_new_clone (interface); + call->bridge_device = g_object_ref (bridge_device); + call->interface_device = g_object_ref (interface_device); break; case OVSDB_DEL_INTERFACE: call->ifname = g_strdup (ifname); @@ -336,18 +342,33 @@ _set_port_interfaces (json_t *params, const char *ifname, json_t *new_interfaces * Returns an commands that adds new interface from a given connection. */ static void -_insert_interface (json_t *params, NMConnection *interface) +_insert_interface (json_t *params, NMConnection *interface, NMDevice *interface_device) { const char *type = NULL; NMSettingOvsInterface *s_ovs_iface; NMSettingOvsDpdk *s_ovs_dpdk; NMSettingOvsPatch *s_ovs_patch; json_t *options = json_array (); + gs_free char *cloned_mac = NULL; + gs_free_error GError *error = NULL; + json_t *row; s_ovs_iface = nm_connection_get_setting_ovs_interface (interface); if (s_ovs_iface) type = nm_setting_ovs_interface_get_interface_type (s_ovs_iface); + if (!nm_device_hw_addr_get_cloned (interface_device, + interface, + FALSE, + &cloned_mac, + NULL, + &error)) { + _LOGW ("Cannot determine cloned mac for OVS %s '%s': %s", + "interface", + nm_connection_get_interface_name (interface), + error->message); + } + json_array_append_new (options, json_string ("map")); s_ovs_dpdk = (NMSettingOvsDpdk *) nm_connection_get_setting (interface, @@ -367,14 +388,22 @@ _insert_interface (json_t *params, NMConnection *interface) json_array_append_new (options, json_array ()); } + row = json_pack ("{s:s, s:s, s:o, s:[s, [[s, s]]]}", + "name", nm_connection_get_interface_name (interface), + "type", type ?: "", + "options", options, + "external_ids", "map", + "NM.connection.uuid", nm_connection_get_uuid (interface)); + + if (cloned_mac) + json_object_set_new (row, "mac", json_string (cloned_mac)); + json_array_append_new (params, - json_pack ("{s:s, s:s, s:{s:s, s:s, s:o, s:[s, [[s, s]]]}, s:s}", - "op", "insert", "table", "Interface", "row", - "name", nm_connection_get_interface_name (interface), - "type", type ?: "", - "options", options, - "external_ids", "map", "NM.connection.uuid", nm_connection_get_uuid (interface), - "uuid-name", "rowInterface")); + json_pack ("{s:s, s:s, s:o, s:s}", + "op", "insert", + "table", "Interface", + "row", row, + "uuid-name", "rowInterface")); } /** @@ -438,7 +467,7 @@ _insert_port (json_t *params, NMConnection *port, json_t *new_interfaces) * Returns an commands that adds new bridge from a given connection. */ static void -_insert_bridge (json_t *params, NMConnection *bridge, json_t *new_ports) +_insert_bridge (json_t *params, NMConnection *bridge, NMDevice *bridge_device, json_t *new_ports) { NMSettingOvsBridge *s_ovs_bridge; const char *fail_mode = NULL; @@ -447,9 +476,23 @@ _insert_bridge (json_t *params, NMConnection *bridge, json_t *new_ports) gboolean stp_enable = FALSE; const char *datapath_type = NULL; json_t *row; + gs_free_error GError *error = NULL; + gs_free char *cloned_mac = NULL; s_ovs_bridge = nm_connection_get_setting_ovs_bridge (bridge); + if (!nm_device_hw_addr_get_cloned (bridge_device, + bridge, + FALSE, + &cloned_mac, + NULL, + &error)) { + _LOGW ("Cannot determine cloned mac for OVS %s '%s': %s", + "bridge", + nm_connection_get_interface_name (bridge), + error->message); + } + row = json_object (); if (s_ovs_bridge) { @@ -477,6 +520,12 @@ _insert_bridge (json_t *params, NMConnection *bridge, json_t *new_ports) json_pack ("[s, [[s, s]]]", "map", "NM.connection.uuid", nm_connection_get_uuid (bridge))); + if (cloned_mac) { + json_object_set_new (row, "other_config", + json_pack ("[s, [[s, s]]]", "map", + "hwaddr", cloned_mac)); + } + /* Create a new one. */ json_array_append_new (params, json_pack ("{s:s, s:s, s:o, s:s}", "op", "insert", "table", "Bridge", @@ -506,7 +555,8 @@ _inc_next_cfg (const char *db_uuid) */ static void _add_interface (NMOvsdb *self, json_t *params, - NMConnection *bridge, NMConnection *port, NMConnection *interface) + NMConnection *bridge, NMConnection *port, NMConnection *interface, + NMDevice *bridge_device, NMDevice *interface_device) { NMOvsdbPrivate *priv = NM_OVSDB_GET_PRIVATE (self); GHashTableIter iter; @@ -588,7 +638,7 @@ _add_interface (NMOvsdb *self, json_t *params, _expect_ovs_bridges (params, priv->db_uuid, bridges); json_array_append_new (new_bridges, json_pack ("[s, s]", "named-uuid", "rowBridge")); _set_ovs_bridges (params, priv->db_uuid, new_bridges); - _insert_bridge (params, bridge, new_ports); + _insert_bridge (params, bridge, bridge_device, new_ports); } else { /* Bridge already exists. */ g_return_if_fail (ovs_bridge); @@ -606,7 +656,7 @@ _add_interface (NMOvsdb *self, json_t *params, } if (!has_interface) { - _insert_interface (params, interface); + _insert_interface (params, interface, interface_device); json_array_append_new (new_interfaces, json_pack ("[s, s]", "named-uuid", "rowInterface")); } } @@ -766,7 +816,8 @@ ovsdb_next_command (NMOvsdb *self) json_array_append_new (params, json_string ("Open_vSwitch")); json_array_append_new (params, _inc_next_cfg (priv->db_uuid)); - _add_interface (self, params, call->bridge, call->port, call->interface); + _add_interface (self, params, call->bridge, call->port, call->interface, + call->bridge_device, call->interface_device); msg = json_pack ("{s:i, s:s, s:o}", "id", call->id, @@ -1107,7 +1158,7 @@ ovsdb_got_msg (NMOvsdb *self, json_t *msg) OvsdbMethodCall *call = NULL; OvsdbMethodCallback callback; gpointer user_data; - GError *local = NULL; + gs_free_error GError *local = NULL; if (json_unpack_ex (msg, &json_error, 0, "{s?:o, s?:s, s?:o, s?:o, s?:o}", "id", &json_id, @@ -1424,7 +1475,7 @@ ovsdb_try_connect (NMOvsdb *self) /* Queue a monitor call before any other command, ensuring that we have an up * to date view of existing bridged that we need for add and remove ops. */ ovsdb_call_method (self, OVSDB_MONITOR, NULL, - NULL, NULL, NULL, _monitor_bridges_cb, NULL); + NULL, NULL, NULL, NULL, NULL, _monitor_bridges_cb, NULL); } /*****************************************************************************/ @@ -1465,6 +1516,7 @@ out: void nm_ovsdb_add_interface (NMOvsdb *self, NMConnection *bridge, NMConnection *port, NMConnection *interface, + NMDevice *bridge_device, NMDevice *interface_device, NMOvsdbCallback callback, gpointer user_data) { OvsdbCall *call; @@ -1474,7 +1526,9 @@ nm_ovsdb_add_interface (NMOvsdb *self, call->user_data = user_data; ovsdb_call_method (self, OVSDB_ADD_INTERFACE, NULL, - bridge, port, interface, _transact_cb, call); + bridge, port, interface, + bridge_device, interface_device, + _transact_cb, call); } void @@ -1488,7 +1542,7 @@ nm_ovsdb_del_interface (NMOvsdb *self, const char *ifname, call->user_data = user_data; ovsdb_call_method (self, OVSDB_DEL_INTERFACE, ifname, - NULL, NULL, NULL, _transact_cb, call); + NULL, NULL, NULL, NULL, NULL, _transact_cb, call); } /*****************************************************************************/ @@ -1505,6 +1559,8 @@ _clear_call (gpointer data) g_clear_object (&call->bridge); g_clear_object (&call->port); g_clear_object (&call->interface); + g_clear_object (&call->bridge_device); + g_clear_object (&call->interface_device); break; case OVSDB_DEL_INTERFACE: g_clear_pointer (&call->ifname, g_free); diff --git a/src/devices/ovs/nm-ovsdb.h b/src/devices/ovs/nm-ovsdb.h index 279155a4..e7f9d719 100644 --- a/src/devices/ovs/nm-ovsdb.h +++ b/src/devices/ovs/nm-ovsdb.h @@ -42,6 +42,7 @@ GType nm_ovsdb_get_type (void); void nm_ovsdb_add_interface (NMOvsdb *self, NMConnection *bridge, NMConnection *port, NMConnection *interface, + NMDevice *bridge_device, NMDevice *interface_device, NMOvsdbCallback callback, gpointer user_data); void nm_ovsdb_del_interface (NMOvsdb *self, const char *ifname, diff --git a/src/devices/wifi/nm-device-iwd.c b/src/devices/wifi/nm-device-iwd.c index 6ef9ef94..0e6759e1 100644 --- a/src/devices/wifi/nm-device-iwd.c +++ b/src/devices/wifi/nm-device-iwd.c @@ -1881,7 +1881,9 @@ out: } static guint32 -get_configured_mtu (NMDevice *device, NMDeviceMtuSource *out_source) +get_configured_mtu (NMDevice *device, + NMDeviceMtuSource *out_source, + gboolean *out_force) { return nm_device_get_configured_mtu_from_connection (device, NM_TYPE_SETTING_WIRELESS, diff --git a/src/devices/wifi/nm-device-wifi-p2p.c b/src/devices/wifi/nm-device-wifi-p2p.c index c9e6189b..649f36d0 100644 --- a/src/devices/wifi/nm-device-wifi-p2p.c +++ b/src/devices/wifi/nm-device-wifi-p2p.c @@ -629,7 +629,9 @@ deactivate (NMDevice *device) } static guint32 -get_configured_mtu (NMDevice *device, NMDeviceMtuSource *out_source) +get_configured_mtu (NMDevice *device, + NMDeviceMtuSource *out_source, + gboolean *out_force) { *out_source = NM_DEVICE_MTU_SOURCE_NONE; return 0; diff --git a/src/devices/wifi/nm-device-wifi.c b/src/devices/wifi/nm-device-wifi.c index 8c80b0aa..f690100b 100644 --- a/src/devices/wifi/nm-device-wifi.c +++ b/src/devices/wifi/nm-device-wifi.c @@ -2969,7 +2969,9 @@ act_stage3_ip_config_start (NMDevice *device, } static guint32 -get_configured_mtu (NMDevice *device, NMDeviceMtuSource *out_source) +get_configured_mtu (NMDevice *device, + NMDeviceMtuSource *out_source, + gboolean *out_force) { return nm_device_get_configured_mtu_from_connection (device, NM_TYPE_SETTING_WIRELESS, diff --git a/src/devices/wwan/nm-modem.c b/src/devices/wwan/nm-modem.c index 617096a7..fb2316d5 100644 --- a/src/devices/wwan/nm-modem.c +++ b/src/devices/wwan/nm-modem.c @@ -875,7 +875,9 @@ nm_modem_stage3_ip6_config_start (NMModem *self, } guint32 -nm_modem_get_configured_mtu (NMDevice *self, NMDeviceMtuSource *out_source) +nm_modem_get_configured_mtu (NMDevice *self, + NMDeviceMtuSource *out_source, + gboolean *out_force) { NMConnection *connection; NMSetting *setting; diff --git a/src/devices/wwan/nm-modem.h b/src/devices/wwan/nm-modem.h index f5b386e8..fccb4fec 100644 --- a/src/devices/wwan/nm-modem.h +++ b/src/devices/wwan/nm-modem.h @@ -287,7 +287,7 @@ void nm_modem_emit_ip6_config_result (NMModem *self, const char *nm_modem_ip_type_to_string (NMModemIPType ip_type); -guint32 nm_modem_get_configured_mtu (NMDevice *self, NMDeviceMtuSource *out_source); +guint32 nm_modem_get_configured_mtu (NMDevice *self, NMDeviceMtuSource *out_source, gboolean *out_force); void _nm_modem_set_operator_code (NMModem *self, const char *operator_code); void _nm_modem_set_apn (NMModem *self, const char *apn); diff --git a/src/dhcp/nm-dhcp-nettools.c b/src/dhcp/nm-dhcp-nettools.c index 6140a916..a71a7a13 100644 --- a/src/dhcp/nm-dhcp-nettools.c +++ b/src/dhcp/nm-dhcp-nettools.c @@ -371,6 +371,7 @@ lease_parse_address (NDhcp4ClientLease *lease, const gint64 ts_clock_boottime = nm_utils_monotonic_timestamp_as_boottime (ts, 1); struct in_addr a_address; struct in_addr a_netmask; + struct in_addr a_next_server; guint32 a_plen; guint64 nettools_lifetime; gint64 a_lifetime; @@ -440,6 +441,16 @@ lease_parse_address (NDhcp4ClientLease *lease, NM_DHCP_OPTION_DHCP4_NM_EXPIRY, (guint64) a_expiry); + + n_dhcp4_client_lease_get_siaddr (lease, &a_next_server); + if (a_next_server.s_addr != INADDR_ANY) { + nm_utils_inet4_ntop (a_next_server.s_addr, addr_str); + nm_dhcp_option_add_option (options, + _nm_dhcp_option_dhcp4_options, + NM_DHCP_OPTION_DHCP4_NM_NEXT_SERVER, + addr_str); + } + nm_ip4_config_add_address (ip4_config, &((const NMPlatformIP4Address) { .address = a_address.s_addr, diff --git a/src/dhcp/nm-dhcp-options.c b/src/dhcp/nm-dhcp-options.c index 21963070..22e7d90e 100644 --- a/src/dhcp/nm-dhcp-options.c +++ b/src/dhcp/nm-dhcp-options.c @@ -180,6 +180,7 @@ const NMDhcpOption _nm_dhcp_option_dhcp4_options[] = { /* Internal values */ REQ (NM_DHCP_OPTION_DHCP4_NM_IP_ADDRESS, "ip_address", FALSE ), REQ (NM_DHCP_OPTION_DHCP4_NM_EXPIRY, "expiry", FALSE ), + REQ (NM_DHCP_OPTION_DHCP4_NM_NEXT_SERVER, "next_server", FALSE ), { 0 } }; diff --git a/src/dhcp/nm-dhcp-options.h b/src/dhcp/nm-dhcp-options.h index 0dc7a276..f56edb19 100644 --- a/src/dhcp/nm-dhcp-options.h +++ b/src/dhcp/nm-dhcp-options.h @@ -164,6 +164,7 @@ typedef enum { /* Internal values */ NM_DHCP_OPTION_DHCP4_NM_IP_ADDRESS = 1024, NM_DHCP_OPTION_DHCP4_NM_EXPIRY = 1025, + NM_DHCP_OPTION_DHCP4_NM_NEXT_SERVER = 1026, } NMDhcpOptionDhcp4Options; typedef enum { diff --git a/src/dhcp/nm-dhcp-systemd.c b/src/dhcp/nm-dhcp-systemd.c index 073a6da0..96409345 100644 --- a/src/dhcp/nm-dhcp-systemd.c +++ b/src/dhcp/nm-dhcp-systemd.c @@ -119,6 +119,7 @@ lease_to_ip4_config (NMDedupMultiIndex *multi_idx, gint64 ts_time = time (NULL); struct in_addr a_address; struct in_addr a_netmask; + struct in_addr a_next_server; struct in_addr server_id; struct in_addr broadcast; const struct in_addr *a_router; @@ -178,6 +179,14 @@ lease_to_ip4_config (NMDedupMultiIndex *multi_idx, NM_DHCP_OPTION_DHCP4_NM_EXPIRY, (guint64) (ts_time + a_lifetime)); + if (sd_dhcp_lease_get_next_server (lease, &a_next_server) == 0) { + nm_utils_inet4_ntop (a_next_server.s_addr, addr_str); + nm_dhcp_option_add_option (options, + _nm_dhcp_option_dhcp4_options, + NM_DHCP_OPTION_DHCP4_NM_NEXT_SERVER, + addr_str); + } + nm_ip4_config_add_address (ip4_config, &((const NMPlatformIP4Address) { .address = a_address.s_addr, diff --git a/src/initrd/nmi-cmdline-reader.c b/src/initrd/nmi-cmdline-reader.c index b90ee203..c305cd4d 100644 --- a/src/initrd/nmi-cmdline-reader.c +++ b/src/initrd/nmi-cmdline-reader.c @@ -47,6 +47,49 @@ _connection_matches_type (gpointer key, gpointer value, gpointer user_data) } static NMConnection * +add_conn (GHashTable *connections, + const char *basename, + const char *id, + const char *ifname, + const char *type_name, + NMConnectionMultiConnect multi_connect) +{ + NMConnection *connection; + NMSetting *setting; + + connection = nm_simple_connection_new (); + g_hash_table_insert (connections, g_strdup (basename), connection); + + /* Start off assuming dynamic IP configurations. */ + + setting = nm_setting_ip4_config_new (); + nm_connection_add_setting (connection, setting); + g_object_set (setting, + NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, + NM_SETTING_IP_CONFIG_MAY_FAIL, TRUE, + NULL); + + setting = nm_setting_ip6_config_new (); + nm_connection_add_setting (connection, setting); + g_object_set (setting, + NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, + NM_SETTING_IP_CONFIG_MAY_FAIL, TRUE, + NULL); + + setting = nm_setting_connection_new (); + nm_connection_add_setting (connection, setting); + g_object_set (setting, + NM_SETTING_CONNECTION_ID, id, + NM_SETTING_CONNECTION_UUID, nm_utils_uuid_generate_a (), + NM_SETTING_CONNECTION_INTERFACE_NAME, ifname, + NM_SETTING_CONNECTION_TYPE, type_name, + NM_SETTING_CONNECTION_MULTI_CONNECT, multi_connect, + NULL); + + return connection; +} + +static NMConnection * get_conn (GHashTable *connections, const char *ifname, const char *type_name) { NMConnection *connection; @@ -76,40 +119,15 @@ get_conn (GHashTable *connections, const char *ifname, const char *type_name) (gpointer) type_name); } - if (connection) { - setting = (NMSetting *)nm_connection_get_setting_connection (connection); - } else { - connection = nm_simple_connection_new (); - g_hash_table_insert (connections, g_strdup (basename), connection); - - /* Start off assuming dynamic IP configurations. */ - - setting = nm_setting_ip4_config_new (); - nm_connection_add_setting (connection, setting); - g_object_set (setting, - NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, - NM_SETTING_IP_CONFIG_MAY_FAIL, TRUE, - NULL); - - setting = nm_setting_ip6_config_new (); - nm_connection_add_setting (connection, setting); - g_object_set (setting, - NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, - NM_SETTING_IP_CONFIG_MAY_FAIL, TRUE, - NULL); - - setting = nm_setting_connection_new (); - nm_connection_add_setting (connection, setting); - g_object_set (setting, - NM_SETTING_CONNECTION_ID, ifname ?: "Wired Connection", - NM_SETTING_CONNECTION_UUID, nm_utils_uuid_generate_a (), - NM_SETTING_CONNECTION_INTERFACE_NAME, ifname, - NM_SETTING_CONNECTION_MULTI_CONNECT, multi_connect, - NULL); - + if (!connection) { if (!type_name) type_name = NM_SETTING_WIRED_SETTING_NAME; + + connection = add_conn (connections, basename, + ifname ?: "Wired Connection", + ifname, type_name, multi_connect); } + setting = (NMSetting *)nm_connection_get_setting_connection (connection); if (type_name) { g_object_set (setting, NM_SETTING_CONNECTION_TYPE, type_name, NULL); @@ -480,7 +498,10 @@ parse_ip (GHashTable *connections, const char *sysfs_dir, char *argument) } static void -parse_master (GHashTable *connections, char *argument, const char *type_name) +parse_master (GHashTable *connections, + char *argument, + const char *type_name, + const char *default_name) { NMConnection *connection; NMSettingConnection *s_con; @@ -496,7 +517,7 @@ parse_master (GHashTable *connections, char *argument, const char *type_name) master = get_word (&argument, ':'); if (!master) - master = master_to_free = g_strdup_printf ("%s0", type_name); + master = master_to_free = g_strdup_printf ("%s0", default_name ?: type_name); slaves = get_word (&argument, ':'); connection = get_conn (connections, master, type_name); @@ -634,6 +655,13 @@ parse_bootdev (GHashTable *connections, char *argument) connection = get_conn (connections, NULL, NULL); + if ( nm_connection_get_interface_name (connection) + && strcmp (nm_connection_get_interface_name (connection), argument) != 0) { + /* If the default connection already has an interface name, + * we should not overwrite it. Create a new one instead. */ + connection = get_conn (connections, argument, NULL); + } + s_con = nm_connection_get_setting_connection (connection); g_object_set (s_con, NM_SETTING_CONNECTION_INTERFACE_NAME, argument, @@ -803,11 +831,11 @@ nmi_cmdline_reader_parse (const char *sysfs_dir, const char *const*argv) else if (strcmp (tag, "rd.route") == 0) parse_rd_route (connections, argument); else if (strcmp (tag, "bridge") == 0) - parse_master (connections, argument, NM_SETTING_BRIDGE_SETTING_NAME); + parse_master (connections, argument, NM_SETTING_BRIDGE_SETTING_NAME, "br"); else if (strcmp (tag, "bond") == 0) - parse_master (connections, argument, NM_SETTING_BOND_SETTING_NAME); + parse_master (connections, argument, NM_SETTING_BOND_SETTING_NAME, NULL); else if (strcmp (tag, "team") == 0) - parse_master (connections, argument, NM_SETTING_TEAM_SETTING_NAME); + parse_master (connections, argument, NM_SETTING_TEAM_SETTING_NAME, NULL); else if (strcmp (tag, "vlan") == 0) parse_vlan (connections, argument); else if (strcmp (tag, "bootdev") == 0) @@ -846,8 +874,19 @@ nmi_cmdline_reader_parse (const char *sysfs_dir, const char *const*argv) } connection = get_conn (connections, NULL, NM_SETTING_WIRED_SETTING_NAME); - s_wired = nm_connection_get_setting_wired (connection); + + if ( nm_connection_get_interface_name (connection) + || ( nm_setting_wired_get_mac_address (s_wired) + && !nm_utils_hwaddr_matches (nm_setting_wired_get_mac_address (s_wired), -1, + bootif, -1))) { + connection = add_conn (connections, "bootif_connection", "BOOTIF Connection", + NULL, NM_SETTING_WIRED_SETTING_NAME, + NM_CONNECTION_MULTI_CONNECT_SINGLE); + s_wired = (NMSettingWired *) nm_setting_wired_new (); + nm_connection_add_setting (connection, (NMSetting *) s_wired); + } + g_object_set (s_wired, NM_SETTING_WIRED_MAC_ADDRESS, bootif, NULL); diff --git a/src/initrd/tests/test-cmdline-reader.c b/src/initrd/tests/test-cmdline-reader.c index 5ac82f50..a28c634d 100644 --- a/src/initrd/tests/test-cmdline-reader.c +++ b/src/initrd/tests/test-cmdline-reader.c @@ -283,8 +283,7 @@ test_multiple (void) { gs_unref_hashtable GHashTable *connections = NULL; const char *const*ARGV = NM_MAKE_STRV ("ip=192.0.2.2:::::eth0", - "ip=[2001:db8::2]:::::eth0", - "BOOTIF=00:53:AB:cd:02:03"); + "ip=[2001:db8::2]:::::eth0"); NMConnection *connection; NMSettingWired *s_wired; NMSettingIPConfig *s_ip4; @@ -302,7 +301,6 @@ test_multiple (void) s_wired = nm_connection_get_setting_wired (connection); g_assert (s_wired); - g_assert_cmpstr (nm_setting_wired_get_mac_address (s_wired), ==, "00:53:AB:CD:02:03"); s_ip4 = nm_connection_get_setting_ip4_config (connection); g_assert (s_ip4); @@ -324,12 +322,45 @@ test_multiple (void) } static void +test_bootdev (void) +{ + gs_unref_hashtable GHashTable *connections = NULL; + const char *const*ARGV = NM_MAKE_STRV ("vlan=vlan2:ens5", "bootdev=ens3"); + NMConnection *connection; + NMSettingConnection *s_con; + + connections = nmi_cmdline_reader_parse (TEST_INITRD_DIR "/sysfs", ARGV); + g_assert (connections); + g_assert_cmpint (g_hash_table_size (connections), ==, 2); + + connection = g_hash_table_lookup (connections, "ens3"); + g_assert (connection); + nmtst_assert_connection_verifies_without_normalization (connection); + + s_con = nm_connection_get_setting_connection (connection); + g_assert (s_con); + g_assert_cmpstr (nm_setting_connection_get_connection_type (s_con), ==, NM_SETTING_WIRED_SETTING_NAME); + g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, "ens3"); + g_assert_cmpstr (nm_setting_connection_get_interface_name (s_con), ==, "ens3"); + + connection = g_hash_table_lookup (connections, "vlan2"); + g_assert (connection); + nmtst_assert_connection_verifies_without_normalization (connection); + + s_con = nm_connection_get_setting_connection (connection); + g_assert (s_con); + g_assert_cmpstr (nm_setting_connection_get_connection_type (s_con), ==, NM_SETTING_VLAN_SETTING_NAME); + g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, "vlan2"); + g_assert_cmpstr (nm_setting_connection_get_interface_name (s_con), ==, "vlan2"); +} + +static void test_some_more (void) { gs_unref_hashtable GHashTable *connections = NULL; const char *const*ARGV = NM_MAKE_STRV ("bootdev=eth1", "hail", "nameserver=[2001:DB8:3::53]", "satan", "nameserver=192.0.2.53", "worship", - "BOOTIF=01-00-53-AB-cd-02-03", "doom", "rd.peerdns=0", + "doom", "rd.peerdns=0", "rd.route=[2001:DB8:3::/48]:[2001:DB8:2::1]:ens10"); NMConnection *connection; NMSettingConnection *s_con; @@ -355,7 +386,6 @@ test_some_more (void) s_wired = nm_connection_get_setting_wired (connection); g_assert (s_wired); - g_assert_cmpstr (nm_setting_wired_get_mac_address (s_wired), ==, "00:53:AB:CD:02:03"); s_ip4 = nm_connection_get_setting_ip4_config (connection); g_assert (s_ip4); @@ -406,17 +436,6 @@ test_some_more (void) } static void -test_no_bootif (void) -{ - gs_unref_hashtable GHashTable *connections = NULL; - const char *const*ARGV = NM_MAKE_STRV ("BOOTIF=01-00-53-AB-cd-02-03", "rd.bootif=0"); - - connections = nmi_cmdline_reader_parse (TEST_INITRD_DIR "/sysfs", ARGV); - g_assert (connections); - g_assert_cmpint (g_hash_table_size (connections), ==, 0); -} - -static void test_bond (void) { gs_unref_hashtable GHashTable *connections = NULL; @@ -651,12 +670,12 @@ test_bridge_default (void) g_assert (connections); g_assert_cmpint (g_hash_table_size (connections), ==, 2); - connection = g_hash_table_lookup (connections, "bridge0"); + connection = g_hash_table_lookup (connections, "br0"); g_assert (connection); nmtst_assert_connection_verifies_without_normalization (connection); g_assert_cmpstr (nm_connection_get_connection_type (connection), ==, NM_SETTING_BRIDGE_SETTING_NAME); - g_assert_cmpstr (nm_connection_get_id (connection), ==, "bridge0"); + g_assert_cmpstr (nm_connection_get_id (connection), ==, "br0"); master_uuid = nm_connection_get_uuid (connection); g_assert (master_uuid); @@ -917,6 +936,109 @@ test_rd_znet_legacy (void) nmtst_assert_connection_verifies_without_normalization (connection); } +static void +test_bootif (void) +{ + gs_unref_hashtable GHashTable *connections = NULL; + const char *const*ARGV = NM_MAKE_STRV ("BOOTIF=00:53:AB:cd:02:03", + "ip=dhcp"); + NMConnection *connection; + NMSettingWired *s_wired; + NMSettingIPConfig *s_ip4; + NMSettingIPConfig *s_ip6; + + connections = nmi_cmdline_reader_parse (TEST_INITRD_DIR "/sysfs", ARGV); + g_assert (connections); + g_assert_cmpint (g_hash_table_size (connections), ==, 1); + + connection = g_hash_table_lookup (connections, "default_connection"); + g_assert (connection); + nmtst_assert_connection_verifies_without_normalization (connection); + g_assert_cmpstr (nm_connection_get_id (connection), ==, "Wired Connection"); + + s_wired = nm_connection_get_setting_wired (connection); + g_assert_cmpstr (nm_setting_wired_get_mac_address (s_wired), ==, "00:53:AB:CD:02:03"); + g_assert (s_wired); + + s_ip4 = nm_connection_get_setting_ip4_config (connection); + g_assert (s_ip4); + g_assert_cmpstr (nm_setting_ip_config_get_method (s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_AUTO); + g_assert (!nm_setting_ip_config_get_ignore_auto_dns (s_ip4)); + g_assert (!nm_setting_ip_config_get_may_fail (s_ip4)); + + s_ip6 = nm_connection_get_setting_ip6_config (connection); + g_assert (s_ip6); + g_assert_cmpstr (nm_setting_ip_config_get_method (s_ip6), ==, NM_SETTING_IP6_CONFIG_METHOD_DISABLED); + g_assert (!nm_setting_ip_config_get_ignore_auto_dns (s_ip6)); +} + +static void +test_bootif_hwtype (void) +{ + gs_unref_hashtable GHashTable *connections = NULL; + const char *const*ARGV = NM_MAKE_STRV ("ip=eth0:dhcp", + "BOOTIF=01-00-53-AB-cd-02-03"); + NMConnection *connection; + NMSettingWired *s_wired; + NMSettingIPConfig *s_ip4; + NMSettingIPConfig *s_ip6; + + connections = nmi_cmdline_reader_parse (TEST_INITRD_DIR "/sysfs", ARGV); + g_assert (connections); + g_assert_cmpint (g_hash_table_size (connections), ==, 2); + + connection = g_hash_table_lookup (connections, "eth0"); + g_assert (connection); + nmtst_assert_connection_verifies_without_normalization (connection); + g_assert_cmpstr (nm_connection_get_id (connection), ==, "eth0"); + + s_wired = nm_connection_get_setting_wired (connection); + g_assert (!nm_setting_wired_get_mac_address (s_wired)); + g_assert (s_wired); + + s_ip4 = nm_connection_get_setting_ip4_config (connection); + g_assert (s_ip4); + g_assert_cmpstr (nm_setting_ip_config_get_method (s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_AUTO); + g_assert (!nm_setting_ip_config_get_ignore_auto_dns (s_ip4)); + g_assert (!nm_setting_ip_config_get_may_fail (s_ip4)); + + s_ip6 = nm_connection_get_setting_ip6_config (connection); + g_assert (s_ip6); + g_assert_cmpstr (nm_setting_ip_config_get_method (s_ip6), ==, NM_SETTING_IP6_CONFIG_METHOD_DISABLED); + g_assert (!nm_setting_ip_config_get_ignore_auto_dns (s_ip6)); + + connection = g_hash_table_lookup (connections, "bootif_connection"); + g_assert (connection); + nmtst_assert_connection_verifies_without_normalization (connection); + g_assert_cmpstr (nm_connection_get_id (connection), ==, "BOOTIF Connection"); + + s_wired = nm_connection_get_setting_wired (connection); + g_assert_cmpstr (nm_setting_wired_get_mac_address (s_wired), ==, "00:53:AB:CD:02:03"); + g_assert (s_wired); + + s_ip4 = nm_connection_get_setting_ip4_config (connection); + g_assert (s_ip4); + g_assert_cmpstr (nm_setting_ip_config_get_method (s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_AUTO); + g_assert (!nm_setting_ip_config_get_ignore_auto_dns (s_ip4)); + g_assert (nm_setting_ip_config_get_may_fail (s_ip4)); + + s_ip6 = nm_connection_get_setting_ip6_config (connection); + g_assert (s_ip6); + g_assert_cmpstr (nm_setting_ip_config_get_method (s_ip6), ==, NM_SETTING_IP6_CONFIG_METHOD_AUTO); + g_assert (!nm_setting_ip_config_get_ignore_auto_dns (s_ip6)); + g_assert (nm_setting_ip_config_get_may_fail (s_ip6)); +} + +static void +test_bootif_off (void) +{ + gs_unref_hashtable GHashTable *connections = NULL; + const char *const*ARGV = NM_MAKE_STRV ("BOOTIF=01-00-53-AB-cd-02-03", "rd.bootif=0"); + + connections = nmi_cmdline_reader_parse (TEST_INITRD_DIR "/sysfs", ARGV); + g_assert (connections); + g_assert_cmpint (g_hash_table_size (connections), ==, 0); +} NMTST_DEFINE (); @@ -932,7 +1054,7 @@ int main (int argc, char **argv) g_test_add_func ("/initrd/cmdline/if_ip6_manual", test_if_ip6_manual); g_test_add_func ("/initrd/cmdline/multiple", test_multiple); g_test_add_func ("/initrd/cmdline/some_more", test_some_more); - g_test_add_func ("/initrd/cmdline/no_bootif", test_no_bootif); + g_test_add_func ("/initrd/cmdline/bootdev", test_bootdev); g_test_add_func ("/initrd/cmdline/bond", test_bond); g_test_add_func ("/initrd/cmdline/bond/default", test_bond_default); g_test_add_func ("/initrd/cmdline/team", test_team); @@ -942,6 +1064,9 @@ int main (int argc, char **argv) g_test_add_func ("/initrd/cmdline/ignore_extra", test_ignore_extra); g_test_add_func ("/initrd/cmdline/rd_znet", test_rd_znet); g_test_add_func ("/initrd/cmdline/rd_znet/legacy", test_rd_znet_legacy); + g_test_add_func ("/initrd/cmdline/bootif", test_bootif); + g_test_add_func ("/initrd/cmdline/bootif/hwtype", test_bootif_hwtype); + g_test_add_func ("/initrd/cmdline/bootif/off", test_bootif_off); return g_test_run (); } diff --git a/src/ndisc/nm-lndp-ndisc.c b/src/ndisc/nm-lndp-ndisc.c index 5643c192..9352a753 100644 --- a/src/ndisc/nm-lndp-ndisc.c +++ b/src/ndisc/nm-lndp-ndisc.c @@ -116,6 +116,7 @@ receive_ra (struct ndp *ndp, struct ndp_msg *msg, gpointer user_data) gint32 now = nm_utils_get_monotonic_timestamp_s (); int offset; int hop_limit; + guint32 val; /* Router discovery is subject to the following RFC documents: * @@ -294,6 +295,18 @@ receive_ra (struct ndp *ndp, struct ndp_msg *msg, gpointer user_data) changed |= NM_NDISC_CONFIG_HOP_LIMIT; } + val = ndp_msgra_reachable_time (msgra); + if (val && rdata->public.reachable_time_ms != val) { + rdata->public.reachable_time_ms = val; + changed |= NM_NDISC_CONFIG_REACHABLE_TIME; + } + + val = ndp_msgra_retransmit_time (msgra); + if (val && rdata->public.retrans_timer_ms != val) { + rdata->public.retrans_timer_ms = val; + changed |= NM_NDISC_CONFIG_RETRANS_TIMER; + } + /* MTU */ ndp_msg_opt_for_each_offset(offset, msg, NDP_MSG_OPT_MTU) { guint32 mtu = ndp_msg_opt_mtu(msg, offset); diff --git a/src/ndisc/nm-ndisc.c b/src/ndisc/nm-ndisc.c index 1acf5ba9..a8fabb56 100644 --- a/src/ndisc/nm-ndisc.c +++ b/src/ndisc/nm-ndisc.c @@ -1039,6 +1039,14 @@ _config_changed_log (NMNDisc *ndisc, NMNDiscConfigMap changed) config_map_to_string (changed, changedstr); _LOGD ("neighbor discovery configuration changed [%s]:", changedstr); _LOGD (" dhcp-level %s", dhcp_level_to_string (priv->rdata.public.dhcp_level)); + + if (rdata->public.hop_limit) + _LOGD (" hop limit : %d", rdata->public.hop_limit); + if (rdata->public.reachable_time_ms) + _LOGD (" reachable time : %u", (guint) rdata->public.reachable_time_ms); + if (rdata->public.retrans_timer_ms) + _LOGD (" retrans timer : %u", (guint) rdata->public.retrans_timer_ms); + for (i = 0; i < rdata->gateways->len; i++) { NMNDiscGateway *gateway = &g_array_index (rdata->gateways, NMNDiscGateway, i); diff --git a/src/ndisc/nm-ndisc.h b/src/ndisc/nm-ndisc.h index 766d4ab9..8e07ca41 100644 --- a/src/ndisc/nm-ndisc.h +++ b/src/ndisc/nm-ndisc.h @@ -112,6 +112,8 @@ typedef enum { NM_NDISC_CONFIG_DNS_DOMAINS = 1 << 5, NM_NDISC_CONFIG_HOP_LIMIT = 1 << 6, NM_NDISC_CONFIG_MTU = 1 << 7, + NM_NDISC_CONFIG_REACHABLE_TIME = 1 << 8, + NM_NDISC_CONFIG_RETRANS_TIMER = 1 << 9, } NMNDiscConfigMap; typedef enum { @@ -137,6 +139,8 @@ typedef struct { NMNDiscDHCPLevel dhcp_level; guint32 mtu; int hop_limit; + guint32 reachable_time_ms; + guint32 retrans_timer_ms; guint gateways_n; guint addresses_n; diff --git a/src/nm-iface-helper.c b/src/nm-iface-helper.c index dd5bb327..afe3fc5d 100644 --- a/src/nm-iface-helper.c +++ b/src/nm-iface-helper.c @@ -220,6 +220,18 @@ ndisc_config_changed (NMNDisc *ndisc, const NMNDiscData *rdata, guint changed_in if (changed & NM_NDISC_CONFIG_HOP_LIMIT) nm_platform_sysctl_ip_conf_set_ipv6_hop_limit_safe (NM_PLATFORM_GET, global_opt.ifname, rdata->hop_limit); + if (changed & NM_NDISC_CONFIG_REACHABLE_TIME) { + nm_platform_sysctl_ip_neigh_set_ipv6_reachable_time (NM_PLATFORM_GET, + global_opt.ifname, + rdata->reachable_time_ms); + } + + if (changed & NM_NDISC_CONFIG_RETRANS_TIMER) { + nm_platform_sysctl_ip_neigh_set_ipv6_retrans_time (NM_PLATFORM_GET, + global_opt.ifname, + rdata->retrans_timer_ms); + } + if (changed & NM_NDISC_CONFIG_MTU) { nm_platform_sysctl_ip_conf_set_int64 (NM_PLATFORM_GET, AF_INET6, @@ -557,10 +569,7 @@ main (int argc, char *argv[]) if (iid) nm_ndisc_set_iid (ndisc, *iid); - nm_platform_sysctl_ip_conf_set (NM_PLATFORM_GET, AF_INET6, global_opt.ifname, "accept_ra", "1"); - nm_platform_sysctl_ip_conf_set (NM_PLATFORM_GET, AF_INET6, global_opt.ifname, "accept_ra_defrtr", "0"); - nm_platform_sysctl_ip_conf_set (NM_PLATFORM_GET, AF_INET6, global_opt.ifname, "accept_ra_pinfo", "0"); - nm_platform_sysctl_ip_conf_set (NM_PLATFORM_GET, AF_INET6, global_opt.ifname, "accept_ra_rtr_pref", "0"); + nm_platform_sysctl_ip_conf_set (NM_PLATFORM_GET, AF_INET6, global_opt.ifname, "accept_ra", "0"); g_signal_connect (NM_PLATFORM_GET, NM_PLATFORM_SIGNAL_IP6_ADDRESS_CHANGED, diff --git a/src/nm-manager.c b/src/nm-manager.c index 78f3722c..d112fcf7 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c @@ -2741,6 +2741,12 @@ recheck_assume_connection (NMManager *self, activation_type_assume = TRUE; if (generated) { + /* Reset the IPv4 setting to empty method=auto, regardless of what assumption guessed. */ + nm_connection_add_setting (nm_settings_connection_get_connection (sett_conn), + g_object_new (NM_TYPE_SETTING_IP4_CONFIG, + NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, + NULL)); + nm_settings_connection_update (sett_conn, NULL, NM_SETTINGS_CONNECTION_PERSIST_MODE_KEEP, diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c index 6ead15ed..0a7acba9 100644 --- a/src/platform/nm-platform.c +++ b/src/platform/nm-platform.c @@ -610,6 +610,54 @@ nm_platform_sysctl_ip_conf_set_ipv6_hop_limit_safe (NMPlatform *self, return TRUE; } +gboolean +nm_platform_sysctl_ip_neigh_set_ipv6_reachable_time (NMPlatform *self, + const char *iface, + guint value_ms) +{ + char path[NM_UTILS_SYSCTL_IP_CONF_PATH_BUFSIZE]; + char str[128]; + guint clamped; + + _CHECK_SELF (self, klass, FALSE); + + if (!value_ms) + return TRUE; + + /* RFC 4861 says the value can't be greater than one hour. + * Also use a reasonable lower threshold. */ + clamped = NM_CLAMP (value_ms, 100, 3600000); + nm_sprintf_buf (path, "/proc/sys/net/ipv6/neigh/%s/base_reachable_time_ms", iface); + nm_sprintf_buf (str, "%u", clamped); + if (!nm_platform_sysctl_set (self, NMP_SYSCTL_PATHID_ABSOLUTE (path), str)) + return FALSE; + + /* Set stale time in the same way as kernel */ + nm_sprintf_buf (path, "/proc/sys/net/ipv6/neigh/%s/gc_stale_time", iface); + nm_sprintf_buf (str, "%u", clamped * 3 / 1000); + + return nm_platform_sysctl_set (self, NMP_SYSCTL_PATHID_ABSOLUTE (path), str); +} + +gboolean +nm_platform_sysctl_ip_neigh_set_ipv6_retrans_time (NMPlatform *self, + const char *iface, + guint value_ms) +{ + char path[NM_UTILS_SYSCTL_IP_CONF_PATH_BUFSIZE]; + char str[128]; + + _CHECK_SELF (self, klass, FALSE); + + if (!value_ms) + return TRUE; + + nm_sprintf_buf (path, "/proc/sys/net/ipv6/neigh/%s/retrans_time_ms", iface); + nm_sprintf_buf (str, "%u", NM_CLAMP (value_ms, 10, 3600000)); + + return nm_platform_sysctl_set (self, NMP_SYSCTL_PATHID_ABSOLUTE (path), str); +} + /** * nm_platform_sysctl_get: * @self: platform instance diff --git a/src/platform/nm-platform.h b/src/platform/nm-platform.h index 248eca44..44733809 100644 --- a/src/platform/nm-platform.h +++ b/src/platform/nm-platform.h @@ -1353,6 +1353,12 @@ gboolean nm_platform_sysctl_ip_conf_set_int64 (NMPlatform *self, gboolean nm_platform_sysctl_ip_conf_set_ipv6_hop_limit_safe (NMPlatform *self, const char *iface, int value); +gboolean nm_platform_sysctl_ip_neigh_set_ipv6_reachable_time (NMPlatform *self, + const char *iface, + guint value_ms); +gboolean nm_platform_sysctl_ip_neigh_set_ipv6_retrans_time (NMPlatform *self, + const char *iface, + guint value_ms); int nm_platform_sysctl_ip_conf_get_rp_filter_ipv4 (NMPlatform *platform, const char *iface, gboolean consider_all, diff --git a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c index 020766c8..68ebd781 100644 --- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c +++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c @@ -3573,6 +3573,11 @@ next: return NULL; } + g_object_set (s_8021x, + NM_SETTING_802_1X_SYSTEM_CA_CERTS, + svGetValueBoolean (ifcfg, "IEEE_8021X_SYSTEM_CA_CERTS", FALSE), + NULL); + nm_clear_g_free (&value); v = svGetValueStr (ifcfg, "IEEE_8021X_SUBJECT_MATCH", &value); g_object_set (s_8021x, NM_SETTING_802_1X_SUBJECT_MATCH, v, NULL); diff --git a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c index f3cd71bd..809d3769 100644 --- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c +++ b/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c @@ -432,35 +432,37 @@ write_8021x_setting (NMConnection *connection, nm_setting_802_1x_get_password_raw_flags (s_8021x)); g_free (tmp); - /* PEAP version */ + svSetValueBoolean_cond_true (ifcfg, + "IEEE_8021X_SYSTEM_CA_CERTS", + nm_setting_802_1x_get_system_ca_certs (s_8021x)); + value = nm_setting_802_1x_get_phase1_peapver (s_8021x); - svUnsetValue (ifcfg, "IEEE_8021X_PEAP_VERSION"); - if (value && (!strcmp (value, "0") || !strcmp (value, "1"))) + if (NM_IN_STRSET (value, "0", "1")) svSetValueStr (ifcfg, "IEEE_8021X_PEAP_VERSION", value); + else + svUnsetValue (ifcfg, "IEEE_8021X_PEAP_VERSION"); - /* Force new PEAP label */ - value = nm_setting_802_1x_get_phase1_peaplabel (s_8021x); - svUnsetValue (ifcfg, "IEEE_8021X_PEAP_FORCE_NEW_LABEL"); - if (value && !strcmp (value, "1")) - svSetValueStr (ifcfg, "IEEE_8021X_PEAP_FORCE_NEW_LABEL", "yes"); + svSetValueBoolean_cond_true (ifcfg, + "IEEE_8021X_PEAP_FORCE_NEW_LABEL", + nm_streq0 (nm_setting_802_1x_get_phase1_peaplabel (s_8021x), "1")); - /* PAC file */ - value = nm_setting_802_1x_get_pac_file (s_8021x); - svUnsetValue (ifcfg, "IEEE_8021X_PAC_FILE"); - if (value) - svSetValueStr (ifcfg, "IEEE_8021X_PAC_FILE", value); + svSetValueStr (ifcfg, + "IEEE_8021X_PAC_FILE", + nm_setting_802_1x_get_pac_file (s_8021x)); /* FAST PAC provisioning */ value = nm_setting_802_1x_get_phase1_fast_provisioning (s_8021x); - svUnsetValue (ifcfg, "IEEE_8021X_FAST_PROVISIONING"); if (value) { if (strcmp (value, "1") == 0) - svSetValueStr (ifcfg, "IEEE_8021X_FAST_PROVISIONING", "allow-unauth"); + value = "allow-unauth"; else if (strcmp (value, "2") == 0) - svSetValueStr (ifcfg, "IEEE_8021X_FAST_PROVISIONING", "allow-auth"); + value = "allow-auth"; else if (strcmp (value, "3") == 0) - svSetValueStr (ifcfg, "IEEE_8021X_FAST_PROVISIONING", "allow-unauth allow-auth"); + value = "allow-unauth allow-auth"; + else + value = NULL; } + svSetValueStr (ifcfg, "IEEE_8021X_FAST_PROVISIONING", value); /* Phase2 auth methods */ svUnsetValue (ifcfg, "IEEE_8021X_INNER_AUTH_METHODS"); @@ -537,10 +539,9 @@ write_8021x_setting (NMConnection *connection, vint = nm_setting_802_1x_get_auth_timeout (s_8021x); svSetValueInt64_cond (ifcfg, "IEEE_8021X_AUTH_TIMEOUT", vint > 0, vint); - if (nm_setting_802_1x_get_optional (s_8021x)) - svSetValueBoolean (ifcfg, "IEEE_8021X_OPTIONAL", TRUE); - else - svUnsetValue (ifcfg, "IEEE_8021X_OPTIONAL"); + svSetValueBoolean_cond_true (ifcfg, + "IEEE_8021X_OPTIONAL", + nm_setting_802_1x_get_optional (s_8021x)); if (!write_8021x_certs (s_8021x, secrets, blobs, FALSE, ifcfg, error)) return FALSE; diff --git a/src/settings/plugins/ifcfg-rh/shvar.c b/src/settings/plugins/ifcfg-rh/shvar.c index 94e31aac..d4bc71f3 100644 --- a/src/settings/plugins/ifcfg-rh/shvar.c +++ b/src/settings/plugins/ifcfg-rh/shvar.c @@ -1357,6 +1357,12 @@ svSetValueBoolean (shvarFile *s, const char *key, gboolean value) } gboolean +svSetValueBoolean_cond_true (shvarFile *s, const char *key, gboolean value) +{ + return svSetValue (s, key, value ? "yes" : NULL); +} + +gboolean svSetValueEnum (shvarFile *s, const char *key, GType gtype, int value) { gs_free char *v = NULL; diff --git a/src/settings/plugins/ifcfg-rh/shvar.h b/src/settings/plugins/ifcfg-rh/shvar.h index 67fb5404..2f6912b3 100644 --- a/src/settings/plugins/ifcfg-rh/shvar.h +++ b/src/settings/plugins/ifcfg-rh/shvar.h @@ -96,6 +96,7 @@ gboolean svGetValueEnum (shvarFile *s, const char *key, gboolean svSetValue (shvarFile *s, const char *key, const char *value); gboolean svSetValueStr (shvarFile *s, const char *key, const char *value); gboolean svSetValueBoolean (shvarFile *s, const char *key, gboolean value); +gboolean svSetValueBoolean_cond_true (shvarFile *s, const char *key, gboolean value); gboolean svSetValueInt64 (shvarFile *s, const char *key, gint64 value); gboolean svSetValueInt64_cond (shvarFile *s, const char *key, gboolean do_set, gint64 value); gboolean svSetValueEnum (shvarFile *s, const char *key, GType gtype, int value); |