summaryrefslogtreecommitdiff
path: root/src/devices/nm-device.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/nm-device.c')
-rw-r--r--src/devices/nm-device.c193
1 files changed, 119 insertions, 74 deletions
diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c
index aab14708bc..3d5cda21b9 100644
--- a/src/devices/nm-device.c
+++ b/src/devices/nm-device.c
@@ -189,6 +189,7 @@ typedef struct {
int ip_ifindex;
NMDeviceType type;
char * type_desc;
+ char * type_description;
NMDeviceCapabilities capabilities;
char * driver;
char * driver_version;
@@ -734,50 +735,63 @@ nm_device_get_priority (NMDevice *self)
return 11000;
}
-guint32
-nm_device_get_ip4_route_metric (NMDevice *self)
+static guint32
+_get_ipx_route_metric (NMDevice *self,
+ gboolean is_v4)
{
+ char *value;
+ gint64 route_metric;
+ NMSettingIPConfig *s_ip;
NMConnection *connection;
- NMSettingIPConfig *s_ip = NULL;
- gint64 route_metric = -1;
g_return_val_if_fail (NM_IS_DEVICE (self), G_MAXUINT32);
connection = nm_device_get_connection (self);
- if (connection)
- s_ip = nm_connection_get_setting_ip4_config (connection);
+ if (connection) {
+ s_ip = is_v4
+ ? nm_connection_get_setting_ip4_config (connection)
+ : nm_connection_get_setting_ip6_config (connection);
- /* Slave interfaces don't have IP settings, but we may get here when
- * external changes are made or when noticing IP changes when starting
- * the slave connection.
- */
- if (s_ip)
- route_metric = nm_setting_ip_config_get_route_metric (s_ip);
+ /* Slave interfaces don't have IP settings, but we may get here when
+ * external changes are made or when noticing IP changes when starting
+ * the slave connection.
+ */
+ if (s_ip) {
+ route_metric = nm_setting_ip_config_get_route_metric (s_ip);
+ if (route_metric >= 0)
+ goto out;
+ }
+ }
+
+ /* use the current NMConfigData, which makes this configuration reloadable.
+ * Note that that means that the route-metric might change between SIGHUP.
+ * You must cache the returned value if that is a problem. */
+ value = nm_config_data_get_connection_default (nm_config_get_data (nm_config_get ()),
+ is_v4 ? "ipv4.route-metric" : "ipv6.route-metric", self);
+ if (value) {
+ route_metric = _nm_utils_ascii_str_to_int64 (value, 10, 0, G_MAXUINT32, -1);
+ g_free (value);
- return route_metric >= 0 ? route_metric : nm_device_get_priority (self);
+ if (route_metric >= 0)
+ goto out;
+ }
+ route_metric = nm_device_get_priority (self);
+out:
+ if (!is_v4)
+ route_metric = nm_utils_ip6_route_metric_normalize (route_metric);
+ return route_metric;
}
guint32
-nm_device_get_ip6_route_metric (NMDevice *self)
+nm_device_get_ip4_route_metric (NMDevice *self)
{
- NMConnection *connection;
- NMSettingIPConfig *s_ip = NULL;
- gint64 route_metric = -1;
-
- g_return_val_if_fail (NM_IS_DEVICE (self), G_MAXUINT32);
-
- connection = nm_device_get_connection (self);
- if (connection)
- s_ip = nm_connection_get_setting_ip6_config (connection);
-
- /* Slave interfaces don't have IP settings, but we may get here when
- * external changes are made or when noticing IP changes when starting
- * the slave connection.
- */
- if (s_ip)
- route_metric = nm_setting_ip_config_get_route_metric (s_ip);
+ return _get_ipx_route_metric (self, TRUE);
+}
- return route_metric >= 0 ? route_metric : nm_device_get_priority (self);
+guint32
+nm_device_get_ip6_route_metric (NMDevice *self)
+{
+ return _get_ipx_route_metric (self, FALSE);
}
const NMPlatformIP4Route *
@@ -818,6 +832,34 @@ nm_device_get_type_desc (NMDevice *self)
return NM_DEVICE_GET_PRIVATE (self)->type_desc;
}
+const char *
+nm_device_get_type_description (NMDevice *self)
+{
+ g_return_val_if_fail (self != NULL, NULL);
+
+ /* Beware: this function should return the same
+ * value as nm_device_get_type_description() in libnm. */
+
+ return NM_DEVICE_GET_CLASS (self)->get_type_description (self);
+}
+
+static const char *
+get_type_description (NMDevice *self)
+{
+ NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
+
+ if (!priv->type_description) {
+ const char *typename;
+
+ typename = G_OBJECT_TYPE_NAME (self);
+ if (g_str_has_prefix (typename, "NMDevice"))
+ typename += 8;
+ priv->type_description = g_ascii_strdown (typename, -1);
+ }
+
+ return priv->type_description;
+}
+
gboolean
nm_device_has_carrier (NMDevice *self)
{
@@ -4555,8 +4597,10 @@ set_nm_ipv6ll (NMDevice *self, gboolean enable)
}
}
+/************************************************************************/
+
static NMSettingIP6ConfigPrivacy
-use_tempaddr_clamp (NMSettingIP6ConfigPrivacy use_tempaddr)
+_ip6_privacy_clamp (NMSettingIP6ConfigPrivacy use_tempaddr)
{
switch (use_tempaddr) {
case NM_SETTING_IP6_CONFIG_PRIVACY_DISABLED:
@@ -4568,45 +4612,51 @@ use_tempaddr_clamp (NMSettingIP6ConfigPrivacy use_tempaddr)
}
}
-/* Get net.ipv6.conf.default.use_tempaddr value from /etc/sysctl.conf or
- * /lib/sysctl.d/sysctl.conf
- */
static NMSettingIP6ConfigPrivacy
-ip6_use_tempaddr (void)
+_ip6_privacy_get (NMDevice *self)
{
- char *contents = NULL;
- const char *group_name = "[forged_group]\n";
- char *sysctl_data = NULL;
- GKeyFile *keyfile;
- GError *error = NULL;
- gint tmp;
- NMSettingIP6ConfigPrivacy ret = NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN;
+ NMSettingIP6ConfigPrivacy ip6_privacy;
+ gs_free char *value = NULL;
+ NMConnection *connection;
- /* Read file contents to a string. */
- if (!g_file_get_contents ("/etc/sysctl.conf", &contents, NULL, NULL))
- if (!g_file_get_contents ("/lib/sysctl.d/sysctl.conf", &contents, NULL, NULL))
- return NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN;
+ g_return_val_if_fail (self, NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN);
- /* Prepend a group so that we can use GKeyFile parser. */
- sysctl_data = g_strdup_printf ("%s%s", group_name, contents);
+ /* 1.) First look at the per-connection setting. If it is not -1 (unknown),
+ * use it. */
+ connection = nm_device_get_connection (self);
+ if (connection) {
+ NMSettingIPConfig *s_ip6 = nm_connection_get_setting_ip6_config (connection);
- keyfile = g_key_file_new ();
- if (!g_key_file_load_from_data (keyfile, sysctl_data, -1, G_KEY_FILE_NONE, NULL))
- goto done;
+ if (s_ip6) {
+ ip6_privacy = nm_setting_ip6_config_get_ip6_privacy (NM_SETTING_IP6_CONFIG (s_ip6));
+ ip6_privacy = _ip6_privacy_clamp (ip6_privacy);
+ if (ip6_privacy != NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN)
+ return ip6_privacy;
+ }
+ }
- tmp = g_key_file_get_integer (keyfile, "forged_group", "net.ipv6.conf.default.use_tempaddr", &error);
- if (error == NULL)
- ret = use_tempaddr_clamp (tmp);
+ value = nm_config_data_get_connection_default (nm_config_get_data (nm_config_get ()),
+ "ipv6.ip6-privacy", self);
-done:
- g_free (contents);
- g_free (sysctl_data);
- g_clear_error (&error);
- g_key_file_free (keyfile);
+ /* 2.) use the default value from the configuration. */
+ ip6_privacy = _nm_utils_ascii_str_to_int64 (value, 10,
+ NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN,
+ NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR,
+ NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN);
+ if (ip6_privacy != NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN)
+ return ip6_privacy;
- return ret;
+ /* 3.) No valid default-value configured. Fallback to reading sysctl.
+ *
+ * Instead of reading static config files in /etc, just read the current sysctl value.
+ * This works as NM only writes to "/proc/sys/net/ipv6/conf/IFNAME/use_tempaddr", but leaves
+ * the "default" entry untouched. */
+ ip6_privacy = nm_platform_sysctl_get_int32 (NM_PLATFORM_GET, "/proc/sys/net/ipv6/conf/default/use_tempaddr", NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN);
+ return _ip6_privacy_clamp (ip6_privacy);
}
+/****************************************************************/
+
static gboolean
ip6_requires_slaves (NMConnection *connection)
{
@@ -4705,18 +4755,7 @@ act_stage3_ip6_config_start (NMDevice *self,
/* Re-enable IPv6 on the interface */
set_disable_ipv6 (self, "0");
- /* Enable/disable IPv6 Privacy Extensions.
- * If a global value is configured by sysadmin (e.g. /etc/sysctl.conf),
- * use that value instead of per-connection value.
- */
- ip6_privacy = ip6_use_tempaddr ();
- if (ip6_privacy == NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN) {
- NMSettingIPConfig *s_ip6 = nm_connection_get_setting_ip6_config (connection);
-
- if (s_ip6)
- ip6_privacy = nm_setting_ip6_config_get_ip6_privacy (NM_SETTING_IP6_CONFIG (s_ip6));
- }
- ip6_privacy = use_tempaddr_clamp (ip6_privacy);
+ ip6_privacy = _ip6_privacy_get (self);
if (strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_AUTO) == 0) {
if (!addrconf6_start (self, ip6_privacy)) {
@@ -8354,6 +8393,10 @@ spec_match_list (NMDevice *self, const GSList *specs)
m = nm_match_spec_interface_name (specs, nm_device_get_iface (self));
matched = MAX (matched, m);
}
+ if (matched != NM_MATCH_SPEC_NEG_MATCH) {
+ m = nm_match_spec_device_type (specs, nm_device_get_type_description (self));
+ matched = MAX (matched, m);
+ }
return matched;
}
@@ -8638,6 +8681,7 @@ finalize (GObject *object)
g_free (priv->driver_version);
g_free (priv->firmware_version);
g_free (priv->type_desc);
+ g_free (priv->type_description);
g_free (priv->dhcp_anycast_address);
g_hash_table_unref (priv->ip6_saved_properties);
@@ -8655,7 +8699,7 @@ set_property (GObject *object, guint prop_id,
NMPlatformLink *platform_device;
const char *hw_addr, *p;
guint count;
-
+
switch (prop_id) {
case PROP_PLATFORM_DEVICE:
platform_device = g_value_get_pointer (value);
@@ -8917,6 +8961,7 @@ nm_device_class_init (NMDeviceClass *klass)
klass->act_stage4_ip6_config_timeout = act_stage4_ip6_config_timeout;
klass->have_any_ready_slaves = have_any_ready_slaves;
+ klass->get_type_description = get_type_description;
klass->spec_match_list = spec_match_list;
klass->can_auto_connect = can_auto_connect;
klass->check_connection_compatible = check_connection_compatible;