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