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