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 @@ + + The gateway in use. + 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), ...] - - The nameservers in use. - - - The Windows Internet Name Service servers associated with the connection. Each address is in network byte order. - - - A list of domains this address belongs to. - 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), ...] + + The nameservers in use. + + + A list of domains this address belongs to. + + + A list of dns searches. + + + The Windows Internet Name Service servers associated with the connection. Each address is in network byte order. + 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 @@ + + The gateway in use. + Tuples of IPv6 address/prefix/gateway. + + Tuples of IPv6 route/prefix/next-hop/metric. + The nameservers in use. A list of domains this address belongs to. - - Tuples of IPv6 route/prefix/next-hop/metric. + + A list of dns searches. 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)); @@ -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 #NMSettingIP4Routes 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 #NMSettingIP4Routes 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 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 }; @@ -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)); + } 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) - 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; } 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_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); 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__);