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