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>
This commit is contained in:
Thomas Haller 2013-09-06 11:56:41 +02:00
parent f0fccd99a5
commit db9b7e10ac
12 changed files with 580 additions and 159 deletions

View file

@ -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>

View file

@ -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>

View file

@ -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));
@ -217,6 +236,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:
*
@ -229,6 +263,18 @@ nm_ip4_config_class_init (NMIP4ConfigClass *config_class)
"Addresses",
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:
*
@ -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:
@ -299,6 +348,25 @@ nm_ip4_config_new (DBusGConnection *connection, const char *object_path)
NULL);
}
/**
* 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
@ -353,6 +421,26 @@ nm_ip4_config_get_domains (NMIP4Config *config)
return handle_ptr_array_return (NM_IP4_CONFIG_GET_PRIVATE (config)->domains);
}
/**
* 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

View file

@ -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

View file

@ -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
};
@ -108,6 +112,16 @@ demarshal_domains (NMObject *object, GParamSpec *pspec, GValue *value, gpointer
return TRUE;
}
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)
{
@ -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 },
};
@ -140,6 +156,25 @@ register_properties (NMIP6Config *config)
property_info);
}
/**
* 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
@ -197,6 +232,26 @@ nm_ip6_config_get_domains (NMIP6Config *config)
return handle_ptr_array_return (NM_IP6_CONFIG_GET_PRIVATE (config)->domains);
}
/**
* 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);
@ -300,6 +368,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:
*
@ -315,6 +398,21 @@ nm_ip6_config_class_init (NMIP6ConfigClass *config_class)
NM_TYPE_IP6_ADDRESS_OBJECT_ARRAY,
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:
*
@ -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));
}

View file

@ -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

View file

@ -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)
g_object_unref (old_config);
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 (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 (new_config) {
priv->ip6_config = g_object_ref (new_config);
if (success || !commit) {
/* Export over D-Bus */
if (!nm_ip6_config_get_dbus_path (new_config))
nm_ip6_config_export (new_config);
}
if (!success && reason)
*reason = NM_DEVICE_STATE_REASON_CONFIG_FAILED;
if (!success)
reason_local = NM_DEVICE_STATE_REASON_CONFIG_FAILED;
}
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 (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 (old_config)
g_object_unref (old_config);
if (success && !nm_ip6_config_get_dbus_path (new_config)) {
/* Export over D-Bus */
nm_ip6_config_export (new_config);
}
}
} 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));
}
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 (reason)
*reason = reason_local;
return success;
}

View file

@ -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);
}

View file

@ -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);

View file

@ -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_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_spec_boxed (NM_IP6_CONFIG_DOMAINS,
"Domains",
"Domains",
DBUS_TYPE_G_ARRAY_OF_STRING,
G_PARAM_READABLE));
g_object_class_install_property (object_class, PROP_ROUTES,
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));
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);
obj_properties[PROP_DOMAINS] =
g_param_spec_boxed (NM_IP6_CONFIG_DOMAINS,
"Domains",
"Domains",
DBUS_TYPE_G_ARRAY_OF_STRING,
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_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);

View file

@ -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);

View file

@ -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__);