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