summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2013-09-06 11:56:41 +0200
committerThomas Haller <thaller@redhat.com>2013-09-25 23:12:37 +0200
commitdb9b7e10aca5456ec4960b75617e032209b98bc1 (patch)
tree9c70cc450812700e1c4b32eaa2193e5275607df3
parentf0fccd99a55cecc4288ddba5c314b86579a27192 (diff)
downloadNetworkManager-db9b7e10aca5456ec4960b75617e032209b98bc1.tar.gz
core: update existing IP[46]Config of device instead of replacing it (bgo #707617)
When the IP[46]Config changes, a new configuration gets assembled. Before, whenever the new configuration was different than the current one, the IP[46]Config of the device was completely replaced. This also meant, that the old dbus IP[46]Config object was removed and the new one was exported. Now instead of recreating a new configuration, it updates the existing (already exported) configuration in-place. Also, add new gobject properties 'gateway' and 'searches' to the config class, they will be exported over dbus. Also, whenever any of the exported properties changes, make sure that a notify signal gets emitted. https://bugzilla.gnome.org/show_bug.cgi?id=707617 Signed-off-by: Thomas Haller <thaller@redhat.com>
-rw-r--r--introspection/nm-ip4-config.xml24
-rw-r--r--introspection/nm-ip6-config.xml10
-rw-r--r--libnm-glib/nm-ip4-config.c118
-rw-r--r--libnm-glib/nm-ip4-config.h8
-rw-r--r--libnm-glib/nm-ip6-config.c129
-rw-r--r--libnm-glib/nm-ip6-config.h8
-rw-r--r--src/devices/nm-device.c108
-rw-r--r--src/nm-ip4-config.c138
-rw-r--r--src/nm-ip4-config.h4
-rw-r--r--src/nm-ip6-config.c136
-rw-r--r--src/nm-ip6-config.h4
-rw-r--r--src/nm-policy.c32
12 files changed, 570 insertions, 149 deletions
diff --git a/introspection/nm-ip4-config.xml b/introspection/nm-ip4-config.xml
index 70d3e1ce43..f21a2e4a0e 100644
--- a/introspection/nm-ip4-config.xml
+++ b/introspection/nm-ip4-config.xml
@@ -2,21 +2,15 @@
<node name="/" xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0">
<interface name="org.freedesktop.NetworkManager.IP4Config">
+ <property name="Gateway" type="s" access="read">
+ <tp:docstring>The gateway in use.</tp:docstring>
+ </property>
<property name="Addresses" type="aau" access="read">
<tp:docstring>Array of tuples of IPv4 address/prefix/gateway. All 3
elements of each tuple are in network byte order. Essentially:
[(addr, prefix, gateway), (addr, prefix, gateway), ...]
</tp:docstring>
</property>
- <property name="Nameservers" type="au" access="read">
- <tp:docstring>The nameservers in use.</tp:docstring>
- </property>
- <property name="WinsServers" type="au" access="read">
- <tp:docstring>The Windows Internet Name Service servers associated with the connection. Each address is in network byte order.</tp:docstring>
- </property>
- <property name="Domains" type="as" access="read">
- <tp:docstring>A list of domains this address belongs to.</tp:docstring>
- </property>
<property name="Routes" type="aau" access="read">
<tp:docstring>Tuples of IPv4 route/prefix/next-hop/metric. All 4 elements
of each tuple are in network byte order. 'route' and 'next hop' are IPv4
@@ -24,6 +18,18 @@
[(route, prefix, next-hop, metric), (route, prefix, next-hop, metric), ...]
</tp:docstring>
</property>
+ <property name="Nameservers" type="au" access="read">
+ <tp:docstring>The nameservers in use.</tp:docstring>
+ </property>
+ <property name="Domains" type="as" access="read">
+ <tp:docstring>A list of domains this address belongs to.</tp:docstring>
+ </property>
+ <property name="Searches" type="as" access="read">
+ <tp:docstring>A list of dns searches.</tp:docstring>
+ </property>
+ <property name="WinsServers" type="au" access="read">
+ <tp:docstring>The Windows Internet Name Service servers associated with the connection. Each address is in network byte order.</tp:docstring>
+ </property>
</interface>
</node>
diff --git a/introspection/nm-ip6-config.xml b/introspection/nm-ip6-config.xml
index 604781857e..dcec871391 100644
--- a/introspection/nm-ip6-config.xml
+++ b/introspection/nm-ip6-config.xml
@@ -2,17 +2,23 @@
<node name="/" xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0">
<interface name="org.freedesktop.NetworkManager.IP6Config">
+ <property name="Gateway" type="s" access="read">
+ <tp:docstring>The gateway in use.</tp:docstring>
+ </property>
<property name="Addresses" type="a(ayuay)" access="read">
<tp:docstring>Tuples of IPv6 address/prefix/gateway.</tp:docstring>
</property>
+ <property name="Routes" type="a(ayuayu)" access="read">
+ <tp:docstring>Tuples of IPv6 route/prefix/next-hop/metric.</tp:docstring>
+ </property>
<property name="Nameservers" type="aay" access="read">
<tp:docstring>The nameservers in use.</tp:docstring>
</property>
<property name="Domains" type="as" access="read">
<tp:docstring>A list of domains this address belongs to.</tp:docstring>
</property>
- <property name="Routes" type="a(ayuayu)" access="read">
- <tp:docstring>Tuples of IPv6 route/prefix/next-hop/metric.</tp:docstring>
+ <property name="Searches" type="as" access="read">
+ <tp:docstring>A list of dns searches.</tp:docstring>
</property>
</interface>
</node>
diff --git a/libnm-glib/nm-ip4-config.c b/libnm-glib/nm-ip4-config.c
index 86873d7253..ab53e382f1 100644
--- a/libnm-glib/nm-ip4-config.c
+++ b/libnm-glib/nm-ip4-config.c
@@ -37,19 +37,23 @@ G_DEFINE_TYPE (NMIP4Config, nm_ip4_config, NM_TYPE_OBJECT)
typedef struct {
DBusGProxy *proxy;
+ char *gateway;
GSList *addresses;
+ GSList *routes;
GArray *nameservers;
GPtrArray *domains;
- GSList *routes;
+ GPtrArray *searches;
GArray *wins;
} NMIP4ConfigPrivate;
enum {
PROP_0,
+ PROP_GATEWAY,
PROP_ADDRESSES,
+ PROP_ROUTES,
PROP_NAMESERVERS,
PROP_DOMAINS,
- PROP_ROUTES,
+ PROP_SEARCHES,
PROP_WINS_SERVERS,
LAST_PROP
@@ -90,12 +94,12 @@ demarshal_ip4_array (NMObject *object, GParamSpec *pspec, GValue *value, gpointe
}
static gboolean
-demarshal_domains (NMObject *object, GParamSpec *pspec, GValue *value, gpointer field)
+demarshal_string_array (NMObject *object, GParamSpec *pspec, GValue *value, gpointer field)
{
if (!_nm_string_array_demarshal (value, (GPtrArray **) field))
return FALSE;
- _nm_object_queue_notify (object, NM_IP4_CONFIG_DOMAINS);
+ _nm_object_queue_notify (object, pspec->name);
return TRUE;
}
@@ -119,10 +123,12 @@ register_properties (NMIP4Config *config)
{
NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
const NMPropertiesInfo property_info[] = {
+ { NM_IP4_CONFIG_GATEWAY, &priv->gateway, },
{ NM_IP4_CONFIG_ADDRESSES, &priv->addresses, demarshal_ip4_address_array },
- { NM_IP4_CONFIG_NAMESERVERS, &priv->nameservers, demarshal_ip4_array },
- { NM_IP4_CONFIG_DOMAINS, &priv->domains, demarshal_domains },
{ NM_IP4_CONFIG_ROUTES, &priv->routes, demarshal_ip4_routes_array },
+ { NM_IP4_CONFIG_NAMESERVERS, &priv->nameservers, demarshal_ip4_array },
+ { NM_IP4_CONFIG_DOMAINS, &priv->domains, demarshal_string_array },
+ { NM_IP4_CONFIG_SEARCHES, &priv->searches, demarshal_string_array },
{ NM_IP4_CONFIG_WINS_SERVERS, &priv->wins, demarshal_ip4_array },
{ NULL },
};
@@ -148,6 +154,8 @@ finalize (GObject *object)
{
NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (object);
+ g_free (priv->gateway);
+
g_slist_foreach (priv->addresses, (GFunc) g_free, NULL);
g_slist_free (priv->addresses);
@@ -165,6 +173,11 @@ finalize (GObject *object)
g_ptr_array_free (priv->domains, TRUE);
}
+ if (priv->searches) {
+ g_ptr_array_foreach (priv->searches, (GFunc) g_free, NULL);
+ g_ptr_array_free (priv->searches, TRUE);
+ }
+
g_object_unref (priv->proxy);
G_OBJECT_CLASS (nm_ip4_config_parent_class)->finalize (object);
@@ -182,17 +195,23 @@ get_property (GObject *object,
_nm_object_ensure_inited (NM_OBJECT (object));
switch (prop_id) {
+ case PROP_GATEWAY:
+ g_value_set_string (value, nm_ip4_config_get_gateway (self));
+ break;
case PROP_ADDRESSES:
nm_utils_ip4_addresses_to_gvalue (priv->addresses, value);
break;
+ case PROP_ROUTES:
+ nm_utils_ip4_routes_to_gvalue (priv->routes, value);
+ break;
case PROP_NAMESERVERS:
g_value_set_boxed (value, nm_ip4_config_get_nameservers (self));
break;
case PROP_DOMAINS:
g_value_set_boxed (value, nm_ip4_config_get_domains (self));
break;
- case PROP_ROUTES:
- nm_utils_ip4_routes_to_gvalue (priv->routes, value);
+ case PROP_SEARCHES:
+ g_value_set_boxed (value, nm_ip4_config_get_searches (self));
break;
case PROP_WINS_SERVERS:
g_value_set_boxed (value, nm_ip4_config_get_wins_servers (self));
@@ -218,6 +237,21 @@ nm_ip4_config_class_init (NMIP4ConfigClass *config_class)
/* properties */
/**
+ * NMIP4Config:gateway:
+ *
+ * The IP4 gateway address of the configuration as string.
+ *
+ * Since: 0.9.10
+ **/
+ g_object_class_install_property
+ (object_class, PROP_GATEWAY,
+ g_param_spec_string (NM_IP4_CONFIG_GATEWAY,
+ "Gateway",
+ "Gateway",
+ NULL,
+ G_PARAM_READABLE));
+
+ /**
* NMIP4Config:addresses:
*
* The #GPtrArray containing #NMSettingIP4Address<!-- -->es of the configuration.
@@ -230,6 +264,18 @@ nm_ip4_config_class_init (NMIP4ConfigClass *config_class)
G_PARAM_READABLE));
/**
+ * NMIP4Config:routes:
+ *
+ * The #GPtrArray containing #NMSettingIP4Route<!-- -->s of the configuration.
+ **/
+ g_object_class_install_property
+ (object_class, PROP_ROUTES,
+ g_param_spec_pointer (NM_IP4_CONFIG_ROUTES,
+ "Routes",
+ "Routes",
+ G_PARAM_READABLE));
+
+ /**
* NMIP4Config:nameservers:
*
* The #GArray containing name servers (%guint32<!-- -->es) of the configuration.
@@ -256,16 +302,19 @@ nm_ip4_config_class_init (NMIP4ConfigClass *config_class)
G_PARAM_READABLE));
/**
- * NMIP4Config:routes:
+ * NMIP4Config:searches:
*
- * The #GPtrArray containing #NMSettingIP4Route<!-- -->s of the configuration.
+ * The #GPtrArray containing dns search strings of the configuration.
+ *
+ * Since: 0.9.10
**/
g_object_class_install_property
- (object_class, PROP_ROUTES,
- g_param_spec_pointer (NM_IP4_CONFIG_ROUTES,
- "Routes",
- "Routes",
- G_PARAM_READABLE));
+ (object_class, PROP_SEARCHES,
+ g_param_spec_boxed (NM_IP4_CONFIG_SEARCHES,
+ "Searches",
+ "DNS searches",
+ NM_TYPE_STRING_ARRAY,
+ G_PARAM_READABLE));
/**
* NMIP4Config:wins-servers:
@@ -300,6 +349,25 @@ nm_ip4_config_new (DBusGConnection *connection, const char *object_path)
}
/**
+ * nm_ip4_config_get_gateway:
+ * @config: a #NMIP4Config
+ *
+ * Gets the IP4 gateway address.
+ *
+ * Returns: the IP4 address of the gateway.
+ *
+ * Since: 0.9.10
+ **/
+const char *
+nm_ip4_config_get_gateway (NMIP4Config *config)
+{
+ g_return_val_if_fail (NM_IS_IP4_CONFIG (config), NULL);
+
+ _nm_object_ensure_inited (NM_OBJECT (config));
+ return NM_IP4_CONFIG_GET_PRIVATE (config)->gateway;
+}
+
+/**
* nm_ip4_config_get_addresses:
* @config: a #NMIP4Config
*
@@ -354,6 +422,26 @@ nm_ip4_config_get_domains (NMIP4Config *config)
}
/**
+ * nm_ip4_config_get_searches:
+ * @config: a #NMIP4Config
+ *
+ * Gets the dns searches.
+ *
+ * Returns: (element-type utf8): the #GPtrArray containing dns searches as strings. This is the
+ * internal copy used by the configuration, and must not be modified.
+ *
+ * Since: 0.9.10
+ **/
+const GPtrArray *
+nm_ip4_config_get_searches (NMIP4Config *config)
+{
+ g_return_val_if_fail (NM_IS_IP4_CONFIG (config), NULL);
+
+ _nm_object_ensure_inited (NM_OBJECT (config));
+ return handle_ptr_array_return (NM_IP4_CONFIG_GET_PRIVATE (config)->searches);
+}
+
+/**
* nm_ip4_config_get_wins_servers:
* @config: a #NMIP4Config
*
diff --git a/libnm-glib/nm-ip4-config.h b/libnm-glib/nm-ip4-config.h
index b76fdf8b34..8d17693fe1 100644
--- a/libnm-glib/nm-ip4-config.h
+++ b/libnm-glib/nm-ip4-config.h
@@ -54,20 +54,24 @@ typedef struct {
void (*_reserved6) (void);
} NMIP4ConfigClass;
+#define NM_IP4_CONFIG_GATEWAY "gateway"
#define NM_IP4_CONFIG_ADDRESSES "addresses"
+#define NM_IP4_CONFIG_ROUTES "routes"
#define NM_IP4_CONFIG_NAMESERVERS "nameservers"
#define NM_IP4_CONFIG_DOMAINS "domains"
-#define NM_IP4_CONFIG_ROUTES "routes"
+#define NM_IP4_CONFIG_SEARCHES "searches"
#define NM_IP4_CONFIG_WINS_SERVERS "wins-servers"
GType nm_ip4_config_get_type (void);
GObject *nm_ip4_config_new (DBusGConnection *connection, const char *object_path);
+const char * nm_ip4_config_get_gateway (NMIP4Config *config);
const GSList * nm_ip4_config_get_addresses (NMIP4Config *config);
+const GSList * nm_ip4_config_get_routes (NMIP4Config *config);
const GArray * nm_ip4_config_get_nameservers (NMIP4Config *config);
const GPtrArray *nm_ip4_config_get_domains (NMIP4Config *config);
-const GSList * nm_ip4_config_get_routes (NMIP4Config *config);
+const GPtrArray *nm_ip4_config_get_searches (NMIP4Config *config);
const GArray * nm_ip4_config_get_wins_servers (NMIP4Config *config);
G_END_DECLS
diff --git a/libnm-glib/nm-ip6-config.c b/libnm-glib/nm-ip6-config.c
index f7cbfb382a..e27af0d82e 100644
--- a/libnm-glib/nm-ip6-config.c
+++ b/libnm-glib/nm-ip6-config.c
@@ -37,18 +37,22 @@ G_DEFINE_TYPE (NMIP6Config, nm_ip6_config, NM_TYPE_OBJECT)
typedef struct {
DBusGProxy *proxy;
+ char *gateway;
GSList *addresses;
+ GSList *routes;
GSList *nameservers;
GPtrArray *domains;
- GSList *routes;
+ GPtrArray *searches;
} NMIP6ConfigPrivate;
enum {
PROP_0,
+ PROP_GATEWAY,
PROP_ADDRESSES,
+ PROP_ROUTES,
PROP_NAMESERVERS,
PROP_DOMAINS,
- PROP_ROUTES,
+ PROP_SEARCHES,
LAST_PROP
};
@@ -109,6 +113,16 @@ demarshal_domains (NMObject *object, GParamSpec *pspec, GValue *value, gpointer
}
static gboolean
+demarshal_searches (NMObject *object, GParamSpec *pspec, GValue *value, gpointer field)
+{
+ if (!_nm_string_array_demarshal (value, (GPtrArray **) field))
+ return FALSE;
+
+ _nm_object_queue_notify (object, NM_IP6_CONFIG_SEARCHES);
+ return TRUE;
+}
+
+static gboolean
demarshal_ip6_routes_array (NMObject *object, GParamSpec *pspec, GValue *value, gpointer field)
{
NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (object);
@@ -128,10 +142,12 @@ register_properties (NMIP6Config *config)
{
NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config);
const NMPropertiesInfo property_info[] = {
+ { NM_IP6_CONFIG_GATEWAY, &priv->gateway, },
{ NM_IP6_CONFIG_ADDRESSES, &priv->addresses, demarshal_ip6_address_array },
+ { NM_IP6_CONFIG_ROUTES, &priv->routes, demarshal_ip6_routes_array },
{ NM_IP6_CONFIG_NAMESERVERS, &priv->nameservers, demarshal_ip6_nameserver_array },
{ NM_IP6_CONFIG_DOMAINS, &priv->domains, demarshal_domains },
- { NM_IP6_CONFIG_ROUTES, &priv->routes, demarshal_ip6_routes_array },
+ { NM_IP6_CONFIG_SEARCHES, &priv->searches, demarshal_searches },
{ NULL },
};
@@ -141,6 +157,25 @@ register_properties (NMIP6Config *config)
}
/**
+ * nm_ip6_config_get_gateway:
+ * @config: a #NMIP6Config
+ *
+ * Gets the IP6 gateway.
+ *
+ * Returns: the IPv6 gateway of the configuration.
+ *
+ * Since: 0.9.10
+ **/
+const char *
+nm_ip6_config_get_gateway (NMIP6Config *config)
+{
+ g_return_val_if_fail (NM_IS_IP6_CONFIG (config), NULL);
+
+ _nm_object_ensure_inited (NM_OBJECT (config));
+ return NM_IP6_CONFIG_GET_PRIVATE (config)->gateway;
+}
+
+/**
* nm_ip6_config_get_addresses:
* @config: a #NMIP6Config
*
@@ -198,6 +233,26 @@ nm_ip6_config_get_domains (NMIP6Config *config)
}
/**
+ * nm_ip6_config_get_searches:
+ * @config: a #NMIP6Config
+ *
+ * Gets the dns searches.
+ *
+ * Returns: (element-type utf8): the #GPtrArray containing dns searches as strings.
+ * This is the internal copy used by the configuration, and must not be modified.
+ *
+ * Since: 0.9.10
+ **/
+const GPtrArray *
+nm_ip6_config_get_searches (NMIP6Config *config)
+{
+ g_return_val_if_fail (NM_IS_IP6_CONFIG (config), NULL);
+
+ _nm_object_ensure_inited (NM_OBJECT (config));
+ return handle_ptr_array_return (NM_IP6_CONFIG_GET_PRIVATE (config)->searches);
+}
+
+/**
* nm_ip6_config_get_routes:
* @config: a #NMIP6Config
*
@@ -232,6 +287,8 @@ finalize (GObject *object)
{
NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (object);
+ g_free (priv->gateway);
+
g_slist_foreach (priv->addresses, (GFunc) nm_ip6_address_unref, NULL);
g_slist_free (priv->addresses);
@@ -246,6 +303,11 @@ finalize (GObject *object)
g_ptr_array_free (priv->domains, TRUE);
}
+ if (priv->searches) {
+ g_ptr_array_foreach (priv->searches, (GFunc) g_free, NULL);
+ g_ptr_array_free (priv->searches, TRUE);
+ }
+
g_object_unref (priv->proxy);
G_OBJECT_CLASS (nm_ip6_config_parent_class)->finalize (object);
@@ -263,17 +325,23 @@ get_property (GObject *object,
_nm_object_ensure_inited (NM_OBJECT (object));
switch (prop_id) {
+ case PROP_GATEWAY:
+ g_value_set_string (value, nm_ip6_config_get_gateway (self));
+ break;
case PROP_ADDRESSES:
nm_utils_ip6_addresses_to_gvalue (priv->addresses, value);
break;
+ case PROP_ROUTES:
+ nm_utils_ip6_routes_to_gvalue (priv->routes, value);
+ break;
case PROP_NAMESERVERS:
g_value_set_boxed (value, nm_ip6_config_get_nameservers (self));
break;
case PROP_DOMAINS:
g_value_set_boxed (value, nm_ip6_config_get_domains (self));
break;
- case PROP_ROUTES:
- nm_utils_ip6_routes_to_gvalue (priv->routes, value);
+ case PROP_SEARCHES:
+ g_value_set_boxed (value, nm_ip6_config_get_searches (self));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -301,6 +369,21 @@ nm_ip6_config_class_init (NMIP6ConfigClass *config_class)
/* properties */
/**
+ * NMIP6Config:gateway:
+ *
+ * The IPv6 gateway as string
+ *
+ * Since: 0.9.10
+ **/
+ g_object_class_install_property
+ (object_class, PROP_ROUTES,
+ g_param_spec_string (NM_IP6_CONFIG_ROUTES,
+ "Gateway",
+ "Gateway",
+ NULL,
+ G_PARAM_READABLE));
+
+ /**
* NMIP6Config:addresses:
*
* The #GPtrArray containing the IPv6 addresses; use
@@ -316,6 +399,21 @@ nm_ip6_config_class_init (NMIP6ConfigClass *config_class)
G_PARAM_READABLE));
/**
+ * NMIP6Config:routes:
+ *
+ * The #GPtrArray containing the IPv6 routes; use
+ * nm_utils_ip6_routes_from_gvalue() to return a #GSList of
+ * #NMSettingIP6Address objects that is more usable than the raw data.
+ **/
+ g_object_class_install_property
+ (object_class, PROP_ROUTES,
+ g_param_spec_boxed (NM_IP6_CONFIG_ROUTES,
+ "Routes",
+ "Routes",
+ NM_TYPE_IP6_ROUTE_OBJECT_ARRAY,
+ G_PARAM_READABLE));
+
+ /**
* NMIP6Config:nameservers:
*
* The #GPtrArray containing elements of type 'struct ip6_addr' which
@@ -343,18 +441,19 @@ nm_ip6_config_class_init (NMIP6ConfigClass *config_class)
G_PARAM_READABLE));
/**
- * NMIP6Config:routes:
+ * NMIP6Config:searches:
*
- * The #GPtrArray containing the IPv6 routes; use
- * nm_utils_ip6_routes_from_gvalue() to return a #GSList of
- * #NMSettingIP6Address objects that is more usable than the raw data.
+ * The #GPtrArray containing dns search strings of the configuration.
+ *
+ * Since: 0.9.10
**/
g_object_class_install_property
- (object_class, PROP_ROUTES,
- g_param_spec_boxed (NM_IP6_CONFIG_ROUTES,
- "Routes",
- "Routes",
- NM_TYPE_IP6_ROUTE_OBJECT_ARRAY,
- G_PARAM_READABLE));
+ (object_class, PROP_SEARCHES,
+ g_param_spec_boxed (NM_IP6_CONFIG_SEARCHES,
+ "Searches",
+ "DNS Searches",
+ NM_TYPE_STRING_ARRAY,
+ G_PARAM_READABLE));
+
}
diff --git a/libnm-glib/nm-ip6-config.h b/libnm-glib/nm-ip6-config.h
index 9692c65585..a71d74b856 100644
--- a/libnm-glib/nm-ip6-config.h
+++ b/libnm-glib/nm-ip6-config.h
@@ -54,19 +54,23 @@ typedef struct {
void (*_reserved6) (void);
} NMIP6ConfigClass;
+#define NM_IP6_CONFIG_GATEWAY "gateway"
#define NM_IP6_CONFIG_ADDRESSES "addresses"
+#define NM_IP6_CONFIG_ROUTES "routes"
#define NM_IP6_CONFIG_NAMESERVERS "nameservers"
#define NM_IP6_CONFIG_DOMAINS "domains"
-#define NM_IP6_CONFIG_ROUTES "routes"
+#define NM_IP6_CONFIG_SEARCHES "searches"
GType nm_ip6_config_get_type (void);
GObject *nm_ip6_config_new (DBusGConnection *connection, const char *object_path);
+const char * nm_ip6_config_get_gateway (NMIP6Config *config);
const GSList * nm_ip6_config_get_addresses (NMIP6Config *config);
+const GSList * nm_ip6_config_get_routes (NMIP6Config *config);
const GSList * nm_ip6_config_get_nameservers (NMIP6Config *config);
const GPtrArray *nm_ip6_config_get_domains (NMIP6Config *config);
-const GSList * nm_ip6_config_get_routes (NMIP6Config *config);
+const GPtrArray *nm_ip6_config_get_searches (NMIP6Config *config);
G_END_DECLS
diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c
index d40457b4f4..d99b3d726a 100644
--- a/src/devices/nm-device.c
+++ b/src/devices/nm-device.c
@@ -4558,7 +4558,9 @@ nm_device_set_ip4_config (NMDevice *self,
NMDevicePrivate *priv;
const char *ip_iface;
NMIP4Config *old_config = NULL;
+ gboolean has_changes = FALSE;
gboolean success = TRUE;
+ NMDeviceStateReason reason_local = NM_DEVICE_STATE_REASON_NONE;
int ip_ifindex;
g_return_val_if_fail (NM_IS_DEVICE (self), FALSE);
@@ -4570,36 +4572,52 @@ nm_device_set_ip4_config (NMDevice *self,
old_config = priv->ip4_config;
/* Always commit to nm-platform to update lifetimes */
- if (commit && new_config)
+ if (commit && new_config) {
success = nm_ip4_config_commit (new_config, ip_ifindex, nm_device_get_priority (self));
-
- if (nm_ip4_config_equal (new_config, old_config))
- return success;
-
- priv->ip4_config = NULL;
+ if (!success)
+ reason_local = NM_DEVICE_STATE_REASON_CONFIG_FAILED;
+ }
if (new_config) {
- priv->ip4_config = g_object_ref (new_config);
+ if (old_config) {
+ /* has_changes is set only on relevant changes, because when the configuration changes,
+ * this causes a re-read and reset. This should only happen for relevant changes */
+ nm_ip4_config_replace (old_config, new_config, &has_changes);
+ if (has_changes) {
+ nm_log_dbg (LOGD_IP4, "(%s): update IP4Config instance (%s)",
+ ip_iface, nm_ip4_config_get_dbus_path (old_config));
+ }
+ } else {
+ has_changes = TRUE;
+ priv->ip4_config = g_object_ref (new_config);
- if (success || !commit) {
- /* Export over D-Bus */
- if (!nm_ip4_config_get_dbus_path (new_config))
+ if (success && !nm_ip4_config_get_dbus_path (new_config)) {
+ /* Export over D-Bus */
nm_ip4_config_export (new_config);
- _update_ip4_address (self);
+ }
}
-
- if (!success && reason)
- *reason = NM_DEVICE_STATE_REASON_CONFIG_FAILED;
- } else {
+ } else if (old_config) {
+ has_changes = TRUE;
+ priv->ip4_config = NULL;
+ nm_log_dbg (LOGD_IP4, "(%s): clear IP4Config instance (%s)",
+ ip_iface, nm_ip4_config_get_dbus_path (old_config));
/* Device config is invalid if combined config is invalid */
g_clear_object (&priv->dev_ip4_config);
}
- g_object_notify (G_OBJECT (self), NM_DEVICE_IP4_CONFIG);
- g_signal_emit (self, signals[IP4_CONFIG_CHANGED], 0, priv->ip4_config, old_config);
+ if (has_changes) {
+ _update_ip4_address (self);
+
+ if (old_config != priv->ip4_config)
+ g_object_notify (G_OBJECT (self), NM_DEVICE_IP4_CONFIG);
+ g_signal_emit (self, signals[IP4_CONFIG_CHANGED], 0, priv->ip4_config, old_config);
+
+ if (old_config != priv->ip4_config && old_config)
+ g_object_unref (old_config);
+ }
- if (old_config)
- g_object_unref (old_config);
+ if (reason)
+ *reason = reason_local;
return success;
}
@@ -4632,7 +4650,9 @@ nm_device_set_ip6_config (NMDevice *self,
NMDevicePrivate *priv;
const char *ip_iface;
NMIP6Config *old_config = NULL;
+ gboolean has_changes = FALSE;
gboolean success = TRUE;
+ NMDeviceStateReason reason_local = NM_DEVICE_STATE_REASON_NONE;
int ip_ifindex;
g_return_val_if_fail (NM_IS_DEVICE (self), FALSE);
@@ -4644,32 +4664,48 @@ nm_device_set_ip6_config (NMDevice *self,
old_config = priv->ip6_config;
/* Always commit to nm-platform to update lifetimes */
- if (commit && new_config)
+ if (commit && new_config) {
success = nm_ip6_config_commit (new_config, ip_ifindex, nm_device_get_priority (self));
-
- if (nm_ip6_config_equal (new_config, old_config))
- return success;
-
- priv->ip6_config = NULL;
+ if (!success)
+ reason_local = NM_DEVICE_STATE_REASON_CONFIG_FAILED;
+ }
if (new_config) {
- priv->ip6_config = g_object_ref (new_config);
+ if (old_config) {
+ /* has_changes is set only on relevant changes, because when the configuration changes,
+ * this causes a re-read and reset. This should only happen for relevant changes */
+ nm_ip6_config_replace (old_config, new_config, &has_changes);
+ if (has_changes) {
+ nm_log_dbg (LOGD_IP6, "(%s): update IP6Config instance (%s)",
+ ip_iface, nm_ip6_config_get_dbus_path (old_config));
+ }
+ } else {
+ has_changes = TRUE;
+ priv->ip6_config = g_object_ref (new_config);
- if (success || !commit) {
- /* Export over D-Bus */
- if (!nm_ip6_config_get_dbus_path (new_config))
+ if (success && !nm_ip6_config_get_dbus_path (new_config)) {
+ /* Export over D-Bus */
nm_ip6_config_export (new_config);
+ }
}
-
- if (!success && reason)
- *reason = NM_DEVICE_STATE_REASON_CONFIG_FAILED;
+ } else if (old_config) {
+ has_changes = TRUE;
+ priv->ip6_config = NULL;
+ nm_log_dbg (LOGD_IP6, "(%s): clear IP6Config instance (%s)",
+ ip_iface, nm_ip6_config_get_dbus_path (old_config));
}
- g_object_notify (G_OBJECT (self), NM_DEVICE_IP6_CONFIG);
- g_signal_emit (self, signals[IP6_CONFIG_CHANGED], 0, priv->ip6_config, old_config);
+ if (has_changes) {
+ if (old_config != priv->ip6_config)
+ g_object_notify (G_OBJECT (self), NM_DEVICE_IP6_CONFIG);
+ g_signal_emit (self, signals[IP6_CONFIG_CHANGED], 0, priv->ip6_config, old_config);
+
+ if (old_config != priv->ip6_config && old_config)
+ g_object_unref (old_config);
+ }
- if (old_config)
- g_object_unref (old_config);
+ if (reason)
+ *reason = reason_local;
return success;
}
diff --git a/src/nm-ip4-config.c b/src/nm-ip4-config.c
index 79ec2d481f..c321b83b7b 100644
--- a/src/nm-ip4-config.c
+++ b/src/nm-ip4-config.c
@@ -53,17 +53,24 @@ typedef struct {
guint32 mtu;
} NMIP4ConfigPrivate;
+/* internal guint32 are assigned to gobject properties of type uint. Ensure, that uint is large enough */
+G_STATIC_ASSERT (sizeof (uint) >= sizeof (guint32));
+G_STATIC_ASSERT (G_MAXUINT >= 0xFFFFFFFF);
enum {
PROP_0,
+ PROP_GATEWAY,
PROP_ADDRESSES,
+ PROP_ROUTES,
PROP_NAMESERVERS,
PROP_DOMAINS,
- PROP_ROUTES,
+ PROP_SEARCHES,
PROP_WINS_SERVERS,
LAST_PROP
};
+static GParamSpec *obj_properties[LAST_PROP] = { NULL, };
+#define _NOTIFY(config, prop) G_STMT_START { g_object_notify_by_pspec (G_OBJECT (config), obj_properties[prop]); } G_STMT_END
NMIP4Config *
@@ -129,6 +136,10 @@ nm_ip4_config_capture (int ifindex)
priv->addresses = nm_platform_ip4_address_get_all (ifindex);
priv->routes = nm_platform_ip4_route_get_all (ifindex, FALSE);
+ /* actually, nobody should be connected to the signal, just to be sure, notify */
+ _NOTIFY (config, PROP_ADDRESSES);
+ _NOTIFY (config, PROP_ROUTES);
+
return config;
}
@@ -193,6 +204,8 @@ nm_ip4_config_merge_setting (NMIP4Config *config, NMSettingIP4Config *setting)
if (!setting)
return;
+ g_object_freeze_notify (G_OBJECT (config));
+
naddresses = nm_setting_ip4_config_get_num_addresses (setting);
nroutes = nm_setting_ip4_config_get_num_routes (setting);
nnameservers = nm_setting_ip4_config_get_num_dns (setting);
@@ -252,6 +265,8 @@ nm_ip4_config_merge_setting (NMIP4Config *config, NMSettingIP4Config *setting)
nm_ip4_config_add_nameserver (config, nm_setting_ip4_config_get_dns (setting, i));
for (i = 0; i < nsearches; i++)
nm_ip4_config_add_search (config, nm_setting_ip4_config_get_dns_search (setting, i));
+
+ g_object_thaw_notify (G_OBJECT (config));
}
void
@@ -345,6 +360,8 @@ nm_ip4_config_merge (NMIP4Config *dst, NMIP4Config *src)
g_return_if_fail (src != NULL);
g_return_if_fail (dst != NULL);
+ g_object_freeze_notify (G_OBJECT (dst));
+
/* addresses */
for (i = 0; i < nm_ip4_config_get_num_addresses (src); i++)
nm_ip4_config_add_address (dst, nm_ip4_config_get_address (src, i));
@@ -386,6 +403,8 @@ nm_ip4_config_merge (NMIP4Config *dst, NMIP4Config *src)
/* WINS */
for (i = 0; i < nm_ip4_config_get_num_wins (src); i++)
nm_ip4_config_add_wins (dst, nm_ip4_config_get_wins (src, i));
+
+ g_object_thaw_notify (G_OBJECT (dst));
}
/**
@@ -403,6 +422,8 @@ nm_ip4_config_subtract (NMIP4Config *dst, NMIP4Config *src)
g_return_if_fail (src != NULL);
g_return_if_fail (dst != NULL);
+ g_object_freeze_notify (G_OBJECT (dst));
+
/* addresses */
for (i = 0; i < nm_ip4_config_get_num_addresses (src); i++) {
const NMPlatformIP4Address *src_addr = nm_ip4_config_get_address (src, i);
@@ -515,6 +536,8 @@ nm_ip4_config_subtract (NMIP4Config *dst, NMIP4Config *src)
}
}
}
+
+ g_object_thaw_notify (G_OBJECT (dst));
}
@@ -555,6 +578,8 @@ nm_ip4_config_replace (NMIP4Config *dst, NMIP4Config *src, gboolean *relevant_ch
dst_priv = NM_IP4_CONFIG_GET_PRIVATE (dst);
src_priv = NM_IP4_CONFIG_GET_PRIVATE (src);
+ g_object_freeze_notify (G_OBJECT (dst));
+
/* never_default */
if (src_priv->never_default != dst_priv->never_default) {
dst_priv->never_default = src_priv->never_default;
@@ -733,6 +758,8 @@ nm_ip4_config_replace (NMIP4Config *dst, NMIP4Config *src, gboolean *relevant_ch
* regardless of config_equal. But config_equal must correspond to has_relevant_changes. */
g_assert (config_equal == !has_relevant_changes);
+ g_object_thaw_notify (G_OBJECT (dst));
+
if (relevant_changes)
*relevant_changes = has_relevant_changes;
@@ -856,7 +883,10 @@ nm_ip4_config_set_gateway (NMIP4Config *config, guint32 gateway)
{
NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
- priv->gateway = gateway;
+ if (priv->gateway != gateway) {
+ priv->gateway = gateway;
+ _NOTIFY (config, PROP_GATEWAY);
+ }
}
guint32
@@ -874,7 +904,10 @@ nm_ip4_config_reset_addresses (NMIP4Config *config)
{
NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
- g_array_set_size (priv->addresses, 0);
+ if (priv->addresses->len != 0) {
+ g_array_set_size (priv->addresses, 0);
+ _NOTIFY (config, PROP_ADDRESSES);
+ }
}
void
@@ -889,12 +922,16 @@ nm_ip4_config_add_address (NMIP4Config *config, const NMPlatformIP4Address *new)
NMPlatformIP4Address *item = &g_array_index (priv->addresses, NMPlatformIP4Address, i);
if (addresses_are_duplicate (item, new, FALSE)) {
+ if (nm_platform_ip4_address_cmp (item, new) == 0)
+ return;
memcpy (item, new, sizeof (*item));
- return;
+ goto NOTIFY;
}
}
g_array_append_val (priv->addresses, *new);
+NOTIFY:
+ _NOTIFY (config, PROP_ADDRESSES);
}
void
@@ -905,6 +942,7 @@ nm_ip4_config_del_address (NMIP4Config *config, guint i)
g_return_if_fail (i < priv->addresses->len);
g_array_remove_index (priv->addresses, i);
+ _NOTIFY (config, PROP_ADDRESSES);
}
guint
@@ -930,7 +968,10 @@ nm_ip4_config_reset_routes (NMIP4Config *config)
{
NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
- g_array_set_size (priv->routes, 0);
+ if (priv->routes->len != 0) {
+ g_array_set_size (priv->routes, 0);
+ _NOTIFY (config, PROP_ROUTES);
+ }
}
void
@@ -945,12 +986,16 @@ nm_ip4_config_add_route (NMIP4Config *config, const NMPlatformIP4Route *new)
NMPlatformIP4Route *item = &g_array_index (priv->routes, NMPlatformIP4Route, i);
if (routes_are_duplicate (item, new, FALSE)) {
+ if (nm_platform_ip4_route_cmp (item, new) == 0)
+ return;
memcpy (item, new, sizeof (*item));
- return;
+ goto NOTIFY;
}
}
g_array_append_val (priv->routes, *new);
+NOTIFY:
+ _NOTIFY (config, PROP_ROUTES);
}
void
@@ -961,6 +1006,7 @@ nm_ip4_config_del_route (NMIP4Config *config, guint i)
g_return_if_fail (i < priv->routes->len);
g_array_remove_index (priv->routes, i);
+ _NOTIFY (config, PROP_ROUTES);
}
guint
@@ -986,7 +1032,10 @@ nm_ip4_config_reset_nameservers (NMIP4Config *config)
{
NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
- g_array_set_size (priv->nameservers, 0);
+ if (priv->nameservers->len != 0) {
+ g_array_set_size (priv->nameservers, 0);
+ _NOTIFY (config, PROP_NAMESERVERS);
+ }
}
void
@@ -1002,6 +1051,7 @@ nm_ip4_config_add_nameserver (NMIP4Config *config, guint32 new)
return;
g_array_append_val (priv->nameservers, new);
+ _NOTIFY (config, PROP_NAMESERVERS);
}
void
@@ -1012,6 +1062,7 @@ nm_ip4_config_del_nameserver (NMIP4Config *config, guint i)
g_return_if_fail (i < priv->nameservers->len);
g_array_remove_index (priv->nameservers, i);
+ _NOTIFY (config, PROP_NAMESERVERS);
}
guint32
@@ -1037,7 +1088,10 @@ nm_ip4_config_reset_domains (NMIP4Config *config)
{
NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
- g_ptr_array_set_size (priv->domains, 0);
+ if (priv->domains->len != 0) {
+ g_ptr_array_set_size (priv->domains, 0);
+ _NOTIFY (config, PROP_DOMAINS);
+ }
}
void
@@ -1054,6 +1108,7 @@ nm_ip4_config_add_domain (NMIP4Config *config, const char *domain)
return;
g_ptr_array_add (priv->domains, g_strdup (domain));
+ _NOTIFY (config, PROP_DOMAINS);
}
void
@@ -1064,6 +1119,7 @@ nm_ip4_config_del_domain (NMIP4Config *config, guint i)
g_return_if_fail (i < priv->domains->len);
g_ptr_array_remove_index (priv->domains, i);
+ _NOTIFY (config, PROP_DOMAINS);
}
guint32
@@ -1089,7 +1145,10 @@ nm_ip4_config_reset_searches (NMIP4Config *config)
{
NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
- g_ptr_array_set_size (priv->searches, 0);
+ if (priv->searches->len != 0) {
+ g_ptr_array_set_size (priv->searches, 0);
+ _NOTIFY (config, PROP_SEARCHES);
+ }
}
void
@@ -1106,6 +1165,7 @@ nm_ip4_config_add_search (NMIP4Config *config, const char *new)
return;
g_ptr_array_add (priv->searches, g_strdup (new));
+ _NOTIFY (config, PROP_SEARCHES);
}
void
@@ -1116,6 +1176,7 @@ nm_ip4_config_del_search (NMIP4Config *config, guint i)
g_return_if_fail (i < priv->searches->len);
g_ptr_array_remove_index (priv->searches, i);
+ _NOTIFY (config, PROP_SEARCHES);
}
guint32
@@ -1243,7 +1304,10 @@ nm_ip4_config_reset_wins (NMIP4Config *config)
{
NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
- g_array_set_size (priv->wins, 0);
+ if (priv->wins->len != 0) {
+ g_array_set_size (priv->wins, 0);
+ _NOTIFY (config, PROP_WINS_SERVERS);
+ }
}
void
@@ -1259,6 +1323,7 @@ nm_ip4_config_add_wins (NMIP4Config *config, guint32 wins)
return;
g_array_append_val (priv->wins, wins);
+ _NOTIFY (config, PROP_WINS_SERVERS);
}
void
@@ -1269,6 +1334,7 @@ nm_ip4_config_del_wins (NMIP4Config *config, guint i)
g_return_if_fail (i < priv->wins->len);
g_array_remove_index (priv->wins, i);
+ _NOTIFY (config, PROP_WINS_SERVERS);
}
guint32
@@ -1435,9 +1501,15 @@ get_property (GObject *object, guint prop_id,
{
NMIP4Config *config = NM_IP4_CONFIG (object);
NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (object);
- in_addr_t gateway = nm_ip4_config_get_gateway (config);
switch (prop_id) {
+ case PROP_GATEWAY:
+ if (priv->gateway) {
+ char addr_buf[INET_ADDRSTRLEN];
+ g_value_set_string (value, inet_ntop (AF_INET, &priv->gateway, addr_buf, sizeof (addr_buf)));
+ } else
+ g_value_set_string (value, NULL);
+ break;
case PROP_ADDRESSES:
{
GPtrArray *addresses = g_ptr_array_new ();
@@ -1450,7 +1522,7 @@ get_property (GObject *object, guint prop_id,
g_array_append_val (array, address->address);
g_array_append_val (array, address->plen);
- g_array_append_val (array, gateway);
+ g_array_append_val (array, priv->gateway);
g_ptr_array_add (addresses, array);
}
@@ -1485,6 +1557,9 @@ get_property (GObject *object, guint prop_id,
case PROP_DOMAINS:
g_value_set_boxed (value, priv->domains);
break;
+ case PROP_SEARCHES:
+ g_value_set_boxed (value, priv->searches);
+ break;
case PROP_WINS_SERVERS:
g_value_set_boxed (value, priv->wins);
break;
@@ -1504,41 +1579,50 @@ nm_ip4_config_class_init (NMIP4ConfigClass *config_class)
object_class->get_property = get_property;
object_class->finalize = finalize;
- g_object_class_install_property
- (object_class, PROP_ADDRESSES,
+ obj_properties[PROP_GATEWAY] =
+ g_param_spec_string (NM_IP4_CONFIG_GATEWAY,
+ "Gateway",
+ "IP4 gateway",
+ NULL,
+ G_PARAM_READABLE);
+ obj_properties[PROP_ADDRESSES] =
g_param_spec_boxed (NM_IP4_CONFIG_ADDRESSES,
"Addresses",
"IP4 addresses",
DBUS_TYPE_G_ARRAY_OF_ARRAY_OF_UINT,
- G_PARAM_READABLE));
- g_object_class_install_property
- (object_class, PROP_ROUTES,
+ G_PARAM_READABLE);
+ obj_properties[PROP_ROUTES] =
g_param_spec_boxed (NM_IP4_CONFIG_ROUTES,
"Routes",
"Routes",
DBUS_TYPE_G_ARRAY_OF_ARRAY_OF_UINT,
- G_PARAM_READABLE));
- g_object_class_install_property
- (object_class, PROP_NAMESERVERS,
+ G_PARAM_READABLE);
+ obj_properties[PROP_NAMESERVERS] =
g_param_spec_boxed (NM_IP4_CONFIG_NAMESERVERS,
"Nameservers",
"DNS list",
DBUS_TYPE_G_UINT_ARRAY,
- G_PARAM_READABLE));
- g_object_class_install_property
- (object_class, PROP_DOMAINS,
+ G_PARAM_READABLE);
+ obj_properties[PROP_DOMAINS] =
g_param_spec_boxed (NM_IP4_CONFIG_DOMAINS,
"Domains",
"Domains",
DBUS_TYPE_G_ARRAY_OF_STRING,
- G_PARAM_READABLE));
- g_object_class_install_property
- (object_class, PROP_WINS_SERVERS,
+ G_PARAM_READABLE);
+ obj_properties[PROP_SEARCHES] =
+ g_param_spec_boxed (NM_IP4_CONFIG_SEARCHES,
+ "Searches",
+ "Searches",
+ DBUS_TYPE_G_ARRAY_OF_STRING,
+ G_PARAM_READABLE);
+ obj_properties[PROP_WINS_SERVERS] =
g_param_spec_boxed (NM_IP4_CONFIG_WINS_SERVERS,
"WinsServers",
"WINS server list",
DBUS_TYPE_G_UINT_ARRAY,
- G_PARAM_READABLE));
+ G_PARAM_READABLE);
+
+ g_object_class_install_properties (object_class, LAST_PROP, obj_properties);
dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (config_class), &dbus_glib_nm_ip4_config_object_info);
}
diff --git a/src/nm-ip4-config.h b/src/nm-ip4-config.h
index 5c8a4552d8..2e25fb7e30 100644
--- a/src/nm-ip4-config.h
+++ b/src/nm-ip4-config.h
@@ -41,10 +41,12 @@ typedef struct {
GObjectClass parent;
} NMIP4ConfigClass;
+#define NM_IP4_CONFIG_GATEWAY "gateway"
#define NM_IP4_CONFIG_ADDRESSES "addresses"
+#define NM_IP4_CONFIG_ROUTES "routes"
#define NM_IP4_CONFIG_NAMESERVERS "nameservers"
#define NM_IP4_CONFIG_DOMAINS "domains"
-#define NM_IP4_CONFIG_ROUTES "routes"
+#define NM_IP4_CONFIG_SEARCHES "searches"
#define NM_IP4_CONFIG_WINS_SERVERS "wins-servers"
GType nm_ip4_config_get_type (void);
diff --git a/src/nm-ip6-config.c b/src/nm-ip6-config.c
index 159d5fec5f..18f0ef8055 100644
--- a/src/nm-ip6-config.c
+++ b/src/nm-ip6-config.c
@@ -52,13 +52,17 @@ typedef struct {
enum {
PROP_0,
+ PROP_GATEWAY,
PROP_ADDRESSES,
+ PROP_ROUTES,
PROP_NAMESERVERS,
PROP_DOMAINS,
- PROP_ROUTES,
+ PROP_SEARCHES,
LAST_PROP
};
+static GParamSpec *obj_properties[LAST_PROP] = { NULL, };
+#define _NOTIFY(config, prop) G_STMT_START { g_object_notify_by_pspec (G_OBJECT (config), obj_properties[prop]); } G_STMT_END
NMIP6Config *
@@ -132,6 +136,10 @@ nm_ip6_config_capture (int ifindex)
priv->addresses = nm_platform_ip6_address_get_all (ifindex);
priv->routes = nm_platform_ip6_route_get_all (ifindex, FALSE);
+ /* actually, nobody should be connected to the signal, just to be sure, notify */
+ _NOTIFY (config, PROP_ADDRESSES);
+ _NOTIFY (config, PROP_ROUTES);
+
return config;
}
@@ -194,6 +202,8 @@ nm_ip6_config_merge_setting (NMIP6Config *config, NMSettingIP6Config *setting)
nnameservers = nm_setting_ip6_config_get_num_dns (setting);
nsearches = nm_setting_ip6_config_get_num_dns_searches (setting);
+ g_object_freeze_notify (G_OBJECT (config));
+
/* Gateway */
if (nm_setting_ip6_config_get_never_default (setting))
nm_ip6_config_set_never_default (config, TRUE);
@@ -248,6 +258,8 @@ nm_ip6_config_merge_setting (NMIP6Config *config, NMSettingIP6Config *setting)
nm_ip6_config_add_nameserver (config, nm_setting_ip6_config_get_dns (setting, i));
for (i = 0; i < nsearches; i++)
nm_ip6_config_add_search (config, nm_setting_ip6_config_get_dns_search (setting, i));
+
+ g_object_thaw_notify (G_OBJECT (config));
}
void
@@ -345,6 +357,8 @@ nm_ip6_config_merge (NMIP6Config *dst, NMIP6Config *src)
g_return_if_fail (src != NULL);
g_return_if_fail (dst != NULL);
+ g_object_freeze_notify (G_OBJECT (dst));
+
/* addresses */
for (i = 0; i < nm_ip6_config_get_num_addresses (src); i++)
nm_ip6_config_add_address (dst, nm_ip6_config_get_address (src, i));
@@ -375,6 +389,8 @@ nm_ip6_config_merge (NMIP6Config *dst, NMIP6Config *src)
if (!nm_ip6_config_get_mss (dst))
nm_ip6_config_set_mss (dst, nm_ip6_config_get_mss (src));
+
+ g_object_thaw_notify (G_OBJECT (dst));
}
gboolean
@@ -409,6 +425,8 @@ nm_ip6_config_subtract (NMIP6Config *dst, NMIP6Config *src)
g_return_if_fail (src != NULL);
g_return_if_fail (dst != NULL);
+ g_object_freeze_notify (G_OBJECT (dst));
+
/* addresses */
for (i = 0; i < nm_ip6_config_get_num_addresses (src); i++) {
const NMPlatformIP6Address *src_addr = nm_ip6_config_get_address (src, i);
@@ -493,6 +511,8 @@ nm_ip6_config_subtract (NMIP6Config *dst, NMIP6Config *src)
if (nm_ip6_config_get_mss (src) == nm_ip6_config_get_mss (dst))
nm_ip6_config_set_mss (dst, 0);
+
+ g_object_thaw_notify (G_OBJECT (dst));
}
/**
@@ -532,6 +552,8 @@ nm_ip6_config_replace (NMIP6Config *dst, NMIP6Config *src, gboolean *relevant_ch
dst_priv = NM_IP6_CONFIG_GET_PRIVATE (dst);
src_priv = NM_IP6_CONFIG_GET_PRIVATE (src);
+ g_object_freeze_notify (G_OBJECT (dst));
+
/* never_default */
if (src_priv->never_default != dst_priv->never_default) {
dst_priv->never_default = src_priv->never_default;
@@ -663,6 +685,8 @@ nm_ip6_config_replace (NMIP6Config *dst, NMIP6Config *src, gboolean *relevant_ch
* regardless of config_equal. But config_equal must correspond to has_relevant_changes. */
g_assert (config_equal == !has_relevant_changes);
+ g_object_thaw_notify (G_OBJECT (dst));
+
if (relevant_changes)
*relevant_changes = has_relevant_changes;
@@ -692,10 +716,16 @@ nm_ip6_config_set_gateway (NMIP6Config *config, const struct in6_addr *gateway)
{
NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config);
- if (gateway)
- memcpy (&priv->gateway, gateway, sizeof (priv->gateway));
- else
+ if (gateway) {
+ if (IN6_ARE_ADDR_EQUAL (&priv->gateway, gateway))
+ return;
+ priv->gateway = *gateway;
+ } else {
+ if (IN6_IS_ADDR_UNSPECIFIED (&priv->gateway))
+ return;
memset (&priv->gateway, 0, sizeof (priv->gateway));
+ }
+ _NOTIFY (config, PROP_GATEWAY);
}
const struct in6_addr *
@@ -713,7 +743,10 @@ nm_ip6_config_reset_addresses (NMIP6Config *config)
{
NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config);
- g_array_set_size (priv->addresses, 0);
+ if (priv->addresses->len != 0) {
+ g_array_set_size (priv->addresses, 0);
+ _NOTIFY (config, PROP_ADDRESSES);
+ }
}
void
@@ -728,13 +761,17 @@ nm_ip6_config_add_address (NMIP6Config *config, const NMPlatformIP6Address *new)
NMPlatformIP6Address *item = &g_array_index (priv->addresses, NMPlatformIP6Address, i);
if (IN6_ARE_ADDR_EQUAL (&item->address, &new->address)) {
+ if (nm_platform_ip6_address_cmp (item, new) == 0)
+ return;
/* Copy over old item to get new lifetime, timestamp, preferred */
- memcpy (item, new, sizeof (*item));
- return;
+ *item = *new;
+ goto NOTIFY;
}
}
g_array_append_val (priv->addresses, *new);
+NOTIFY:
+ _NOTIFY (config, PROP_ADDRESSES);
}
void
@@ -745,6 +782,7 @@ nm_ip6_config_del_address (NMIP6Config *config, guint i)
g_return_if_fail (i < priv->addresses->len);
g_array_remove_index (priv->addresses, i);
+ _NOTIFY (config, PROP_ADDRESSES);
}
guint
@@ -770,7 +808,10 @@ nm_ip6_config_reset_routes (NMIP6Config *config)
{
NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config);
- g_array_set_size (priv->routes, 0);
+ if (priv->routes->len != 0) {
+ g_array_set_size (priv->routes, 0);
+ _NOTIFY (config, PROP_ROUTES);
+ }
}
void
@@ -785,12 +826,16 @@ nm_ip6_config_add_route (NMIP6Config *config, const NMPlatformIP6Route *new)
NMPlatformIP6Route *item = &g_array_index (priv->routes, NMPlatformIP6Route, i);
if (routes_are_duplicate (item, new, FALSE)) {
- memcpy (item, new, sizeof (*item));
- return;
+ if (nm_platform_ip6_route_cmp (item, new) == 0)
+ return;
+ *item = *new;
+ goto NOTIFY;
}
}
g_array_append_val (priv->routes, *new);
+NOTIFY:
+ _NOTIFY (config, PROP_ROUTES);
}
void
@@ -801,6 +846,7 @@ nm_ip6_config_del_route (NMIP6Config *config, guint i)
g_return_if_fail (i < priv->routes->len);
g_array_remove_index (priv->routes, i);
+ _NOTIFY (config, PROP_ROUTES);
}
guint
@@ -826,7 +872,10 @@ nm_ip6_config_reset_nameservers (NMIP6Config *config)
{
NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config);
- g_array_set_size (priv->nameservers, 0);
+ if (priv->nameservers->len != 0) {
+ g_array_set_size (priv->nameservers, 0);
+ _NOTIFY (config, PROP_NAMESERVERS);
+ }
}
void
@@ -842,6 +891,7 @@ nm_ip6_config_add_nameserver (NMIP6Config *config, const struct in6_addr *new)
return;
g_array_append_val (priv->nameservers, *new);
+ _NOTIFY (config, PROP_NAMESERVERS);
}
void
@@ -852,6 +902,7 @@ nm_ip6_config_del_nameserver (NMIP6Config *config, guint i)
g_return_if_fail (i < priv->nameservers->len);
g_array_remove_index (priv->nameservers, i);
+ _NOTIFY (config, PROP_NAMESERVERS);
}
guint32
@@ -877,7 +928,10 @@ nm_ip6_config_reset_domains (NMIP6Config *config)
{
NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config);
- g_ptr_array_set_size (priv->domains, 0);
+ if (priv->domains->len != 0) {
+ g_ptr_array_set_size (priv->domains, 0);
+ _NOTIFY (config, PROP_DOMAINS);
+ }
}
void
@@ -894,6 +948,7 @@ nm_ip6_config_add_domain (NMIP6Config *config, const char *domain)
return;
g_ptr_array_add (priv->domains, g_strdup (domain));
+ _NOTIFY (config, PROP_DOMAINS);
}
void
@@ -904,6 +959,7 @@ nm_ip6_config_del_domain (NMIP6Config *config, guint i)
g_return_if_fail (i < priv->domains->len);
g_ptr_array_remove_index (priv->domains, i);
+ _NOTIFY (config, PROP_DOMAINS);
}
guint32
@@ -929,7 +985,10 @@ nm_ip6_config_reset_searches (NMIP6Config *config)
{
NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config);
- g_ptr_array_set_size (priv->searches, 0);
+ if (priv->searches->len != 0) {
+ g_ptr_array_set_size (priv->searches, 0);
+ _NOTIFY (config, PROP_SEARCHES);
+ }
}
void
@@ -946,6 +1005,7 @@ nm_ip6_config_add_search (NMIP6Config *config, const char *new)
return;
g_ptr_array_add (priv->searches, g_strdup (new));
+ _NOTIFY (config, PROP_SEARCHES);
}
void
@@ -956,6 +1016,7 @@ nm_ip6_config_del_search (NMIP6Config *config, guint i)
g_return_if_fail (i < priv->searches->len);
g_ptr_array_remove_index (priv->searches, i);
+ _NOTIFY (config, PROP_SEARCHES);
}
guint32
@@ -1163,6 +1224,13 @@ get_property (GObject *object, guint prop_id,
NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (object);
switch (prop_id) {
+ case PROP_GATEWAY:
+ if (!IN6_IS_ADDR_UNSPECIFIED (&priv->gateway)) {
+ char addr_buf[INET6_ADDRSTRLEN];
+ g_value_set_string (value, inet_ntop (AF_INET6, &priv->gateway, addr_buf, sizeof (addr_buf)));
+ } else
+ g_value_set_string (value, NULL);
+ break;
case PROP_ADDRESSES:
{
GPtrArray *addresses = g_ptr_array_new ();
@@ -1254,6 +1322,9 @@ get_property (GObject *object, guint prop_id,
case PROP_DOMAINS:
g_value_set_boxed (value, priv->domains);
break;
+ case PROP_SEARCHES:
+ g_value_set_boxed (value, priv->searches);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -1272,33 +1343,44 @@ nm_ip6_config_class_init (NMIP6ConfigClass *config_class)
object_class->finalize = finalize;
/* properties */
- g_object_class_install_property (object_class, PROP_ADDRESSES,
+ obj_properties[PROP_GATEWAY] =
+ g_param_spec_string (NM_IP6_CONFIG_GATEWAY,
+ "Gateway",
+ "IP6 Gateway",
+ NULL,
+ G_PARAM_READABLE);
+ obj_properties[PROP_ADDRESSES] =
g_param_spec_boxed (NM_IP6_CONFIG_ADDRESSES,
"Addresses",
"IP6 addresses",
DBUS_TYPE_G_ARRAY_OF_IP6_ADDRESS,
- G_PARAM_READABLE));
-
- g_object_class_install_property (object_class, PROP_NAMESERVERS,
+ G_PARAM_READABLE);
+ obj_properties[PROP_ROUTES] =
+ g_param_spec_boxed (NM_IP6_CONFIG_ROUTES,
+ "Routes",
+ "Routes",
+ DBUS_TYPE_G_ARRAY_OF_IP6_ROUTE,
+ G_PARAM_READABLE);
+ obj_properties[PROP_NAMESERVERS] =
g_param_spec_boxed (NM_IP6_CONFIG_NAMESERVERS,
"Nameservers",
"DNS list",
DBUS_TYPE_G_ARRAY_OF_ARRAY_OF_UCHAR,
- G_PARAM_READABLE));
-
- g_object_class_install_property (object_class, PROP_DOMAINS,
+ G_PARAM_READABLE);
+ obj_properties[PROP_DOMAINS] =
g_param_spec_boxed (NM_IP6_CONFIG_DOMAINS,
"Domains",
"Domains",
DBUS_TYPE_G_ARRAY_OF_STRING,
- G_PARAM_READABLE));
+ G_PARAM_READABLE);
+ obj_properties[PROP_SEARCHES] =
+ g_param_spec_boxed (NM_IP6_CONFIG_SEARCHES,
+ "Searches",
+ "Searches",
+ DBUS_TYPE_G_ARRAY_OF_STRING,
+ G_PARAM_READABLE);
- g_object_class_install_property (object_class, PROP_ROUTES,
- g_param_spec_boxed (NM_IP6_CONFIG_ROUTES,
- "Routes",
- "Routes",
- DBUS_TYPE_G_ARRAY_OF_IP6_ROUTE,
- G_PARAM_READABLE));
+ g_object_class_install_properties (object_class, LAST_PROP, obj_properties);
dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (config_class),
&dbus_glib_nm_ip6_config_object_info);
diff --git a/src/nm-ip6-config.h b/src/nm-ip6-config.h
index d0994e26cc..f4c689f68b 100644
--- a/src/nm-ip6-config.h
+++ b/src/nm-ip6-config.h
@@ -41,10 +41,12 @@ typedef struct {
GObjectClass parent;
} NMIP6ConfigClass;
+#define NM_IP6_CONFIG_GATEWAY "gateway"
#define NM_IP6_CONFIG_ADDRESSES "addresses"
+#define NM_IP6_CONFIG_ROUTES "routes"
#define NM_IP6_CONFIG_NAMESERVERS "nameservers"
#define NM_IP6_CONFIG_DOMAINS "domains"
-#define NM_IP6_CONFIG_ROUTES "routes"
+#define NM_IP6_CONFIG_SEARCHES "searches"
GType nm_ip6_config_get_type (void);
diff --git a/src/nm-policy.c b/src/nm-policy.c
index d7ac3696f9..a0eda7ad22 100644
--- a/src/nm-policy.c
+++ b/src/nm-policy.c
@@ -1524,19 +1524,23 @@ device_ip4_config_changed (NMDevice *device,
nm_dns_manager_begin_updates (priv->dns_manager, __func__);
- /* Old configs get removed immediately */
- if (old_config)
- nm_dns_manager_remove_ip4_config (priv->dns_manager, old_config);
-
/* Ignore IP config changes while the device is activating, because we'll
* catch all the changes when the device moves to ACTIVATED state.
* Prevents unecessary changes to DNS information.
*/
if (!nm_device_is_activating (device)) {
- if (new_config)
- nm_dns_manager_add_ip4_config (priv->dns_manager, ip_iface, new_config, NM_DNS_IP_CONFIG_TYPE_DEFAULT);
+ if (old_config != new_config) {
+ if (old_config)
+ nm_dns_manager_remove_ip4_config (priv->dns_manager, old_config);
+ if (new_config)
+ nm_dns_manager_add_ip4_config (priv->dns_manager, ip_iface, new_config, NM_DNS_IP_CONFIG_TYPE_DEFAULT);
+ }
update_ip4_dns (policy, priv->dns_manager);
update_ip4_routing (policy, TRUE);
+ } else {
+ /* Old configs get removed immediately */
+ if (old_config)
+ nm_dns_manager_remove_ip4_config (priv->dns_manager, old_config);
}
nm_dns_manager_end_updates (priv->dns_manager, __func__);
@@ -1554,19 +1558,23 @@ device_ip6_config_changed (NMDevice *device,
nm_dns_manager_begin_updates (priv->dns_manager, __func__);
- /* Old configs get removed immediately */
- if (old_config)
- nm_dns_manager_remove_ip6_config (priv->dns_manager, old_config);
-
/* Ignore IP config changes while the device is activating, because we'll
* catch all the changes when the device moves to ACTIVATED state.
* Prevents unecessary changes to DNS information.
*/
if (!nm_device_is_activating (device)) {
- if (new_config)
- nm_dns_manager_add_ip6_config (priv->dns_manager, ip_iface, new_config, NM_DNS_IP_CONFIG_TYPE_DEFAULT);
+ if (old_config != new_config) {
+ if (old_config)
+ nm_dns_manager_remove_ip6_config (priv->dns_manager, old_config);
+ if (new_config)
+ nm_dns_manager_add_ip6_config (priv->dns_manager, ip_iface, new_config, NM_DNS_IP_CONFIG_TYPE_DEFAULT);
+ }
update_ip6_dns (policy, priv->dns_manager);
update_ip6_routing (policy, TRUE);
+ } else {
+ /* Old configs get removed immediately */
+ if (old_config)
+ nm_dns_manager_remove_ip6_config (priv->dns_manager, old_config);
}
nm_dns_manager_end_updates (priv->dns_manager, __func__);