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

« back to all changes in this revision

Viewing changes to .pc/libnl3-port.patch/src/nm-policy.c

  • Committer: Bazaar Package Importer
  • Author(s): Mathieu Trudel-Lapierre
  • Date: 2011-08-08 10:17:28 UTC
  • Revision ID: james.westby@ubuntu.com-20110808101728-nbhqa7aztcwetla2
Tags: 0.8.9997+git.20110721t045648.36db194-0ubuntu2
* debian/control: bump libnl Build-Depends to libnl3-dev.
* debian/patches/libnl3-port.patch: backport changes from NM's libnl3 git
  branch to port to libnl3 APIs.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
 
2
/* NetworkManager -- Network link manager
 
3
 *
 
4
 * This program is free software; you can redistribute it and/or modify
 
5
 * it under the terms of the GNU General Public License as published by
 
6
 * the Free Software Foundation; either version 2 of the License, or
 
7
 * (at your option) any later version.
 
8
 *
 
9
 * This program is distributed in the hope that it will be useful,
 
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
12
 * GNU General Public License for more details.
 
13
 *
 
14
 * You should have received a copy of the GNU General Public License along
 
15
 * with this program; if not, write to the Free Software Foundation, Inc.,
 
16
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 
17
 *
 
18
 * Copyright (C) 2004 - 2011 Red Hat, Inc.
 
19
 * Copyright (C) 2007 - 2008 Novell, Inc.
 
20
 */
 
21
 
 
22
#include <config.h>
 
23
#include <string.h>
 
24
#include <unistd.h>
 
25
#include <errno.h>
 
26
#include <netdb.h>
 
27
#include <ctype.h>
 
28
 
 
29
#include "nm-policy.h"
 
30
#include "NetworkManagerUtils.h"
 
31
#include "nm-wifi-ap.h"
 
32
#include "nm-activation-request.h"
 
33
#include "nm-logging.h"
 
34
#include "nm-device-interface.h"
 
35
#include "nm-device.h"
 
36
#include "nm-device-wifi.h"
 
37
#include "nm-device-ethernet.h"
 
38
#include "nm-device-modem.h"
 
39
#if WITH_WIMAX
 
40
#include "nm-device-wimax.h"
 
41
#endif
 
42
#include "nm-dbus-manager.h"
 
43
#include "nm-setting-ip4-config.h"
 
44
#include "nm-setting-connection.h"
 
45
#include "nm-system.h"
 
46
#include "nm-dns-manager.h"
 
47
#include "nm-vpn-manager.h"
 
48
#include "nm-policy-hostname.h"
 
49
#include "nm-manager-auth.h"
 
50
 
 
51
struct NMPolicy {
 
52
        NMManager *manager;
 
53
        guint update_state_id;
 
54
        GSList *pending_activation_checks;
 
55
        GSList *manager_ids;
 
56
        GSList *settings_ids;
 
57
        GSList *dev_ids;
 
58
 
 
59
        NMVPNManager *vpn_manager;
 
60
        gulong vpn_activated_id;
 
61
        gulong vpn_deactivated_id;
 
62
 
 
63
        NMSettings *settings;
 
64
 
 
65
        NMDevice *default_device4;
 
66
        NMDevice *default_device6;
 
67
 
 
68
        HostnameThread *lookup;
 
69
 
 
70
        gint reset_retries_id;  /* idle handler for resetting the retries count */
 
71
 
 
72
        char *orig_hostname; /* hostname at NM start time */
 
73
        char *cur_hostname;  /* hostname we want to assign */
 
74
};
 
75
 
 
76
#define RETRIES_TAG "autoconnect-retries"
 
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"
 
81
 
 
82
static NMDevice *
 
83
get_best_ip4_device (NMManager *manager, NMActRequest **out_req)
 
84
{
 
85
        GSList *devices, *iter;
 
86
        NMDevice *best = NULL;
 
87
        int best_prio = G_MAXINT;
 
88
 
 
89
        g_return_val_if_fail (manager != NULL, NULL);
 
90
        g_return_val_if_fail (NM_IS_MANAGER (manager), NULL);
 
91
        g_return_val_if_fail (out_req != NULL, NULL);
 
92
        g_return_val_if_fail (*out_req == NULL, NULL);
 
93
 
 
94
        devices = nm_manager_get_devices (manager);
 
95
        for (iter = devices; iter; iter = g_slist_next (iter)) {
 
96
                NMDevice *dev = NM_DEVICE (iter->data);
 
97
                NMActRequest *req;
 
98
                NMConnection *connection;
 
99
                NMIP4Config *ip4_config;
 
100
                NMSettingIP4Config *s_ip4;
 
101
                int prio;
 
102
                guint i;
 
103
                gboolean can_default = FALSE;
 
104
                const char *method = NULL;
 
105
 
 
106
                if (nm_device_get_state (dev) != NM_DEVICE_STATE_ACTIVATED)
 
107
                        continue;
 
108
 
 
109
                ip4_config = nm_device_get_ip4_config (dev);
 
110
                if (!ip4_config)
 
111
                        continue;
 
112
 
 
113
                req = nm_device_get_act_request (dev);
 
114
                g_assert (req);
 
115
                connection = nm_act_request_get_connection (req);
 
116
                g_assert (connection);
 
117
 
 
118
                /* Never set the default route through an IPv4LL-addressed device */
 
119
                s_ip4 = (NMSettingIP4Config *) nm_connection_get_setting (connection, NM_TYPE_SETTING_IP4_CONFIG);
 
120
                if (s_ip4)
 
121
                        method = nm_setting_ip4_config_get_method (s_ip4);
 
122
 
 
123
                if (s_ip4 && !strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL))
 
124
                        continue;
 
125
 
 
126
                /* Make sure at least one of this device's IP addresses has a gateway */
 
127
                for (i = 0; i < nm_ip4_config_get_num_addresses (ip4_config); i++) {
 
128
                        NMIP4Address *addr;
 
129
 
 
130
                        addr = nm_ip4_config_get_address (ip4_config, i);
 
131
                        if (nm_ip4_address_get_gateway (addr)) {
 
132
                                can_default = TRUE;
 
133
                                break;
 
134
                        }
 
135
                }
 
136
 
 
137
                if (!can_default && !NM_IS_DEVICE_MODEM (dev))
 
138
                        continue;
 
139
 
 
140
                /* 'never-default' devices can't ever be the default */
 
141
                if (   (s_ip4 && nm_setting_ip4_config_get_never_default (s_ip4))
 
142
                    || nm_ip4_config_get_never_default (ip4_config))
 
143
                        continue;
 
144
 
 
145
                prio = nm_device_get_priority (dev);
 
146
                if (prio > 0 && prio < best_prio) {
 
147
                        best = dev;
 
148
                        best_prio = prio;
 
149
                        *out_req = req;
 
150
                }
 
151
        }
 
152
 
 
153
        return best;
 
154
}
 
155
 
 
156
static NMDevice *
 
157
get_best_ip6_device (NMManager *manager, NMActRequest **out_req)
 
158
{
 
159
        GSList *devices, *iter;
 
160
        NMDevice *best = NULL;
 
161
        int best_prio = G_MAXINT;
 
162
 
 
163
        g_return_val_if_fail (manager != NULL, NULL);
 
164
        g_return_val_if_fail (NM_IS_MANAGER (manager), NULL);
 
165
        g_return_val_if_fail (out_req != NULL, NULL);
 
166
        g_return_val_if_fail (*out_req == NULL, NULL);
 
167
 
 
168
        devices = nm_manager_get_devices (manager);
 
169
        for (iter = devices; iter; iter = g_slist_next (iter)) {
 
170
                NMDevice *dev = NM_DEVICE (iter->data);
 
171
                NMActRequest *req;
 
172
                NMConnection *connection;
 
173
                NMIP6Config *ip6_config;
 
174
                NMSettingIP6Config *s_ip6;
 
175
                int prio;
 
176
                guint i;
 
177
                gboolean can_default = FALSE;
 
178
                const char *method = NULL;
 
179
 
 
180
                if (nm_device_get_state (dev) != NM_DEVICE_STATE_ACTIVATED)
 
181
                        continue;
 
182
 
 
183
                ip6_config = nm_device_get_ip6_config (dev);
 
184
                if (!ip6_config)
 
185
                        continue;
 
186
 
 
187
                req = nm_device_get_act_request (dev);
 
188
                g_assert (req);
 
189
                connection = nm_act_request_get_connection (req);
 
190
                g_assert (connection);
 
191
 
 
192
                /* Never set the default route through an IPv4LL-addressed device */
 
193
                s_ip6 = (NMSettingIP6Config *) nm_connection_get_setting (connection, NM_TYPE_SETTING_IP6_CONFIG);
 
194
                if (s_ip6)
 
195
                        method = nm_setting_ip6_config_get_method (s_ip6);
 
196
 
 
197
                if (method && !strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL))
 
198
                        continue;
 
199
 
 
200
                /* Make sure at least one of this device's IP addresses has a gateway */
 
201
                for (i = 0; i < nm_ip6_config_get_num_addresses (ip6_config); i++) {
 
202
                        NMIP6Address *addr;
 
203
 
 
204
                        addr = nm_ip6_config_get_address (ip6_config, i);
 
205
                        if (nm_ip6_address_get_gateway (addr)) {
 
206
                                can_default = TRUE;
 
207
                                break;
 
208
                        }
 
209
                }
 
210
 
 
211
                if (!can_default && !NM_IS_DEVICE_MODEM (dev))
 
212
                        continue;
 
213
 
 
214
                /* 'never-default' devices can't ever be the default */
 
215
                if (s_ip6 && nm_setting_ip6_config_get_never_default (s_ip6))
 
216
                        continue;
 
217
 
 
218
                prio = nm_device_get_priority (dev);
 
219
                if (prio > 0 && prio < best_prio) {
 
220
                        best = dev;
 
221
                        best_prio = prio;
 
222
                        *out_req = req;
 
223
                }
 
224
        }
 
225
 
 
226
        return best;
 
227
}
 
228
 
 
229
static void
 
230
_set_hostname (NMPolicy *policy,
 
231
               gboolean change_hostname,
 
232
               const char *new_hostname,
 
233
               const char *msg)
 
234
{
 
235
        if (change_hostname) {
 
236
                NMDnsManager *dns_mgr;
 
237
 
 
238
                g_free (policy->cur_hostname);
 
239
                policy->cur_hostname = g_strdup (new_hostname);
 
240
 
 
241
                dns_mgr = nm_dns_manager_get (NULL);
 
242
                nm_dns_manager_set_hostname (dns_mgr, policy->cur_hostname);
 
243
                g_object_unref (dns_mgr);
 
244
        }
 
245
 
 
246
        if (nm_policy_set_system_hostname (policy->cur_hostname, msg))
 
247
                nm_utils_call_dispatcher ("hostname", NULL, NULL, NULL, NULL, NULL);
 
248
}
 
249
 
 
250
static void
 
251
lookup_callback (HostnameThread *thread,
 
252
                 int result,
 
253
                 const char *hostname,
 
254
                 gpointer user_data)
 
255
{
 
256
        NMPolicy *policy = (NMPolicy *) user_data;
 
257
        char *msg;
 
258
 
 
259
        /* Update the hostname if the calling lookup thread is the in-progress one */
 
260
        if (!hostname_thread_is_dead (thread) && (thread == policy->lookup)) {
 
261
                policy->lookup = NULL;
 
262
                if (!hostname) {
 
263
                        /* Fall back to localhost.localdomain */
 
264
                        msg = g_strdup_printf ("address lookup failed: %d", result);
 
265
                        _set_hostname (policy, TRUE, NULL, msg);
 
266
                        g_free (msg);
 
267
                } else
 
268
                        _set_hostname (policy, TRUE, hostname, "from address lookup");
 
269
        }
 
270
        hostname_thread_free (thread);
 
271
}
 
272
 
 
273
static void
 
274
update_system_hostname (NMPolicy *policy, NMDevice *best4, NMDevice *best6)
 
275
{
 
276
        char *configured_hostname = NULL;
 
277
        NMActRequest *best_req4 = NULL;
 
278
        NMActRequest *best_req6 = NULL;
 
279
        const char *dhcp_hostname, *p;
 
280
 
 
281
        g_return_if_fail (policy != NULL);
 
282
 
 
283
        if (policy->lookup) {
 
284
                hostname_thread_kill (policy->lookup);
 
285
                policy->lookup = NULL;
 
286
        }
 
287
 
 
288
        /* Hostname precedence order:
 
289
         *
 
290
         * 1) a configured hostname (from settings)
 
291
         * 2) automatic hostname from the default device's config (DHCP, VPN, etc)
 
292
         * 3) the original hostname when NM started
 
293
         * 4) reverse-DNS of the best device's IPv4 address
 
294
         *
 
295
         */
 
296
 
 
297
        /* Try a persistent hostname first */
 
298
        g_object_get (G_OBJECT (policy->manager), NM_MANAGER_HOSTNAME, &configured_hostname, NULL);
 
299
        if (configured_hostname) {
 
300
                _set_hostname (policy, TRUE, configured_hostname, "from system configuration");
 
301
                g_free (configured_hostname);
 
302
                return;
 
303
        }
 
304
 
 
305
        /* Try automatically determined hostname from the best device's IP config */
 
306
        if (!best4)
 
307
                best4 = get_best_ip4_device (policy->manager, &best_req4);
 
308
        if (!best6)
 
309
                best6 = get_best_ip6_device (policy->manager, &best_req6);
 
310
 
 
311
        if (!best4 && !best6) {
 
312
                /* No best device; fall back to original hostname or if there wasn't
 
313
                 * one, 'localhost.localdomain'
 
314
                 */
 
315
                _set_hostname (policy, TRUE, policy->orig_hostname, "no default device");
 
316
                return;
 
317
        }
 
318
 
 
319
        if (best4) {
 
320
                NMDHCP4Config *dhcp4_config;
 
321
 
 
322
                /* Grab a hostname out of the device's DHCP4 config */
 
323
                dhcp4_config = nm_device_get_dhcp4_config (best4);
 
324
                if (dhcp4_config) {
 
325
                        p = dhcp_hostname = nm_dhcp4_config_get_option (dhcp4_config, "new_host_name");
 
326
                        if (dhcp_hostname && strlen (dhcp_hostname)) {
 
327
                                /* Sanity check; strip leading spaces */
 
328
                                while (*p) {
 
329
                                        if (!isblank (*p++)) {
 
330
                                                _set_hostname (policy, TRUE, p-1, "from DHCPv4");
 
331
                                                return;
 
332
                                        }
 
333
                                }
 
334
                                nm_log_warn (LOGD_DNS, "DHCPv4-provided hostname '%s' looks invalid; ignoring it",
 
335
                                             dhcp_hostname);
 
336
                        }
 
337
                }
 
338
        } else if (best6) {
 
339
                NMDHCP6Config *dhcp6_config;
 
340
 
 
341
                /* Grab a hostname out of the device's DHCP6 config */
 
342
                dhcp6_config = nm_device_get_dhcp6_config (best6);
 
343
                if (dhcp6_config) {
 
344
                        p = dhcp_hostname = nm_dhcp6_config_get_option (dhcp6_config, "new_host_name");
 
345
                        if (dhcp_hostname && strlen (dhcp_hostname)) {
 
346
                                /* Sanity check; strip leading spaces */
 
347
                                while (*p) {
 
348
                                        if (!isblank (*p++)) {
 
349
                                                _set_hostname (policy, TRUE, p-1, "from DHCPv6");
 
350
                                                return;
 
351
                                        }
 
352
                                }
 
353
                                nm_log_warn (LOGD_DNS, "DHCPv6-provided hostname '%s' looks invalid; ignoring it",
 
354
                                             dhcp_hostname);
 
355
                        }
 
356
                }
 
357
        }
 
358
 
 
359
        /* If no automatically-configured hostname, try using the hostname from
 
360
         * when NM started up.
 
361
         */
 
362
        if (policy->orig_hostname) {
 
363
                _set_hostname (policy, TRUE, policy->orig_hostname, "from system startup");
 
364
                return;
 
365
        }
 
366
 
 
367
        /* No configured hostname, no automatically determined hostname, and no
 
368
         * bootup hostname. Start reverse DNS of the current IPv4 or IPv6 address.
 
369
         */
 
370
        if (best4) {
 
371
                NMIP4Config *ip4_config;
 
372
                NMIP4Address *addr4;
 
373
 
 
374
                ip4_config = nm_device_get_ip4_config (best4);
 
375
                if (   !ip4_config
 
376
                    || (nm_ip4_config_get_num_nameservers (ip4_config) == 0)
 
377
                    || (nm_ip4_config_get_num_addresses (ip4_config) == 0)) {
 
378
                        /* No valid IP4 config (!!); fall back to localhost.localdomain */
 
379
                        _set_hostname (policy, TRUE, NULL, "no IPv4 config");
 
380
                        return;
 
381
                }
 
382
 
 
383
                addr4 = nm_ip4_config_get_address (ip4_config, 0);
 
384
                g_assert (addr4); /* checked for > 1 address above */
 
385
 
 
386
                /* Start the hostname lookup thread */
 
387
                policy->lookup = hostname4_thread_new (nm_ip4_address_get_address (addr4), lookup_callback, policy);
 
388
        } else if (best6) {
 
389
                NMIP6Config *ip6_config;
 
390
                NMIP6Address *addr6;
 
391
 
 
392
                ip6_config = nm_device_get_ip6_config (best6);
 
393
                if (   !ip6_config
 
394
                    || (nm_ip6_config_get_num_nameservers (ip6_config) == 0)
 
395
                    || (nm_ip6_config_get_num_addresses (ip6_config) == 0)) {
 
396
                        /* No valid IP6 config (!!); fall back to localhost.localdomain */
 
397
                        _set_hostname (policy, TRUE, NULL, "no IPv6 config");
 
398
                        return;
 
399
                }
 
400
 
 
401
                addr6 = nm_ip6_config_get_address (ip6_config, 0);
 
402
                g_assert (addr6); /* checked for > 1 address above */
 
403
 
 
404
                /* Start the hostname lookup thread */
 
405
                policy->lookup = hostname6_thread_new (nm_ip6_address_get_address (addr6), lookup_callback, policy);
 
406
        }
 
407
 
 
408
        if (!policy->lookup) {
 
409
                /* Fall back to 'localhost.localdomain' */
 
410
                _set_hostname (policy, TRUE, NULL, "error starting hostname thread");
 
411
        }
 
412
}
 
413
 
 
414
static void
 
415
update_ip4_routing_and_dns (NMPolicy *policy, gboolean force_update)
 
416
{
 
417
        NMDnsIPConfigType dns_type = NM_DNS_IP_CONFIG_TYPE_BEST_DEVICE;
 
418
        NMDevice *best = NULL;
 
419
        NMActRequest *best_req = NULL;
 
420
        NMDnsManager *dns_mgr;
 
421
        GSList *devices = NULL, *iter, *vpns;
 
422
        NMIP4Config *ip4_config = NULL;
 
423
        NMIP4Address *addr;
 
424
        const char *ip_iface = NULL;
 
425
        NMConnection *connection = NULL;
 
426
        NMSettingConnection *s_con = NULL;
 
427
        const char *connection_id;
 
428
 
 
429
        best = get_best_ip4_device (policy->manager, &best_req);
 
430
        if (!best)
 
431
                goto out;
 
432
        if (!force_update && (best == policy->default_device4))
 
433
                goto out;
 
434
 
 
435
        /* If a VPN connection is active, it is preferred */
 
436
        vpns = nm_vpn_manager_get_active_connections (policy->vpn_manager);
 
437
        for (iter = vpns; iter; iter = g_slist_next (iter)) {
 
438
                NMVPNConnection *candidate = NM_VPN_CONNECTION (iter->data);
 
439
                NMConnection *vpn_connection;
 
440
                NMSettingIP4Config *s_ip4;
 
441
                gboolean can_default = TRUE;
 
442
                NMVPNConnectionState vpn_state;
 
443
 
 
444
                /* If it's marked 'never-default', don't make it default */
 
445
                vpn_connection = nm_vpn_connection_get_connection (candidate);
 
446
                g_assert (vpn_connection);
 
447
 
 
448
                /* Check the active IP4 config from the VPN service daemon */
 
449
                ip4_config = nm_vpn_connection_get_ip4_config (candidate);
 
450
                if (ip4_config && nm_ip4_config_get_never_default (ip4_config))
 
451
                        can_default = FALSE;
 
452
 
 
453
                /* Check the user's preference from the NMConnection */
 
454
                s_ip4 = (NMSettingIP4Config *) nm_connection_get_setting (vpn_connection, NM_TYPE_SETTING_IP4_CONFIG);
 
455
                if (s_ip4 && nm_setting_ip4_config_get_never_default (s_ip4))
 
456
                        can_default = FALSE;
 
457
 
 
458
                vpn_state = nm_vpn_connection_get_vpn_state (candidate);
 
459
                if (can_default && (vpn_state == NM_VPN_CONNECTION_STATE_ACTIVATED)) {
 
460
                        NMIP4Config *parent_ip4;
 
461
                        NMDevice *parent;
 
462
 
 
463
                        ip_iface = nm_vpn_connection_get_ip_iface (candidate);
 
464
                        connection = nm_vpn_connection_get_connection (candidate);
 
465
                        addr = nm_ip4_config_get_address (ip4_config, 0);
 
466
 
 
467
                        parent = nm_vpn_connection_get_parent_device (candidate);
 
468
                        parent_ip4 = nm_device_get_ip4_config (parent);
 
469
 
 
470
                        nm_system_replace_default_ip4_route_vpn (ip_iface,
 
471
                                                                 nm_ip4_address_get_gateway (addr),
 
472
                                                                 nm_vpn_connection_get_ip4_internal_gateway (candidate),
 
473
                                                                 nm_ip4_config_get_mss (ip4_config),
 
474
                                                                 nm_device_get_ip_iface (parent),
 
475
                                                                 nm_ip4_config_get_mss (parent_ip4));
 
476
 
 
477
                        dns_type = NM_DNS_IP_CONFIG_TYPE_VPN;
 
478
                }
 
479
        }
 
480
        g_slist_free (vpns);
 
481
 
 
482
        /* The best device gets the default route if a VPN connection didn't */
 
483
        if (!ip_iface || !ip4_config) {
 
484
                connection = nm_act_request_get_connection (best_req);
 
485
                ip_iface = nm_device_get_ip_iface (best);
 
486
                ip4_config = nm_device_get_ip4_config (best);
 
487
                g_assert (ip4_config);
 
488
                addr = nm_ip4_config_get_address (ip4_config, 0);
 
489
 
 
490
                nm_system_replace_default_ip4_route (ip_iface, nm_ip4_address_get_gateway (addr), nm_ip4_config_get_mss (ip4_config));
 
491
 
 
492
                dns_type = NM_DNS_IP_CONFIG_TYPE_BEST_DEVICE;
 
493
        }
 
494
 
 
495
        if (!ip_iface || !ip4_config) {
 
496
                nm_log_warn (LOGD_CORE, "couldn't determine IP interface (%p) or IPv4 config (%p)!",
 
497
                             ip_iface, ip4_config);
 
498
                goto out;
 
499
        }
 
500
 
 
501
        /* Update the default active connection.  Only mark the new default
 
502
         * active connection after setting default = FALSE on all other connections
 
503
         * first.  The order is important, we don't want two connections marked
 
504
         * default at the same time ever.
 
505
         */
 
506
        devices = nm_manager_get_devices (policy->manager);
 
507
        for (iter = devices; iter; iter = g_slist_next (iter)) {
 
508
                NMDevice *dev = NM_DEVICE (iter->data);
 
509
                NMActRequest *req;
 
510
 
 
511
                req = nm_device_get_act_request (dev);
 
512
                if (req && (req != best_req))
 
513
                        nm_act_request_set_default (req, FALSE);
 
514
        }
 
515
 
 
516
        dns_mgr = nm_dns_manager_get (NULL);
 
517
        nm_dns_manager_add_ip4_config (dns_mgr, ip_iface, ip4_config, dns_type);
 
518
        g_object_unref (dns_mgr);
 
519
 
 
520
        /* Now set new default active connection _after_ updating DNS info, so that
 
521
         * if the connection is shared dnsmasq picks up the right stuff.
 
522
         */
 
523
        if (best_req)
 
524
                nm_act_request_set_default (best_req, TRUE);
 
525
 
 
526
        if (connection)
 
527
                s_con = (NMSettingConnection *) nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION);
 
528
 
 
529
        connection_id = s_con ? nm_setting_connection_get_id (s_con) : NULL;
 
530
        if (connection_id) {
 
531
                nm_log_info (LOGD_CORE, "Policy set '%s' (%s) as default for IPv4 routing and DNS.", connection_id, ip_iface);
 
532
        } else {
 
533
                nm_log_info (LOGD_CORE, "Policy set (%s) as default for IPv4 routing and DNS.", ip_iface);
 
534
        }
 
535
 
 
536
out:
 
537
        policy->default_device4 = best;
 
538
}
 
539
 
 
540
static void
 
541
update_ip6_routing_and_dns (NMPolicy *policy, gboolean force_update)
 
542
{
 
543
        NMDnsIPConfigType dns_type = NM_DNS_IP_CONFIG_TYPE_BEST_DEVICE;
 
544
        NMDevice *best = NULL;
 
545
        NMActRequest *best_req = NULL;
 
546
        NMDnsManager *dns_mgr;
 
547
        GSList *devices = NULL, *iter;
 
548
#if 0
 
549
        GSList *vpns;
 
550
#endif
 
551
        NMIP6Config *ip6_config = NULL;
 
552
        NMIP6Address *addr;
 
553
        const char *ip_iface = NULL;
 
554
        NMConnection *connection = NULL;
 
555
        NMSettingConnection *s_con = NULL;
 
556
        const char *connection_id;
 
557
 
 
558
        best = get_best_ip6_device (policy->manager, &best_req);
 
559
        if (!best)
 
560
                goto out;
 
561
        if (!force_update && (best == policy->default_device6))
 
562
                goto out;
 
563
 
 
564
#if 0
 
565
        /* If a VPN connection is active, it is preferred */
 
566
        vpns = nm_vpn_manager_get_active_connections (policy->vpn_manager);
 
567
        for (iter = vpns; iter; iter = g_slist_next (iter)) {
 
568
                NMVPNConnection *candidate = NM_VPN_CONNECTION (iter->data);
 
569
                NMConnection *vpn_connection;
 
570
                NMSettingIP6Config *s_ip6;
 
571
                gboolean can_default = TRUE;
 
572
                NMVPNConnectionState vpn_state;
 
573
 
 
574
                /* If it's marked 'never-default', don't make it default */
 
575
                vpn_connection = nm_vpn_connection_get_connection (candidate);
 
576
                g_assert (vpn_connection);
 
577
                s_ip6 = (NMSettingIP6Config *) nm_connection_get_setting (vpn_connection, NM_TYPE_SETTING_IP6_CONFIG);
 
578
                if (s_ip6 && nm_setting_ip6_config_get_never_default (s_ip6))
 
579
                        can_default = FALSE;
 
580
 
 
581
                vpn_state = nm_vpn_connection_get_vpn_state (candidate);
 
582
                if (can_default && (vpn_state == NM_VPN_CONNECTION_STATE_ACTIVATED)) {
 
583
                        NMIP6Config *parent_ip6;
 
584
                        NMDevice *parent;
 
585
 
 
586
                        ip_iface = nm_vpn_connection_get_ip_iface (candidate);
 
587
                        connection = nm_vpn_connection_get_connection (candidate);
 
588
                        ip6_config = nm_vpn_connection_get_ip6_config (candidate);
 
589
                        addr = nm_ip6_config_get_address (ip6_config, 0);
 
590
 
 
591
                        parent = nm_vpn_connection_get_parent_device (candidate);
 
592
                        parent_ip6 = nm_device_get_ip6_config (parent);
 
593
 
 
594
                        nm_system_replace_default_ip6_route_vpn (ip_iface,
 
595
                                                                 nm_ip6_address_get_gateway (addr),
 
596
                                                                 nm_vpn_connection_get_ip4_internal_gateway (candidate),
 
597
                                                                 nm_ip6_config_get_mss (ip4_config),
 
598
                                                                 nm_device_get_ip_iface (parent),
 
599
                                                                 nm_ip6_config_get_mss (parent_ip4));
 
600
 
 
601
                        dns_type = NM_DNS_IP_CONFIG_TYPE_VPN;
 
602
                }
 
603
        }
 
604
        g_slist_free (vpns);
 
605
#endif
 
606
 
 
607
        /* The best device gets the default route if a VPN connection didn't */
 
608
        if (!ip_iface || !ip6_config) {
 
609
                connection = nm_act_request_get_connection (best_req);
 
610
                ip_iface = nm_device_get_ip_iface (best);
 
611
                ip6_config = nm_device_get_ip6_config (best);
 
612
                g_assert (ip6_config);
 
613
                addr = nm_ip6_config_get_address (ip6_config, 0);
 
614
 
 
615
                nm_system_replace_default_ip6_route (ip_iface, nm_ip6_address_get_gateway (addr));
 
616
 
 
617
                dns_type = NM_DNS_IP_CONFIG_TYPE_BEST_DEVICE;
 
618
        }
 
619
 
 
620
        if (!ip_iface || !ip6_config) {
 
621
                nm_log_warn (LOGD_CORE, "couldn't determine IP interface (%p) or IPv6 config (%p)!",
 
622
                             ip_iface, ip6_config);
 
623
                goto out;
 
624
        }
 
625
 
 
626
        /* Update the default active connection.  Only mark the new default
 
627
         * active connection after setting default = FALSE on all other connections
 
628
         * first.  The order is important, we don't want two connections marked
 
629
         * default at the same time ever.
 
630
         */
 
631
        devices = nm_manager_get_devices (policy->manager);
 
632
        for (iter = devices; iter; iter = g_slist_next (iter)) {
 
633
                NMDevice *dev = NM_DEVICE (iter->data);
 
634
                NMActRequest *req;
 
635
 
 
636
                req = nm_device_get_act_request (dev);
 
637
                if (req && (req != best_req))
 
638
                        nm_act_request_set_default6 (req, FALSE);
 
639
        }
 
640
 
 
641
        dns_mgr = nm_dns_manager_get (NULL);
 
642
        nm_dns_manager_add_ip6_config (dns_mgr, ip_iface, ip6_config, dns_type);
 
643
        g_object_unref (dns_mgr);
 
644
 
 
645
        /* Now set new default active connection _after_ updating DNS info, so that
 
646
         * if the connection is shared dnsmasq picks up the right stuff.
 
647
         */
 
648
        if (best_req)
 
649
                nm_act_request_set_default6 (best_req, TRUE);
 
650
 
 
651
        if (connection)
 
652
                s_con = (NMSettingConnection *) nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION);
 
653
 
 
654
        connection_id = s_con ? nm_setting_connection_get_id (s_con) : NULL;
 
655
        if (connection_id) {
 
656
                nm_log_info (LOGD_CORE, "Policy set '%s' (%s) as default for IPv6 routing and DNS.", connection_id, ip_iface);
 
657
        } else {
 
658
                nm_log_info (LOGD_CORE, "Policy set (%s) as default for IPv6 routing and DNS.", ip_iface);
 
659
        }
 
660
 
 
661
out:
 
662
        policy->default_device6 = best;
 
663
}
 
664
 
 
665
static void
 
666
update_routing_and_dns (NMPolicy *policy, gboolean force_update)
 
667
{
 
668
        update_ip4_routing_and_dns (policy, force_update);
 
669
        update_ip6_routing_and_dns (policy, force_update);
 
670
 
 
671
        /* Update the system hostname */
 
672
        update_system_hostname (policy, policy->default_device4, policy->default_device6);
 
673
}
 
674
 
 
675
static void
 
676
set_connection_auto_retries (NMConnection *connection, guint retries)
 
677
{
 
678
        /* add +1 so that the tag still exists if the # retries is 0 */
 
679
        g_object_set_data (G_OBJECT (connection), RETRIES_TAG, GUINT_TO_POINTER (retries + 1));
 
680
}
 
681
 
 
682
static guint32
 
683
get_connection_auto_retries (NMConnection *connection)
 
684
{
 
685
        /* subtract 1 to handle the +1 from set_connection_auto_retries() */
 
686
        return GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (connection), RETRIES_TAG)) - 1;
 
687
}
 
688
 
 
689
typedef struct {
 
690
        NMPolicy *policy;
 
691
        NMDevice *device;
 
692
        guint id;
 
693
} ActivateData;
 
694
 
 
695
static void
 
696
activate_data_free (ActivateData *data)
 
697
{
 
698
        if (data->id)
 
699
                g_source_remove (data->id);
 
700
        g_object_unref (data->device);
 
701
        memset (data, 0, sizeof (*data));
 
702
        g_free (data);
 
703
}
 
704
 
 
705
static gboolean
 
706
auto_activate_device (gpointer user_data)
 
707
{
 
708
        ActivateData *data = (ActivateData *) user_data;
 
709
        NMPolicy *policy;
 
710
        NMConnection *best_connection;
 
711
        char *specific_object = NULL;
 
712
        GSList *connections, *iter;
 
713
 
 
714
        g_assert (data);
 
715
        policy = data->policy;
 
716
 
 
717
        data->id = 0;
 
718
        policy->pending_activation_checks = g_slist_remove (policy->pending_activation_checks, data);
 
719
 
 
720
        // FIXME: if a device is already activating (or activated) with a connection
 
721
        // but another connection now overrides the current one for that device,
 
722
        // deactivate the device and activate the new connection instead of just
 
723
        // bailing if the device is already active
 
724
        if (nm_device_get_act_request (data->device))
 
725
                goto out;
 
726
 
 
727
        iter = connections = nm_settings_get_connections (policy->settings);
 
728
 
 
729
        /* Remove connections that shouldn't be auto-activated */
 
730
        while (iter) {
 
731
                NMSettingsConnection *candidate = NM_SETTINGS_CONNECTION (iter->data);
 
732
                gboolean remove_it = FALSE;
 
733
                const char *permission;
 
734
 
 
735
                /* Grab next item before we possibly delete the current item */
 
736
                iter = g_slist_next (iter);
 
737
 
 
738
                /* Ignore connections that were tried too many times or are not visible
 
739
                 * to any logged-in users.  Also ignore shared wifi connections for
 
740
                 * which no user has the shared wifi permission.
 
741
                 */
 
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)
 
754
                        connections = g_slist_remove (connections, candidate);
 
755
        }
 
756
 
 
757
        best_connection = nm_device_get_best_auto_connection (data->device, connections, &specific_object);
 
758
        if (best_connection) {
 
759
                GError *error = NULL;
 
760
 
 
761
                nm_log_info (LOGD_DEVICE, "Auto-activating connection '%s'.",
 
762
                             nm_connection_get_id (best_connection));
 
763
                if (!nm_manager_activate_connection (policy->manager,
 
764
                                                     best_connection,
 
765
                                                     specific_object,
 
766
                                                     nm_device_get_path (data->device),
 
767
                                                     NULL,
 
768
                                                     &error)) {
 
769
                        nm_log_info (LOGD_DEVICE, "Connection '%s' auto-activation failed: (%d) %s",
 
770
                                     nm_connection_get_id (best_connection), error->code, error->message);
 
771
                        g_error_free (error);
 
772
                }
 
773
        }
 
774
 
 
775
        g_slist_free (connections);
 
776
 
 
777
 out:
 
778
        activate_data_free (data);
 
779
        return FALSE;
 
780
}
 
781
 
 
782
static ActivateData *
 
783
activate_data_new (NMPolicy *policy, NMDevice *device, guint delay_seconds)
 
784
{
 
785
        ActivateData *data;
 
786
 
 
787
        data = g_malloc0 (sizeof (ActivateData));
 
788
        data->policy = policy;
 
789
        data->device = g_object_ref (device);
 
790
        if (delay_seconds > 0)
 
791
                data->id = g_timeout_add_seconds (delay_seconds, auto_activate_device, data);
 
792
        else
 
793
                data->id = g_idle_add (auto_activate_device, data);
 
794
        return data;
 
795
}
 
796
 
 
797
static ActivateData *
 
798
find_pending_activation (GSList *list, NMDevice *device)
 
799
{
 
800
        GSList *iter;
 
801
 
 
802
        for (iter = list; iter; iter = g_slist_next (iter)) {
 
803
                if (((ActivateData *) iter->data)->device == device)
 
804
                        return iter->data;
 
805
        }
 
806
        return NULL;
 
807
}
 
808
 
 
809
/*****************************************************************************/
 
810
 
 
811
static void
 
812
vpn_connection_activated (NMVPNManager *manager,
 
813
                          NMVPNConnection *vpn,
 
814
                          gpointer user_data)
 
815
{
 
816
        update_routing_and_dns ((NMPolicy *) user_data, TRUE);
 
817
}
 
818
 
 
819
static void
 
820
vpn_connection_deactivated (NMVPNManager *manager,
 
821
                            NMVPNConnection *vpn,
 
822
                            NMVPNConnectionState state,
 
823
                            NMVPNConnectionStateReason reason,
 
824
                            gpointer user_data)
 
825
{
 
826
        update_routing_and_dns ((NMPolicy *) user_data, TRUE);
 
827
}
 
828
 
 
829
static void
 
830
global_state_changed (NMManager *manager, NMState state, gpointer user_data)
 
831
{
 
832
}
 
833
 
 
834
static void
 
835
hostname_changed (NMManager *manager, GParamSpec *pspec, gpointer user_data)
 
836
{
 
837
        update_system_hostname ((NMPolicy *) user_data, NULL, NULL);
 
838
}
 
839
 
 
840
static void
 
841
reset_retries_all (NMSettings *settings, NMDevice *device)
 
842
{
 
843
        GSList *connections, *iter;
 
844
        GError *error = NULL;
 
845
 
 
846
        connections = nm_settings_get_connections (settings);
 
847
        for (iter = connections; iter; iter = g_slist_next (iter)) {
 
848
                if (!device || nm_device_interface_check_connection_compatible (NM_DEVICE_INTERFACE (device), iter->data, &error))
 
849
                        set_connection_auto_retries (NM_CONNECTION (iter->data), RETRIES_DEFAULT);
 
850
                g_clear_error (&error);
 
851
        }
 
852
        g_slist_free (connections);
 
853
}
 
854
 
 
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
 
873
sleeping_changed (NMManager *manager, GParamSpec *pspec, gpointer user_data)
 
874
{
 
875
        NMPolicy *policy = user_data;
 
876
        gboolean sleeping = FALSE, enabled = FALSE;
 
877
 
 
878
        g_object_get (G_OBJECT (manager), NM_MANAGER_SLEEPING, &sleeping, NULL);
 
879
        g_object_get (G_OBJECT (manager), NM_MANAGER_NETWORKING_ENABLED, &enabled, NULL);
 
880
 
 
881
        /* Reset retries on all connections so they'll checked on wakeup */
 
882
        if (sleeping || !enabled)
 
883
                reset_retries_all (policy->settings, NULL);
 
884
}
 
885
 
 
886
static void
 
887
schedule_activate_check (NMPolicy *policy, NMDevice *device, guint delay_seconds)
 
888
{
 
889
        ActivateData *data;
 
890
        NMDeviceState state;
 
891
 
 
892
        if (nm_manager_get_state (policy->manager) == NM_STATE_ASLEEP)
 
893
                return;
 
894
 
 
895
        state = nm_device_interface_get_state (NM_DEVICE_INTERFACE (device));
 
896
        if (state < NM_DEVICE_STATE_DISCONNECTED)
 
897
                return;
 
898
 
 
899
        if (!nm_device_autoconnect_allowed (device))
 
900
                return;
 
901
 
 
902
        /* Schedule an auto-activation if there isn't one already for this device */
 
903
        if (find_pending_activation (policy->pending_activation_checks, device) == NULL) {
 
904
                data = activate_data_new (policy, device, delay_seconds);
 
905
                policy->pending_activation_checks = g_slist_append (policy->pending_activation_checks, data);
 
906
        }
 
907
}
 
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
 
 
940
static NMConnection *
 
941
get_device_connection (NMDevice *device)
 
942
{
 
943
        NMActRequest *req;
 
944
 
 
945
        req = nm_device_get_act_request (device);
 
946
        if (!req)
 
947
                return NULL;
 
948
 
 
949
        return nm_act_request_get_connection (req);
 
950
}
 
951
 
 
952
static void
 
953
device_state_changed (NMDevice *device,
 
954
                      NMDeviceState new_state,
 
955
                      NMDeviceState old_state,
 
956
                      NMDeviceStateReason reason,
 
957
                      gpointer user_data)
 
958
{
 
959
        NMPolicy *policy = (NMPolicy *) user_data;
 
960
        NMConnection *connection = get_device_connection (device);
 
961
 
 
962
        if (connection)
 
963
                g_object_set_data (G_OBJECT (connection), FAILURE_REASON_TAG, GUINT_TO_POINTER (0));
 
964
 
 
965
        switch (new_state) {
 
966
        case NM_DEVICE_STATE_FAILED:
 
967
                /* Mark the connection invalid if it failed during activation so that
 
968
                 * it doesn't get automatically chosen over and over and over again.
 
969
                 */
 
970
                if (connection && IS_ACTIVATING_STATE (old_state)) {
 
971
                        guint32 tries = get_connection_auto_retries (connection);
 
972
 
 
973
                        if (reason == NM_DEVICE_STATE_REASON_NO_SECRETS) {
 
974
                                /* If the connection couldn't get the secrets it needed (ex because
 
975
                                 * the user canceled, or no secrets exist), there's no point in
 
976
                                 * automatically retrying because it's just going to fail anyway.
 
977
                                 */
 
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));
 
984
                        } else if (tries > 0) {
 
985
                                /* Otherwise if it's a random failure, just decrease the number
 
986
                                 * of automatic retries so that the connection gets tried again
 
987
                                 * if it still has a retry count.
 
988
                                 */
 
989
                                set_connection_auto_retries (connection, tries - 1);
 
990
                        }
 
991
 
 
992
                        if (get_connection_auto_retries (connection) == 0) {
 
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
                        }
 
999
                        nm_connection_clear_secrets (connection);
 
1000
                }
 
1001
                schedule_activate_check (policy, device, 3);
 
1002
                break;
 
1003
        case NM_DEVICE_STATE_ACTIVATED:
 
1004
                if (connection) {
 
1005
                        /* Reset auto retries back to default since connection was successful */
 
1006
                        set_connection_auto_retries (connection, RETRIES_DEFAULT);
 
1007
 
 
1008
                        /* And clear secrets so they will always be requested from the
 
1009
                         * settings service when the next connection is made.
 
1010
                         */
 
1011
                        nm_connection_clear_secrets (connection);
 
1012
                }
 
1013
 
 
1014
                update_routing_and_dns (policy, FALSE);
 
1015
                break;
 
1016
        case NM_DEVICE_STATE_UNMANAGED:
 
1017
        case NM_DEVICE_STATE_UNAVAILABLE:
 
1018
                update_routing_and_dns (policy, FALSE);
 
1019
                break;
 
1020
        case NM_DEVICE_STATE_DISCONNECTED:
 
1021
                /* Reset RETRIES_TAG when carrier on. If cable was unplugged
 
1022
                 * and plugged again, we should try to reconnect */
 
1023
                if (reason == NM_DEVICE_STATE_REASON_CARRIER && old_state == NM_DEVICE_STATE_UNAVAILABLE)
 
1024
                        reset_retries_all (policy->settings, device);
 
1025
 
 
1026
                /* Device is now available for auto-activation */
 
1027
                update_routing_and_dns (policy, FALSE);
 
1028
                schedule_activate_check (policy, device, 0);
 
1029
                break;
 
1030
        default:
 
1031
                break;
 
1032
        }
 
1033
}
 
1034
 
 
1035
static void
 
1036
device_ip_config_changed (NMDevice *device,
 
1037
                          GParamSpec *pspec,
 
1038
                          gpointer user_data)
 
1039
{
 
1040
        update_routing_and_dns ((NMPolicy *) user_data, TRUE);
 
1041
}
 
1042
 
 
1043
static void
 
1044
wireless_networks_changed (NMDeviceWifi *device, NMAccessPoint *ap, gpointer user_data)
 
1045
{
 
1046
        schedule_activate_check ((NMPolicy *) user_data, NM_DEVICE (device), 0);
 
1047
}
 
1048
 
 
1049
#if WITH_WIMAX
 
1050
static void
 
1051
nsps_changed (NMDeviceWimax *device, NMWimaxNsp *nsp, gpointer user_data)
 
1052
{
 
1053
        schedule_activate_check ((NMPolicy *) user_data, NM_DEVICE (device), 0);
 
1054
}
 
1055
#endif
 
1056
 
 
1057
typedef struct {
 
1058
        gulong id;
 
1059
        NMDevice *device;
 
1060
} DeviceSignalId;
 
1061
 
 
1062
static void
 
1063
_connect_device_signal (NMPolicy *policy, NMDevice *device, const char *name, gpointer callback)
 
1064
{
 
1065
        DeviceSignalId *data;
 
1066
 
 
1067
        data = g_slice_new0 (DeviceSignalId);
 
1068
        g_assert (data);
 
1069
        data->id = g_signal_connect (device, name, callback, policy);
 
1070
        data->device = device;
 
1071
        policy->dev_ids = g_slist_prepend (policy->dev_ids, data);
 
1072
}
 
1073
 
 
1074
static void
 
1075
device_added (NMManager *manager, NMDevice *device, gpointer user_data)
 
1076
{
 
1077
        NMPolicy *policy = (NMPolicy *) user_data;
 
1078
 
 
1079
        _connect_device_signal (policy, device, "state-changed", device_state_changed);
 
1080
        _connect_device_signal (policy, device, "notify::" NM_DEVICE_INTERFACE_IP4_CONFIG, device_ip_config_changed);
 
1081
        _connect_device_signal (policy, device, "notify::" NM_DEVICE_INTERFACE_IP6_CONFIG, device_ip_config_changed);
 
1082
 
 
1083
        if (NM_IS_DEVICE_WIFI (device)) {
 
1084
                _connect_device_signal (policy, device, "access-point-added", wireless_networks_changed);
 
1085
                _connect_device_signal (policy, device, "access-point-removed", wireless_networks_changed);
 
1086
#if WITH_WIMAX
 
1087
        } else if (NM_IS_DEVICE_WIMAX (device)) {
 
1088
                _connect_device_signal (policy, device, "nsp-added", nsps_changed);
 
1089
                _connect_device_signal (policy, device, "nsp-removed", nsps_changed);
 
1090
#endif
 
1091
        }
 
1092
}
 
1093
 
 
1094
static void
 
1095
device_removed (NMManager *manager, NMDevice *device, gpointer user_data)
 
1096
{
 
1097
        NMPolicy *policy = (NMPolicy *) user_data;
 
1098
        ActivateData *tmp;
 
1099
        GSList *iter;
 
1100
 
 
1101
        /* Clear any idle callbacks for this device */
 
1102
        tmp = find_pending_activation (policy->pending_activation_checks, device);
 
1103
        if (tmp) {
 
1104
                policy->pending_activation_checks = g_slist_remove (policy->pending_activation_checks, tmp);
 
1105
                activate_data_free (tmp);
 
1106
        }
 
1107
 
 
1108
        /* Clear any signal handlers for this device */
 
1109
        iter = policy->dev_ids;
 
1110
        while (iter) {
 
1111
                DeviceSignalId *data = iter->data;
 
1112
                GSList *next = g_slist_next (iter);
 
1113
 
 
1114
                if (data->device == device) {
 
1115
                        g_signal_handler_disconnect (data->device, data->id);
 
1116
                        g_slice_free (DeviceSignalId, data);
 
1117
                        policy->dev_ids = g_slist_delete_link (policy->dev_ids, iter);
 
1118
                }
 
1119
                iter = next;
 
1120
        }
 
1121
 
 
1122
        update_routing_and_dns (policy, FALSE);
 
1123
}
 
1124
 
 
1125
static void
 
1126
schedule_activate_all (NMPolicy *policy)
 
1127
{
 
1128
        GSList *iter, *devices;
 
1129
 
 
1130
        devices = nm_manager_get_devices (policy->manager);
 
1131
        for (iter = devices; iter; iter = g_slist_next (iter))
 
1132
                schedule_activate_check (policy, NM_DEVICE (iter->data), 0);
 
1133
}
 
1134
 
 
1135
static void
 
1136
connection_added (NMSettings *settings,
 
1137
                  NMConnection *connection,
 
1138
                  gpointer user_data)
 
1139
{
 
1140
        set_connection_auto_retries (connection, RETRIES_DEFAULT);
 
1141
        schedule_activate_all ((NMPolicy *) user_data);
 
1142
}
 
1143
 
 
1144
static void
 
1145
connections_loaded (NMSettings *settings, gpointer user_data)
 
1146
{
 
1147
        // FIXME: "connections-loaded" signal is emmitted *before* we connect to it
 
1148
        // in nm_policy_new(). So this function is never called. Currently we work around
 
1149
        // that by calling reset_retries_all() in nm_policy_new()
 
1150
        
 
1151
        /* Initialize connections' auto-retries */
 
1152
        reset_retries_all (settings, NULL);
 
1153
 
 
1154
        schedule_activate_all ((NMPolicy *) user_data);
 
1155
}
 
1156
 
 
1157
static void
 
1158
connection_updated (NMSettings *settings,
 
1159
                    NMConnection *connection,
 
1160
                    gpointer user_data)
 
1161
{
 
1162
        /* Reset auto retries back to default since connection was updated */
 
1163
        set_connection_auto_retries (connection, RETRIES_DEFAULT);
 
1164
 
 
1165
        schedule_activate_all ((NMPolicy *) user_data);
 
1166
}
 
1167
 
 
1168
static void
 
1169
_deactivate_if_active (NMManager *manager, NMConnection *connection)
 
1170
{
 
1171
        GPtrArray *list;
 
1172
        int i;
 
1173
 
 
1174
        list = nm_manager_get_active_connections_by_connection (manager, connection);
 
1175
        if (!list)
 
1176
                return;
 
1177
 
 
1178
        for (i = 0; i < list->len; i++) {
 
1179
                char *path = g_ptr_array_index (list, i);
 
1180
                GError *error = NULL;
 
1181
 
 
1182
                if (!nm_manager_deactivate_connection (manager, path, NM_DEVICE_STATE_REASON_CONNECTION_REMOVED, &error)) {
 
1183
                        nm_log_warn (LOGD_DEVICE, "Connection '%s' disappeared, but error deactivating it: (%d) %s",
 
1184
                                     nm_connection_get_id (connection), error->code, error->message);
 
1185
                        g_error_free (error);
 
1186
                }
 
1187
                g_free (path);
 
1188
        }
 
1189
        g_ptr_array_free (list, TRUE);
 
1190
}
 
1191
 
 
1192
static void
 
1193
connection_removed (NMSettings *settings,
 
1194
                    NMConnection *connection,
 
1195
                    gpointer user_data)
 
1196
{
 
1197
        NMPolicy *policy = user_data;
 
1198
 
 
1199
        _deactivate_if_active (policy->manager, connection);
 
1200
}
 
1201
 
 
1202
static void
 
1203
connection_visibility_changed (NMSettings *settings,
 
1204
                               NMSettingsConnection *connection,
 
1205
                               gpointer user_data)
 
1206
{
 
1207
        NMPolicy *policy = user_data;
 
1208
 
 
1209
        if (nm_settings_connection_is_visible (connection))
 
1210
                schedule_activate_all (policy);
 
1211
        else
 
1212
                _deactivate_if_active (policy->manager, NM_CONNECTION (connection));
 
1213
}
 
1214
 
 
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
 
1229
_connect_manager_signal (NMPolicy *policy, const char *name, gpointer callback)
 
1230
{
 
1231
        guint id;
 
1232
 
 
1233
        id = g_signal_connect (policy->manager, name, callback, policy);
 
1234
        policy->manager_ids = g_slist_prepend (policy->manager_ids, GUINT_TO_POINTER (id));
 
1235
}
 
1236
 
 
1237
static void
 
1238
_connect_settings_signal (NMPolicy *policy, const char *name, gpointer callback)
 
1239
{
 
1240
        guint id;
 
1241
 
 
1242
        id = g_signal_connect (policy->settings, name, callback, policy);
 
1243
        policy->settings_ids = g_slist_prepend (policy->settings_ids, GUINT_TO_POINTER (id));
 
1244
}
 
1245
 
 
1246
NMPolicy *
 
1247
nm_policy_new (NMManager *manager,
 
1248
               NMVPNManager *vpn_manager,
 
1249
               NMSettings *settings)
 
1250
{
 
1251
        NMPolicy *policy;
 
1252
        static gboolean initialized = FALSE;
 
1253
        gulong id;
 
1254
        char hostname[HOST_NAME_MAX + 2];
 
1255
 
 
1256
        g_return_val_if_fail (NM_IS_MANAGER (manager), NULL);
 
1257
        g_return_val_if_fail (initialized == FALSE, NULL);
 
1258
 
 
1259
        policy = g_malloc0 (sizeof (NMPolicy));
 
1260
        policy->manager = g_object_ref (manager);
 
1261
        policy->settings = g_object_ref (settings);
 
1262
        policy->update_state_id = 0;
 
1263
 
 
1264
        /* Grab hostname on startup and use that if nothing provides one */
 
1265
        memset (hostname, 0, sizeof (hostname));
 
1266
        if (gethostname (&hostname[0], HOST_NAME_MAX) == 0) {
 
1267
                /* only cache it if it's a valid hostname */
 
1268
                if (   strlen (hostname)
 
1269
                    && strcmp (hostname, "localhost")
 
1270
                    && strcmp (hostname, "localhost.localdomain")
 
1271
                    && strcmp (hostname, "(none)"))
 
1272
                        policy->orig_hostname = g_strdup (hostname);
 
1273
        }
 
1274
 
 
1275
        policy->vpn_manager = g_object_ref (vpn_manager);
 
1276
        id = g_signal_connect (policy->vpn_manager, "connection-activated",
 
1277
                               G_CALLBACK (vpn_connection_activated), policy);
 
1278
        policy->vpn_activated_id = id;
 
1279
        id = g_signal_connect (policy->vpn_manager, "connection-deactivated",
 
1280
                               G_CALLBACK (vpn_connection_deactivated), policy);
 
1281
        policy->vpn_deactivated_id = id;
 
1282
 
 
1283
        _connect_manager_signal (policy, "state-changed", global_state_changed);
 
1284
        _connect_manager_signal (policy, "notify::" NM_MANAGER_HOSTNAME, hostname_changed);
 
1285
        _connect_manager_signal (policy, "notify::" NM_MANAGER_SLEEPING, sleeping_changed);
 
1286
        _connect_manager_signal (policy, "notify::" NM_MANAGER_NETWORKING_ENABLED, sleeping_changed);
 
1287
        _connect_manager_signal (policy, "device-added", device_added);
 
1288
        _connect_manager_signal (policy, "device-removed", device_removed);
 
1289
 
 
1290
        _connect_settings_signal (policy, NM_SETTINGS_SIGNAL_CONNECTIONS_LOADED, connections_loaded);
 
1291
        _connect_settings_signal (policy, NM_SETTINGS_SIGNAL_CONNECTION_ADDED, connection_added);
 
1292
        _connect_settings_signal (policy, NM_SETTINGS_SIGNAL_CONNECTION_UPDATED, connection_updated);
 
1293
        _connect_settings_signal (policy, NM_SETTINGS_SIGNAL_CONNECTION_REMOVED, connection_removed);
 
1294
        _connect_settings_signal (policy, NM_SETTINGS_SIGNAL_CONNECTION_VISIBILITY_CHANGED,
 
1295
                                  connection_visibility_changed);
 
1296
        _connect_settings_signal (policy, NM_SETTINGS_SIGNAL_AGENT_REGISTERED, secret_agent_registered);
 
1297
 
 
1298
        /* Initialize connections' auto-retries */
 
1299
        reset_retries_all (policy->settings, NULL);
 
1300
 
 
1301
        initialized = TRUE;
 
1302
        return policy;
 
1303
}
 
1304
 
 
1305
void
 
1306
nm_policy_destroy (NMPolicy *policy)
 
1307
{
 
1308
        GSList *iter;
 
1309
 
 
1310
        g_return_if_fail (policy != NULL);
 
1311
 
 
1312
        /* Tell any existing hostname lookup thread to die, it'll get cleaned up
 
1313
         * by the lookup thread callback.
 
1314
          */
 
1315
        if (policy->lookup) {
 
1316
                hostname_thread_kill (policy->lookup);
 
1317
                policy->lookup = NULL;
 
1318
        }
 
1319
 
 
1320
        g_slist_foreach (policy->pending_activation_checks, (GFunc) activate_data_free, NULL);
 
1321
        g_slist_free (policy->pending_activation_checks);
 
1322
 
 
1323
        g_signal_handler_disconnect (policy->vpn_manager, policy->vpn_activated_id);
 
1324
        g_signal_handler_disconnect (policy->vpn_manager, policy->vpn_deactivated_id);
 
1325
        g_object_unref (policy->vpn_manager);
 
1326
 
 
1327
        for (iter = policy->manager_ids; iter; iter = g_slist_next (iter))
 
1328
                g_signal_handler_disconnect (policy->manager, GPOINTER_TO_UINT (iter->data));
 
1329
        g_slist_free (policy->manager_ids);
 
1330
 
 
1331
        for (iter = policy->settings_ids; iter; iter = g_slist_next (iter))
 
1332
                g_signal_handler_disconnect (policy->settings, GPOINTER_TO_UINT (iter->data));
 
1333
        g_slist_free (policy->settings_ids);
 
1334
 
 
1335
        for (iter = policy->dev_ids; iter; iter = g_slist_next (iter)) {
 
1336
                DeviceSignalId *data = iter->data;
 
1337
 
 
1338
                g_signal_handler_disconnect (data->device, data->id);
 
1339
                g_slice_free (DeviceSignalId, data);
 
1340
        }
 
1341
        g_slist_free (policy->dev_ids);
 
1342
 
 
1343
        if (policy->reset_retries_id)
 
1344
                g_source_remove (policy->reset_retries_id);
 
1345
 
 
1346
        g_free (policy->orig_hostname);
 
1347
        g_free (policy->cur_hostname);
 
1348
 
 
1349
        g_object_unref (policy->settings);
 
1350
        g_object_unref (policy->manager);
 
1351
        g_free (policy);
 
1352
}
 
1353