ip6: don't 'assume' IPv6 connections (bgo #676740)
[NetworkManager.git] / src / nm-device.c
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) 2005 - 2012 Red Hat, Inc.
19  * Copyright (C) 2006 - 2008 Novell, Inc.
20  */
21
22 #include <config.h>
23 #include <glib.h>
24 #include <glib/gi18n.h>
25 #include <dbus/dbus.h>
26 #include <netinet/in.h>
27 #include <string.h>
28 #include <unistd.h>
29 #include <errno.h>
30 #include <sys/ioctl.h>
31 #include <signal.h>
32 #include <sys/types.h>
33 #include <sys/wait.h>
34 #include <arpa/inet.h>
35 #include <fcntl.h>
36 #include <linux/if.h>
37
38 #include "nm-glib-compat.h"
39 #include "nm-device.h"
40 #include "nm-device-private.h"
41 #include "backends/nm-backend.h"
42 #include "NetworkManagerUtils.h"
43 #include "nm-system.h"
44 #include "nm-dhcp-manager.h"
45 #include "nm-dbus-manager.h"
46 #include "nm-dns-manager.h"
47 #include "nm-utils.h"
48 #include "nm-logging.h"
49 #include "nm-netlink-monitor.h"
50 #include "nm-netlink-utils.h"
51 #include "nm-netlink-compat.h"
52 #include "nm-setting-ip4-config.h"
53 #include "nm-setting-ip6-config.h"
54 #include "nm-setting-connection.h"
55 #include "nm-dnsmasq-manager.h"
56 #include "nm-dhcp4-config.h"
57 #include "nm-ip6-manager.h"
58 #include "nm-marshal.h"
59 #include "nm-rfkill.h"
60 #include "nm-firewall-manager.h"
61 #include "nm-properties-changed-signal.h"
62 #include "nm-enum-types.h"
63 #include "nm-settings-connection.h"
64 #include "nm-connection-provider.h"
65 #include "nm-posix-signals.h"
66
67 static void impl_device_disconnect (NMDevice *device, DBusGMethodInvocation *context);
68
69 #include "nm-device-interface-glue.h"
70
71 #define PENDING_IP4_CONFIG "pending-ip4-config"
72 #define PENDING_IP6_CONFIG "pending-ip6-config"
73
74 #define DBUS_G_TYPE_UINT_STRUCT (dbus_g_type_get_struct ("GValueArray", G_TYPE_UINT, G_TYPE_UINT, G_TYPE_INVALID))
75
76 /***********************************************************/
77 #define NM_DEVICE_ERROR (nm_device_error_quark ())
78
79 static GQuark
80 nm_device_error_quark (void)
81 {
82         static GQuark quark = 0;
83         if (!quark)
84                 quark = g_quark_from_static_string ("nm-device-error");
85         return quark;
86 }
87
88 /***********************************************************/
89
90 enum {
91         STATE_CHANGED,
92         DISCONNECT_REQUEST,
93         AUTOCONNECT_ALLOWED,
94         LAST_SIGNAL,
95 };
96 static guint signals[LAST_SIGNAL] = { 0 };
97
98 enum {
99         PROP_0,
100         PROP_UDI,
101         PROP_IFACE,
102         PROP_IP_IFACE,
103         PROP_DRIVER,
104         PROP_CAPABILITIES,
105         PROP_IP4_ADDRESS,
106         PROP_IP4_CONFIG,
107         PROP_DHCP4_CONFIG,
108         PROP_IP6_CONFIG,
109         PROP_DHCP6_CONFIG,
110         PROP_STATE,
111         PROP_STATE_REASON,
112         PROP_ACTIVE_CONNECTION,
113         PROP_DEVICE_TYPE,
114         PROP_MANAGED,
115         PROP_AUTOCONNECT,
116         PROP_FIRMWARE_MISSING,
117         PROP_TYPE_DESC,
118         PROP_RFKILL_TYPE,
119         PROP_IFINDEX,
120         LAST_PROP
121 };
122
123 #define DEFAULT_AUTOCONNECT TRUE
124
125 /***********************************************************/
126
127 G_DEFINE_ABSTRACT_TYPE (NMDevice, nm_device, G_TYPE_OBJECT)
128
129 #define NM_DEVICE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE, NMDevicePrivate))
130
131 typedef enum {
132         IP_NONE = 0,
133         IP_CONF,
134         IP_DONE
135 } IpState;
136
137 typedef struct {
138         NMDeviceState state;
139         NMDeviceStateReason reason;
140         guint id;
141 } QueuedState;
142
143 typedef struct {
144         gboolean disposed;
145         gboolean initialized;
146
147         NMDeviceState state;
148         NMDeviceStateReason state_reason;
149         QueuedState   queued_state;
150
151         char *        udi;
152         char *        path;
153         char *        iface;   /* may change, could be renamed by user */
154         int           ifindex;
155         char *        ip_iface;
156         int           ip_ifindex;
157         NMDeviceType  type;
158         char *        type_desc;
159         guint32       capabilities;
160         char *        driver;
161         gboolean      managed; /* whether managed by NM or not */
162         RfKillType    rfkill_type;
163         gboolean      firmware_missing;
164
165         guint32         ip4_address;
166
167         NMActRequest *  act_request;
168         guint           act_source_id;
169         gpointer        act_source_func;
170         guint           act_source6_id;
171         gpointer        act_source6_func;
172         guint           act_dep_result_id;
173         guint           act_dep_timeout_id;
174         gulong          secrets_updated_id;
175         gulong          secrets_failed_id;
176
177         /* Generic DHCP stuff */
178         NMDHCPManager * dhcp_manager;
179         guint32         dhcp_timeout;
180         GByteArray *    dhcp_anycast_address;
181
182         /* IP4 configuration info */
183         NMIP4Config *   ip4_config;                     /* Config from DHCP, PPP, or system config files */
184         IpState         ip4_state;
185         NMDHCPClient *  dhcp4_client;
186         gulong          dhcp4_state_sigid;
187         gulong          dhcp4_timeout_sigid;
188         NMDHCP4Config * dhcp4_config;
189
190         /* dnsmasq stuff for shared connections */
191         NMDnsMasqManager *dnsmasq_manager;
192         gulong            dnsmasq_state_id;
193
194         /* Firewall Manager */
195         NMFirewallManager *fw_manager;
196         DBusGProxyCall    *fw_call;
197
198         /* avahi-autoipd stuff */
199         GPid    aipd_pid;
200         guint   aipd_watch;
201         guint   aipd_timeout;
202
203         /* IP6 configuration info */
204         NMIP6Config *  ip6_config;
205         IpState        ip6_state;
206
207         NMIP6Manager * ip6_manager;
208         gulong         ip6_addrconf_sigid;
209         gulong         ip6_config_changed_sigid;
210         gboolean       ip6_waiting_for_config;
211         /* IP6 config from autoconf */
212         NMIP6Config *  ac_ip6_config;
213
214         char *         ip6_accept_ra_path;
215         gint32         ip6_accept_ra_save;
216
217         /* IPv6 privacy extensions (RFC4941) */
218         char *         ip6_privacy_tempaddr_path;
219         gint32         ip6_privacy_tempaddr_save;
220
221         NMDHCPClient *  dhcp6_client;
222         guint32         dhcp6_mode;
223         gulong          dhcp6_state_sigid;
224         gulong          dhcp6_timeout_sigid;
225         NMDHCP6Config * dhcp6_config;
226         /* IP6 config from DHCP */
227         NMIP6Config *   dhcp6_ip6_config;
228
229         /* allow autoconnect feature */
230         gboolean        autoconnect;
231
232         /* master interface for bridge, bond, vlan, etc */
233         NMDevice *      master;
234
235         NMConnectionProvider *con_provider;
236 } NMDevicePrivate;
237
238 static void nm_device_take_down (NMDevice *dev, gboolean wait, NMDeviceStateReason reason);
239
240 static gboolean nm_device_bring_up (NMDevice *self, gboolean block, gboolean *no_firmware);
241 static gboolean nm_device_is_up (NMDevice *self);
242
243 static gboolean nm_device_set_ip4_config (NMDevice *dev,
244                                           NMIP4Config *config,
245                                           gboolean assumed,
246                                           NMDeviceStateReason *reason);
247 static gboolean nm_device_set_ip6_config (NMDevice *dev,
248                                           NMIP6Config *config,
249                                           NMDeviceStateReason *reason);
250
251 static gboolean nm_device_activate_ip6_config_commit (gpointer user_data);
252
253 static void dhcp4_cleanup (NMDevice *self, gboolean stop, gboolean release);
254
255 static const char *reason_to_string (NMDeviceStateReason reason);
256
257 static void
258 nm_device_init (NMDevice *self)
259 {
260         NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
261
262         priv->type = NM_DEVICE_TYPE_UNKNOWN;
263         priv->capabilities = NM_DEVICE_CAP_NONE;
264         priv->state = NM_DEVICE_STATE_UNMANAGED;
265         priv->state_reason = NM_DEVICE_STATE_REASON_NONE;
266         priv->dhcp_timeout = 0;
267         priv->rfkill_type = RFKILL_TYPE_UNKNOWN;
268         priv->autoconnect = DEFAULT_AUTOCONNECT;
269 }
270
271 static void
272 update_accept_ra_save (NMDevice *self)
273 {
274         NMDevicePrivate *priv;
275         const char *ip_iface;
276         char *new_path;
277
278         g_return_if_fail (self != NULL);
279         g_return_if_fail (NM_IS_DEVICE (self));
280
281         priv = NM_DEVICE_GET_PRIVATE (self);
282         ip_iface = nm_device_get_ip_iface (self);
283
284         new_path = g_strdup_printf ("/proc/sys/net/ipv6/conf/%s/accept_ra", ip_iface);
285         g_assert (new_path);
286
287         if (priv->ip6_accept_ra_path) {
288                 /* If the IP iface is different from before, use the new value */
289                 if (!strcmp (new_path, priv->ip6_accept_ra_path)) {
290                         g_free (new_path);
291                         return;
292                 }
293                 g_free (priv->ip6_accept_ra_path);
294         }
295
296         /* Grab the original value of "accept_ra" so we can restore it when NM exits */
297         priv->ip6_accept_ra_path = new_path;
298         if (!nm_utils_get_proc_sys_net_value_with_bounds (priv->ip6_accept_ra_path,
299                                                           ip_iface,
300                                                           &priv->ip6_accept_ra_save,
301                                                           0, 1)) {
302                 g_free (priv->ip6_accept_ra_path);
303                 priv->ip6_accept_ra_path = NULL;
304         }
305 }
306
307 static void
308 update_ip6_privacy_save (NMDevice *self)
309 {
310         NMDevicePrivate *priv;
311         const char *ip_iface;
312         char *new_path;
313
314         g_return_if_fail (self != NULL);
315         g_return_if_fail (NM_IS_DEVICE (self));
316
317         priv = NM_DEVICE_GET_PRIVATE (self);
318         ip_iface = nm_device_get_ip_iface (self);
319
320         new_path = g_strdup_printf ("/proc/sys/net/ipv6/conf/%s/use_tempaddr", ip_iface);
321         g_assert (new_path);
322
323         if (priv->ip6_privacy_tempaddr_path) {
324                 /* If the IP iface is different from before, use the new value */
325                 if (!strcmp (new_path, priv->ip6_privacy_tempaddr_path)) {
326                         g_free (new_path);
327                         return;
328                 }
329                 g_free (priv->ip6_privacy_tempaddr_path);
330         }
331
332         /* Grab the original value of "use_tempaddr" so we can restore it when NM exits */
333         priv->ip6_privacy_tempaddr_path = new_path;
334         if (!nm_utils_get_proc_sys_net_value (priv->ip6_privacy_tempaddr_path,
335                                               ip_iface,
336                                               &priv->ip6_privacy_tempaddr_save)) {
337                 g_free (priv->ip6_privacy_tempaddr_path);
338                 priv->ip6_privacy_tempaddr_path = NULL;
339         }
340 }
341
342 static GObject*
343 constructor (GType type,
344                          guint n_construct_params,
345                          GObjectConstructParam *construct_params)
346 {
347         GObject *object;
348         NMDevice *dev;
349         NMDevicePrivate *priv;
350
351         object = G_OBJECT_CLASS (nm_device_parent_class)->constructor (type,
352                                                                                                            n_construct_params,
353                                                                                                            construct_params);
354         if (!object)
355                 return NULL;
356
357         dev = NM_DEVICE (object);
358         priv = NM_DEVICE_GET_PRIVATE (dev);
359
360         if (!priv->udi) {
361                 nm_log_err (LOGD_DEVICE, "No device udi provided, ignoring");
362                 goto error;
363         }
364
365         if (!priv->iface) {
366                 nm_log_err (LOGD_DEVICE, "No device interface provided, ignoring");
367                 goto error;
368         }
369
370         priv->capabilities |= NM_DEVICE_GET_CLASS (dev)->get_generic_capabilities (dev);
371         if (!(priv->capabilities & NM_DEVICE_CAP_NM_SUPPORTED)) {
372                 nm_log_warn (LOGD_DEVICE, "(%s): Device unsupported, ignoring.", priv->iface);
373                 goto error;
374         }
375
376         priv->dhcp_manager = nm_dhcp_manager_get ();
377
378         priv->fw_manager = nm_firewall_manager_get ();
379
380         update_accept_ra_save (dev);
381         update_ip6_privacy_save (dev);
382
383         priv->initialized = TRUE;
384         return object;
385
386 error:
387         g_object_unref (dev);
388         return NULL;
389 }
390
391 static void
392 constructed (GObject *object)
393 {
394         NMDevice *dev = NM_DEVICE (object);
395
396         if (NM_DEVICE_GET_CLASS (dev)->update_hw_address)
397                 NM_DEVICE_GET_CLASS (dev)->update_hw_address (dev);
398
399         if (NM_DEVICE_GET_CLASS (dev)->update_permanent_hw_address)
400                 NM_DEVICE_GET_CLASS (dev)->update_permanent_hw_address (dev);
401
402         if (NM_DEVICE_GET_CLASS (dev)->update_initial_hw_address)
403                 NM_DEVICE_GET_CLASS (dev)->update_initial_hw_address (dev);
404
405         if (G_OBJECT_CLASS (nm_device_parent_class)->constructed)
406                 G_OBJECT_CLASS (nm_device_parent_class)->constructed (object);
407 }
408
409 static gboolean
410 nm_device_hw_is_up (NMDevice *self)
411 {
412         g_return_val_if_fail (NM_IS_DEVICE (self), FALSE);
413
414         if (NM_DEVICE_GET_CLASS (self)->hw_is_up)
415                 return NM_DEVICE_GET_CLASS (self)->hw_is_up (self);
416
417         return TRUE;
418 }
419
420 static guint32
421 real_get_generic_capabilities (NMDevice *dev)
422 {
423         return 0;
424 }
425
426 void
427 nm_device_set_path (NMDevice *self, const char *path)
428 {
429         NMDevicePrivate *priv;
430
431         g_return_if_fail (self != NULL);
432
433         priv = NM_DEVICE_GET_PRIVATE (self);
434         g_return_if_fail (priv->path == NULL);
435
436         priv->path = g_strdup (path);
437 }
438
439 const char *
440 nm_device_get_path (NMDevice *self)
441 {
442         g_return_val_if_fail (self != NULL, NULL);
443
444         return NM_DEVICE_GET_PRIVATE (self)->path;
445 }
446
447 const char *
448 nm_device_get_udi (NMDevice *self)
449 {
450         g_return_val_if_fail (self != NULL, NULL);
451
452         return NM_DEVICE_GET_PRIVATE (self)->udi;
453 }
454
455 /*
456  * Get/set functions for iface
457  */
458 const char *
459 nm_device_get_iface (NMDevice *self)
460 {
461         g_return_val_if_fail (self != NULL, NULL);
462
463         return NM_DEVICE_GET_PRIVATE (self)->iface;
464 }
465
466 int
467 nm_device_get_ifindex (NMDevice *self)
468 {
469         g_return_val_if_fail (self != NULL, 0);
470
471         return NM_DEVICE_GET_PRIVATE (self)->ifindex;
472 }
473
474 const char *
475 nm_device_get_ip_iface (NMDevice *self)
476 {
477         NMDevicePrivate *priv;
478
479         g_return_val_if_fail (self != NULL, NULL);
480
481         priv = NM_DEVICE_GET_PRIVATE (self);
482         /* If it's not set, default to iface */
483         return priv->ip_iface ? priv->ip_iface : priv->iface;
484 }
485
486 int
487 nm_device_get_ip_ifindex (NMDevice *self)
488 {
489         NMDevicePrivate *priv;
490
491         g_return_val_if_fail (self != NULL, 0);
492
493         priv = NM_DEVICE_GET_PRIVATE (self);
494         /* If it's not set, default to iface */
495         return priv->ip_iface ? priv->ip_ifindex : priv->ifindex;
496 }
497
498 void
499 nm_device_set_ip_iface (NMDevice *self, const char *iface)
500 {
501         NMDevicePrivate *priv;
502         char *old_ip_iface;
503
504         g_return_if_fail (NM_IS_DEVICE (self));
505
506         priv = NM_DEVICE_GET_PRIVATE (self);
507         old_ip_iface = priv->ip_iface;
508         priv->ip_ifindex = 0;
509
510         priv->ip_iface = g_strdup (iface);
511         if (priv->ip_iface) {
512                 priv->ip_ifindex = nm_netlink_iface_to_index (priv->ip_iface);
513                 if (priv->ip_ifindex <= 0) {
514                         /* Device IP interface must always be a kernel network interface */
515                         nm_log_warn (LOGD_HW, "(%s): failed to look up interface index", iface);
516                 }
517         }
518
519         /* Emit change notification */
520         if (g_strcmp0 (old_ip_iface, priv->ip_iface))
521                 g_object_notify (G_OBJECT (self), NM_DEVICE_IP_IFACE);
522         g_free (old_ip_iface);
523 }
524
525
526 /*
527  * Get/set functions for driver
528  */
529 const char *
530 nm_device_get_driver (NMDevice *self)
531 {
532         g_return_val_if_fail (self != NULL, NULL);
533
534         return NM_DEVICE_GET_PRIVATE (self)->driver;
535 }
536
537
538 /*
539  * Get/set functions for type
540  */
541 NMDeviceType
542 nm_device_get_device_type (NMDevice *self)
543 {
544         g_return_val_if_fail (NM_IS_DEVICE (self), NM_DEVICE_TYPE_UNKNOWN);
545
546         return NM_DEVICE_GET_PRIVATE (self)->type;
547 }
548
549
550 /**
551  * nm_device_get_priority():
552  * @dev: the #NMDevice
553  *
554  * Returns: the device's routing priority.  Lower numbers means a "better"
555  *  device, eg higher priority.
556  */
557 int
558 nm_device_get_priority (NMDevice *dev)
559 {
560         g_return_val_if_fail (NM_IS_DEVICE (dev), 100);
561
562         /* Device 'priority' is used for two things:
563          *
564          * a) two devices on the same IP subnet: the "better" (ie, lower number)
565          *     device is the default outgoing device for that subnet
566          * b) default route: the "better" device gets the default route.  This can
567          *     always be modified by setting a connection to never-default=TRUE, in
568          *     which case that device will never take the default route when
569          *     it's using that connection.
570          */
571
572         switch (nm_device_get_device_type (dev)) {
573         case NM_DEVICE_TYPE_ETHERNET:
574                 return 1;
575         case NM_DEVICE_TYPE_INFINIBAND:
576                 return 2;
577         case NM_DEVICE_TYPE_ADSL:
578                 return 3;
579         case NM_DEVICE_TYPE_WIMAX:
580                 return 4;
581         case NM_DEVICE_TYPE_BOND:
582                 return 5;
583         case NM_DEVICE_TYPE_VLAN:
584                 return 6;
585         case NM_DEVICE_TYPE_MODEM:
586                 return 7;
587         case NM_DEVICE_TYPE_BT:
588                 return 8;
589         case NM_DEVICE_TYPE_WIFI:
590                 return 9;
591         case NM_DEVICE_TYPE_OLPC_MESH:
592                 return 10;
593         default:
594                 return 20;
595         }
596 }
597
598
599 /*
600  * Accessor for capabilities
601  */
602 guint32
603 nm_device_get_capabilities (NMDevice *self)
604 {
605         g_return_val_if_fail (self != NULL, NM_DEVICE_CAP_NONE);
606
607         return NM_DEVICE_GET_PRIVATE (self)->capabilities;
608 }
609
610 /*
611  * Accessor for type-specific capabilities
612  */
613 guint32
614 nm_device_get_type_capabilities (NMDevice *self)
615 {
616         g_return_val_if_fail (self != NULL, NM_DEVICE_CAP_NONE);
617
618         return NM_DEVICE_GET_CLASS (self)->get_type_capabilities (self);
619 }
620
621 static guint32
622 real_get_type_capabilities (NMDevice *self)
623 {
624         return NM_DEVICE_CAP_NONE;
625 }
626
627
628 const char *
629 nm_device_get_type_desc (NMDevice *self)
630 {
631         g_return_val_if_fail (self != NULL, NULL);
632
633         return NM_DEVICE_GET_PRIVATE (self)->type_desc;
634 }
635
636 void
637 nm_device_set_connection_provider (NMDevice *device,
638                                    NMConnectionProvider *provider)
639 {
640         NMDevicePrivate *priv;
641
642         g_return_if_fail (device != NULL);
643         g_return_if_fail (provider != NULL);
644         g_return_if_fail (NM_IS_CONNECTION_PROVIDER (provider));
645
646         priv = NM_DEVICE_GET_PRIVATE (device);
647         g_return_if_fail (priv->con_provider == NULL);
648
649         priv->con_provider = provider;
650 }
651
652 NMConnectionProvider *
653 nm_device_get_connection_provider (NMDevice *device)
654 {
655         g_return_val_if_fail (device != NULL, NULL);
656
657         return NM_DEVICE_GET_PRIVATE (device)->con_provider;
658 }
659
660 /**
661  * nm_device_enslave_slave:
662  * @dev: the master device
663  * @slave: the slave device to enslave
664  *
665  * If @dev is capable of enslaving other devices (ie it's a bridge, bond, etc)
666  * then this function enslaves @slave.
667  *
668  * Returns: %TRUE on success, %FALSE on failure or if this device cannot enslave
669  *  other devices.
670  */
671 gboolean
672 nm_device_enslave_slave (NMDevice *dev, NMDevice *slave)
673 {
674         g_return_val_if_fail (dev != NULL, FALSE);
675         g_return_val_if_fail (slave != NULL, FALSE);
676         g_return_val_if_fail (nm_device_get_state (slave) >= NM_DEVICE_STATE_DISCONNECTED, FALSE);
677
678         if (NM_DEVICE_GET_CLASS (dev)->enslave_slave)
679                 return NM_DEVICE_GET_CLASS (dev)->enslave_slave (dev, slave);
680         return FALSE;
681 }
682
683 /**
684  * nm_device_release_slave:
685  * @dev: the master device
686  * @slave: the slave device to release
687  *
688  * If @dev is capable of enslaving other devices (ie it's a bridge, bond, etc)
689  * then this function releases the previously enslaved @slave.
690  *
691  * Returns: %TRUE on success, %FALSE on failure, if this device cannot enslave
692  *  other devices, or if @slave was never enslaved.
693  */
694 gboolean
695 nm_device_release_slave (NMDevice *dev, NMDevice *slave)
696 {
697         g_return_val_if_fail (dev != NULL, FALSE);
698         g_return_val_if_fail (slave != NULL, FALSE);
699
700         if (NM_DEVICE_GET_CLASS (dev)->release_slave)
701                 return NM_DEVICE_GET_CLASS (dev)->release_slave (dev, slave);
702         return FALSE;
703 }
704
705 /*
706  * nm_device_get_act_request
707  *
708  * Return the devices activation request, if any.
709  *
710  */
711 NMActRequest *
712 nm_device_get_act_request (NMDevice *self)
713 {
714         g_return_val_if_fail (self != NULL, NULL);
715
716         return NM_DEVICE_GET_PRIVATE (self)->act_request;
717 }
718
719 NMConnection *
720 nm_device_get_connection (NMDevice *self)
721 {
722         NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
723
724         return priv->act_request ? nm_act_request_get_connection (priv->act_request) : NULL;
725 }
726
727 gboolean
728 nm_device_is_available (NMDevice *self)
729 {
730         NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
731
732         if (priv->firmware_missing)
733                 return FALSE;
734
735         if (NM_DEVICE_GET_CLASS (self)->is_available)
736                 return NM_DEVICE_GET_CLASS (self)->is_available (self);
737         return TRUE;
738 }
739
740 gboolean
741 nm_device_get_enabled (NMDevice *self)
742 {
743         g_return_val_if_fail (self != NULL, FALSE);
744         g_return_val_if_fail (NM_IS_DEVICE (self), FALSE);
745
746         if (NM_DEVICE_GET_CLASS (self)->get_enabled)
747                 return NM_DEVICE_GET_CLASS (self)->get_enabled (self);
748         return TRUE;
749 }
750
751 void
752 nm_device_set_enabled (NMDevice *self, gboolean enabled)
753 {
754         g_return_if_fail (self != NULL);
755         g_return_if_fail (NM_IS_DEVICE (self));
756
757         if (NM_DEVICE_GET_CLASS (self)->set_enabled)
758                 NM_DEVICE_GET_CLASS (self)->set_enabled (self, enabled);
759 }
760
761 RfKillType
762 nm_device_get_rfkill_type (NMDevice *self)
763 {
764         g_return_val_if_fail (self != NULL, FALSE);
765         g_return_val_if_fail (NM_IS_DEVICE (self), FALSE);
766
767         return NM_DEVICE_GET_PRIVATE (self)->rfkill_type;
768 }
769
770 static gboolean
771 autoconnect_allowed_accumulator (GSignalInvocationHint *ihint,
772                                  GValue *return_accu,
773                                  const GValue *handler_return, gpointer data)
774 {
775         if (!g_value_get_boolean (handler_return))
776                 g_value_set_boolean (return_accu, FALSE);
777         return TRUE;
778 }
779
780 gboolean
781 nm_device_autoconnect_allowed (NMDevice *self)
782 {
783         NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
784         GValue instance = { 0, };
785         GValue retval = { 0, };
786
787         g_value_init (&instance, G_TYPE_OBJECT);
788         g_value_take_object (&instance, self);
789
790         g_value_init (&retval, G_TYPE_BOOLEAN);
791         if (priv->autoconnect)
792                 g_value_set_boolean (&retval, TRUE);
793         else
794                 g_value_set_boolean (&retval, FALSE);
795
796         /* Use g_signal_emitv() rather than g_signal_emit() to avoid the return
797          * value being changed if no handlers are connected */
798         g_signal_emitv (&instance, signals[AUTOCONNECT_ALLOWED], 0, &retval);
799         return g_value_get_boolean (&retval);
800 }
801
802 NMConnection *
803 nm_device_get_best_auto_connection (NMDevice *dev,
804                                     GSList *connections,
805                                     char **specific_object)
806 {
807         guint32 caps;
808
809         g_return_val_if_fail (NM_IS_DEVICE (dev), NULL);
810         g_return_val_if_fail (specific_object != NULL, NULL);
811         g_return_val_if_fail (*specific_object == NULL, NULL);
812
813         caps = nm_device_get_capabilities (dev);
814         /* Don't use devices that SUCK */
815         if (!(caps & NM_DEVICE_CAP_NM_SUPPORTED))
816                 return NULL;
817
818         if (!NM_DEVICE_GET_CLASS (dev)->get_best_auto_connection)
819                 return NULL;
820
821         return NM_DEVICE_GET_CLASS (dev)->get_best_auto_connection (dev, connections, specific_object);
822 }
823
824 gboolean
825 nm_device_complete_connection (NMDevice *self,
826                                NMConnection *connection,
827                                const char *specific_object,
828                                const GSList *existing_connections,
829                                GError **error)
830 {
831         gboolean success = FALSE;
832
833         g_return_val_if_fail (self != NULL, FALSE);
834         g_return_val_if_fail (connection != NULL, FALSE);
835
836         if (!NM_DEVICE_GET_CLASS (self)->complete_connection) {
837                 g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CONNECTION_INVALID,
838                              "Device class %s had no complete_connection method",
839                              G_OBJECT_TYPE_NAME (self));
840                 return FALSE;
841         }
842
843         success = NM_DEVICE_GET_CLASS (self)->complete_connection (self,
844                                                                    connection,
845                                                                    specific_object,
846                                                                    existing_connections,
847                                                                    error);
848         if (success)
849                 success = nm_connection_verify (connection, error);
850
851         /* If ip6-privacy is unknown, enable it with temporary address preferred */
852         if (success) {
853                 NMSettingIP6Config *s_ip6 = nm_connection_get_setting_ip6_config (connection);
854                 if (s_ip6 && nm_setting_ip6_config_get_ip6_privacy (s_ip6) == NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN)
855                         g_object_set (s_ip6, NM_SETTING_IP6_CONFIG_IP6_PRIVACY,
856                                       NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR, NULL);
857         }
858
859         return success;
860 }
861
862 gboolean
863 nm_device_check_connection_compatible (NMDevice *device,
864                                        NMConnection *connection,
865                                        GError **error)
866 {
867         g_return_val_if_fail (device != NULL, FALSE);
868         g_return_val_if_fail (NM_IS_DEVICE (device), FALSE);
869         g_return_val_if_fail (connection != NULL, FALSE);
870         g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE);
871
872         if (NM_DEVICE_GET_CLASS (device)->check_connection_compatible)
873                 return NM_DEVICE_GET_CLASS (device)->check_connection_compatible (device, connection, error);
874         return TRUE;
875 }
876
877 gboolean
878 nm_device_can_assume_connections (NMDevice *device)
879 {
880         g_return_val_if_fail (device != NULL, FALSE);
881         g_return_val_if_fail (NM_IS_DEVICE (device), FALSE);
882
883         return !!NM_DEVICE_GET_CLASS (device)->connection_match_config;
884 }
885
886 static void
887 dnsmasq_state_changed_cb (NMDnsMasqManager *manager, guint32 status, gpointer user_data)
888 {
889         NMDevice *self = NM_DEVICE (user_data);
890
891         switch (status) {
892         case NM_DNSMASQ_STATUS_DEAD:
893                 nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_SHARED_START_FAILED);
894                 break;
895         default:
896                 break;
897         }
898 }
899
900 static void
901 activation_source_clear (NMDevice *self, gboolean remove_source, int family)
902 {
903         NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
904         guint *act_source_id;
905         gpointer *act_source_func;
906
907         if (family == AF_INET6) {
908                 act_source_id = &priv->act_source6_id;
909                 act_source_func = &priv->act_source6_func;
910         } else {
911                 act_source_id = &priv->act_source_id;
912                 act_source_func = &priv->act_source_func;
913         }
914
915         if (*act_source_id) {
916                 if (remove_source)
917                         g_source_remove (*act_source_id);
918                 *act_source_id = 0;
919                 *act_source_func = NULL;
920         }
921 }
922
923 static void
924 activation_source_schedule (NMDevice *self, GSourceFunc func, int family)
925 {
926         NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
927         guint *act_source_id;
928         gpointer *act_source_func;
929
930         if (family == AF_INET6) {
931                 act_source_id = &priv->act_source6_id;
932                 act_source_func = &priv->act_source6_func;
933         } else {
934                 act_source_id = &priv->act_source_id;
935                 act_source_func = &priv->act_source_func;
936         }
937
938         if (*act_source_id) {
939                 nm_log_err (LOGD_DEVICE, "activation stage already scheduled");
940         }
941
942         /* Don't bother rescheduling the same function that's about to
943          * run anyway.  Fixes issues with crappy wireless drivers sending
944          * streams of associate events before NM has had a chance to process
945          * the first one.
946          */
947         if (!*act_source_id || (*act_source_func != func)) {
948                 activation_source_clear (self, TRUE, family);
949                 *act_source_id = g_idle_add (func, self);
950                 *act_source_func = func;
951         }
952 }
953
954 gboolean
955 nm_device_ip_config_should_fail (NMDevice *self, gboolean ip6)
956 {
957         NMConnection *connection;
958         NMSettingIP4Config *s_ip4;
959         NMSettingIP6Config *s_ip6;
960
961         g_return_val_if_fail (self != NULL, TRUE);
962
963         connection = nm_device_get_connection (self);
964         g_assert (connection);
965
966         /* Fail the connection if the failed IP method is required to complete */
967         if (ip6) {
968                 s_ip6 = nm_connection_get_setting_ip6_config (connection);
969                 if (s_ip6 && !nm_setting_ip6_config_get_may_fail (s_ip6))
970                         return TRUE;
971         } else {
972                 s_ip4 = nm_connection_get_setting_ip4_config (connection);
973                 if (s_ip4 && !nm_setting_ip4_config_get_may_fail (s_ip4))
974                         return TRUE;
975         }
976
977         return FALSE;
978 }
979
980 static gboolean
981 ip6_method_matches (NMConnection *connection, const char *match)
982 {
983         NMSettingIP6Config *s_ip6;
984         const char *method = NULL;
985
986         s_ip6 = nm_connection_get_setting_ip6_config (connection);
987         if (s_ip6) {
988                 method = nm_setting_ip6_config_get_method (s_ip6);
989                 g_assert (method);
990         }
991
992         /* Treat missing IP6 setting as AUTO */
993         if (!s_ip6 && !strcmp (match, NM_SETTING_IP6_CONFIG_METHOD_AUTO))
994                 return TRUE;
995
996         return method && !strcmp (method, match);
997 }
998
999 static NMActStageReturn
1000 real_act_stage1_prepare (NMDevice *self, NMDeviceStateReason *reason)
1001 {
1002         NMActRequest *req;
1003         NMActiveConnection *master_ac;
1004         NMDevice *master;
1005         NMActStageReturn ret = NM_ACT_STAGE_RETURN_SUCCESS;
1006
1007         req = nm_device_get_act_request (self);
1008         g_assert (req);
1009
1010         /* If the interface is going to be a slave, let the master enslave it here */
1011         master_ac = nm_act_request_get_dependency (req);
1012         if (master_ac && NM_IS_ACT_REQUEST (master_ac)) {
1013                 /* FIXME: handle VPNs here too */
1014
1015                 master = NM_DEVICE (nm_act_request_get_device (NM_ACT_REQUEST (master_ac)));
1016                 g_assert (master);
1017                 if (!nm_device_enslave_slave (master, self))
1018                         ret = NM_ACT_STAGE_RETURN_FAILURE;
1019         }
1020
1021         return ret;
1022 }
1023
1024 /*
1025  * nm_device_activate_stage1_device_prepare
1026  *
1027  * Prepare for device activation
1028  *
1029  */
1030 static gboolean
1031 nm_device_activate_stage1_device_prepare (gpointer user_data)
1032 {
1033         NMDevice *self = NM_DEVICE (user_data);
1034         NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
1035         const char *iface;
1036         NMActStageReturn ret;
1037         NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE;
1038
1039         /* Clear the activation source ID now that this stage has run */
1040         activation_source_clear (self, FALSE, 0);
1041
1042         if (priv->act_dep_timeout_id) {
1043                 g_source_remove (priv->act_dep_timeout_id);
1044                 priv->act_dep_timeout_id = 0;
1045         }
1046
1047         priv->ip4_state = priv->ip6_state = IP_NONE;
1048
1049         iface = nm_device_get_iface (self);
1050         nm_log_info (LOGD_DEVICE, "Activation (%s) Stage 1 of 5 (Device Prepare) started...", iface);
1051         nm_device_state_changed (self, NM_DEVICE_STATE_PREPARE, NM_DEVICE_STATE_REASON_NONE);
1052
1053         ret = NM_DEVICE_GET_CLASS (self)->act_stage1_prepare (self, &reason);
1054         if (ret == NM_ACT_STAGE_RETURN_POSTPONE) {
1055                 goto out;
1056         } else if (ret == NM_ACT_STAGE_RETURN_FAILURE) {
1057                 nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, reason);
1058                 goto out;
1059         }
1060         g_assert (ret == NM_ACT_STAGE_RETURN_SUCCESS);
1061
1062         nm_device_activate_schedule_stage2_device_config (self);
1063
1064 out:
1065         nm_log_info (LOGD_DEVICE, "Activation (%s) Stage 1 of 5 (Device Prepare) complete.", iface);
1066         return FALSE;
1067 }
1068
1069
1070 /*
1071  * nm_device_activate_schedule_stage1_device_prepare
1072  *
1073  * Prepare a device for activation
1074  *
1075  */
1076 void
1077 nm_device_activate_schedule_stage1_device_prepare (NMDevice *self)
1078 {
1079         NMDevicePrivate *priv;
1080
1081         g_return_if_fail (NM_IS_DEVICE (self));
1082
1083         priv = NM_DEVICE_GET_PRIVATE (self);
1084         g_return_if_fail (priv->act_request);
1085
1086         activation_source_schedule (self, nm_device_activate_stage1_device_prepare, 0);
1087
1088         nm_log_info (LOGD_DEVICE, "Activation (%s) Stage 1 of 5 (Device Prepare) scheduled...",
1089                      nm_device_get_iface (self));
1090 }
1091
1092 static NMActStageReturn
1093 real_act_stage2_config (NMDevice *dev, NMDeviceStateReason *reason)
1094 {
1095         /* Nothing to do */
1096         return NM_ACT_STAGE_RETURN_SUCCESS;
1097 }
1098
1099 /*
1100  * nm_device_activate_stage2_device_config
1101  *
1102  * Determine device parameters and set those on the device, ie
1103  * for wireless devices, set SSID, keys, etc.
1104  *
1105  */
1106 static gboolean
1107 nm_device_activate_stage2_device_config (gpointer user_data)
1108 {
1109         NMDevice *self = NM_DEVICE (user_data);
1110         const char *     iface;
1111         NMActStageReturn ret;
1112         NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE;
1113         gboolean no_firmware = FALSE;
1114
1115         /* Clear the activation source ID now that this stage has run */
1116         activation_source_clear (self, FALSE, 0);
1117
1118         iface = nm_device_get_iface (self);
1119         nm_log_info (LOGD_DEVICE, "Activation (%s) Stage 2 of 5 (Device Configure) starting...", iface);
1120         nm_device_state_changed (self, NM_DEVICE_STATE_CONFIG, NM_DEVICE_STATE_REASON_NONE);
1121
1122         if (!nm_device_bring_up (self, FALSE, &no_firmware)) {
1123                 if (no_firmware)
1124                         nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_FIRMWARE_MISSING);
1125                 else
1126                         nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_CONFIG_FAILED);
1127                 goto out;
1128         }
1129
1130         ret = NM_DEVICE_GET_CLASS (self)->act_stage2_config (self, &reason);
1131         if (ret == NM_ACT_STAGE_RETURN_POSTPONE)
1132                 goto out;
1133         else if (ret == NM_ACT_STAGE_RETURN_FAILURE)
1134         {
1135                 nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, reason);
1136                 goto out;
1137         }
1138         g_assert (ret == NM_ACT_STAGE_RETURN_SUCCESS);  
1139
1140         nm_log_info (LOGD_DEVICE, "Activation (%s) Stage 2 of 5 (Device Configure) successful.", iface);
1141
1142         nm_device_activate_schedule_stage3_ip_config_start (self);
1143
1144 out:
1145         nm_log_info (LOGD_DEVICE, "Activation (%s) Stage 2 of 5 (Device Configure) complete.", iface);
1146         return FALSE;
1147 }
1148
1149
1150 /*
1151  * nm_device_activate_schedule_stage2_device_config
1152  *
1153  * Schedule setup of the hardware device
1154  *
1155  */
1156 void
1157 nm_device_activate_schedule_stage2_device_config (NMDevice *self)
1158 {
1159         NMDevicePrivate *priv;
1160
1161         g_return_if_fail (NM_IS_DEVICE (self));
1162
1163         priv = NM_DEVICE_GET_PRIVATE (self);
1164         g_return_if_fail (priv->act_request);
1165
1166         activation_source_schedule (self, nm_device_activate_stage2_device_config, 0);
1167
1168         nm_log_info (LOGD_DEVICE, "Activation (%s) Stage 2 of 5 (Device Configure) scheduled...",
1169                  nm_device_get_iface (self));
1170 }
1171
1172 /*********************************************/
1173 /* avahi-autoipd stuff */
1174
1175 static void
1176 aipd_timeout_remove (NMDevice *self)
1177 {
1178         NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
1179
1180         if (priv->aipd_timeout) {
1181                 g_source_remove (priv->aipd_timeout);
1182                 priv->aipd_timeout = 0;
1183         }
1184 }
1185
1186 static void
1187 aipd_cleanup (NMDevice *self)
1188 {
1189         NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
1190
1191         if (priv->aipd_watch) {
1192                 g_source_remove (priv->aipd_watch);
1193                 priv->aipd_watch = 0;
1194         }
1195
1196         if (priv->aipd_pid > 0) {
1197                 kill (priv->aipd_pid, SIGKILL);
1198
1199                 /* ensure the child is reaped */
1200                 nm_log_dbg (LOGD_AUTOIP4, "waiting for avahi-autoipd pid %d to exit", priv->aipd_pid);
1201                 waitpid (priv->aipd_pid, NULL, 0);
1202                 nm_log_dbg (LOGD_AUTOIP4, "avahi-autoip pid %d cleaned up", priv->aipd_pid);
1203
1204                 priv->aipd_pid = -1;
1205         }
1206
1207         aipd_timeout_remove (self);
1208 }
1209
1210 static NMIP4Config *
1211 aipd_get_ip4_config (NMDevice *self, struct in_addr lla)
1212 {
1213         NMIP4Config *config = NULL;
1214         NMIP4Address *addr;
1215         NMIP4Route *route;
1216
1217         config = nm_ip4_config_new ();
1218         g_assert (config);
1219
1220         addr = nm_ip4_address_new ();
1221         nm_ip4_address_set_address (addr, (guint32) lla.s_addr);
1222         nm_ip4_address_set_prefix (addr, 16);
1223         nm_ip4_config_take_address (config, addr);
1224
1225         /* Add a multicast route for link-local connections: destination= 224.0.0.0, netmask=240.0.0.0 */
1226         route = nm_ip4_route_new ();
1227         nm_ip4_route_set_dest (route, (guint32) htonl (0xE0000000L));
1228         nm_ip4_route_set_prefix (route, 4);
1229         nm_ip4_route_set_next_hop (route, (guint32) 0);
1230         nm_ip4_route_set_metric (route, 0);
1231         nm_ip4_config_take_route (config, route);
1232
1233         return config;  
1234 }
1235
1236 static void
1237 autoip_changed (NMDevice *self,
1238                 NMIP4Config *config,
1239                 NMSettingIP4Config *s_ip4)
1240 {
1241         NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE;
1242
1243         nm_utils_merge_ip4_config (config, s_ip4);
1244         if (!nm_device_set_ip4_config (self, config, FALSE, &reason)) {
1245                 nm_log_err (LOGD_AUTOIP4, "(%s): failed to update IP4 config in response to autoip event.",
1246                                 nm_device_get_iface (self));
1247                 nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, reason);
1248         }
1249 }
1250
1251 #define IPV4LL_NETWORK (htonl (0xA9FE0000L))
1252 #define IPV4LL_NETMASK (htonl (0xFFFF0000L))
1253
1254 void
1255 nm_device_handle_autoip4_event (NMDevice *self,
1256                                 const char *event,
1257                                 const char *address)
1258 {
1259         NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
1260         NMConnection *connection = NULL;
1261         NMSettingIP4Config *s_ip4 = NULL;
1262         const char *iface, *method = NULL;
1263
1264         g_return_if_fail (event != NULL);
1265
1266         if (priv->act_request == NULL)
1267                 return;
1268
1269         connection = nm_act_request_get_connection (priv->act_request);
1270         g_assert (connection);
1271
1272         /* Ignore if the connection isn't an AutoIP connection */
1273         s_ip4 = nm_connection_get_setting_ip4_config (connection);
1274         if (s_ip4)
1275                 method = nm_setting_ip4_config_get_method (s_ip4);
1276
1277         if (g_strcmp0 (method, NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL) != 0)
1278                 return;
1279
1280         iface = nm_device_get_iface (self);
1281
1282         if (strcmp (event, "BIND") == 0) {
1283                 struct in_addr lla;
1284                 NMIP4Config *config;
1285
1286                 if (inet_pton (AF_INET, address, &lla) <= 0) {
1287                         nm_log_err (LOGD_AUTOIP4, "(%s): invalid address %s received from avahi-autoipd.",
1288                                     iface, address);
1289                         nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_AUTOIP_ERROR);
1290                         return;
1291                 }
1292
1293                 if ((lla.s_addr & IPV4LL_NETMASK) != IPV4LL_NETWORK) {
1294                         nm_log_err (LOGD_AUTOIP4, "(%s): invalid address %s received from avahi-autoipd (not link-local).",
1295                                     iface, address);
1296                         nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_AUTOIP_ERROR);
1297                         return;
1298                 }
1299
1300                 config = aipd_get_ip4_config (self, lla);
1301                 if (config == NULL) {
1302                         nm_log_err (LOGD_AUTOIP4, "failed to get autoip config");
1303                         nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE);
1304                         return;
1305                 }
1306
1307                 if (priv->ip4_state == IP_CONF) {
1308                         aipd_timeout_remove (self);
1309                         nm_device_activate_schedule_ip4_config_result (self, config);
1310                 } else if (priv->ip4_state == IP_DONE) {
1311                         autoip_changed (self, config, s_ip4);
1312                 } else
1313                         g_assert_not_reached ();
1314
1315                 g_object_unref (config);
1316         } else {
1317                 nm_log_warn (LOGD_AUTOIP4, "(%s): autoip address %s no longer valid because '%s'.",
1318                             iface, address, event);
1319
1320                 /* The address is gone; terminate the connection or fail activation */
1321                 nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_IP_CONFIG_EXPIRED);
1322         }
1323 }
1324
1325 static void
1326 aipd_watch_cb (GPid pid, gint status, gpointer user_data)
1327 {
1328         NMDevice *self = NM_DEVICE (user_data);
1329         NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
1330         NMDeviceState state;
1331         const char *iface;
1332
1333         if (!priv->aipd_watch)
1334                 return;
1335         priv->aipd_watch = 0;
1336
1337         iface = nm_device_get_iface (self);
1338
1339         if (WIFEXITED (status)) {
1340                 nm_log_dbg (LOGD_AUTOIP4, "(%s): avahi-autoipd exited with error code %d",
1341                             iface, WEXITSTATUS (status));
1342         } else if (WIFSTOPPED (status)) {
1343                 nm_log_warn (LOGD_AUTOIP4, "(%s): avahi-autoipd stopped unexpectedly with signal %d",
1344                             iface, WSTOPSIG (status));
1345         } else if (WIFSIGNALED (status)) {
1346                 nm_log_warn (LOGD_AUTOIP4, "(%s): avahi-autoipd died with signal %d",
1347                              iface, WTERMSIG (status));
1348         } else {
1349                 nm_log_warn (LOGD_AUTOIP4, "(%s): avahi-autoipd died from an unknown cause", iface);
1350         }
1351
1352         aipd_cleanup (self);
1353
1354         state = nm_device_get_state (self);
1355         if (nm_device_is_activating (self) || (state == NM_DEVICE_STATE_ACTIVATED))
1356                 nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_AUTOIP_FAILED);
1357 }
1358
1359 static gboolean
1360 aipd_timeout_cb (gpointer user_data)
1361 {
1362         NMDevice *self = NM_DEVICE (user_data);
1363         NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
1364
1365         if (priv->aipd_timeout) {
1366                 nm_log_info (LOGD_AUTOIP4, "(%s): avahi-autoipd timed out.", nm_device_get_iface (self));
1367                 priv->aipd_timeout = 0;
1368                 aipd_cleanup (self);
1369
1370                 if (priv->ip4_state == IP_CONF)
1371                         nm_device_activate_schedule_ip4_config_timeout (self);
1372         }
1373
1374         return FALSE;
1375 }
1376
1377 static void
1378 aipd_child_setup (gpointer user_data G_GNUC_UNUSED)
1379 {
1380         /* We are in the child process at this point.
1381          * Give child it's own program group for signal
1382          * separation.
1383          */
1384         pid_t pid = getpid ();
1385         setpgid (pid, pid);
1386
1387         /*
1388          * We blocked signals in main(). We need to restore original signal
1389          * mask for avahi-autoipd here so that it can receive signals.
1390          */
1391         nm_unblock_posix_signals (NULL);
1392 }
1393
1394 static NMActStageReturn
1395 aipd_start (NMDevice *self, NMDeviceStateReason *reason)
1396 {
1397         NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
1398         const char *iface = nm_device_get_iface (self);
1399         char *argv[6], *cmdline;
1400         const char **aipd_binary = NULL;
1401         static const char *aipd_paths[] = {
1402                 "/usr/sbin/avahi-autoipd",
1403                 "/usr/local/sbin/avahi-autoipd",
1404                 NULL
1405         };
1406         int i = 0;
1407         GError *error = NULL;
1408
1409         aipd_cleanup (self);
1410
1411         /* Find avahi-autoipd */
1412         aipd_binary = aipd_paths;
1413         while (*aipd_binary != NULL) {
1414                 if (g_file_test (*aipd_binary, G_FILE_TEST_EXISTS))
1415                         break;
1416                 aipd_binary++;
1417         }
1418
1419         if (!*aipd_binary) {
1420                 nm_log_warn (LOGD_DEVICE | LOGD_AUTOIP4,
1421                              "Activation (%s) Stage 3 of 5 (IP Configure Start) failed"
1422                              " to start avahi-autoipd: not found", iface);
1423                 *reason = NM_DEVICE_STATE_REASON_AUTOIP_START_FAILED;
1424                 return NM_ACT_STAGE_RETURN_FAILURE;
1425         }
1426
1427         argv[i++] = (char *) (*aipd_binary);
1428         argv[i++] = "--script";
1429         argv[i++] = LIBEXECDIR "/nm-avahi-autoipd.action";
1430         if (nm_logging_level_enabled (LOGL_DEBUG))
1431                 argv[i++] = "--debug";
1432         argv[i++] = (char *) nm_device_get_ip_iface (self);
1433         argv[i++] = NULL;
1434
1435         cmdline = g_strjoinv (" ", argv);
1436         nm_log_dbg (LOGD_AUTOIP4, "running: %s", cmdline);
1437         g_free (cmdline);
1438
1439         if (!g_spawn_async ("/", argv, NULL, G_SPAWN_DO_NOT_REAP_CHILD,
1440                             &aipd_child_setup, NULL, &(priv->aipd_pid), &error)) {
1441                 nm_log_warn (LOGD_DEVICE | LOGD_AUTOIP4,
1442                              "Activation (%s) Stage 3 of 5 (IP Configure Start) failed"
1443                              " to start avahi-autoipd: %s",
1444                              iface,
1445                              error && error->message ? error->message : "(unknown)");
1446                 g_clear_error (&error);
1447                 aipd_cleanup (self);
1448                 return NM_ACT_STAGE_RETURN_FAILURE;
1449         }
1450
1451         nm_log_info (LOGD_DEVICE | LOGD_AUTOIP4,
1452                      "Activation (%s) Stage 3 of 5 (IP Configure Start) started"
1453                      " avahi-autoipd...", iface);
1454
1455         /* Monitor the child process so we know when it dies */
1456         priv->aipd_watch = g_child_watch_add (priv->aipd_pid, aipd_watch_cb, self);
1457
1458         /* Start a timeout to bound the address attempt */
1459         priv->aipd_timeout = g_timeout_add_seconds (20, aipd_timeout_cb, self);
1460
1461         return NM_ACT_STAGE_RETURN_POSTPONE;
1462 }
1463
1464 /*********************************************/
1465 /* DHCPv4 stuff */
1466
1467 static void
1468 dhcp4_add_option_cb (gpointer key, gpointer value, gpointer user_data)
1469 {
1470         nm_dhcp4_config_add_option (NM_DHCP4_CONFIG (user_data),
1471                                     (const char *) key,
1472                                     (const char *) value);
1473 }
1474
1475 static void
1476 dhcp4_lease_change (NMDevice *device, NMIP4Config *config)
1477 {
1478         NMConnection *connection;
1479         NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE;
1480
1481         if (config == NULL) {
1482                 nm_log_warn (LOGD_DHCP4, "(%s): failed to get DHCPv4 config for rebind",
1483                              nm_device_get_ip_iface (device));
1484                 nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_IP_CONFIG_EXPIRED);
1485                 return;
1486         }
1487
1488         connection = nm_device_get_connection (device);
1489         g_assert (connection);
1490
1491         /* Merge with user overrides */
1492         nm_utils_merge_ip4_config (config, nm_connection_get_setting_ip4_config (connection));
1493
1494         if (!nm_device_set_ip4_config (device, config, FALSE, &reason)) {
1495                 nm_log_warn (LOGD_DHCP6, "(%s): failed to update IPv4 config in response to DHCP event.",
1496                              nm_device_get_ip_iface (device));
1497                 nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, reason);
1498                 return;
1499         }
1500
1501         /* Notify dispatcher scripts of new DHCP4 config */
1502         nm_utils_call_dispatcher ("dhcp4-change", connection, device, NULL, NULL, NULL);
1503 }
1504
1505 static void
1506 dhcp4_fail (NMDevice *device, gboolean timeout)
1507 {
1508         NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device);
1509
1510         nm_dhcp4_config_reset (priv->dhcp4_config);
1511
1512         if (timeout || (priv->ip4_state == IP_CONF))
1513                 nm_device_activate_schedule_ip4_config_timeout (device);
1514         else if (priv->ip4_state == IP_DONE)
1515                 nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_IP_CONFIG_EXPIRED);
1516 }
1517
1518 static void
1519 dhcp4_state_changed (NMDHCPClient *client,
1520                      NMDHCPState state,
1521                      gpointer user_data)
1522 {
1523         NMDevice *device = NM_DEVICE (user_data);
1524         NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device);
1525         NMDeviceState dev_state;
1526         NMIP4Config *config;
1527
1528         g_return_if_fail (nm_dhcp_client_get_ipv6 (client) == FALSE);
1529
1530         nm_log_dbg (LOGD_DHCP4, "(%s): new DHCPv4 client state %d",
1531                     nm_device_get_iface (device), state);
1532
1533         dev_state = nm_device_get_state (device);
1534
1535         switch (state) {
1536         case DHC_BOUND4:     /* lease obtained */
1537         case DHC_RENEW4:     /* lease renewed */
1538         case DHC_REBOOT:     /* have valid lease, but now obtained a different one */
1539         case DHC_REBIND4:    /* new, different lease */
1540                 config = nm_dhcp_client_get_ip4_config (priv->dhcp4_client, FALSE);
1541                 if (priv->ip4_state == IP_CONF)
1542                         nm_device_activate_schedule_ip4_config_result (device, config);
1543                 else if (priv->ip4_state == IP_DONE)
1544                         dhcp4_lease_change (device, config);
1545
1546                 if (config) {
1547                         /* Update the DHCP4 config object with new DHCP options */
1548                         nm_dhcp4_config_reset (priv->dhcp4_config);
1549                         nm_dhcp_client_foreach_option (priv->dhcp4_client,
1550                                                        dhcp4_add_option_cb,
1551                                                        priv->dhcp4_config);
1552                         g_object_notify (G_OBJECT (device), NM_DEVICE_DHCP4_CONFIG);
1553
1554                         g_object_unref (config);
1555                 }
1556                 break;
1557         case DHC_TIMEOUT: /* timed out contacting DHCP server */
1558                 dhcp4_fail (device, TRUE);
1559                 break;
1560         case DHC_END: /* dhclient exited normally */
1561         case DHC_FAIL: /* all attempts to contact server timed out, sleeping */
1562         case DHC_ABEND: /* dhclient exited abnormally */
1563                 /* dhclient quit and can't get/renew a lease; so kill the connection */
1564                 dhcp4_fail (device, FALSE);
1565                 break;
1566         default:
1567                 break;
1568         }
1569 }
1570
1571 static void
1572 dhcp4_timeout (NMDHCPClient *client, gpointer user_data)
1573 {
1574         NMDevice *device = NM_DEVICE (user_data);
1575
1576         g_return_if_fail (nm_device_get_act_request (device) != NULL);
1577         g_return_if_fail (nm_dhcp_client_get_ipv6 (client) == FALSE);
1578
1579         nm_dhcp_client_stop (client, FALSE);
1580         dhcp4_fail (device, TRUE);
1581 }
1582
1583 static NMActStageReturn
1584 dhcp4_start (NMDevice *self,
1585              NMConnection *connection,
1586              NMDeviceStateReason *reason)
1587 {
1588         NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
1589         NMSettingIP4Config *s_ip4;
1590         guint8 *anycast = NULL;
1591
1592         s_ip4 = nm_connection_get_setting_ip4_config (connection);
1593
1594         if (priv->dhcp_anycast_address)
1595                 anycast = priv->dhcp_anycast_address->data;
1596
1597         /* Clear old exported DHCP options */
1598         if (priv->dhcp4_config)
1599                 g_object_unref (priv->dhcp4_config);
1600         priv->dhcp4_config = nm_dhcp4_config_new ();
1601
1602         /* Begin DHCP on the interface */
1603         g_warn_if_fail (priv->dhcp4_client == NULL);
1604         priv->dhcp4_client = nm_dhcp_manager_start_ip4 (priv->dhcp_manager,
1605                                                         nm_device_get_ip_iface (self),
1606                                                         nm_connection_get_uuid (connection),
1607                                                         s_ip4,
1608                                                         priv->dhcp_timeout,
1609                                                         anycast);
1610         if (!priv->dhcp4_client) {
1611                 *reason = NM_DEVICE_STATE_REASON_DHCP_START_FAILED;
1612                 return NM_ACT_STAGE_RETURN_FAILURE;
1613         }
1614
1615         priv->dhcp4_state_sigid = g_signal_connect (priv->dhcp4_client,
1616                                                     "state-changed",
1617                                                     G_CALLBACK (dhcp4_state_changed),
1618                                                     self);
1619         priv->dhcp4_timeout_sigid = g_signal_connect (priv->dhcp4_client,
1620                                                       "timeout",
1621                                                       G_CALLBACK (dhcp4_timeout),
1622                                                       self);
1623
1624         /* DHCP devices will be notified by the DHCP manager when stuff happens */
1625         return NM_ACT_STAGE_RETURN_POSTPONE;
1626 }
1627
1628 gboolean
1629 nm_device_dhcp4_renew (NMDevice *self, gboolean release)
1630 {
1631         NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
1632         NMActStageReturn ret;
1633         NMDeviceStateReason reason;
1634         NMConnection *connection;
1635
1636         g_return_val_if_fail (priv->dhcp4_client != NULL, FALSE);
1637
1638         nm_log_info (LOGD_DHCP4, "(%s): DHCPv4 lease renewal requested",
1639                      nm_device_get_iface (self));
1640
1641         /* Terminate old DHCP instance and release the old lease */
1642         dhcp4_cleanup (self, TRUE, release);
1643
1644         connection = nm_device_get_connection (self);
1645         g_assert (connection);
1646
1647         /* Start DHCP again on the interface */
1648         ret = dhcp4_start (self, connection, &reason);
1649
1650         return (ret != NM_ACT_STAGE_RETURN_FAILURE);
1651 }
1652
1653 /*********************************************/
1654
1655 static GHashTable *shared_ips = NULL;
1656
1657 static void
1658 release_shared_ip (gpointer data)
1659 {
1660         g_hash_table_remove (shared_ips, data);
1661 }
1662
1663 static guint32
1664 reserve_shared_ip (void)
1665 {
1666         guint32 start = (guint32) ntohl (0x0a2a0001); /* 10.42.0.1 */
1667         guint32 count = 0;
1668
1669         while (g_hash_table_lookup (shared_ips, GUINT_TO_POINTER (start + count))) {
1670                 count += ntohl (0x100);
1671                 if (count > ntohl (0xFE00)) {
1672                         nm_log_err (LOGD_SHARING, "ran out of shared IP addresses!");
1673                         return 0;
1674                 }
1675         }
1676
1677         g_hash_table_insert (shared_ips, GUINT_TO_POINTER (start + count), GUINT_TO_POINTER (TRUE));
1678         return start + count;
1679 }
1680
1681 static NMIP4Config *
1682 shared4_new_config (NMDevice *self, NMDeviceStateReason *reason)
1683 {
1684         NMIP4Config *config = NULL;
1685         NMIP4Address *addr;
1686         guint32 tmp_addr;
1687
1688         g_return_val_if_fail (self != NULL, NULL);
1689
1690         if (G_UNLIKELY (shared_ips == NULL))
1691                 shared_ips = g_hash_table_new (g_direct_hash, g_direct_equal);
1692
1693         tmp_addr = reserve_shared_ip ();
1694         if (!tmp_addr) {
1695                 *reason = NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE;
1696                 return NULL;
1697         }
1698
1699         config = nm_ip4_config_new ();
1700         addr = nm_ip4_address_new ();
1701         nm_ip4_address_set_address (addr, tmp_addr);
1702         nm_ip4_address_set_prefix (addr, 24);
1703         nm_ip4_config_take_address (config, addr);
1704
1705         /* Remove the address lock when the object gets disposed */
1706         g_object_set_data_full (G_OBJECT (config), "shared-ip",
1707                                 GUINT_TO_POINTER (tmp_addr), release_shared_ip);
1708
1709         return config;
1710 }
1711
1712 /*********************************************/
1713
1714 static NMActStageReturn
1715 real_act_stage3_ip4_config_start (NMDevice *self,
1716                                   NMIP4Config **out_config,
1717                                   NMDeviceStateReason *reason)
1718 {
1719         NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
1720         NMConnection *connection;
1721         NMSettingIP4Config *s_ip4;
1722         NMActStageReturn ret = NM_ACT_STAGE_RETURN_FAILURE;
1723         const char *method = NM_SETTING_IP4_CONFIG_METHOD_AUTO;
1724
1725         g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE);
1726
1727         connection = nm_device_get_connection (self);
1728         g_assert (connection);
1729
1730         /* If we did not receive IP4 configuration information, default to DHCP */
1731         s_ip4 = nm_connection_get_setting_ip4_config (connection);
1732         if (s_ip4)
1733                 method = nm_setting_ip4_config_get_method (s_ip4);
1734         else if (nm_connection_is_type (connection, NM_SETTING_BOND_SETTING_NAME))
1735                 method = NM_SETTING_IP4_CONFIG_METHOD_DISABLED;
1736
1737         /* Start IPv4 addressing based on the method requested */
1738         if (strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_AUTO) == 0)
1739                 ret = dhcp4_start (self, connection, reason);
1740         else if (strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL) == 0)
1741                 ret = aipd_start (self, reason);
1742         else if (strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_MANUAL) == 0) {
1743                 /* Use only IPv4 config from the connection data */
1744                 *out_config = nm_ip4_config_new ();
1745                 g_assert (*out_config);
1746                 ret = NM_ACT_STAGE_RETURN_SUCCESS;
1747         } else if (strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_SHARED) == 0) {
1748                 *out_config = shared4_new_config (self, reason);
1749                 if (*out_config) {
1750                         priv->dnsmasq_manager = nm_dnsmasq_manager_new (nm_device_get_ip_iface (self));
1751                         ret = NM_ACT_STAGE_RETURN_SUCCESS;
1752                 } else
1753                         ret = NM_ACT_STAGE_RETURN_FAILURE;
1754         } else if (s_ip4 && !strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_DISABLED)) {
1755                 /* Nothing to do... */
1756                 ret = NM_ACT_STAGE_RETURN_STOP;
1757         } else {
1758                 nm_log_warn (LOGD_IP4, "(%s): unhandled IPv4 config method; will fail",
1759                              nm_device_get_ip_iface (self));
1760         }
1761
1762         return ret;
1763 }
1764
1765 /*********************************************/
1766 /* DHCPv6 stuff */
1767
1768 static void
1769 dhcp6_add_option_cb (gpointer key, gpointer value, gpointer user_data)
1770 {
1771         nm_dhcp6_config_add_option (NM_DHCP6_CONFIG (user_data),
1772                                     (const char *) key,
1773                                     (const char *) value);
1774 }
1775
1776 static void
1777 merge_ip6_configs (NMIP6Config *dst, NMIP6Config *src)
1778 {
1779         guint32 i;
1780
1781         g_return_if_fail (src != NULL);
1782         g_return_if_fail (dst != NULL);
1783
1784         /* addresses */
1785         for (i = 0; i < nm_ip6_config_get_num_addresses (src); i++)
1786                 nm_ip6_config_add_address (dst, nm_ip6_config_get_address (src, i));
1787
1788         /* ptp address; only replace if src doesn't have one */
1789         if (!nm_ip6_config_get_ptp_address (dst))
1790                 nm_ip6_config_set_ptp_address (dst, nm_ip6_config_get_ptp_address (src));
1791
1792         /* nameservers */
1793         for (i = 0; i < nm_ip6_config_get_num_nameservers (src); i++)
1794                 nm_ip6_config_add_nameserver (dst, nm_ip6_config_get_nameserver (src, i));
1795
1796         /* default gateway */
1797         if (!nm_ip6_config_get_gateway (dst))
1798                 nm_ip6_config_set_gateway (dst, nm_ip6_config_get_gateway (src));
1799
1800         /* routes */
1801         for (i = 0; i < nm_ip6_config_get_num_routes (src); i++)
1802                 nm_ip6_config_add_route (dst, nm_ip6_config_get_route (src, i));
1803
1804         /* domains */
1805         for (i = 0; i < nm_ip6_config_get_num_domains (src); i++)
1806                 nm_ip6_config_add_domain (dst, nm_ip6_config_get_domain (src, i));
1807
1808         /* dns searches */
1809         for (i = 0; i < nm_ip6_config_get_num_searches (src); i++)
1810                 nm_ip6_config_add_search (dst, nm_ip6_config_get_search (src, i));
1811
1812         if (!nm_ip6_config_get_mss (dst))
1813                 nm_ip6_config_set_mss (dst, nm_ip6_config_get_mss (src));
1814 }
1815
1816 static gboolean
1817 ip6_config_merge_and_apply (NMDevice *self,
1818                             NMIP6Config *src_config,
1819                             NMDeviceStateReason *out_reason)
1820 {
1821         NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
1822         NMConnection *connection;
1823         gboolean success;
1824         NMIP6Config *composite;
1825
1826         connection = nm_device_get_connection (self);
1827         g_assert (connection);
1828
1829         /* If no config was passed in, create a new one */
1830         composite = nm_ip6_config_new ();
1831         g_assert (composite);
1832
1833         /* Merge in the given config first, if any */
1834         if (src_config)
1835                 merge_ip6_configs (composite, src_config);
1836
1837         /* Merge RA and DHCPv6 configs into the composite config */
1838         if (priv->ac_ip6_config && (src_config != priv->ac_ip6_config))
1839                 merge_ip6_configs (composite, priv->ac_ip6_config);
1840         if (priv->dhcp6_ip6_config && (src_config != priv->dhcp6_ip6_config))
1841                 merge_ip6_configs (composite, priv->dhcp6_ip6_config);
1842
1843         /* Merge user overrides into the composite config */
1844         nm_utils_merge_ip6_config (composite, nm_connection_get_setting_ip6_config (connection));
1845
1846         success = nm_device_set_ip6_config (self, composite, out_reason);
1847         g_object_unref (composite);
1848         return success;
1849 }
1850
1851 static void
1852 dhcp6_lease_change (NMDevice *device)
1853 {
1854         NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device);
1855         NMConnection *connection;
1856         NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE;
1857
1858         if (priv->dhcp6_ip6_config == NULL) {
1859                 nm_log_warn (LOGD_DHCP6, "(%s): failed to get DHCPv6 config for rebind",
1860                              nm_device_get_ip_iface (device));
1861                 nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_IP_CONFIG_EXPIRED);
1862                 return;
1863         }
1864
1865         g_assert (priv->dhcp6_client);  /* sanity check */
1866
1867         connection = nm_device_get_connection (device);
1868         g_assert (connection);
1869
1870         /* Apply the updated config */
1871         if (ip6_config_merge_and_apply (device, NULL, &reason) == FALSE) {
1872                 nm_log_warn (LOGD_DHCP6, "(%s): failed to update IPv6 config in response to DHCP event.",
1873                              nm_device_get_ip_iface (device));
1874                 nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, reason);
1875         } else {
1876                 /* Notify dispatcher scripts of new DHCPv6 config */
1877                 nm_utils_call_dispatcher ("dhcp6-change", connection, device, NULL, NULL, NULL);
1878         }
1879 }
1880
1881 static void
1882 dhcp6_fail (NMDevice *device, gboolean timeout)
1883 {
1884         NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device);
1885
1886         nm_dhcp6_config_reset (priv->dhcp6_config);
1887
1888         if (timeout || (priv->ip6_state == IP_CONF))
1889                 nm_device_activate_schedule_ip6_config_timeout (device);
1890         else if (priv->ip6_state == IP_DONE)
1891                 nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_IP_CONFIG_EXPIRED);
1892 }
1893
1894 static void
1895 dhcp6_state_changed (NMDHCPClient *client,
1896                      NMDHCPState state,
1897                      gpointer user_data)
1898 {
1899         NMDevice *device = NM_DEVICE (user_data);
1900         NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device);
1901         NMDeviceState dev_state;
1902
1903         g_return_if_fail (nm_dhcp_client_get_ipv6 (client) == TRUE);
1904
1905         nm_log_dbg (LOGD_DHCP6, "(%s): new DHCPv6 client state %d",
1906                     nm_device_get_iface (device), state);
1907
1908         dev_state = nm_device_get_state (device);
1909
1910         switch (state) {
1911         case DHC_BOUND6:
1912         case DHC_RENEW6:     /* lease renewed */
1913         case DHC_REBOOT:     /* have valid lease, but now obtained a different one */
1914         case DHC_REBIND6:    /* new, different lease */
1915                 if (priv->dhcp6_ip6_config)
1916                         g_object_unref (priv->dhcp6_ip6_config);
1917                 priv->dhcp6_ip6_config = nm_dhcp_client_get_ip6_config (priv->dhcp6_client, FALSE);
1918                 if (priv->ip6_state == IP_CONF)
1919                         nm_device_activate_schedule_ip6_config_result (device, priv->dhcp6_ip6_config);
1920                 else if (priv->ip6_state == IP_DONE)
1921                         dhcp6_lease_change (device);
1922
1923                 if (priv->dhcp6_ip6_config) {
1924                         /* Update the DHCP6 config object with new DHCP options */
1925                         nm_dhcp6_config_reset (priv->dhcp6_config);
1926                         nm_dhcp_client_foreach_option (priv->dhcp6_client,
1927                                                        dhcp6_add_option_cb,
1928                                                        priv->dhcp6_config);
1929                         g_object_notify (G_OBJECT (device), NM_DEVICE_DHCP6_CONFIG);
1930                 }
1931                 break;
1932         case DHC_TIMEOUT: /* timed out contacting DHCP server */
1933                 dhcp6_fail (device, TRUE);
1934                 break;
1935         case DHC_END: /* dhclient exited normally */
1936                 /* In IPv6 info-only mode, the client doesn't handle leases so it
1937                  * may exit right after getting a response from the server.  That's
1938                  * normal.  In that case we just ignore the exit.
1939                  */
1940                 if (priv->dhcp6_mode == IP6_DHCP_OPT_OTHERCONF)
1941                         break;
1942                 /* Otherwise, fall through */
1943         case DHC_FAIL: /* all attempts to contact server timed out, sleeping */
1944         case DHC_ABEND: /* dhclient exited abnormally */
1945                 /* dhclient quit and can't get/renew a lease; so kill the connection */
1946                 dhcp6_fail (device, FALSE);
1947                 break;
1948         default:
1949                 break;
1950         }
1951 }
1952
1953 static void
1954 dhcp6_timeout (NMDHCPClient *client, gpointer user_data)
1955 {
1956         NMDevice *device = NM_DEVICE (user_data);
1957
1958         g_return_if_fail (nm_device_get_act_request (device) != NULL);
1959         g_return_if_fail (nm_dhcp_client_get_ipv6 (client) == TRUE);
1960
1961         nm_dhcp_client_stop (client, FALSE);
1962         dhcp6_fail (device, TRUE);
1963 }
1964
1965 static NMActStageReturn
1966 dhcp6_start (NMDevice *self,
1967              NMConnection *connection,
1968              guint32 dhcp_opt,
1969              NMDeviceStateReason *reason)
1970 {
1971         NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
1972         NMActStageReturn ret = NM_ACT_STAGE_RETURN_FAILURE;
1973         guint8 *anycast = NULL;
1974         const char *ip_iface;
1975         const struct in6_addr dest = { { { 0xFF,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } } };
1976         int err;
1977
1978         if (!connection) {
1979                 connection = nm_device_get_connection (self);
1980                 g_assert (connection);
1981         }
1982
1983         /* Begin a DHCP transaction on the interface */
1984
1985         if (priv->dhcp_anycast_address)
1986                 anycast = priv->dhcp_anycast_address->data;
1987
1988         /* Clear old exported DHCP options */
1989         if (priv->dhcp6_config)
1990                 g_object_unref (priv->dhcp6_config);
1991         priv->dhcp6_config = nm_dhcp6_config_new ();
1992
1993         g_warn_if_fail (priv->dhcp6_ip6_config == NULL);
1994         if (priv->dhcp6_ip6_config) {
1995                 g_object_unref (priv->dhcp6_ip6_config);
1996                 priv->dhcp6_ip6_config = NULL;
1997         }
1998
1999         /* DHCPv6 communicates with the DHCPv6 server via two multicast addresses,
2000          * ff02::1:2 (link-scope) and ff05::1:3 (site-scope).  Make sure we have
2001          * a multicast route (ff00::/8) for client <-> server communication.
2002          */
2003         err = nm_system_set_ip6_route (priv->ip_iface ? priv->ip_ifindex : priv->ifindex,
2004                                        &dest, 8, NULL, 256, 0, RTPROT_BOOT, RT_TABLE_LOCAL, NULL);
2005         if (err && (err != -NLE_EXIST)) {
2006                 nm_log_err (LOGD_DEVICE | LOGD_IP6,
2007                             "(%s): failed to add IPv6 multicast route: %s",
2008                             priv->ip_iface ? priv->ip_iface : priv->iface, nl_geterror (err));
2009         }
2010
2011         ip_iface = nm_device_get_ip_iface (self);
2012         priv->dhcp6_client = nm_dhcp_manager_start_ip6 (priv->dhcp_manager,
2013                                                         ip_iface,
2014                                                         nm_connection_get_uuid (connection),
2015                                                         nm_connection_get_setting_ip6_config (connection),
2016                                                         priv->dhcp_timeout,
2017                                                         anycast,
2018                                                         (dhcp_opt == IP6_DHCP_OPT_OTHERCONF) ? TRUE : FALSE);
2019         if (priv->dhcp6_client) {
2020                 priv->dhcp6_state_sigid = g_signal_connect (priv->dhcp6_client,
2021                                                             "state-changed",
2022                                                             G_CALLBACK (dhcp6_state_changed),
2023                                                             self);
2024                 priv->dhcp6_timeout_sigid = g_signal_connect (priv->dhcp6_client,
2025                                                               "timeout",
2026                                                               G_CALLBACK (dhcp6_timeout),
2027                                                               self);
2028
2029                 /* DHCP devices will be notified by the DHCP manager when stuff happens */
2030                 ret = NM_ACT_STAGE_RETURN_POSTPONE;
2031         } else {
2032                 *reason = NM_DEVICE_STATE_REASON_DHCP_START_FAILED;
2033                 ret = NM_ACT_STAGE_RETURN_FAILURE;
2034         }
2035
2036         return ret;
2037 }
2038
2039 /******************************************/
2040
2041 static void
2042 ip6_addrconf_complete (NMIP6Manager *ip6_manager,
2043                        int ifindex,
2044                        guint dhcp_opts,
2045                        gboolean success,
2046                        gpointer user_data)
2047 {
2048         NMDevice *self = NM_DEVICE (user_data);
2049         NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
2050         NMConnection *connection;
2051         NMActStageReturn ret;
2052         NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE;
2053
2054         if (ifindex != nm_device_get_ip_ifindex (self))
2055                 return;
2056         g_return_if_fail (priv->act_request != NULL);
2057         connection = nm_device_get_connection (self);
2058         g_assert (connection);
2059
2060         if (!priv->ip6_waiting_for_config)
2061                 return;
2062
2063         priv->ip6_waiting_for_config = FALSE;
2064
2065         if (!success) {
2066                 nm_device_activate_schedule_ip6_config_timeout (self);
2067                 return;
2068         }
2069
2070         priv->dhcp6_mode = dhcp_opts;
2071
2072         /* If addrconf is all that's required, we're done */
2073         if (priv->dhcp6_mode == IP6_DHCP_OPT_NONE) {
2074                 priv->ac_ip6_config = nm_ip6_manager_get_ip6_config (ip6_manager, ifindex);
2075                 nm_device_activate_schedule_ip6_config_result (self, priv->ac_ip6_config);
2076                 return;
2077         }
2078
2079         /* If the router said to use DHCP for managed or otherconf, do it */
2080
2081         /* Don't re-start DHCPv6 if it's already in progress */
2082         if (priv->ip6_state != IP_CONF)
2083                 return;
2084
2085         nm_log_info (LOGD_DEVICE | LOGD_DHCP6,
2086                      "Activation (%s) Stage 3 of 5 (IP Configure Start) starting DHCPv6"
2087                      " as requested by IPv6 router...",
2088                      priv->iface);
2089
2090         ret = dhcp6_start (self, connection, priv->dhcp6_mode, &reason);
2091         switch (ret) {
2092         case NM_ACT_STAGE_RETURN_SUCCESS:
2093                 /* Shouldn't get this, but handle it anyway */
2094                 g_warn_if_reached ();
2095                 priv->ac_ip6_config = nm_ip6_manager_get_ip6_config (ip6_manager, ifindex);
2096                 nm_device_activate_schedule_ip6_config_result (self, priv->ac_ip6_config);
2097                 break;
2098         case NM_ACT_STAGE_RETURN_POSTPONE:
2099                 /* Cache acquired autoconf config and wait for DHCPv6 to complete */
2100                 priv->ac_ip6_config = nm_ip6_manager_get_ip6_config (ip6_manager, ifindex);
2101                 break;
2102         default:
2103                 nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, reason);
2104                 break;
2105         }
2106 }
2107
2108 static void
2109 ip6_config_changed (NMIP6Manager *ip6_manager,
2110                     int ifindex,
2111                     guint dhcp_opts,
2112                     gboolean success,
2113                     gpointer user_data)
2114 {
2115         NMDevice *self = NM_DEVICE (user_data);
2116         NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
2117         NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE;
2118
2119         if (ifindex != nm_device_get_ip_ifindex (self))
2120                 return;
2121         g_return_if_fail (priv->act_request != NULL);
2122
2123         /* If autoconf failed and IPv6 previously succeeded, fail */
2124         if (!success && (priv->ip6_state == IP_DONE)) {
2125                 nm_device_state_changed (self,
2126                                          NM_DEVICE_STATE_FAILED,
2127                                          NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE);
2128                 return;
2129         }
2130
2131         /* FIXME: re-run DHCPv6 here to get any new nameservers or whatever */
2132
2133         if (priv->ac_ip6_config)
2134                 g_object_unref (priv->ac_ip6_config);
2135         priv->ac_ip6_config = nm_ip6_manager_get_ip6_config (ip6_manager, ifindex);
2136
2137         if (ip6_config_merge_and_apply (self, NULL, &reason) == FALSE) {
2138                 nm_log_warn (LOGD_DHCP6, "(%s): failed to update IPv6 config in response to Router Advertisement.",
2139                              nm_device_get_ip_iface (self));
2140                 nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, reason);
2141         }
2142 }
2143
2144 static gboolean
2145 addrconf6_start (NMDevice *self)
2146 {
2147         NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
2148         NMConnection *connection;
2149         gboolean success;
2150
2151         connection = nm_device_get_connection (self);
2152         g_assert (connection);
2153
2154         g_warn_if_fail (priv->ac_ip6_config == NULL);
2155         if (priv->ac_ip6_config) {
2156                 g_object_unref (priv->ac_ip6_config);
2157                 priv->ac_ip6_config = NULL;
2158         }
2159
2160         if (!priv->ip6_manager) {
2161                 priv->ip6_manager = nm_ip6_manager_get ();
2162                 priv->ip6_addrconf_sigid = g_signal_connect (priv->ip6_manager,
2163                                                              "addrconf-complete",
2164                                                              G_CALLBACK (ip6_addrconf_complete),
2165                                                              self);
2166                 priv->ip6_config_changed_sigid = g_signal_connect (priv->ip6_manager,
2167                                                                    "config-changed",
2168                                                                    G_CALLBACK (ip6_config_changed),
2169                                                                    self);
2170         }
2171
2172         success = nm_ip6_manager_prepare_interface (priv->ip6_manager,
2173                                                     nm_device_get_ip_ifindex (self),
2174                                                     nm_connection_get_setting_ip6_config (connection),
2175                                                     priv->ip6_accept_ra_path);
2176         if (success) {
2177                 priv->ip6_waiting_for_config = TRUE;
2178                 nm_ip6_manager_begin_addrconf (priv->ip6_manager, nm_device_get_ip_ifindex (self));
2179         }
2180
2181         return success;
2182 }
2183
2184 static void
2185 addrconf6_cleanup (NMDevice *self)
2186 {
2187         NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
2188
2189         if (priv->ac_ip6_config) {
2190                 g_object_unref (priv->ac_ip6_config);
2191                 priv->ac_ip6_config = NULL;
2192         }
2193
2194         if (!priv->ip6_manager)
2195                 return;
2196
2197         if (priv->ip6_addrconf_sigid) {
2198                 g_signal_handler_disconnect (priv->ip6_manager,
2199                                              priv->ip6_addrconf_sigid);
2200                 priv->ip6_addrconf_sigid = 0;
2201         }
2202         if (priv->ip6_config_changed_sigid) {
2203                 g_signal_handler_disconnect (priv->ip6_manager,
2204                                              priv->ip6_config_changed_sigid);
2205                 priv->ip6_config_changed_sigid = 0;
2206         }
2207
2208         nm_ip6_manager_cancel_addrconf (priv->ip6_manager, nm_device_get_ip_ifindex (self));
2209         g_object_unref (priv->ip6_manager);
2210         priv->ip6_manager = NULL;
2211 }
2212
2213 /******************************************/
2214
2215 static NMActStageReturn
2216 real_act_stage3_ip6_config_start (NMDevice *self,
2217                                   NMIP6Config **out_config,
2218                                   NMDeviceStateReason *reason)
2219 {
2220         NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
2221         const char *ip_iface;
2222         NMActStageReturn ret = NM_ACT_STAGE_RETURN_FAILURE;
2223         NMConnection *connection;
2224         NMSettingIP6Config *s_ip6;
2225         int conf_use_tempaddr;
2226         NMSettingIP6ConfigPrivacy ip6_privacy = NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN;
2227         const char *ip6_privacy_str = "0\n";
2228
2229         g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE);
2230
2231         connection = nm_device_get_connection (self);
2232         g_assert (connection);
2233
2234         ip_iface = nm_device_get_ip_iface (self);
2235
2236         update_accept_ra_save (self);
2237         update_ip6_privacy_save (self);
2238
2239         priv->dhcp6_mode = IP6_DHCP_OPT_NONE;
2240
2241         if (   ip6_method_matches (connection, NM_SETTING_IP6_CONFIG_METHOD_AUTO)
2242             || ip6_method_matches (connection, NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL)) {
2243                 if (!addrconf6_start (self)) {
2244                         *reason = NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE;
2245                         ret = NM_ACT_STAGE_RETURN_FAILURE;
2246                 } else
2247                         ret = NM_ACT_STAGE_RETURN_POSTPONE;
2248         } else if (ip6_method_matches (connection, NM_SETTING_IP6_CONFIG_METHOD_DHCP)) {
2249                 /* Router advertisements shouldn't be used in pure DHCP mode */
2250                 if (priv->ip6_accept_ra_path)
2251                         nm_utils_do_sysctl (priv->ip6_accept_ra_path, "0\n");
2252
2253                 priv->dhcp6_mode = IP6_DHCP_OPT_MANAGED;
2254                 ret = dhcp6_start (self, connection, priv->dhcp6_mode, reason);
2255         } else if (ip6_method_matches (connection, NM_SETTING_IP6_CONFIG_METHOD_IGNORE)) {
2256                 /* reset the saved RA value when ipv6 is ignored */
2257                 if (priv->ip6_accept_ra_path) {
2258                         nm_utils_do_sysctl (priv->ip6_accept_ra_path,
2259                                             priv->ip6_accept_ra_save ? "1\n" : "0\n");
2260                 }
2261                 ret = NM_ACT_STAGE_RETURN_STOP;
2262         } else if (ip6_method_matches (connection, NM_SETTING_IP6_CONFIG_METHOD_MANUAL)) {
2263                 /* New blank config */
2264                 *out_config = nm_ip6_config_new ();
2265                 g_assert (*out_config);
2266
2267                 /* Router advertisements shouldn't be used in manual mode */
2268                 if (priv->ip6_accept_ra_path)
2269                         nm_utils_do_sysctl (priv->ip6_accept_ra_path, "0\n");
2270                 ret = NM_ACT_STAGE_RETURN_SUCCESS;
2271         } else {
2272                 nm_log_warn (LOGD_IP6, "(%s): unhandled IPv6 config method; will fail",
2273                              nm_device_get_ip_iface (self));
2274         }
2275
2276         /* Other methods (shared) aren't implemented yet */
2277
2278         /* Enable/disable IPv6 Privacy Extensions.
2279          * If a global value is configured by sysadmin (e.g. /etc/sysctl.conf),
2280          * use that value instead of per-connection value.
2281          */
2282         conf_use_tempaddr = nm_backend_ipv6_use_tempaddr ();
2283         if (conf_use_tempaddr >= 0)
2284                 ip6_privacy = conf_use_tempaddr;
2285         else {
2286                 s_ip6 = nm_connection_get_setting_ip6_config (connection);
2287                 if (s_ip6)
2288                         ip6_privacy = nm_setting_ip6_config_get_ip6_privacy (s_ip6);
2289         }
2290         ip6_privacy = CLAMP (ip6_privacy, NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN, NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR);
2291
2292         switch (ip6_privacy) {
2293         case NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN:
2294         case NM_SETTING_IP6_CONFIG_PRIVACY_DISABLED:
2295                 ip6_privacy_str = "0\n";
2296         break;
2297         case NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_PUBLIC_ADDR:
2298                 ip6_privacy_str = "1\n";
2299         break;
2300         case NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR:
2301                 ip6_privacy_str = "2\n";
2302         break;
2303         }
2304         if (priv->ip6_privacy_tempaddr_path)
2305                 nm_utils_do_sysctl (priv->ip6_privacy_tempaddr_path, ip6_privacy_str);
2306
2307         return ret;
2308 }
2309
2310
2311 /*
2312  * nm_device_activate_stage3_ip_config_start
2313  *
2314  * Begin automatic/manual IP configuration
2315  *
2316  */
2317 static gboolean
2318 nm_device_activate_stage3_ip_config_start (gpointer user_data)
2319 {
2320         NMDevice *self = NM_DEVICE (user_data);
2321         NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
2322         const char *iface;
2323         NMActStageReturn ret;
2324         NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE;
2325         NMIP4Config *ip4_config = NULL;
2326         NMIP6Config *ip6_config = NULL;
2327         int ifindex;
2328
2329         /* Clear the activation source ID now that this stage has run */
2330         activation_source_clear (self, FALSE, 0);
2331
2332         iface = nm_device_get_iface (self);
2333         nm_log_info (LOGD_DEVICE, "Activation (%s) Stage 3 of 5 (IP Configure Start) started...", iface);
2334         nm_device_state_changed (self, NM_DEVICE_STATE_IP_CONFIG, NM_DEVICE_STATE_REASON_NONE);
2335
2336         /* Make sure the interface is up before trying to do anything with it */
2337         ifindex = nm_device_get_ip_ifindex (self);
2338         if ((ifindex > 0) && (nm_system_iface_is_up (ifindex) == FALSE))
2339                 nm_system_iface_set_up (ifindex, TRUE, NULL);
2340
2341         priv->ip4_state = priv->ip6_state = IP_CONF;
2342
2343         ret = NM_DEVICE_GET_CLASS (self)->act_stage3_ip4_config_start (self, &ip4_config, &reason);
2344         if (ret == NM_ACT_STAGE_RETURN_SUCCESS) {
2345                 g_assert (ip4_config);
2346                 nm_device_activate_schedule_ip4_config_result (self, ip4_config);
2347                 g_object_unref (ip4_config);
2348         } else if (ret == NM_ACT_STAGE_RETURN_FAILURE) {
2349                 nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, reason);
2350                 goto out;
2351         } else if (ret == NM_ACT_STAGE_RETURN_STOP) {
2352                 /* Nothing to do */
2353                 priv->ip4_state = IP_DONE;
2354         } else
2355                 g_assert (ret == NM_ACT_STAGE_RETURN_POSTPONE);
2356
2357         ret = NM_DEVICE_GET_CLASS (self)->act_stage3_ip6_config_start (self, &ip6_config, &reason);
2358         if (ret == NM_ACT_STAGE_RETURN_SUCCESS) {
2359                 g_assert (ip6_config);
2360                 nm_device_activate_schedule_ip6_config_result (self, ip6_config);
2361                 g_object_unref (ip6_config);
2362         } else if (ret == NM_ACT_STAGE_RETURN_FAILURE) {
2363                 nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, reason);
2364                 goto out;
2365         } else if (ret == NM_ACT_STAGE_RETURN_STOP) {
2366                 /* Nothing to do */
2367                 priv->ip6_state = IP_DONE;
2368         } else
2369                 g_assert (ret == NM_ACT_STAGE_RETURN_POSTPONE);
2370
2371 out:
2372         nm_log_info (LOGD_DEVICE, "Activation (%s) Stage 3 of 5 (IP Configure Start) complete.", iface);
2373
2374         /* Handle interfaces (bond slaves, etc) that won't have any IP config; they
2375          * need to move to ACTIVATED.
2376          */
2377         if (priv->ip4_state == IP_DONE && priv->ip6_state == IP_DONE) {
2378                 /* FIXME: call layer2 stuff to set MTU? */
2379                 nm_device_state_changed (self, NM_DEVICE_STATE_ACTIVATED, NM_DEVICE_STATE_REASON_NONE);
2380         }
2381
2382         return FALSE;
2383 }
2384
2385
2386 static void
2387 fw_add_to_zone_cb (GError *error, gpointer user_data)
2388 {
2389         NMDevice *self = NM_DEVICE (user_data);
2390         NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
2391
2392         priv->fw_call = NULL;
2393
2394         if (error) {
2395                 /* FIXME: fail the device activation? */
2396         }
2397
2398         activation_source_schedule (self, nm_device_activate_stage3_ip_config_start, 0);
2399
2400         nm_log_info (LOGD_DEVICE, "Activation (%s) Stage 3 of 5 (IP Configure Start) scheduled.",
2401                      nm_device_get_iface (self));
2402 }
2403
2404 /*
2405  * nm_device_activate_schedule_stage3_ip_config_start
2406  *
2407  * Schedule IP configuration start
2408  */
2409 void
2410 nm_device_activate_schedule_stage3_ip_config_start (NMDevice *self)
2411 {
2412         NMDevicePrivate *priv;
2413         NMConnection *connection;
2414         NMSettingConnection *s_con = NULL;
2415         NMDeviceState state;
2416         const char *zone;
2417
2418         g_return_if_fail (NM_IS_DEVICE (self));
2419
2420         priv = NM_DEVICE_GET_PRIVATE (self);
2421         g_return_if_fail (priv->act_request);
2422
2423         state = nm_device_get_state (self);
2424         g_warn_if_fail (state >= NM_DEVICE_STATE_PREPARE && state <= NM_DEVICE_STATE_NEED_AUTH);
2425
2426         /* Add the interface to the specified firewall zone */
2427         connection = nm_device_get_connection (self);
2428         g_assert (connection);
2429         s_con = nm_connection_get_setting_connection (connection);
2430
2431         zone = nm_setting_connection_get_zone (s_con);
2432         nm_log_dbg (LOGD_DEVICE, "Activation (%s) setting firewall zone '%s'",
2433                     nm_device_get_iface (self), zone ? zone : "default");
2434         priv->fw_call = nm_firewall_manager_add_or_change_zone (priv->fw_manager,
2435                                                                 nm_device_get_ip_iface (self),
2436                                                                 zone,
2437                                                                 TRUE,
2438                                                                 fw_add_to_zone_cb,
2439                                                                 self);
2440 }
2441
2442 static NMActStageReturn
2443 real_act_stage4_ip4_config_timeout (NMDevice *self, NMDeviceStateReason *reason)
2444 {
2445         if (nm_device_ip_config_should_fail (self, FALSE)) {
2446                 *reason = NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE;
2447                 return NM_ACT_STAGE_RETURN_FAILURE;
2448         }
2449         return NM_ACT_STAGE_RETURN_SUCCESS;
2450 }
2451
2452
2453 /*
2454  * nm_device_activate_stage4_ip4_config_timeout
2455  *
2456  * Time out on retrieving the IPv4 config.
2457  *
2458  */
2459 static gboolean
2460 nm_device_activate_ip4_config_timeout (gpointer user_data)
2461 {
2462         NMDevice *self = NM_DEVICE (user_data);
2463         NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
2464         const char *iface;
2465         NMActStageReturn ret = NM_ACT_STAGE_RETURN_FAILURE;
2466         NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE;
2467
2468         /* Clear the activation source ID now that this stage has run */
2469         activation_source_clear (self, FALSE, AF_INET);
2470
2471         iface = nm_device_get_iface (self);
2472         nm_log_info (LOGD_DEVICE | LOGD_IP4,
2473                      "Activation (%s) Stage 4 of 5 (IPv4 Configure Timeout) started...",
2474                      iface);
2475
2476         ret = NM_DEVICE_GET_CLASS (self)->act_stage4_ip4_config_timeout (self, &reason);
2477         if (ret == NM_ACT_STAGE_RETURN_POSTPONE)
2478                 goto out;
2479         else if (ret == NM_ACT_STAGE_RETURN_FAILURE) {
2480                 nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, reason);
2481                 goto out;
2482         }
2483         g_assert (ret == NM_ACT_STAGE_RETURN_SUCCESS);  
2484
2485         priv->ip4_state = IP_DONE;
2486
2487         /* If IPv4 failed and IPv6 failed, the activation fails */
2488         if ((priv->ip6_state == IP_DONE) && (priv->ip6_config == NULL)) {
2489                 nm_device_state_changed (self,
2490                                                  NM_DEVICE_STATE_FAILED,
2491                                                  NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE);
2492         }
2493
2494 out:
2495         nm_log_info (LOGD_DEVICE | LOGD_IP4,
2496                      "Activation (%s) Stage 4 of 5 (IPv4 Configure Timeout) complete.",
2497                      iface);
2498         return FALSE;
2499 }
2500
2501
2502 /*
2503  * nm_device_activate_schedule_ip4_config_timeout
2504  *
2505  * Deal with a timeout of the IPv4 configuration
2506  *
2507  */
2508 void
2509 nm_device_activate_schedule_ip4_config_timeout (NMDevice *self)
2510 {
2511         NMDevicePrivate *priv;
2512
2513         g_return_if_fail (NM_IS_DEVICE (self));
2514
2515         priv = NM_DEVICE_GET_PRIVATE (self);
2516         g_return_if_fail (priv->act_request);
2517
2518         activation_source_schedule (self, nm_device_activate_ip4_config_timeout, AF_INET);
2519
2520         nm_log_info (LOGD_DEVICE | LOGD_IP4,
2521                      "Activation (%s) Stage 4 of 5 (IPv4 Configure Timeout) scheduled...",
2522                      nm_device_get_iface (self));
2523 }
2524
2525
2526 static NMActStageReturn
2527 real_act_stage4_ip6_config_timeout (NMDevice *self, NMDeviceStateReason *reason)
2528 {
2529         if (nm_device_ip_config_should_fail (self, TRUE)) {
2530                 *reason = NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE;
2531                 return NM_ACT_STAGE_RETURN_FAILURE;
2532         }
2533
2534         return NM_ACT_STAGE_RETURN_SUCCESS;
2535 }
2536
2537
2538 /*
2539  * nm_device_activate_ip6_config_timeout
2540  *
2541  * Time out on retrieving the IPv6 config.
2542  *
2543  */
2544 static gboolean
2545 nm_device_activate_ip6_config_timeout (gpointer user_data)
2546 {
2547         NMDevice *self = NM_DEVICE (user_data);
2548         NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
2549         const char *iface;
2550         NMActStageReturn ret = NM_ACT_STAGE_RETURN_FAILURE;
2551         NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE;
2552
2553         /* Clear the activation source ID now that this stage has run */
2554         activation_source_clear (self, FALSE, AF_INET6);
2555
2556         iface = nm_device_get_iface (self);
2557         nm_log_info (LOGD_DEVICE | LOGD_IP6,
2558                      "Activation (%s) Stage 4 of 5 (IPv6 Configure Timeout) started...",
2559                      iface);
2560
2561         ret = NM_DEVICE_GET_CLASS (self)->act_stage4_ip6_config_timeout (self, &reason);
2562         if (ret == NM_ACT_STAGE_RETURN_POSTPONE)
2563                 goto out;
2564         else if (ret == NM_ACT_STAGE_RETURN_FAILURE) {
2565                 nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, reason);
2566                 goto out;
2567         }
2568         g_assert (ret == NM_ACT_STAGE_RETURN_SUCCESS);
2569
2570         priv->ip6_state = IP_DONE;
2571
2572         /* If IPv6 failed and IPv4 failed, the activation fails */
2573         if ((priv->ip4_state == IP_DONE) && (priv->ip4_config == NULL)) {
2574                 nm_device_state_changed (self,
2575                                                  NM_DEVICE_STATE_FAILED,
2576                                                  NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE);
2577         }
2578
2579 out:
2580         nm_log_info (LOGD_DEVICE | LOGD_IP6,
2581                      "Activation (%s) Stage 4 of 5 (IPv6 Configure Timeout) complete.",
2582                      iface);
2583         return FALSE;
2584 }
2585
2586
2587 /*
2588  * nm_device_activate_schedule_ip6_config_timeout
2589  *
2590  * Deal with a timeout of the IPv6 configuration
2591  *
2592  */
2593 void
2594 nm_device_activate_schedule_ip6_config_timeout (NMDevice *self)
2595 {
2596         NMDevicePrivate *priv;
2597
2598         g_return_if_fail (NM_IS_DEVICE (self));
2599
2600         priv = NM_DEVICE_GET_PRIVATE (self);
2601         g_return_if_fail (priv->act_request);
2602
2603         activation_source_schedule (self, nm_device_activate_ip6_config_timeout, AF_INET6);
2604
2605         nm_log_info (LOGD_DEVICE | LOGD_IP6,
2606                      "Activation (%s) Stage 4 of 5 (IPv6 Configure Timeout) scheduled...",
2607                      nm_device_get_iface (self));
2608 }
2609
2610 static void
2611 share_child_setup (gpointer user_data G_GNUC_UNUSED)
2612 {
2613         /* We are in the child process at this point */
2614         pid_t pid = getpid ();
2615         setpgid (pid, pid);
2616
2617         nm_unblock_posix_signals (NULL);
2618 }
2619
2620 static gboolean
2621 share_init (void)
2622 {
2623         int status;
2624         char *modules[] = { "ip_tables", "iptable_nat", "nf_nat_ftp", "nf_nat_irc",
2625                             "nf_nat_sip", "nf_nat_tftp", "nf_nat_pptp", "nf_nat_h323",
2626                             NULL };
2627         char **iter;
2628
2629         if (!nm_utils_do_sysctl ("/proc/sys/net/ipv4/ip_forward", "1\n")) {
2630                 nm_log_err (LOGD_SHARING, "Error starting IP forwarding: (%d) %s",
2631                                         errno, strerror (errno));
2632                 return FALSE;
2633         }
2634
2635         if (!nm_utils_do_sysctl ("/proc/sys/net/ipv4/ip_dynaddr", "1\n")) {
2636                 nm_log_err (LOGD_SHARING, "error starting IP forwarding: (%d) %s",
2637                                         errno, strerror (errno));
2638         }
2639
2640         for (iter = modules; *iter; iter++) {
2641                 char *argv[3] = { "/sbin/modprobe", *iter, NULL };
2642                 char *envp[1] = { NULL };
2643                 GError *error = NULL;
2644
2645                 if (!g_spawn_sync ("/", argv, envp, G_SPAWN_STDOUT_TO_DEV_NULL | G_SPAWN_STDERR_TO_DEV_NULL,
2646                                    share_child_setup, NULL, NULL, NULL, &status, &error)) {
2647                         nm_log_err (LOGD_SHARING, "error loading NAT module %s: (%d) %s",
2648                                     *iter, error ? error->code : 0,
2649                                     (error && error->message) ? error->message : "unknown");
2650                         if (error)
2651                                 g_error_free (error);
2652                 }
2653         }
2654
2655         return TRUE;
2656 }
2657
2658 static void
2659 add_share_rule (NMActRequest *req, const char *table, const char *fmt, ...)
2660 {
2661         va_list args;
2662         char *cmd;
2663
2664         va_start (args, fmt);
2665         cmd = g_strdup_vprintf (fmt, args);
2666         va_end (args);
2667
2668         nm_act_request_add_share_rule (req, table, cmd);
2669         g_free (cmd);
2670 }
2671
2672 static gboolean
2673 start_sharing (NMDevice *self, NMIP4Config *config)
2674 {
2675         NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
2676         NMActRequest *req;
2677         GError *error = NULL;
2678         char str_addr[INET_ADDRSTRLEN + 1];
2679         char str_mask[INET_ADDRSTRLEN + 1];
2680         guint32 netmask, network;
2681         NMIP4Address *ip4_addr;
2682         const char *ip_iface;
2683
2684         g_return_val_if_fail (config != NULL, FALSE);
2685
2686         ip_iface = nm_device_get_ip_iface (self);
2687
2688         ip4_addr = nm_ip4_config_get_address (config, 0);
2689         if (!ip4_addr || !nm_ip4_address_get_address (ip4_addr))
2690                 return FALSE;
2691
2692         netmask = nm_utils_ip4_prefix_to_netmask (nm_ip4_address_get_prefix (ip4_addr));
2693         if (!inet_ntop (AF_INET, &netmask, str_mask, sizeof (str_mask)))
2694                 return FALSE;
2695
2696         network = nm_ip4_address_get_address (ip4_addr) & netmask;
2697         if (!inet_ntop (AF_INET, &network, str_addr, sizeof (str_addr)))
2698                 return FALSE;
2699
2700         if (!share_init ())
2701                 return FALSE;
2702
2703         req = nm_device_get_act_request (self);
2704         g_assert (req);
2705
2706         add_share_rule (req, "filter", "INPUT --in-interface %s --protocol tcp --destination-port 53 --jump ACCEPT", ip_iface);
2707         add_share_rule (req, "filter", "INPUT --in-interface %s --protocol udp --destination-port 53 --jump ACCEPT", ip_iface);
2708         add_share_rule (req, "filter", "INPUT --in-interface %s --protocol tcp --destination-port 67 --jump ACCEPT", ip_iface);
2709         add_share_rule (req, "filter", "INPUT --in-interface %s --protocol udp --destination-port 67 --jump ACCEPT", ip_iface);
2710         add_share_rule (req, "filter", "FORWARD --in-interface %s --jump REJECT", ip_iface);
2711         add_share_rule (req, "filter", "FORWARD --out-interface %s --jump REJECT", ip_iface);
2712         add_share_rule (req, "filter", "FORWARD --in-interface %s --out-interface %s --jump ACCEPT", ip_iface, ip_iface);
2713         add_share_rule (req, "filter", "FORWARD --source %s/%s --in-interface %s --jump ACCEPT", str_addr, str_mask, ip_iface);
2714         add_share_rule (req, "filter", "FORWARD --destination %s/%s --out-interface %s --match state --state ESTABLISHED,RELATED --jump ACCEPT", str_addr, str_mask, ip_iface);
2715         add_share_rule (req, "nat", "POSTROUTING --source %s/%s ! --destination %s/%s --jump MASQUERADE", str_addr, str_mask, str_addr, str_mask);
2716
2717         nm_act_request_set_shared (req, TRUE);
2718
2719         if (!nm_dnsmasq_manager_start (priv->dnsmasq_manager, config, &error)) {
2720                 nm_log_err (LOGD_SHARING, "(%s/%s): failed to start dnsmasq: %s",
2721                             nm_device_get_iface (self), ip_iface, error->message);
2722                 g_error_free (error);
2723                 nm_act_request_set_shared (req, FALSE);
2724                 return FALSE;
2725         }
2726
2727         priv->dnsmasq_state_id = g_signal_connect (priv->dnsmasq_manager, "state-changed",
2728                                                    G_CALLBACK (dnsmasq_state_changed_cb),
2729                                                    self);
2730         return TRUE;
2731 }
2732
2733 static gboolean
2734 nm_device_activate_ip4_config_commit (gpointer user_data)
2735 {
2736         NMDevice *self = NM_DEVICE (user_data);
2737         NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
2738         NMActRequest *req;
2739         NMIP4Config *config = NULL;
2740         const char *iface, *method = NULL;
2741         NMConnection *connection;
2742         NMSettingIP4Config *s_ip4;
2743         NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE;
2744         gboolean assumed;
2745         int ifindex;
2746
2747         /* Clear the activation source ID now that this stage has run */
2748         activation_source_clear (self, FALSE, AF_INET);
2749
2750         iface = nm_device_get_iface (self);
2751         nm_log_info (LOGD_DEVICE, "Activation (%s) Stage 5 of 5 (IPv4 Commit) started...",
2752                      iface);
2753
2754         req = nm_device_get_act_request (self);
2755         g_assert (req);
2756         connection = nm_act_request_get_connection (req);
2757         g_assert (connection);
2758
2759         config = g_object_get_data (G_OBJECT (req), PENDING_IP4_CONFIG);
2760         g_assert (config);
2761
2762         /* Make sure the interface is up again just because */
2763         ifindex = nm_device_get_ip_ifindex (self);
2764         if ((ifindex > 0) && (nm_system_iface_is_up (ifindex) == FALSE))
2765                 nm_system_iface_set_up (ifindex, TRUE, NULL);
2766
2767         /* Allow setting MTU etc */
2768         if (NM_DEVICE_GET_CLASS (self)->ip4_config_pre_commit)
2769                 NM_DEVICE_GET_CLASS (self)->ip4_config_pre_commit (self, config);
2770
2771         /* Merge with user overrides */
2772         nm_utils_merge_ip4_config (config, nm_connection_get_setting_ip4_config (connection));
2773
2774         assumed = nm_act_request_get_assumed (priv->act_request);
2775         if (!nm_device_set_ip4_config (self, config, assumed, &reason)) {
2776                 nm_log_info (LOGD_DEVICE | LOGD_IP4,
2777                                  "Activation (%s) Stage 5 of 5 (IPv4 Commit) failed",
2778                                          iface);
2779                 nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, reason);
2780                 goto out;
2781         }
2782
2783         /* Start IPv4 sharing if we need it */
2784         s_ip4 = nm_connection_get_setting_ip4_config (connection);
2785         if (s_ip4)
2786                 method = nm_setting_ip4_config_get_method (s_ip4);
2787
2788         if (g_strcmp0 (method, NM_SETTING_IP4_CONFIG_METHOD_SHARED) == 0) {
2789                 if (!start_sharing (self, config)) {
2790                         nm_log_warn (LOGD_SHARING, "Activation (%s) Stage 5 of 5 (IPv4 Commit) start sharing failed.", iface);
2791                         nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_SHARED_START_FAILED);
2792                         goto out;
2793                 }
2794         }
2795
2796         /* Enter the ACTIVATED state if this is the first method to complete */
2797         priv->ip4_state = IP_DONE;
2798         if (nm_device_get_state (self) == NM_DEVICE_STATE_IP_CONFIG)
2799                 nm_device_state_changed (self, NM_DEVICE_STATE_ACTIVATED, NM_DEVICE_STATE_REASON_NONE);
2800
2801 out:
2802         nm_log_info (LOGD_DEVICE, "Activation (%s) Stage 5 of 5 (IPv4 Commit) complete.",
2803                      iface);
2804
2805         /* Balance IP config creation; nm_device_set_ip4_config() takes a reference */
2806         g_object_set_data (G_OBJECT (req), PENDING_IP4_CONFIG, NULL);
2807
2808         return FALSE;
2809 }
2810
2811 void
2812 nm_device_activate_schedule_ip4_config_result (NMDevice *self, NMIP4Config *config)
2813 {
2814         NMDevicePrivate *priv;
2815
2816         g_return_if_fail (NM_IS_DEVICE (self));
2817
2818         priv = NM_DEVICE_GET_PRIVATE (self);
2819         g_return_if_fail (priv->act_request);
2820
2821         if (config == NULL) {
2822                 nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE);
2823                 return;
2824         }
2825
2826         g_object_set_data_full (G_OBJECT (priv->act_request),
2827                                 PENDING_IP4_CONFIG,
2828                                 g_object_ref (config),
2829                                 g_object_unref);
2830
2831         activation_source_schedule (self, nm_device_activate_ip4_config_commit, AF_INET);
2832
2833         nm_log_info (LOGD_DEVICE | LOGD_IP4,
2834                          "Activation (%s) Stage 5 of 5 (IPv4 Configure Commit) scheduled...",
2835                          nm_device_get_iface (self));
2836 }
2837
2838 gboolean
2839 nm_device_activate_ip4_state_in_conf (NMDevice *self)
2840 {
2841         g_return_val_if_fail (self != NULL, FALSE);
2842         return NM_DEVICE_GET_PRIVATE (self)->ip4_state == IP_CONF;
2843 }
2844
2845 static gboolean
2846 nm_device_activate_ip6_config_commit (gpointer user_data)
2847 {
2848         NMDevice *self = NM_DEVICE (user_data);
2849         NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
2850         NMActRequest *req;
2851         NMIP6Config *config = NULL;
2852         const char *iface;
2853         NMConnection *connection;
2854         NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE;
2855         int ifindex;
2856
2857         /* Clear the activation source ID now that this stage has run */
2858         activation_source_clear (self, FALSE, AF_INET6);
2859
2860         iface = nm_device_get_iface (self);
2861         nm_log_info (LOGD_DEVICE, "Activation (%s) Stage 5 of 5 (IPv6 Commit) started...",
2862                      iface);
2863
2864         req = nm_device_get_act_request (self);
2865         g_assert (req);
2866         connection = nm_act_request_get_connection (req);
2867         g_assert (connection);
2868
2869         config = g_object_get_data (G_OBJECT (req), PENDING_IP6_CONFIG);
2870         g_assert (config);
2871
2872         /* Make sure the interface is up again just because */
2873         ifindex = nm_device_get_ip_ifindex (self);
2874         if ((ifindex > 0) && (nm_system_iface_is_up (ifindex) == FALSE))
2875                 nm_system_iface_set_up (ifindex, TRUE, NULL);
2876
2877         /* Allow setting MTU etc */
2878         if (NM_DEVICE_GET_CLASS (self)->ip6_config_pre_commit)
2879                 NM_DEVICE_GET_CLASS (self)->ip6_config_pre_commit (self, config);
2880
2881         if (ip6_config_merge_and_apply (self, config, &reason)) {
2882                 /* Enter the ACTIVATED state if this is the first method to complete */
2883                 priv->ip6_state = IP_DONE;
2884                 if (nm_device_get_state (self) == NM_DEVICE_STATE_IP_CONFIG)
2885                         nm_device_state_changed (self, NM_DEVICE_STATE_ACTIVATED, NM_DEVICE_STATE_REASON_NONE);
2886         } else {
2887                 nm_log_info (LOGD_DEVICE | LOGD_IP6,
2888                                  "Activation (%s) Stage 5 of 5 (IPv6 Commit) failed",
2889                                          iface);
2890                 nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, reason);
2891         }
2892
2893         nm_log_info (LOGD_DEVICE, "Activation (%s) Stage 5 of 5 (IPv6 Commit) complete.",
2894                      iface);
2895
2896         /* Balance IP config creation; nm_device_set_ip6_config() takes a reference */
2897         g_object_set_data (G_OBJECT (req), PENDING_IP6_CONFIG, NULL);
2898
2899         return FALSE;
2900 }
2901
2902 void
2903 nm_device_activate_schedule_ip6_config_result (NMDevice *self, NMIP6Config *config)
2904 {
2905         NMDevicePrivate *priv;
2906
2907         g_return_if_fail (NM_IS_DEVICE (self));
2908
2909         priv = NM_DEVICE_GET_PRIVATE (self);
2910         g_return_if_fail (priv->act_request);
2911
2912         if (config == NULL) {
2913                 nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE);
2914                 return;
2915         }
2916
2917         /* Save the pending config */
2918         g_object_set_data_full (G_OBJECT (priv->act_request),
2919                                 PENDING_IP6_CONFIG,
2920                                 g_object_ref (config),
2921                                 g_object_unref);
2922
2923         activation_source_schedule (self, nm_device_activate_ip6_config_commit, AF_INET6);
2924
2925         nm_log_info (LOGD_DEVICE | LOGD_IP4,
2926                          "Activation (%s) Stage 5 of 5 (IPv6 Commit) scheduled...",
2927                          nm_device_get_iface (self));
2928 }
2929
2930 gboolean
2931 nm_device_activate_ip6_state_in_conf (NMDevice *self)
2932 {
2933         g_return_val_if_fail (self != NULL, FALSE);
2934         return NM_DEVICE_GET_PRIVATE (self)->ip6_state == IP_CONF;
2935 }
2936
2937 static void
2938 clear_act_request (NMDevice *self)
2939 {
2940         NMDevicePrivate * priv;
2941
2942         g_return_if_fail (self != NULL);
2943
2944         priv = NM_DEVICE_GET_PRIVATE (self);
2945
2946         if (!priv->act_request)
2947                 return;
2948
2949         if (priv->secrets_updated_id) {
2950                 g_signal_handler_disconnect (priv->act_request,
2951                                              priv->secrets_updated_id);
2952                 priv->secrets_updated_id = 0;
2953         }
2954
2955         if (priv->secrets_failed_id) {
2956                 g_signal_handler_disconnect (priv->act_request,
2957                                              priv->secrets_failed_id);
2958                 priv->secrets_failed_id = 0;
2959         }
2960
2961         nm_active_connection_set_default (NM_ACTIVE_CONNECTION (priv->act_request), FALSE);
2962
2963         g_object_unref (priv->act_request);
2964         priv->act_request = NULL;
2965 }
2966
2967 static void
2968 queued_state_clear (NMDevice *self)
2969 {
2970         NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
2971
2972         if (priv->queued_state.id) {
2973                 nm_log_dbg (LOGD_DEVICE, "(%s): clearing queued state transition (id %d)",
2974                             nm_device_get_iface (self), priv->queued_state.id);
2975                 g_source_remove (priv->queued_state.id);
2976         }
2977         memset (&priv->queued_state, 0, sizeof (priv->queued_state));
2978 }
2979
2980 static void
2981 dhcp4_cleanup (NMDevice *self, gboolean stop, gboolean release)
2982 {
2983         NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
2984
2985         if (priv->dhcp4_config) {
2986                 g_object_notify (G_OBJECT (self), NM_DEVICE_DHCP4_CONFIG);
2987                 g_object_unref (priv->dhcp4_config);
2988                 priv->dhcp4_config = NULL;
2989         }
2990
2991         if (priv->dhcp4_client) {
2992                 /* Stop any ongoing DHCP transaction on this device */
2993                 if (priv->dhcp4_state_sigid) {
2994                         g_signal_handler_disconnect (priv->dhcp4_client, priv->dhcp4_state_sigid);
2995                         priv->dhcp4_state_sigid = 0;
2996                 }
2997
2998                 if (priv->dhcp4_timeout_sigid) {
2999                         g_signal_handler_disconnect (priv->dhcp4_client, priv->dhcp4_timeout_sigid);
3000                         priv->dhcp4_timeout_sigid = 0;
3001                 }
3002
3003                 if (stop)
3004                         nm_dhcp_client_stop (priv->dhcp4_client, release);
3005
3006                 g_object_unref (priv->dhcp4_client);
3007                 priv->dhcp4_client = NULL;
3008         }
3009 }
3010
3011 static void
3012 dhcp6_cleanup (NMDevice *self, gboolean stop, gboolean release)
3013 {
3014         NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
3015
3016         priv->dhcp6_mode = IP6_DHCP_OPT_NONE;
3017
3018         if (priv->dhcp6_ip6_config) {
3019                 g_object_unref (priv->dhcp6_ip6_config);
3020                 priv->dhcp6_ip6_config = NULL;
3021         }
3022
3023         if (priv->dhcp6_config) {
3024                 g_object_notify (G_OBJECT (self), NM_DEVICE_DHCP6_CONFIG);
3025                 g_object_unref (priv->dhcp6_config);
3026                 priv->dhcp6_config = NULL;
3027         }
3028
3029         if (priv->dhcp6_client) {
3030                 if (priv->dhcp6_state_sigid) {
3031                         g_signal_handler_disconnect (priv->dhcp6_client, priv->dhcp6_state_sigid);
3032                         priv->dhcp6_state_sigid = 0;
3033                 }
3034
3035                 if (priv->dhcp6_timeout_sigid) {
3036                         g_signal_handler_disconnect (priv->dhcp6_client, priv->dhcp6_timeout_sigid);
3037                         priv->dhcp6_timeout_sigid = 0;
3038                 }
3039
3040                 if (stop)
3041                         nm_dhcp_client_stop (priv->dhcp6_client, release);
3042
3043                 g_object_unref (priv->dhcp6_client);
3044                 priv->dhcp6_client = NULL;
3045         }
3046 }
3047
3048 static void
3049 dnsmasq_cleanup (NMDevice *self)
3050 {
3051         NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
3052
3053         if (!priv->dnsmasq_manager)
3054                 return;
3055
3056         if (priv->dnsmasq_state_id) {
3057                 g_signal_handler_disconnect (priv->dnsmasq_manager, priv->dnsmasq_state_id);
3058                 priv->dnsmasq_state_id = 0;
3059         }
3060
3061         nm_dnsmasq_manager_stop (priv->dnsmasq_manager);
3062         g_object_unref (priv->dnsmasq_manager);
3063         priv->dnsmasq_manager = NULL;
3064 }
3065
3066 static void
3067 _update_ip4_address (NMDevice *self)
3068 {
3069         NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
3070         struct ifreq req;
3071         guint32 new_address;
3072         int fd;
3073
3074         g_return_if_fail (self  != NULL);
3075
3076         fd = socket (PF_INET, SOCK_DGRAM, 0);
3077         if (fd < 0) {
3078                 nm_log_err (LOGD_IP4, "couldn't open control socket.");
3079                 return;
3080         }
3081
3082         memset (&req, 0, sizeof (struct ifreq));
3083         strncpy (req.ifr_name, nm_device_get_ip_iface (self), IFNAMSIZ);
3084         if (ioctl (fd, SIOCGIFADDR, &req) == 0) {
3085                 new_address = ((struct sockaddr_in *)(&req.ifr_addr))->sin_addr.s_addr;
3086                 if (new_address != priv->ip4_address)
3087                         priv->ip4_address = new_address;
3088         }
3089         close (fd);
3090 }
3091
3092 /*
3093  * nm_device_deactivate
3094  *
3095  * Remove a device's routing table entries and IP address.
3096  *
3097  */
3098 static void
3099 nm_device_deactivate (NMDevice *self, NMDeviceStateReason reason)
3100 {
3101         NMDevicePrivate *priv;
3102         NMDeviceStateReason ignored = NM_DEVICE_STATE_REASON_NONE;
3103         NMConnection *connection = NULL;
3104         NMSettingConnection *s_con = NULL;
3105         gboolean tried_ipv6 = FALSE;
3106         int ifindex, family;
3107
3108         g_return_if_fail (self != NULL);
3109         g_return_if_fail (NM_IS_DEVICE (self));
3110
3111         nm_log_info (LOGD_DEVICE, "(%s): deactivating device (reason '%s') [%d]",
3112                      nm_device_get_iface (self), reason_to_string (reason), reason);
3113
3114         /* Save whether or not we tried IPv6 for later */
3115         priv = NM_DEVICE_GET_PRIVATE (self);
3116         if (priv->ip6_manager || priv->ip6_config)
3117                 tried_ipv6 = TRUE;
3118
3119         /* Clean up when device was deactivated during call to firewall */
3120         if (priv->fw_call) {
3121                 nm_firewall_manager_cancel_call (priv->fw_manager, priv->fw_call);
3122                 priv->fw_call = NULL;
3123         }
3124
3125         if (priv->act_request)
3126                 connection = nm_act_request_get_connection (priv->act_request);
3127         if (connection) {
3128                 s_con = nm_connection_get_setting_connection (connection);
3129                 nm_firewall_manager_remove_from_zone (priv->fw_manager,
3130                                                       nm_device_get_ip_iface (self),
3131                                                       nm_setting_connection_get_zone (s_con));
3132         }
3133
3134         /* Break the activation chain */
3135         activation_source_clear (self, TRUE, AF_INET);
3136         activation_source_clear (self, TRUE, AF_INET6);
3137
3138         if (priv->act_dep_result_id) {
3139                 g_source_remove (priv->act_dep_result_id);
3140                 priv->act_dep_result_id = 0;
3141         }
3142         if (priv->act_dep_timeout_id) {
3143                 g_source_remove (priv->act_dep_timeout_id);
3144                 priv->act_dep_timeout_id = 0;
3145         }
3146
3147         /* Clear any queued transitions */
3148         queued_state_clear (self);
3149
3150         priv->ip4_state = priv->ip6_state = IP_NONE;
3151
3152         dhcp4_cleanup (self, TRUE, FALSE);
3153         dhcp6_cleanup (self, TRUE, FALSE);
3154         addrconf6_cleanup (self);
3155         dnsmasq_cleanup (self);
3156         aipd_cleanup (self);
3157
3158         nm_device_set_ip_iface (self, NULL);
3159
3160         /* Turn off router advertisements until they are needed */
3161         if (priv->ip6_accept_ra_path)
3162                 nm_utils_do_sysctl (priv->ip6_accept_ra_path, "0\n");
3163
3164         /* Turn off IPv6 privacy extensions */
3165         if (priv->ip6_privacy_tempaddr_path)
3166                 nm_utils_do_sysctl (priv->ip6_privacy_tempaddr_path, "0\n");
3167
3168         /* Call device type-specific deactivation */
3169         if (NM_DEVICE_GET_CLASS (self)->deactivate)
3170                 NM_DEVICE_GET_CLASS (self)->deactivate (self);
3171
3172         /* Tear down an existing activation request */
3173         clear_act_request (self);
3174
3175         /* Take out any entries in the routing table and any IP address the device had. */
3176         ifindex = nm_device_get_ip_ifindex (self);
3177         family = tried_ipv6 ? AF_UNSPEC : AF_INET;
3178         if (ifindex > 0) {
3179                 nm_system_iface_flush_routes (ifindex, family);
3180                 nm_system_iface_flush_addresses (ifindex, family);
3181         }
3182         _update_ip4_address (self);
3183
3184         /* Clean up nameservers and addresses */
3185         nm_device_set_ip4_config (self, NULL, FALSE, &ignored);
3186         nm_device_set_ip6_config (self, NULL, &ignored);
3187 }
3188
3189 gboolean
3190 nm_device_disconnect (NMDevice *device, GError **error)
3191 {
3192         NMDevicePrivate *priv;
3193
3194         g_return_val_if_fail (device != NULL, FALSE);
3195         g_return_val_if_fail (NM_IS_DEVICE (device), FALSE);
3196
3197         priv = NM_DEVICE_GET_PRIVATE (device);
3198         if (priv->state <= NM_DEVICE_STATE_DISCONNECTED) {
3199                 g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_NOT_ACTIVE,
3200                                      "Cannot disconnect an inactive device.");
3201                 return FALSE;
3202         }
3203
3204         priv->autoconnect = FALSE;
3205         nm_device_state_changed (device,
3206                                  NM_DEVICE_STATE_DISCONNECTED,
3207                                  NM_DEVICE_STATE_REASON_USER_REQUESTED);
3208         return TRUE;
3209 }
3210
3211 static void
3212 impl_device_disconnect (NMDevice *device, DBusGMethodInvocation *context)
3213 {
3214         g_signal_emit (device, signals[DISCONNECT_REQUEST], 0, context);
3215 }
3216
3217 static gboolean
3218 act_dep_timeout_cb (gpointer user_data)
3219 {
3220         NMDevice *self = NM_DEVICE (user_data);
3221         NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
3222         NMConnection *connection;
3223
3224         connection = nm_active_connection_get_connection (NM_ACTIVE_CONNECTION (priv->act_request));
3225         nm_log_warn (LOGD_DEVICE,
3226                      "Activation (%s) connection '%s' dependency timed out",
3227                      nm_device_get_iface (self),
3228                      nm_connection_get_id (connection));
3229
3230         nm_device_queue_state (self, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_DEPENDENCY_FAILED);
3231         return FALSE;
3232 }
3233
3234 static void
3235 act_dep_result_cb (NMActRequest *req,
3236                    NMActRequestDependencyResult result,
3237                    NMDevice *self)
3238 {
3239         NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
3240         NMConnection *connection;
3241
3242         connection = nm_active_connection_get_connection (NM_ACTIVE_CONNECTION (priv->act_request));
3243
3244         switch (result) {
3245         case NM_ACT_REQUEST_DEP_RESULT_FAILED:
3246                 g_source_remove (priv->act_dep_result_id);
3247                 priv->act_dep_result_id = 0;
3248
3249                 nm_log_warn (LOGD_DEVICE,
3250                                  "Activation (%s) connection '%s' dependency failed",
3251                                  nm_device_get_iface (self),
3252                                  nm_connection_get_id (connection));
3253                 nm_device_queue_state (self, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_DEPENDENCY_FAILED);
3254                 break;
3255         case NM_ACT_REQUEST_DEP_RESULT_READY:
3256                 g_warn_if_fail (priv->state == NM_DEVICE_STATE_PREPARE);
3257                 if (priv->state == NM_DEVICE_STATE_PREPARE) {
3258                         nm_log_info (LOGD_DEVICE,
3259                                              "Activation (%s) connection '%s' dependency ready, continuing activation",
3260                                              nm_device_get_iface (self),
3261                                              nm_connection_get_id (connection));
3262                         nm_device_activate_schedule_stage1_device_prepare (self);
3263                 }
3264                 break;
3265         case NM_ACT_REQUEST_DEP_RESULT_WAIT:
3266         default:
3267                 g_assert_not_reached ();
3268                 break;
3269         }
3270 }
3271
3272 gboolean
3273 nm_device_activate (NMDevice *self, NMActRequest *req, GError **error)
3274 {
3275         NMDevicePrivate *priv;
3276         NMConnection *connection;
3277
3278         g_return_val_if_fail (self != NULL, FALSE);
3279         g_return_val_if_fail (NM_IS_DEVICE (self), FALSE);
3280         g_return_val_if_fail (req != NULL, FALSE);
3281         g_return_val_if_fail (NM_IS_ACT_REQUEST (req), FALSE);
3282
3283         priv = NM_DEVICE_GET_PRIVATE (self);
3284
3285         connection = nm_act_request_get_connection (req);
3286         g_assert (connection);
3287
3288         nm_log_info (LOGD_DEVICE, "Activation (%s) starting connection '%s'",
3289                      nm_device_get_iface (self),
3290                      nm_connection_get_id (connection));
3291
3292         /* Make sure this connection isn't activated already, or in the process of
3293          * being activated.
3294          */
3295         if (   nm_device_is_activating (self)
3296             || (nm_device_get_state (self) == NM_DEVICE_STATE_ACTIVATED)) {
3297                 NMConnection *new = nm_act_request_get_connection (req);
3298                 NMConnection *current = nm_act_request_get_connection (priv->act_request);
3299
3300                 if (new == current) {
3301                         g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CONNECTION_ACTIVATING,
3302                                              "Connection is already activating");
3303                         return FALSE;
3304                 }
3305         }
3306
3307         priv->act_request = g_object_ref (req);
3308         g_object_notify (G_OBJECT (self), NM_DEVICE_ACTIVE_CONNECTION);
3309
3310         if (!nm_act_request_get_assumed (req)) {
3311                 NMActiveConnection *dep_ac;
3312                 NMConnection *dep_con;
3313
3314                 /* HACK: update the state a bit early to avoid a race between the 
3315                  * scheduled stage1 handler and nm_policy_device_change_check() thinking
3316                  * that the activation request isn't deferred because the deferred bit
3317                  * gets cleared a bit too early, when the connection becomes valid.
3318                  */
3319                 nm_device_state_changed (self, NM_DEVICE_STATE_PREPARE, NM_DEVICE_STATE_REASON_NONE);
3320
3321                 /* Handle any dependencies this connection might have */
3322                 switch (nm_act_request_get_dependency_result (priv->act_request)) {
3323                 case NM_ACT_REQUEST_DEP_RESULT_FAILED:
3324                         nm_device_queue_state (self, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_DEPENDENCY_FAILED);
3325                         break;
3326                 case NM_ACT_REQUEST_DEP_RESULT_WAIT:
3327                         dep_ac = nm_act_request_get_dependency (priv->act_request);
3328                         g_assert (dep_ac);
3329                         dep_con = nm_active_connection_get_connection (dep_ac);
3330                         g_assert (dep_con);
3331                         nm_log_info (LOGD_DEVICE, "Activation (%s) connection '%s' waiting on dependency '%s'",
3332                                                  nm_device_get_iface (self),
3333                                                  nm_connection_get_id (connection),
3334                                                  nm_connection_get_id (dep_con));
3335
3336                         priv->act_dep_result_id = g_signal_connect (priv->act_request,
3337                                                                             NM_ACT_REQUEST_DEPENDENCY_RESULT,
3338                                                                             G_CALLBACK (act_dep_result_cb),
3339                                                                             self);
3340                         priv->act_dep_timeout_id = g_timeout_add_seconds (60, act_dep_timeout_cb, self);
3341                         break;
3342                 default:
3343                         g_warn_if_reached ();
3344                         /* fall through */
3345                 case NM_ACT_REQUEST_DEP_RESULT_READY:
3346                         nm_device_activate_schedule_stage1_device_prepare (self);
3347                         break;
3348                 }
3349         } else {
3350                 /* If it's an assumed connection, let the device subclass short-circuit
3351                  * the normal connection process and just copy its IP configs from the
3352                  * interface.
3353                  */
3354                 nm_device_state_changed (self, NM_DEVICE_STATE_IP_CONFIG, NM_DEVICE_STATE_REASON_NONE);
3355                 nm_device_activate_schedule_stage3_ip_config_start (self);
3356         }
3357
3358         return TRUE;
3359 }
3360
3361 /*
3362  * nm_device_is_activating
3363  *
3364  * Return whether or not the device is currently activating itself.
3365  *
3366  */
3367 gboolean
3368 nm_device_is_activating (NMDevice *device)
3369 {
3370         NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device);
3371         NMDeviceState state;
3372
3373         g_return_val_if_fail (NM_IS_DEVICE (device), FALSE);
3374
3375         state = nm_device_get_state (device);
3376         if (state >= NM_DEVICE_STATE_PREPARE && state <= NM_DEVICE_STATE_SECONDARIES)
3377                 return TRUE;
3378
3379         /* There's a small race between the time when stage 1 is scheduled
3380          * and when the device actually sets STATE_PREPARE when the activation
3381          * handler is actually run.  If there's an activation handler scheduled
3382          * we're activating anyway.
3383          */
3384         return priv->act_source_id ? TRUE : FALSE;
3385 }
3386
3387
3388 gboolean
3389 nm_device_can_interrupt_activation (NMDevice *self)
3390 {
3391         gboolean        interrupt = FALSE;
3392
3393         g_return_val_if_fail (self != NULL, FALSE);
3394
3395         if (NM_DEVICE_GET_CLASS (self)->can_interrupt_activation)
3396                 interrupt = NM_DEVICE_GET_CLASS (self)->can_interrupt_activation (self);
3397         return interrupt;
3398 }
3399
3400 /* IP Configuration stuff */
3401
3402 NMDHCP4Config *
3403 nm_device_get_dhcp4_config (NMDevice *self)
3404 {
3405         g_return_val_if_fail (self != NULL, NULL);
3406         g_return_val_if_fail (NM_IS_DEVICE (self), NULL);
3407
3408         return NM_DEVICE_GET_PRIVATE (self)->dhcp4_config;
3409 }
3410
3411 NMIP4Config *
3412 nm_device_get_ip4_config (NMDevice *self)
3413 {
3414         g_return_val_if_fail (self != NULL, NULL);
3415         g_return_val_if_fail (NM_IS_DEVICE (self), NULL);
3416
3417         return NM_DEVICE_GET_PRIVATE (self)->ip4_config;
3418 }
3419
3420
3421 static gboolean