diff options
Diffstat (limited to 'src/nm-policy.c')
| -rw-r--r-- | src/nm-policy.c | 637 |
1 files changed, 437 insertions, 200 deletions
diff --git a/src/nm-policy.c b/src/nm-policy.c index 38a03613..e8e7c606 100644 --- a/src/nm-policy.c +++ b/src/nm-policy.c @@ -43,7 +43,7 @@ #include "nm-dispatcher.h" #include "nm-utils.h" -struct NMPolicy { +typedef struct { NMManager *manager; guint update_state_id; GSList *pending_activation_checks; @@ -58,8 +58,8 @@ struct NMPolicy { NMSettings *settings; - NMDevice *default_device4; - NMDevice *default_device6; + NMDevice *default_device4, *activating_device4; + NMDevice *default_device6, *activating_device6; HostnameThread *lookup; guint32 lookup_ipv4_addr; /* IPv4 for reverse lookup */ @@ -72,6 +72,19 @@ struct NMPolicy { char *orig_hostname; /* hostname at NM start time */ char *cur_hostname; /* hostname we want to assign */ gboolean hostname_changed; /* TRUE if NM ever set the hostname */ +} NMPolicyPrivate; + +#define NM_POLICY_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_POLICY, NMPolicyPrivate)) + +G_DEFINE_TYPE (NMPolicy, nm_policy, G_TYPE_OBJECT) + +enum { + PROP_0, + + PROP_DEFAULT_IP4_DEVICE, + PROP_DEFAULT_IP6_DEVICE, + PROP_ACTIVATING_IP4_DEVICE, + PROP_ACTIVATING_IP6_DEVICE }; #define RETRIES_TAG "autoconnect-retries" @@ -84,7 +97,7 @@ static void schedule_activate_all (NMPolicy *policy); static NMDevice * -get_best_ip4_device (NMManager *manager) +get_best_ip4_device (NMManager *manager, gboolean fully_activated) { GSList *devices, *iter; NMDevice *best = NULL; @@ -97,6 +110,7 @@ get_best_ip4_device (NMManager *manager) for (iter = devices; iter; iter = g_slist_next (iter)) { NMDevice *dev = NM_DEVICE (iter->data); NMDeviceType devtype = nm_device_get_device_type (dev); + NMDeviceState state = nm_device_get_state (dev); NMActRequest *req; NMConnection *connection; NMIP4Config *ip4_config; @@ -106,12 +120,33 @@ get_best_ip4_device (NMManager *manager) gboolean can_default = FALSE; const char *method = NULL; - if ( nm_device_get_state (dev) != NM_DEVICE_STATE_ACTIVATED - && nm_device_get_state (dev) != NM_DEVICE_STATE_SECONDARIES) + if ( state <= NM_DEVICE_STATE_DISCONNECTED + || state >= NM_DEVICE_STATE_DEACTIVATING) + continue; + + if (fully_activated && state < NM_DEVICE_STATE_SECONDARIES) continue; ip4_config = nm_device_get_ip4_config (dev); - if (!ip4_config) + if (ip4_config) { + /* Make sure at least one of this device's IP addresses has a gateway */ + for (i = 0; i < nm_ip4_config_get_num_addresses (ip4_config); i++) { + NMIP4Address *addr; + + addr = nm_ip4_config_get_address (ip4_config, i); + if (nm_ip4_address_get_gateway (addr)) { + can_default = TRUE; + break; + } + } + + if (!can_default && (devtype != NM_DEVICE_TYPE_MODEM)) + continue; + + /* 'never-default' devices can't ever be the default */ + if (nm_ip4_config_get_never_default (ip4_config)) + continue; + } else if (fully_activated) continue; req = nm_device_get_act_request (dev); @@ -119,33 +154,18 @@ get_best_ip4_device (NMManager *manager) connection = nm_act_request_get_connection (req); g_assert (connection); - /* Never set the default route through an IPv4LL-addressed device */ s_ip4 = nm_connection_get_setting_ip4_config (connection); - if (s_ip4) + if (s_ip4) { + /* Never set the default route through an IPv4LL-addressed device */ method = nm_setting_ip4_config_get_method (s_ip4); + if (!strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL)) + continue; - if (s_ip4 && !strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL)) - continue; - - /* Make sure at least one of this device's IP addresses has a gateway */ - for (i = 0; i < nm_ip4_config_get_num_addresses (ip4_config); i++) { - NMIP4Address *addr; - - addr = nm_ip4_config_get_address (ip4_config, i); - if (nm_ip4_address_get_gateway (addr)) { - can_default = TRUE; - break; - } + /* 'never-default' devices can't ever be the default */ + if (nm_setting_ip4_config_get_never_default (s_ip4)) + continue; } - if (!can_default && (devtype != NM_DEVICE_TYPE_MODEM)) - continue; - - /* 'never-default' devices can't ever be the default */ - if ( (s_ip4 && nm_setting_ip4_config_get_never_default (s_ip4)) - || nm_ip4_config_get_never_default (ip4_config)) - continue; - prio = nm_device_get_priority (dev); if (prio > 0 && prio < best_prio) { best = dev; @@ -153,11 +173,25 @@ get_best_ip4_device (NMManager *manager) } } + if (!best) + return NULL; + + if (!fully_activated) { + NMDeviceState state = nm_device_get_state (best); + + /* There's only a best activating device if the best device + * among all activating and already-activated devices is a + * still-activating one. + */ + if (state >= NM_DEVICE_STATE_SECONDARIES) + return NULL; + } + return best; } static NMDevice * -get_best_ip6_device (NMManager *manager) +get_best_ip6_device (NMManager *manager, gboolean fully_activated) { GSList *devices, *iter; NMDevice *best = NULL; @@ -170,6 +204,7 @@ get_best_ip6_device (NMManager *manager) for (iter = devices; iter; iter = g_slist_next (iter)) { NMDevice *dev = NM_DEVICE (iter->data); NMDeviceType devtype = nm_device_get_device_type (dev); + NMDeviceState state = nm_device_get_state (dev); NMActRequest *req; NMConnection *connection; NMIP6Config *ip6_config; @@ -179,12 +214,31 @@ get_best_ip6_device (NMManager *manager) gboolean can_default = FALSE; const char *method = NULL; - if ( nm_device_get_state (dev) != NM_DEVICE_STATE_ACTIVATED - && nm_device_get_state (dev) != NM_DEVICE_STATE_SECONDARIES) + if ( state <= NM_DEVICE_STATE_DISCONNECTED + || state >= NM_DEVICE_STATE_DEACTIVATING) + continue; + + if (fully_activated && state < NM_DEVICE_STATE_SECONDARIES) continue; ip6_config = nm_device_get_ip6_config (dev); - if (!ip6_config) + if (ip6_config) { + for (i = 0; i < nm_ip6_config_get_num_addresses (ip6_config); i++) { + NMIP6Address *addr; + + addr = nm_ip6_config_get_address (ip6_config, i); + if (nm_ip6_address_get_gateway (addr)) { + can_default = TRUE; + break; + } + } + + if (!can_default && (devtype != NM_DEVICE_TYPE_MODEM)) + continue; + + if (nm_ip6_config_get_never_default (ip6_config)) + continue; + } else if (fully_activated) continue; req = nm_device_get_act_request (dev); @@ -192,32 +246,16 @@ get_best_ip6_device (NMManager *manager) connection = nm_act_request_get_connection (req); g_assert (connection); - /* Never set the default route through an IPv4LL-addressed device */ s_ip6 = nm_connection_get_setting_ip6_config (connection); - if (s_ip6) + if (s_ip6) { method = nm_setting_ip6_config_get_method (s_ip6); + if (!strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL)) + continue; - if (method && !strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL)) - continue; - - /* Make sure at least one of this device's IP addresses has a gateway */ - for (i = 0; i < nm_ip6_config_get_num_addresses (ip6_config); i++) { - NMIP6Address *addr; - - addr = nm_ip6_config_get_address (ip6_config, i); - if (nm_ip6_address_get_gateway (addr)) { - can_default = TRUE; - break; - } + if (nm_setting_ip6_config_get_never_default (s_ip6)) + continue; } - if (!can_default && (devtype != NM_DEVICE_TYPE_MODEM)) - continue; - - /* 'never-default' devices can't ever be the default */ - if (s_ip6 && nm_setting_ip6_config_get_never_default (s_ip6)) - continue; - prio = nm_device_get_priority (dev); if (prio > 0 && prio < best_prio) { best = dev; @@ -225,6 +263,20 @@ get_best_ip6_device (NMManager *manager) } } + if (!best) + return NULL; + + if (!fully_activated) { + NMDeviceState state = nm_device_get_state (best); + + /* There's only a best activating device if the best device + * among all activating and already-activated devices is an + * activating one. + */ + if (state >= NM_DEVICE_STATE_SECONDARIES) + return NULL; + } + return best; } @@ -233,6 +285,8 @@ _set_hostname (NMPolicy *policy, const char *new_hostname, const char *msg) { + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); + /* The incoming hostname *can* be NULL, which will get translated to * 'localhost.localdomain' or such in the hostname policy code, but we * keep cur_hostname = NULL in the case because we need to know that @@ -243,32 +297,32 @@ _set_hostname (NMPolicy *policy, * restart reverse lookup thread later. */ if (new_hostname) { - policy->lookup_ipv4_addr = 0; - g_free (policy->lookup_ipv6_addr); - policy->lookup_ipv6_addr = NULL; + priv->lookup_ipv4_addr = 0; + g_free (priv->lookup_ipv6_addr); + priv->lookup_ipv6_addr = NULL; } /* Don't change the hostname or update DNS this is the first time we're * trying to change the hostname, and it's not actually changing. */ - if ( policy->orig_hostname - && (policy->hostname_changed == FALSE) - && g_strcmp0 (policy->orig_hostname, new_hostname) == 0) + if ( priv->orig_hostname + && (priv->hostname_changed == FALSE) + && g_strcmp0 (priv->orig_hostname, new_hostname) == 0) return; /* Don't change the hostname or update DNS if the hostname isn't actually * going to change. */ - if (g_strcmp0 (policy->cur_hostname, new_hostname) == 0) + if (g_strcmp0 (priv->cur_hostname, new_hostname) == 0) return; - g_free (policy->cur_hostname); - policy->cur_hostname = g_strdup (new_hostname); - policy->hostname_changed = TRUE; + g_free (priv->cur_hostname); + priv->cur_hostname = g_strdup (new_hostname); + priv->hostname_changed = TRUE; - nm_dns_manager_set_hostname (policy->dns_manager, policy->cur_hostname); + nm_dns_manager_set_hostname (priv->dns_manager, priv->cur_hostname); - if (nm_policy_set_system_hostname (policy->cur_hostname, msg)) + if (nm_policy_set_system_hostname (priv->cur_hostname, msg)) nm_dispatcher_call (DISPATCHER_ACTION_HOSTNAME, NULL, NULL, NULL, NULL); } @@ -279,11 +333,12 @@ lookup_callback (HostnameThread *thread, gpointer user_data) { NMPolicy *policy = (NMPolicy *) user_data; + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); char *msg; /* Update the hostname if the calling lookup thread is the in-progress one */ - if (!hostname_thread_is_dead (thread) && (thread == policy->lookup)) { - policy->lookup = NULL; + if (!hostname_thread_is_dead (thread) && (thread == priv->lookup)) { + priv->lookup = NULL; if (!hostname) { /* Fall back to localhost.localdomain */ msg = g_strdup_printf ("address lookup failed: %d", result); @@ -298,14 +353,15 @@ lookup_callback (HostnameThread *thread, static void update_system_hostname (NMPolicy *policy, NMDevice *best4, NMDevice *best6) { + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); char *configured_hostname = NULL; const char *dhcp_hostname, *p; g_return_if_fail (policy != NULL); - if (policy->lookup) { - hostname_thread_kill (policy->lookup); - policy->lookup = NULL; + if (priv->lookup) { + hostname_thread_kill (priv->lookup); + priv->lookup = NULL; } /* Hostname precedence order: @@ -318,7 +374,7 @@ update_system_hostname (NMPolicy *policy, NMDevice *best4, NMDevice *best6) */ /* Try a persistent hostname first */ - g_object_get (G_OBJECT (policy->manager), NM_MANAGER_HOSTNAME, &configured_hostname, NULL); + g_object_get (G_OBJECT (priv->manager), NM_MANAGER_HOSTNAME, &configured_hostname, NULL); if (configured_hostname) { _set_hostname (policy, configured_hostname, "from system configuration"); g_free (configured_hostname); @@ -327,15 +383,15 @@ update_system_hostname (NMPolicy *policy, NMDevice *best4, NMDevice *best6) /* Try automatically determined hostname from the best device's IP config */ if (!best4) - best4 = get_best_ip4_device (policy->manager); + best4 = get_best_ip4_device (priv->manager, TRUE); if (!best6) - best6 = get_best_ip6_device (policy->manager); + best6 = get_best_ip6_device (priv->manager, TRUE); if (!best4 && !best6) { /* No best device; fall back to original hostname or if there wasn't * one, 'localhost.localdomain' */ - _set_hostname (policy, policy->orig_hostname, "no default device"); + _set_hostname (policy, priv->orig_hostname, "no default device"); return; } @@ -382,8 +438,8 @@ update_system_hostname (NMPolicy *policy, NMDevice *best4, NMDevice *best6) /* If no automatically-configured hostname, try using the hostname from * when NM started up. */ - if (policy->orig_hostname) { - _set_hostname (policy, policy->orig_hostname, "from system startup"); + if (priv->orig_hostname) { + _set_hostname (policy, priv->orig_hostname, "from system startup"); return; } @@ -407,8 +463,8 @@ update_system_hostname (NMPolicy *policy, NMDevice *best4, NMDevice *best6) g_assert (addr4); /* checked for > 1 address above */ /* Start the hostname lookup thread */ - policy->lookup_ipv4_addr = nm_ip4_address_get_address (addr4); - policy->lookup = hostname4_thread_new (policy->lookup_ipv4_addr, lookup_callback, policy); + priv->lookup_ipv4_addr = nm_ip4_address_get_address (addr4); + priv->lookup = hostname4_thread_new (priv->lookup_ipv4_addr, lookup_callback, policy); } else if (best6) { NMIP6Config *ip6_config; NMIP6Address *addr6; @@ -426,12 +482,12 @@ update_system_hostname (NMPolicy *policy, NMDevice *best4, NMDevice *best6) g_assert (addr6); /* checked for > 1 address above */ /* Start the hostname lookup thread */ - policy->lookup_ipv6_addr = g_malloc0 (sizeof (struct in6_addr)); - memcpy (policy->lookup_ipv6_addr, nm_ip6_address_get_address (addr6), sizeof (struct in6_addr)); - policy->lookup = hostname6_thread_new (policy->lookup_ipv6_addr, lookup_callback, policy); + priv->lookup_ipv6_addr = g_malloc0 (sizeof (struct in6_addr)); + memcpy (priv->lookup_ipv6_addr, nm_ip6_address_get_address (addr6), sizeof (struct in6_addr)); + priv->lookup = hostname6_thread_new (priv->lookup_ipv6_addr, lookup_callback, policy); } - if (!policy->lookup) { + if (!priv->lookup) { /* Fall back to 'localhost.localdomain' */ _set_hostname (policy, NULL, "error starting hostname thread"); } @@ -442,13 +498,14 @@ update_default_ac (NMPolicy *policy, NMActiveConnection *best, void (*set_active_func)(NMActiveConnection*, gboolean)) { + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); const GSList *connections, *iter; /* Clear the 'default[6]' flag on all active connections that aren't the new * default active connection. We'll set the new default after; this ensures * we don't ever have two marked 'default[6]' simultaneously. */ - connections = nm_manager_get_active_connections (policy->manager); + connections = nm_manager_get_active_connections (priv->manager); for (iter = connections; iter; iter = g_slist_next (iter)) { if (NM_ACTIVE_CONNECTION (iter->data) != best) set_active_func (NM_ACTIVE_CONNECTION (iter->data), FALSE); @@ -468,13 +525,14 @@ get_best_ip4_config (NMPolicy *policy, NMDevice **out_device, NMVPNConnection **out_vpn) { + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); const GSList *connections, *iter; NMDevice *device; NMActRequest *req = NULL; NMIP4Config *ip4_config = NULL; /* If a VPN connection is active, it is preferred */ - connections = nm_manager_get_active_connections (policy->manager); + connections = nm_manager_get_active_connections (priv->manager); for (iter = connections; iter; iter = g_slist_next (iter)) { NMActiveConnection *active = NM_ACTIVE_CONNECTION (iter->data); NMVPNConnection *candidate; @@ -524,7 +582,7 @@ get_best_ip4_config (NMPolicy *policy, /* If no VPN connections, we use the best device instead */ if (!ip4_config) { - device = get_best_ip4_device (policy->manager); + device = get_best_ip4_device (priv->manager, TRUE); if (device) { ip4_config = nm_device_get_ip4_config (device); g_assert (ip4_config); @@ -568,6 +626,7 @@ update_ip4_dns (NMPolicy *policy, NMDnsManager *dns_mgr) static void update_ip4_routing (NMPolicy *policy, gboolean force_update) { + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); NMDevice *best = NULL, *parent; NMConnection *connection = NULL; NMVPNConnection *vpn = NULL; @@ -583,12 +642,18 @@ update_ip4_routing (NMPolicy *policy, gboolean force_update) */ ip4_config = get_best_ip4_config (policy, FALSE, &ip_iface, &ip_ifindex, &best_ac, &best, &vpn); if (!ip4_config) { - policy->default_device4 = NULL; + gboolean changed; + + changed = (priv->default_device4 != NULL); + priv->default_device4 = NULL; + if (changed) + g_object_notify (G_OBJECT (policy), NM_POLICY_DEFAULT_IP4_DEVICE); + return; } g_assert ((best || vpn) && best_ac); - if (!force_update && best && (best == policy->default_device4)) + if (!force_update && best && (best == priv->default_device4)) return; /* We set the default route to the first gateway we find. If we don't find @@ -622,11 +687,12 @@ update_ip4_routing (NMPolicy *policy, gboolean force_update) } update_default_ac (policy, best_ac, nm_active_connection_set_default); - policy->default_device4 = best; + priv->default_device4 = best; connection = nm_active_connection_get_connection (best_ac); nm_log_info (LOGD_CORE, "Policy set '%s' (%s) as default for IPv4 routing and DNS.", nm_connection_get_id (connection), ip_iface); + g_object_notify (G_OBJECT (policy), NM_POLICY_DEFAULT_IP4_DEVICE); } static NMIP6Config * @@ -638,13 +704,14 @@ get_best_ip6_config (NMPolicy *policy, NMDevice **out_device, NMVPNConnection **out_vpn) { + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); const GSList *connections, *iter; NMDevice *device; NMActRequest *req = NULL; NMIP6Config *ip6_config = NULL; /* If a VPN connection is active, it is preferred */ - connections = nm_manager_get_active_connections (policy->manager); + connections = nm_manager_get_active_connections (priv->manager); for (iter = connections; iter; iter = g_slist_next (iter)) { NMActiveConnection *active = NM_ACTIVE_CONNECTION (iter->data); NMVPNConnection *candidate; @@ -694,7 +761,7 @@ get_best_ip6_config (NMPolicy *policy, /* If no VPN connections, we use the best device instead */ if (!ip6_config) { - device = get_best_ip6_device (policy->manager); + device = get_best_ip6_device (priv->manager, TRUE); if (device) { req = nm_device_get_act_request (device); g_assert (req); @@ -738,6 +805,7 @@ update_ip6_dns (NMPolicy *policy, NMDnsManager *dns_mgr) static void update_ip6_routing (NMPolicy *policy, gboolean force_update) { + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); NMDevice *best = NULL, *parent; NMConnection *connection = NULL; NMVPNConnection *vpn = NULL; @@ -754,12 +822,18 @@ update_ip6_routing (NMPolicy *policy, gboolean force_update) */ ip6_config = get_best_ip6_config (policy, FALSE, &ip_iface, &ip_ifindex, &best_ac, &best, &vpn); if (!ip6_config) { - policy->default_device6 = NULL; + gboolean changed; + + changed = (priv->default_device6 != NULL); + priv->default_device6 = NULL; + if (changed) + g_object_notify (G_OBJECT (policy), NM_POLICY_DEFAULT_IP6_DEVICE); + return; } g_assert ((best || vpn) && best_ac); - if (!force_update && best && (best == policy->default_device6)) + if (!force_update && best && (best == priv->default_device6)) return; /* If no better gateway is found, use ::; not all configurations will @@ -802,16 +876,18 @@ update_ip6_routing (NMPolicy *policy, gboolean force_update) } update_default_ac (policy, best_ac, nm_active_connection_set_default6); - policy->default_device6 = best; + priv->default_device6 = best; connection = nm_active_connection_get_connection (best_ac); nm_log_info (LOGD_CORE, "Policy set '%s' (%s) as default for IPv6 routing and DNS.", nm_connection_get_id (connection), ip_iface); + g_object_notify (G_OBJECT (policy), NM_POLICY_DEFAULT_IP6_DEVICE); } static void update_routing_and_dns (NMPolicy *policy, gboolean force_update) { + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); NMDnsManager *mgr; mgr = nm_dns_manager_get (NULL); @@ -824,13 +900,37 @@ update_routing_and_dns (NMPolicy *policy, gboolean force_update) update_ip6_routing (policy, force_update); /* Update the system hostname */ - update_system_hostname (policy, policy->default_device4, policy->default_device6); + update_system_hostname (policy, priv->default_device4, priv->default_device6); nm_dns_manager_end_updates (mgr, __func__); g_object_unref (mgr); } static void +check_activating_devices (NMPolicy *policy) +{ + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); + GObject *object = G_OBJECT (policy); + NMDevice *best4, *best6 = NULL; + + best4 = get_best_ip4_device (priv->manager, FALSE); + best6 = get_best_ip6_device (priv->manager, FALSE); + + g_object_freeze_notify (object); + + if (best4 != priv->activating_device4) { + priv->activating_device4 = best4; + g_object_notify (object, NM_POLICY_ACTIVATING_IP4_DEVICE); + } + if (best6 != priv->activating_device6) { + priv->activating_device6 = best6; + g_object_notify (object, NM_POLICY_ACTIVATING_IP6_DEVICE); + } + + g_object_thaw_notify (object); +} + +static void set_connection_auto_retries (NMConnection *connection, guint retries) { /* add +1 so that the tag still exists if the # retries is 0 */ @@ -865,15 +965,17 @@ auto_activate_device (gpointer user_data) { ActivateData *data = (ActivateData *) user_data; NMPolicy *policy; + NMPolicyPrivate *priv; NMConnection *best_connection; char *specific_object = NULL; GSList *connections, *iter; g_assert (data); policy = data->policy; + priv = NM_POLICY_GET_PRIVATE (policy); data->id = 0; - policy->pending_activation_checks = g_slist_remove (policy->pending_activation_checks, data); + priv->pending_activation_checks = g_slist_remove (priv->pending_activation_checks, data); // FIXME: if a device is already activating (or activated) with a connection // but another connection now overrides the current one for that device, @@ -882,7 +984,7 @@ auto_activate_device (gpointer user_data) if (nm_device_get_act_request (data->device)) goto out; - iter = connections = nm_settings_get_connections (policy->settings); + iter = connections = nm_settings_get_connections (priv->settings); /* Remove connections that shouldn't be auto-activated */ while (iter) { @@ -918,7 +1020,7 @@ auto_activate_device (gpointer user_data) nm_log_info (LOGD_DEVICE, "Auto-activating connection '%s'.", nm_connection_get_id (best_connection)); - if (!nm_manager_activate_connection (policy->manager, + if (!nm_manager_activate_connection (priv->manager, best_connection, specific_object, nm_device_get_path (data->device), @@ -998,6 +1100,7 @@ process_secondaries (NMPolicy *policy, NMActiveConnection *active, gboolean connected) { + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); NMDevice *device = NULL; const char *ac_path; GSList *iter, *iter2; @@ -1012,7 +1115,7 @@ process_secondaries (NMPolicy *policy, if (NM_IS_VPN_CONNECTION (active)) device = nm_vpn_connection_get_parent_device (NM_VPN_CONNECTION (active)); - for (iter = policy->pending_secondaries; iter; iter = g_slist_next (iter)) { + for (iter = priv->pending_secondaries; iter; iter = g_slist_next (iter)) { PendingSecondaryData *secondary_data = (PendingSecondaryData *) iter->data; NMDevice *item_device = secondary_data->device; @@ -1027,14 +1130,14 @@ process_secondaries (NMPolicy *policy, g_free (list_ac_path); if (!secondary_data->secondaries) { /* None secondary UUID remained -> remove the secondary data item */ - policy->pending_secondaries = g_slist_remove (policy->pending_secondaries, secondary_data); + priv->pending_secondaries = g_slist_remove (priv->pending_secondaries, secondary_data); pending_secondary_data_free (secondary_data); nm_device_state_changed (item_device, NM_DEVICE_STATE_ACTIVATED, NM_DEVICE_STATE_REASON_NONE); return; } } else { /* Secondary connection failed -> do not watch other connections */ - policy->pending_secondaries = g_slist_remove (policy->pending_secondaries, secondary_data); + priv->pending_secondaries = g_slist_remove (priv->pending_secondaries, secondary_data); pending_secondary_data_free (secondary_data); nm_device_state_changed (item_device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_SECONDARY_CONNECTION_FAILED); @@ -1094,6 +1197,7 @@ static void sleeping_changed (NMManager *manager, GParamSpec *pspec, gpointer user_data) { NMPolicy *policy = user_data; + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); gboolean sleeping = FALSE, enabled = FALSE; g_object_get (G_OBJECT (manager), NM_MANAGER_SLEEPING, &sleeping, NULL); @@ -1101,16 +1205,17 @@ sleeping_changed (NMManager *manager, GParamSpec *pspec, gpointer user_data) /* Reset retries on all connections so they'll checked on wakeup */ if (sleeping || !enabled) - reset_retries_all (policy->settings, NULL); + reset_retries_all (priv->settings, NULL); } static void schedule_activate_check (NMPolicy *policy, NMDevice *device, guint delay_seconds) { + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); ActivateData *data; NMDeviceState state; - if (nm_manager_get_state (policy->manager) == NM_STATE_ASLEEP) + if (nm_manager_get_state (priv->manager) == NM_STATE_ASLEEP) return; state = nm_device_get_state (device); @@ -1124,9 +1229,9 @@ schedule_activate_check (NMPolicy *policy, NMDevice *device, guint delay_seconds return; /* Schedule an auto-activation if there isn't one already for this device */ - if (find_pending_activation (policy->pending_activation_checks, device) == NULL) { + if (find_pending_activation (priv->pending_activation_checks, device) == NULL) { data = activate_data_new (policy, device, delay_seconds); - policy->pending_activation_checks = g_slist_append (policy->pending_activation_checks, data); + priv->pending_activation_checks = g_slist_append (priv->pending_activation_checks, data); } } @@ -1134,14 +1239,15 @@ static gboolean reset_connections_retries (gpointer user_data) { NMPolicy *policy = (NMPolicy *) user_data; + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); GSList *connections, *iter; time_t con_stamp, min_stamp, now; gboolean changed = FALSE; - policy->reset_retries_id = 0; + priv->reset_retries_id = 0; min_stamp = now = time (NULL); - connections = nm_settings_get_connections (policy->settings); + connections = nm_settings_get_connections (priv->settings); for (iter = connections; iter; iter = g_slist_next (iter)) { con_stamp = GPOINTER_TO_SIZE (g_object_get_data (G_OBJECT (iter->data), RESET_RETRIES_TIMESTAMP_TAG)); if (con_stamp == 0) @@ -1159,7 +1265,7 @@ reset_connections_retries (gpointer user_data) /* Schedule the handler again if there are some stamps left */ if (min_stamp != now) - policy->reset_retries_id = g_timeout_add_seconds (RESET_RETRIES_TIMER - (now - min_stamp), reset_connections_retries, policy); + priv->reset_retries_id = g_timeout_add_seconds (RESET_RETRIES_TIMER - (now - min_stamp), reset_connections_retries, policy); /* If anything changed, try to activate the newly re-enabled connections */ if (changed) @@ -1174,13 +1280,14 @@ static void activate_slave_connections (NMPolicy *policy, NMConnection *connection, NMDevice *device) { + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); const char *master_device; GSList *connections, *iter; master_device = nm_device_get_iface (device); g_assert (master_device); - connections = nm_settings_get_connections (policy->settings); + connections = nm_settings_get_connections (priv->settings); for (iter = connections; iter; iter = g_slist_next (iter)) { NMConnection *slave; NMSettingConnection *s_slave_con; @@ -1205,6 +1312,7 @@ activate_secondary_connections (NMPolicy *policy, NMConnection *connection, NMDevice *device) { + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); NMSettingConnection *s_con; NMSettingsConnection *settings_con; NMActiveConnection *ac; @@ -1220,7 +1328,7 @@ activate_secondary_connections (NMPolicy *policy, for (i = 0; i < nm_setting_connection_get_num_secondaries (s_con); i++) { const char *sec_uuid = nm_setting_connection_get_secondary (s_con, i); - settings_con = nm_settings_get_connection_by_uuid (policy->settings, sec_uuid); + settings_con = nm_settings_get_connection_by_uuid (priv->settings, sec_uuid); if (settings_con) { NMActRequest *req = nm_device_get_act_request (device); g_assert (req); @@ -1228,7 +1336,7 @@ activate_secondary_connections (NMPolicy *policy, nm_log_dbg (LOGD_DEVICE, "Activating secondary connection '%s (%s)' for base connection '%s (%s)'", nm_connection_get_id (NM_CONNECTION (settings_con)), sec_uuid, nm_connection_get_id (connection), nm_connection_get_uuid (connection)); - ac = nm_manager_activate_connection (policy->manager, + ac = nm_manager_activate_connection (priv->manager, NM_CONNECTION (settings_con), nm_active_connection_get_path (NM_ACTIVE_CONNECTION (req)), nm_device_get_path (device), @@ -1256,7 +1364,7 @@ activate_secondary_connections (NMPolicy *policy, if (success && secondary_ac_list != NULL) { secondary_data = pending_secondary_data_new (device, secondary_ac_list); - policy->pending_secondaries = g_slist_append (policy->pending_secondaries, secondary_data); + priv->pending_secondaries = g_slist_append (priv->pending_secondaries, secondary_data); } else nm_utils_slist_free (secondary_ac_list, g_free); @@ -1271,6 +1379,7 @@ device_state_changed (NMDevice *device, gpointer user_data) { NMPolicy *policy = (NMPolicy *) user_data; + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); NMConnection *connection = nm_device_get_connection (device); const char *ip_iface = nm_device_get_ip_iface (device); NMIP4Config *ip4_config; @@ -1313,8 +1422,8 @@ device_state_changed (NMDevice *device, nm_log_info (LOGD_DEVICE, "Marking connection '%s' invalid.", nm_connection_get_id (connection)); /* Schedule a handler to reset retries count */ g_object_set_data (G_OBJECT (connection), RESET_RETRIES_TIMESTAMP_TAG, GSIZE_TO_POINTER ((gsize) time (NULL))); - if (!policy->reset_retries_id) - policy->reset_retries_id = g_timeout_add_seconds (RESET_RETRIES_TIMER, reset_connections_retries, policy); + if (!priv->reset_retries_id) + priv->reset_retries_id = g_timeout_add_seconds (RESET_RETRIES_TIMER, reset_connections_retries, policy); } nm_connection_clear_secrets (connection); } @@ -1333,18 +1442,18 @@ device_state_changed (NMDevice *device, /* Add device's new IPv4 and IPv6 configs to DNS */ - nm_dns_manager_begin_updates (policy->dns_manager, __func__); + nm_dns_manager_begin_updates (priv->dns_manager, __func__); ip4_config = nm_device_get_ip4_config (device); if (ip4_config) - nm_dns_manager_add_ip4_config (policy->dns_manager, ip_iface, ip4_config, NM_DNS_IP_CONFIG_TYPE_DEFAULT); + nm_dns_manager_add_ip4_config (priv->dns_manager, ip_iface, ip4_config, NM_DNS_IP_CONFIG_TYPE_DEFAULT); ip6_config = nm_device_get_ip6_config (device); if (ip6_config) - nm_dns_manager_add_ip6_config (policy->dns_manager, ip_iface, ip6_config, NM_DNS_IP_CONFIG_TYPE_DEFAULT); + nm_dns_manager_add_ip6_config (priv->dns_manager, ip_iface, ip6_config, NM_DNS_IP_CONFIG_TYPE_DEFAULT); update_routing_and_dns (policy, FALSE); - nm_dns_manager_end_updates (policy->dns_manager, __func__); + nm_dns_manager_end_updates (priv->dns_manager, __func__); break; case NM_DEVICE_STATE_UNMANAGED: case NM_DEVICE_STATE_UNAVAILABLE: @@ -1355,7 +1464,7 @@ device_state_changed (NMDevice *device, /* Reset RETRIES_TAG when carrier on. If cable was unplugged * and plugged again, we should try to reconnect */ if (reason == NM_DEVICE_STATE_REASON_CARRIER && old_state == NM_DEVICE_STATE_UNAVAILABLE) - reset_retries_all (policy->settings, device); + reset_retries_all (priv->settings, device); if (old_state > NM_DEVICE_STATE_DISCONNECTED) update_routing_and_dns (policy, FALSE); @@ -1387,6 +1496,8 @@ device_state_changed (NMDevice *device, default: break; } + + check_activating_devices (policy); } static void @@ -1396,14 +1507,15 @@ device_ip4_config_changed (NMDevice *device, gpointer user_data) { NMPolicy *policy = user_data; + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); const char *ip_iface = nm_device_get_ip_iface (device); NMIP4ConfigCompareFlags diff = NM_IP4_COMPARE_FLAG_ALL; - nm_dns_manager_begin_updates (policy->dns_manager, __func__); + nm_dns_manager_begin_updates (priv->dns_manager, __func__); /* Old configs get removed immediately */ if (old_config) - nm_dns_manager_remove_ip4_config (policy->dns_manager, 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. @@ -1411,8 +1523,8 @@ device_ip4_config_changed (NMDevice *device, */ if (!nm_device_is_activating (device)) { if (new_config) - nm_dns_manager_add_ip4_config (policy->dns_manager, ip_iface, new_config, NM_DNS_IP_CONFIG_TYPE_DEFAULT); - update_ip4_dns (policy, policy->dns_manager); + 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); /* Only change routing if something actually changed */ diff = nm_ip4_config_diff (new_config, old_config); @@ -1420,7 +1532,7 @@ device_ip4_config_changed (NMDevice *device, update_ip4_routing (policy, TRUE); } - nm_dns_manager_end_updates (policy->dns_manager, __func__); + nm_dns_manager_end_updates (priv->dns_manager, __func__); } static void @@ -1430,14 +1542,15 @@ device_ip6_config_changed (NMDevice *device, gpointer user_data) { NMPolicy *policy = user_data; + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); const char *ip_iface = nm_device_get_ip_iface (device); NMIP4ConfigCompareFlags diff = NM_IP4_COMPARE_FLAG_ALL; - nm_dns_manager_begin_updates (policy->dns_manager, __func__); + nm_dns_manager_begin_updates (priv->dns_manager, __func__); /* Old configs get removed immediately */ if (old_config) - nm_dns_manager_remove_ip6_config (policy->dns_manager, 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. @@ -1445,8 +1558,8 @@ device_ip6_config_changed (NMDevice *device, */ if (!nm_device_is_activating (device)) { if (new_config) - nm_dns_manager_add_ip6_config (policy->dns_manager, ip_iface, new_config, NM_DNS_IP_CONFIG_TYPE_DEFAULT); - update_ip6_dns (policy, policy->dns_manager); + 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); /* Only change routing if something actually changed */ diff = nm_ip6_config_diff (new_config, old_config); @@ -1454,7 +1567,7 @@ device_ip6_config_changed (NMDevice *device, update_ip6_routing (policy, TRUE); } - nm_dns_manager_end_updates (policy->dns_manager, __func__); + nm_dns_manager_end_updates (priv->dns_manager, __func__); } static void @@ -1492,13 +1605,14 @@ typedef struct { static void _connect_device_signal (NMPolicy *policy, NMDevice *device, const char *name, gpointer callback) { + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); DeviceSignalId *data; data = g_slice_new0 (DeviceSignalId); g_assert (data); data->id = g_signal_connect (device, name, callback, policy); data->device = device; - policy->dev_ids = g_slist_prepend (policy->dev_ids, data); + priv->dev_ids = g_slist_prepend (priv->dev_ids, data); } static void @@ -1532,18 +1646,19 @@ static void device_removed (NMManager *manager, NMDevice *device, gpointer user_data) { NMPolicy *policy = (NMPolicy *) user_data; + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); ActivateData *tmp; GSList *iter; /* Clear any idle callbacks for this device */ - tmp = find_pending_activation (policy->pending_activation_checks, device); + tmp = find_pending_activation (priv->pending_activation_checks, device); if (tmp) { - policy->pending_activation_checks = g_slist_remove (policy->pending_activation_checks, tmp); + priv->pending_activation_checks = g_slist_remove (priv->pending_activation_checks, tmp); activate_data_free (tmp); } /* Clear any signal handlers for this device */ - iter = policy->dev_ids; + iter = priv->dev_ids; while (iter) { DeviceSignalId *data = iter->data; GSList *next = g_slist_next (iter); @@ -1551,7 +1666,7 @@ device_removed (NMManager *manager, NMDevice *device, gpointer user_data) if (data->device == device) { g_signal_handler_disconnect (data->device, data->id); g_slice_free (DeviceSignalId, data); - policy->dev_ids = g_slist_delete_link (policy->dev_ids, iter); + priv->dev_ids = g_slist_delete_link (priv->dev_ids, iter); } iter = next; } @@ -1703,9 +1818,10 @@ active_connection_removed (NMManager *manager, static void schedule_activate_all (NMPolicy *policy) { + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); GSList *iter, *devices; - devices = nm_manager_get_devices (policy->manager); + devices = nm_manager_get_devices (priv->manager); for (iter = devices; iter; iter = g_slist_next (iter)) schedule_activate_check (policy, NM_DEVICE (iter->data), 0); } @@ -1747,17 +1863,18 @@ add_or_change_zone_cb (GError *error, gpointer user_data) static void firewall_update_zone (NMPolicy *policy, NMConnection *connection) { + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); NMSettingConnection *s_con = nm_connection_get_setting_connection (connection); GSList *iter, *devices; - devices = nm_manager_get_devices (policy->manager); + devices = nm_manager_get_devices (priv->manager); /* find dev with passed connection and change zone its interface belongs to */ for (iter = devices; iter; iter = g_slist_next (iter)) { NMDevice *dev = NM_DEVICE (iter->data); if ( (nm_device_get_connection (dev) == connection) && (nm_device_get_state (dev) == NM_DEVICE_STATE_ACTIVATED)) { - nm_firewall_manager_add_or_change_zone (policy->fw_manager, + nm_firewall_manager_add_or_change_zone (priv->fw_manager, nm_device_get_ip_iface (dev), nm_setting_connection_get_zone (s_con), FALSE, /* change zone */ @@ -1772,11 +1889,12 @@ firewall_started (NMFirewallManager *manager, gpointer user_data) { NMPolicy *policy = (NMPolicy *) user_data; + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); NMConnection *connection; NMSettingConnection *s_con; GSList *iter, *devices; - devices = nm_manager_get_devices (policy->manager); + devices = nm_manager_get_devices (priv->manager); /* add interface of each device to correct zone */ for (iter = devices; iter; iter = g_slist_next (iter)) { NMDevice *dev = NM_DEVICE (iter->data); @@ -1784,7 +1902,7 @@ firewall_started (NMFirewallManager *manager, connection = nm_device_get_connection (dev); s_con = nm_connection_get_setting_connection (connection); if (nm_device_get_state (dev) == NM_DEVICE_STATE_ACTIVATED) { - nm_firewall_manager_add_or_change_zone (policy->fw_manager, + nm_firewall_manager_add_or_change_zone (priv->fw_manager, nm_device_get_ip_iface (dev), nm_setting_connection_get_zone (s_con), TRUE, /* add zone */ @@ -1798,6 +1916,7 @@ static void dns_config_changed (NMDnsManager *dns_manager, gpointer user_data) { NMPolicy *policy = (NMPolicy *) user_data; + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); /* Restart a thread for reverse-DNS lookup after we are signalled that * DNS changed. Because the result from a previous run may not be right @@ -1805,29 +1924,29 @@ dns_config_changed (NMDnsManager *dns_manager, gpointer user_data) */ /* Stop a lookup thread if any. */ - if (policy->lookup) { - hostname_thread_kill (policy->lookup); - policy->lookup = NULL; + if (priv->lookup) { + hostname_thread_kill (priv->lookup); + priv->lookup = NULL; } /* Re-start the hostname lookup thread if we don't have hostname yet. */ - if (policy->lookup_ipv4_addr) { + if (priv->lookup_ipv4_addr) { char buf[INET_ADDRSTRLEN]; - struct in_addr addr = { .s_addr = policy->lookup_ipv4_addr }; + struct in_addr addr = { .s_addr = priv->lookup_ipv4_addr }; if (!inet_ntop (AF_INET, &addr, buf, sizeof (buf))) strcpy (buf, "(unknown)"); nm_log_dbg (LOGD_DNS, "restarting IPv4 reverse-lookup thread for address %s'", buf); - policy->lookup = hostname4_thread_new (policy->lookup_ipv4_addr, lookup_callback, policy); - } else if (policy->lookup_ipv6_addr) { + priv->lookup = hostname4_thread_new (priv->lookup_ipv4_addr, lookup_callback, policy); + } else if (priv->lookup_ipv6_addr) { char buf[INET6_ADDRSTRLEN]; - if (!inet_ntop (AF_INET6, policy->lookup_ipv6_addr, buf, sizeof (buf))) + if (!inet_ntop (AF_INET6, priv->lookup_ipv6_addr, buf, sizeof (buf))) strcpy (buf, "(unknown)"); nm_log_dbg (LOGD_DNS, "restarting IPv6 reverse-lookup thread for address %s'", buf); - policy->lookup = hostname6_thread_new (policy->lookup_ipv6_addr, lookup_callback, policy); + priv->lookup = hostname6_thread_new (priv->lookup_ipv6_addr, lookup_callback, policy); } } @@ -1854,9 +1973,11 @@ _deactivate_if_active (NMManager *manager, NMConnection *connection) active = nm_manager_get_active_connections (manager); for (iter = active; iter; iter = g_slist_next (iter)) { NMActiveConnection *ac = iter->data; + NMActiveConnectionState state = nm_active_connection_get_state (ac); GError *error = NULL; - if (nm_active_connection_get_connection (ac) == connection) { + if (nm_active_connection_get_connection (ac) == connection && + (state <= NM_ACTIVE_CONNECTION_STATE_ACTIVATED)) { if (!nm_manager_deactivate_connection (manager, nm_active_connection_get_path (ac), NM_DEVICE_STATE_REASON_CONNECTION_REMOVED, @@ -1877,8 +1998,9 @@ connection_removed (NMSettings *settings, gpointer user_data) { NMPolicy *policy = user_data; + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); - _deactivate_if_active (policy->manager, connection); + _deactivate_if_active (priv->manager, connection); } static void @@ -1887,11 +2009,12 @@ connection_visibility_changed (NMSettings *settings, gpointer user_data) { NMPolicy *policy = user_data; + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); if (nm_settings_connection_is_visible (connection)) schedule_activate_all (policy); else - _deactivate_if_active (policy->manager, NM_CONNECTION (connection)); + _deactivate_if_active (priv->manager, NM_CONNECTION (connection)); } static void @@ -1910,25 +2033,28 @@ secret_agent_registered (NMSettings *settings, static void _connect_manager_signal (NMPolicy *policy, const char *name, gpointer callback) { + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); guint id; - id = g_signal_connect (policy->manager, name, callback, policy); - policy->manager_ids = g_slist_prepend (policy->manager_ids, GUINT_TO_POINTER (id)); + id = g_signal_connect (priv->manager, name, callback, policy); + priv->manager_ids = g_slist_prepend (priv->manager_ids, GUINT_TO_POINTER (id)); } static void _connect_settings_signal (NMPolicy *policy, const char *name, gpointer callback) { + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); guint id; - id = g_signal_connect (policy->settings, name, callback, policy); - policy->settings_ids = g_slist_prepend (policy->settings_ids, GUINT_TO_POINTER (id)); + id = g_signal_connect (priv->settings, name, callback, policy); + priv->settings_ids = g_slist_prepend (priv->settings_ids, GUINT_TO_POINTER (id)); } NMPolicy * nm_policy_new (NMManager *manager, NMSettings *settings) { NMPolicy *policy; + NMPolicyPrivate *priv; static gboolean initialized = FALSE; gulong id; char hostname[HOST_NAME_MAX + 2]; @@ -1936,10 +2062,11 @@ nm_policy_new (NMManager *manager, NMSettings *settings) g_return_val_if_fail (NM_IS_MANAGER (manager), NULL); g_return_val_if_fail (initialized == FALSE, NULL); - policy = g_malloc0 (sizeof (NMPolicy)); - policy->manager = g_object_ref (manager); - policy->settings = g_object_ref (settings); - policy->update_state_id = 0; + policy = g_object_new (NM_TYPE_POLICY, NULL); + priv = NM_POLICY_GET_PRIVATE (policy); + priv->manager = manager; + priv->settings = g_object_ref (settings); + priv->update_state_id = 0; /* Grab hostname on startup and use that if nothing provides one */ memset (hostname, 0, sizeof (hostname)); @@ -1949,16 +2076,16 @@ nm_policy_new (NMManager *manager, NMSettings *settings) && strcmp (hostname, "localhost") && strcmp (hostname, "localhost.localdomain") && strcmp (hostname, "(none)")) - policy->orig_hostname = g_strdup (hostname); + priv->orig_hostname = g_strdup (hostname); } - policy->fw_manager = nm_firewall_manager_get(); - id = g_signal_connect (policy->fw_manager, "started", + priv->fw_manager = nm_firewall_manager_get(); + id = g_signal_connect (priv->fw_manager, "started", G_CALLBACK (firewall_started), policy); - policy->fw_started_id = id; + priv->fw_started_id = id; - policy->dns_manager = nm_dns_manager_get (NULL); - policy->config_changed_id = g_signal_connect (policy->dns_manager, "config-changed", + priv->dns_manager = nm_dns_manager_get (NULL); + priv->config_changed_id = g_signal_connect (priv->dns_manager, "config-changed", G_CALLBACK (dns_config_changed), policy); _connect_manager_signal (policy, "state-changed", global_state_changed); @@ -1979,68 +2106,178 @@ nm_policy_new (NMManager *manager, NMSettings *settings) _connect_settings_signal (policy, NM_SETTINGS_SIGNAL_AGENT_REGISTERED, secret_agent_registered); /* Initialize connections' auto-retries */ - reset_retries_all (policy->settings, NULL); + reset_retries_all (priv->settings, NULL); initialized = TRUE; return policy; } -void -nm_policy_destroy (NMPolicy *policy) +NMDevice * +nm_policy_get_default_ip4_device (NMPolicy *policy) { - const GSList *connections, *iter; + return NM_POLICY_GET_PRIVATE (policy)->default_device4; +} - g_return_if_fail (policy != NULL); +NMDevice * +nm_policy_get_default_ip6_device (NMPolicy *policy) +{ + return NM_POLICY_GET_PRIVATE (policy)->default_device6; +} + +NMDevice * +nm_policy_get_activating_ip4_device (NMPolicy *policy) +{ + return NM_POLICY_GET_PRIVATE (policy)->activating_device4; +} + +NMDevice * +nm_policy_get_activating_ip6_device (NMPolicy *policy) +{ + return NM_POLICY_GET_PRIVATE (policy)->activating_device6; +} + +static void +nm_policy_init (NMPolicy *policy) +{ +} + +static void +get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + NMPolicy *policy = NM_POLICY (object); + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); + + switch (prop_id) { + case PROP_DEFAULT_IP4_DEVICE: + g_value_set_object (value, priv->default_device4); + break; + case PROP_DEFAULT_IP6_DEVICE: + g_value_set_object (value, priv->default_device6); + break; + case PROP_ACTIVATING_IP4_DEVICE: + g_value_set_object (value, priv->activating_device4); + break; + case PROP_ACTIVATING_IP6_DEVICE: + g_value_set_object (value, priv->activating_device6); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +dispose (GObject *object) +{ + NMPolicy *policy = NM_POLICY (object); + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); + const GSList *connections, *iter; /* Tell any existing hostname lookup thread to die, it'll get cleaned up * by the lookup thread callback. */ - if (policy->lookup) { - hostname_thread_kill (policy->lookup); - policy->lookup = NULL; + if (priv->lookup) { + hostname_thread_kill (priv->lookup); + priv->lookup = NULL; } - g_free (policy->lookup_ipv6_addr); + g_free (priv->lookup_ipv6_addr); - g_slist_foreach (policy->pending_activation_checks, (GFunc) activate_data_free, NULL); - g_slist_free (policy->pending_activation_checks); + g_slist_free_full (priv->pending_activation_checks, (GDestroyNotify) activate_data_free); + priv->pending_activation_checks = NULL; - g_slist_foreach (policy->pending_secondaries, (GFunc) pending_secondary_data_free, NULL); - g_slist_free (policy->pending_secondaries); + g_slist_free_full (priv->pending_secondaries, (GDestroyNotify) pending_secondary_data_free); + priv->pending_secondaries = NULL; - g_signal_handler_disconnect (policy->fw_manager, policy->fw_started_id); - g_object_unref (policy->fw_manager); + if (priv->fw_manager) { + g_signal_handler_disconnect (priv->fw_manager, priv->fw_started_id); + g_object_unref (priv->fw_manager); + priv->fw_manager = NULL; + } - g_signal_handler_disconnect (policy->dns_manager, policy->config_changed_id); - g_object_unref (policy->dns_manager); + if (priv->dns_manager) { + g_signal_handler_disconnect (priv->dns_manager, priv->config_changed_id); + g_object_unref (priv->dns_manager); + priv->dns_manager = NULL; + } - for (iter = policy->manager_ids; iter; iter = g_slist_next (iter)) - g_signal_handler_disconnect (policy->manager, GPOINTER_TO_UINT (iter->data)); - g_slist_free (policy->manager_ids); + for (iter = priv->manager_ids; iter; iter = g_slist_next (iter)) + g_signal_handler_disconnect (priv->manager, GPOINTER_TO_UINT (iter->data)); + g_slist_free (priv->manager_ids); + priv->manager_ids = NULL; - for (iter = policy->settings_ids; iter; iter = g_slist_next (iter)) - g_signal_handler_disconnect (policy->settings, GPOINTER_TO_UINT (iter->data)); - g_slist_free (policy->settings_ids); + for (iter = priv->settings_ids; iter; iter = g_slist_next (iter)) + g_signal_handler_disconnect (priv->settings, GPOINTER_TO_UINT (iter->data)); + g_slist_free (priv->settings_ids); + priv->settings_ids = NULL; - for (iter = policy->dev_ids; iter; iter = g_slist_next (iter)) { + for (iter = priv->dev_ids; iter; iter = g_slist_next (iter)) { DeviceSignalId *data = iter->data; g_signal_handler_disconnect (data->device, data->id); g_slice_free (DeviceSignalId, data); } - g_slist_free (policy->dev_ids); + g_slist_free (priv->dev_ids); + priv->dev_ids = NULL; - connections = nm_manager_get_active_connections (policy->manager); - for (iter = connections; iter; iter = g_slist_next (iter)) - active_connection_removed (policy->manager, NM_ACTIVE_CONNECTION (iter->data), policy); + /* The manager should have disposed of ActiveConnections already, which + * will have called active_connection_removed() and thus we don't need + * to clean anything up. Assert that this is TRUE. + */ + connections = nm_manager_get_active_connections (priv->manager); + g_assert (connections == NULL); + + if (priv->reset_retries_id) { + g_source_remove (priv->reset_retries_id); + priv->reset_retries_id = 0; + } - if (policy->reset_retries_id) - g_source_remove (policy->reset_retries_id); + g_free (priv->orig_hostname); + priv->orig_hostname = NULL; + g_free (priv->cur_hostname); + priv->cur_hostname = NULL; - g_free (policy->orig_hostname); - g_free (policy->cur_hostname); + g_clear_object (&priv->settings); - g_object_unref (policy->settings); - g_object_unref (policy->manager); - g_free (policy); + G_OBJECT_CLASS (nm_policy_parent_class)->dispose (object); } +static void +nm_policy_class_init (NMPolicyClass *policy_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (policy_class); + + g_type_class_add_private (policy_class, sizeof (NMPolicyPrivate)); + + object_class->get_property = get_property; + object_class->dispose = dispose; + + g_object_class_install_property + (object_class, PROP_DEFAULT_IP4_DEVICE, + g_param_spec_object (NM_POLICY_DEFAULT_IP4_DEVICE, + "Default IP4 device", + "Default IP4 device", + NM_TYPE_DEVICE, + G_PARAM_READABLE)); + g_object_class_install_property + (object_class, PROP_DEFAULT_IP6_DEVICE, + g_param_spec_object (NM_POLICY_DEFAULT_IP6_DEVICE, + "Default IP6 device", + "Default IP6 device", + NM_TYPE_DEVICE, + G_PARAM_READABLE)); + g_object_class_install_property + (object_class, PROP_ACTIVATING_IP4_DEVICE, + g_param_spec_object (NM_POLICY_ACTIVATING_IP4_DEVICE, + "Activating default IP4 device", + "Activating default IP4 device", + NM_TYPE_DEVICE, + G_PARAM_READABLE)); + g_object_class_install_property + (object_class, PROP_ACTIVATING_IP6_DEVICE, + g_param_spec_object (NM_POLICY_ACTIVATING_IP6_DEVICE, + "Activating default IP6 device", + "Activating default IP6 device", + NM_TYPE_DEVICE, + G_PARAM_READABLE)); +} |