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