~ubuntu-branches/ubuntu/oneiric/network-manager/oneiric

« back to all changes in this revision

Viewing changes to src/nm-policy.c

  • Committer: Bazaar Package Importer
  • Author(s): Mathieu Trudel-Lapierre
  • Date: 2011-07-25 20:01:12 UTC
  • mfrom: (1.1.48 upstream)
  • Revision ID: james.westby@ubuntu.com-20110725200112-iwxhtsy6hko0ffkt
Tags: 0.8.9997+git.20110721t045648.36db194-0ubuntu1
* upstream snapshot 2011-07-21 04:56:48 (GMT)
  + 36db194ae95e35cc7b8f431ab984780dea24656d
  - libnm-util: default to allowing v6 connections to fail (set to optional)
* debian/patches/ipv6-dont-block-ipv4.patch: don't block waiting for IPv6 to
  apply IPv4 connection settings.
* debian/libnm-glib4.symbols: add new nm_client_get_device_by_iface symbol.
* debian/libnm-util2.symbols: add new symbols:
  - nm_setting_wired_get_mac_address_blacklist
  - nm_setting_wireless_get_mac_address_blacklist

Show diffs side-by-side

added added

removed removed

Lines of Context:
46
46
#include "nm-dns-manager.h"
47
47
#include "nm-vpn-manager.h"
48
48
#include "nm-policy-hostname.h"
 
49
#include "nm-manager-auth.h"
49
50
 
50
51
struct NMPolicy {
51
52
        NMManager *manager;
66
67
 
67
68
        HostnameThread *lookup;
68
69
 
 
70
        gint reset_retries_id;  /* idle handler for resetting the retries count */
 
71
 
69
72
        char *orig_hostname; /* hostname at NM start time */
70
73
        char *cur_hostname;  /* hostname we want to assign */
71
74
};
72
75
 
73
76
#define RETRIES_TAG "autoconnect-retries"
74
77
#define RETRIES_DEFAULT 4
 
78
#define RESET_RETRIES_TIMESTAMP_TAG "reset-retries-timestamp-tag"
 
79
#define RESET_RETRIES_TIMER 300
 
80
#define FAILURE_REASON_TAG "failure-reason"
75
81
 
76
82
static NMDevice *
77
83
get_best_ip4_device (NMManager *manager, NMActRequest **out_req)
316
322
                /* Grab a hostname out of the device's DHCP4 config */
317
323
                dhcp4_config = nm_device_get_dhcp4_config (best4);
318
324
                if (dhcp4_config) {
319
 
                        p = dhcp_hostname = nm_dhcp4_config_get_option (dhcp4_config, "host_name");
 
325
                        p = dhcp_hostname = nm_dhcp4_config_get_option (dhcp4_config, "new_host_name");
320
326
                        if (dhcp_hostname && strlen (dhcp_hostname)) {
321
327
                                /* Sanity check; strip leading spaces */
322
328
                                while (*p) {
323
329
                                        if (!isblank (*p++)) {
324
 
                                                _set_hostname (policy, TRUE, dhcp_hostname, "from DHCPv4");
 
330
                                                _set_hostname (policy, TRUE, p-1, "from DHCPv4");
325
331
                                                return;
326
332
                                        }
327
333
                                }
328
334
                                nm_log_warn (LOGD_DNS, "DHCPv4-provided hostname '%s' looks invalid; ignoring it",
329
 
                                                 dhcp_hostname);
 
335
                                             dhcp_hostname);
330
336
                        }
331
337
                }
332
338
        } else if (best6) {
333
339
                NMDHCP6Config *dhcp6_config;
334
340
 
335
 
                /* Grab a hostname out of the device's DHCP4 config */
 
341
                /* Grab a hostname out of the device's DHCP6 config */
336
342
                dhcp6_config = nm_device_get_dhcp6_config (best6);
337
343
                if (dhcp6_config) {
338
 
                        p = dhcp_hostname = nm_dhcp6_config_get_option (dhcp6_config, "host_name");
 
344
                        p = dhcp_hostname = nm_dhcp6_config_get_option (dhcp6_config, "new_host_name");
339
345
                        if (dhcp_hostname && strlen (dhcp_hostname)) {
340
346
                                /* Sanity check; strip leading spaces */
341
347
                                while (*p) {
342
348
                                        if (!isblank (*p++)) {
343
 
                                                _set_hostname (policy, TRUE, dhcp_hostname, "from DHCPv6");
 
349
                                                _set_hostname (policy, TRUE, p-1, "from DHCPv6");
344
350
                                                return;
345
351
                                        }
346
352
                                }
347
353
                                nm_log_warn (LOGD_DNS, "DHCPv6-provided hostname '%s' looks invalid; ignoring it",
348
 
                                                 dhcp_hostname);
 
354
                                             dhcp_hostname);
349
355
                        }
350
356
                }
351
357
        }
722
728
 
723
729
        /* Remove connections that shouldn't be auto-activated */
724
730
        while (iter) {
725
 
                NMConnection *candidate = NM_CONNECTION (iter->data);
 
731
                NMSettingsConnection *candidate = NM_SETTINGS_CONNECTION (iter->data);
 
732
                gboolean remove_it = FALSE;
 
733
                const char *permission;
726
734
 
727
735
                /* Grab next item before we possibly delete the current item */
728
736
                iter = g_slist_next (iter);
729
737
 
730
738
                /* Ignore connections that were tried too many times or are not visible
731
 
                 * to any logged-in users.
 
739
                 * to any logged-in users.  Also ignore shared wifi connections for
 
740
                 * which no user has the shared wifi permission.
732
741
                 */
733
 
                if (   get_connection_auto_retries (candidate) == 0
734
 
                    || nm_settings_connection_is_visible (NM_SETTINGS_CONNECTION (candidate)) == FALSE)
 
742
                if (   get_connection_auto_retries (NM_CONNECTION (candidate)) == 0
 
743
                    || nm_settings_connection_is_visible (candidate) == FALSE)
 
744
                        remove_it = TRUE;
 
745
                else {
 
746
                        permission = nm_utils_get_shared_wifi_permission (NM_CONNECTION (candidate));
 
747
                        if (permission) {
 
748
                                if (nm_settings_connection_check_permission (candidate, permission) == FALSE)
 
749
                                        remove_it = TRUE;
 
750
                        }
 
751
                }
 
752
 
 
753
                if (remove_it)
735
754
                        connections = g_slist_remove (connections, candidate);
736
755
        }
737
756
 
834
853
}
835
854
 
836
855
static void
 
856
reset_retries_for_failed_secrets (NMSettings *settings)
 
857
{
 
858
        GSList *connections, *iter;
 
859
 
 
860
        connections = nm_settings_get_connections (settings);
 
861
        for (iter = connections; iter; iter = g_slist_next (iter)) {
 
862
                NMDeviceStateReason reason = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (iter->data), FAILURE_REASON_TAG));
 
863
 
 
864
                if (reason == NM_DEVICE_STATE_REASON_NO_SECRETS) {
 
865
                        set_connection_auto_retries (NM_CONNECTION (iter->data), RETRIES_DEFAULT);
 
866
                        g_object_set_data (G_OBJECT (iter->data), FAILURE_REASON_TAG, GUINT_TO_POINTER (0));
 
867
                }
 
868
        }
 
869
        g_slist_free (connections);
 
870
}
 
871
 
 
872
static void
837
873
sleeping_changed (NMManager *manager, GParamSpec *pspec, gpointer user_data)
838
874
{
839
875
        NMPolicy *policy = user_data;
870
906
        }
871
907
}
872
908
 
 
909
static gboolean
 
910
reset_connections_retries (gpointer user_data)
 
911
{
 
912
        NMPolicy *policy = (NMPolicy *) user_data;
 
913
        GSList *connections, *iter;
 
914
        time_t con_stamp, min_stamp, now;
 
915
 
 
916
        policy->reset_retries_id = 0;
 
917
 
 
918
        min_stamp = now = time (NULL);
 
919
        connections = nm_settings_get_connections (policy->settings);
 
920
        for (iter = connections; iter; iter = g_slist_next (iter)) {
 
921
                con_stamp = GPOINTER_TO_SIZE (g_object_get_data (G_OBJECT (iter->data), RESET_RETRIES_TIMESTAMP_TAG));
 
922
                if (con_stamp == 0)
 
923
                        continue;
 
924
                if (con_stamp + RESET_RETRIES_TIMER <= now) {
 
925
                        set_connection_auto_retries (NM_CONNECTION (iter->data), RETRIES_DEFAULT);
 
926
                        g_object_set_data (G_OBJECT (iter->data), RESET_RETRIES_TIMESTAMP_TAG, GSIZE_TO_POINTER (0));
 
927
                        continue;
 
928
                }
 
929
                if (con_stamp < min_stamp)
 
930
                        min_stamp = con_stamp;
 
931
        }
 
932
        g_slist_free (connections);
 
933
 
 
934
        /* Schedule the handler again if there are some stamps left */
 
935
        if (min_stamp != now)
 
936
                policy->reset_retries_id = g_timeout_add_seconds (RESET_RETRIES_TIMER - (now - min_stamp), reset_connections_retries, policy);
 
937
        return FALSE;
 
938
}
 
939
 
873
940
static NMConnection *
874
941
get_device_connection (NMDevice *device)
875
942
{
892
959
        NMPolicy *policy = (NMPolicy *) user_data;
893
960
        NMConnection *connection = get_device_connection (device);
894
961
 
 
962
        if (connection)
 
963
                g_object_set_data (G_OBJECT (connection), FAILURE_REASON_TAG, GUINT_TO_POINTER (0));
 
964
 
895
965
        switch (new_state) {
896
966
        case NM_DEVICE_STATE_FAILED:
897
967
                /* Mark the connection invalid if it failed during activation so that
906
976
                                 * automatically retrying because it's just going to fail anyway.
907
977
                                 */
908
978
                                set_connection_auto_retries (connection, 0);
 
979
 
 
980
                                /* Mark the connection as failed due to missing secrets so that we can reset
 
981
                                 * RETRIES_TAG and automatically re-try when an secret agent registers.
 
982
                                 */
 
983
                                g_object_set_data (G_OBJECT (connection), FAILURE_REASON_TAG, GUINT_TO_POINTER (NM_DEVICE_STATE_REASON_NO_SECRETS));
909
984
                        } else if (tries > 0) {
910
985
                                /* Otherwise if it's a random failure, just decrease the number
911
986
                                 * of automatic retries so that the connection gets tried again
914
989
                                set_connection_auto_retries (connection, tries - 1);
915
990
                        }
916
991
 
917
 
                        if (get_connection_auto_retries (connection) == 0)
 
992
                        if (get_connection_auto_retries (connection) == 0) {
918
993
                                nm_log_info (LOGD_DEVICE, "Marking connection '%s' invalid.", nm_connection_get_id (connection));
 
994
                                /* Schedule a handler to reset retries count */
 
995
                                g_object_set_data (G_OBJECT (connection), RESET_RETRIES_TIMESTAMP_TAG, GSIZE_TO_POINTER ((gsize) time (NULL)));
 
996
                                if (!policy->reset_retries_id)
 
997
                                        policy->reset_retries_id = g_timeout_add_seconds (RESET_RETRIES_TIMER, reset_connections_retries, policy);
 
998
                        }
919
999
                        nm_connection_clear_secrets (connection);
920
1000
                }
921
1001
                schedule_activate_check (policy, device, 3);
938
1018
                update_routing_and_dns (policy, FALSE);
939
1019
                break;
940
1020
        case NM_DEVICE_STATE_DISCONNECTED:
941
 
                /* Clear INVALID_TAG when carrier on. If cable was unplugged
 
1021
                /* Reset RETRIES_TAG when carrier on. If cable was unplugged
942
1022
                 * and plugged again, we should try to reconnect */
943
1023
                if (reason == NM_DEVICE_STATE_REASON_CARRIER && old_state == NM_DEVICE_STATE_UNAVAILABLE)
944
1024
                        reset_retries_all (policy->settings, device);
1133
1213
}
1134
1214
 
1135
1215
static void
 
1216
secret_agent_registered (NMSettings *settings,
 
1217
                         NMSecretAgent *agent,
 
1218
                         gpointer user_data)
 
1219
{
 
1220
        /* The registered secret agent may provide some missing secrets. Thus we
 
1221
         * reset retries count here and schedule activation, so that the
 
1222
         * connections failed due to missing secrets may re-try auto-connection.
 
1223
         */
 
1224
        reset_retries_for_failed_secrets (settings);
 
1225
        schedule_activate_all ((NMPolicy *) user_data);
 
1226
}
 
1227
 
 
1228
static void
1136
1229
_connect_manager_signal (NMPolicy *policy, const char *name, gpointer callback)
1137
1230
{
1138
1231
        guint id;
1200
1293
        _connect_settings_signal (policy, NM_SETTINGS_SIGNAL_CONNECTION_REMOVED, connection_removed);
1201
1294
        _connect_settings_signal (policy, NM_SETTINGS_SIGNAL_CONNECTION_VISIBILITY_CHANGED,
1202
1295
                                  connection_visibility_changed);
 
1296
        _connect_settings_signal (policy, NM_SETTINGS_SIGNAL_AGENT_REGISTERED, secret_agent_registered);
1203
1297
 
1204
1298
        /* Initialize connections' auto-retries */
1205
1299
        reset_retries_all (policy->settings, NULL);
1246
1340
        }
1247
1341
        g_slist_free (policy->dev_ids);
1248
1342
 
 
1343
        if (policy->reset_retries_id)
 
1344
                g_source_remove (policy->reset_retries_id);
 
1345
 
1249
1346
        g_free (policy->orig_hostname);
1250
1347
        g_free (policy->cur_hostname);
1251
1348