device: renew dhcp leases on awake for software devices
[NetworkManager.git] / libnm-glib / nm-device.c
1 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2 /*
3  * This library is free software; you can redistribute it and/or
4  * modify it under the terms of the GNU Lesser General Public
5  * License as published by the Free Software Foundation; either
6  * version 2 of the License, or (at your option) any later version.
7  *
8  * This library is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11  * Lesser General Public License for more details.
12  *
13  * You should have received a copy of the GNU Lesser General Public
14  * License along with this library; if not, write to the
15  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
16  * Boston, MA 02110-1301 USA.
17  *
18  * Copyright 2007 - 2008 Novell, Inc.
19  * Copyright 2007 - 2012 Red Hat, Inc.
20  */
21
22 #include "nm-default.h"
23
24 #include <string.h>
25 #include <gudev/gudev.h>
26
27 #include "NetworkManager.h"
28 #include "nm-device-ethernet.h"
29 #include "nm-device-adsl.h"
30 #include "nm-device-wifi.h"
31 #include "nm-device-modem.h"
32 #include "nm-device-bt.h"
33 #include "nm-device-olpc-mesh.h"
34 #include "nm-device-wimax.h"
35 #include "nm-device-infiniband.h"
36 #include "nm-device-bond.h"
37 #include "nm-device-team.h"
38 #include "nm-device-bridge.h"
39 #include "nm-device-vlan.h"
40 #include "nm-device-generic.h"
41 #include "nm-device.h"
42 #include "nm-device-private.h"
43 #include "nm-object-private.h"
44 #include "nm-object-cache.h"
45 #include "nm-remote-connection.h"
46 #include "nm-types.h"
47 #include "nm-dbus-glib-types.h"
48 #include "nm-utils.h"
49 #include "nm-dbus-helpers-private.h"
50
51 static GType _nm_device_gtype_for_path (DBusGConnection *connection,
52                                         const char *path);
53 static void _nm_device_gtype_for_path_async (DBusGConnection *connection,
54                                              const char *path,
55                                              NMObjectTypeCallbackFunc callback,
56                                              gpointer user_data);
57 gboolean connection_compatible (NMDevice *device, NMConnection *connection, GError **error);
58
59 G_DEFINE_TYPE_WITH_CODE (NMDevice, nm_device, NM_TYPE_OBJECT,
60                          _nm_object_register_type_func (g_define_type_id, _nm_device_gtype_for_path,
61                                                         _nm_device_gtype_for_path_async);
62                          )
63
64 #define DBUS_G_TYPE_UINT_STRUCT (dbus_g_type_get_struct ("GValueArray", G_TYPE_UINT, G_TYPE_UINT, G_TYPE_INVALID))
65
66 #define NM_DEVICE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE, NMDevicePrivate))
67
68 typedef struct {
69         DBusGProxy *proxy;
70
71         char *iface;
72         char *ip_iface;
73         NMDeviceType device_type;
74         char *udi;
75         char *driver;
76         char *driver_version;
77         char *firmware_version;
78         char *type_description;
79         NMDeviceCapabilities capabilities;
80         gboolean real;
81         gboolean managed;
82         gboolean firmware_missing;
83         gboolean autoconnect;
84         NMIP4Config *ip4_config;
85         NMDHCP4Config *dhcp4_config;
86         NMIP6Config *ip6_config;
87         NMDHCP6Config *dhcp6_config;
88         NMDeviceState state;
89         NMDeviceState last_seen_state;
90         NMDeviceStateReason reason;
91
92         NMActiveConnection *active_connection;
93         GPtrArray *available_connections;
94
95         GUdevClient *client;
96         char *product, *short_product;
97         char *vendor, *short_vendor;
98         char *description, *bus_name;
99
100         char *physical_port_id;
101         guint32 mtu;
102 } NMDevicePrivate;
103
104 enum {
105         PROP_0,
106         PROP_INTERFACE,
107         PROP_UDI,
108         PROP_DRIVER,
109         PROP_DRIVER_VERSION,
110         PROP_FIRMWARE_VERSION,
111         PROP_CAPABILITIES,
112         PROP_REAL,
113         PROP_MANAGED,
114         PROP_AUTOCONNECT,
115         PROP_FIRMWARE_MISSING,
116         PROP_IP4_CONFIG,
117         PROP_DHCP4_CONFIG,
118         PROP_IP6_CONFIG,
119         PROP_STATE,
120         PROP_STATE_REASON,
121         PROP_PRODUCT,
122         PROP_VENDOR,
123         PROP_DHCP6_CONFIG,
124         PROP_IP_INTERFACE,
125         PROP_DEVICE_TYPE,
126         PROP_ACTIVE_CONNECTION,
127         PROP_AVAILABLE_CONNECTIONS,
128         PROP_PHYSICAL_PORT_ID,
129         PROP_MTU,
130
131         LAST_PROP
132 };
133
134 enum {
135         STATE_CHANGED,
136
137         LAST_SIGNAL
138 };
139
140 static guint signals[LAST_SIGNAL] = { 0 };
141
142 /**
143  * nm_device_error_quark:
144  *
145  * Registers an error quark for #NMDevice if necessary.
146  *
147  * Returns: the error quark used for #NMDevice errors.
148  *
149  * Since: 0.9.10
150  **/
151 GQuark
152 nm_device_error_quark (void)
153 {
154         static GQuark quark = 0;
155
156         if (G_UNLIKELY (quark == 0))
157                 quark = g_quark_from_static_string ("nm-device-error-quark");
158         return quark;
159 }
160
161 static void
162 nm_device_init (NMDevice *device)
163 {
164         NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device);
165
166         priv->state = NM_DEVICE_STATE_UNKNOWN;
167         priv->reason = NM_DEVICE_STATE_REASON_NONE;
168 }
169
170 static gboolean
171 demarshal_state_reason (NMObject *object, GParamSpec *pspec, GValue *value, gpointer field)
172 {
173         NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (object);
174
175         if (!G_VALUE_HOLDS (value, DBUS_G_TYPE_UINT_STRUCT))
176                 return FALSE;
177
178         dbus_g_type_struct_get (value,
179                                 0, &priv->state,
180                                 1, &priv->reason,
181                                 G_MAXUINT);
182
183         _nm_object_queue_notify (object, NM_DEVICE_STATE_REASON);
184         return TRUE;
185 }
186
187 static void
188 register_properties (NMDevice *device)
189 {
190         NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device);
191         const NMPropertiesInfo property_info[] = {
192                 { NM_DEVICE_UDI,               &priv->udi },
193                 { NM_DEVICE_INTERFACE,         &priv->iface },
194                 { NM_DEVICE_IP_INTERFACE,      &priv->ip_iface },
195                 { NM_DEVICE_DRIVER,            &priv->driver },
196                 { NM_DEVICE_DRIVER_VERSION,    &priv->driver_version },
197                 { NM_DEVICE_FIRMWARE_VERSION,  &priv->firmware_version },
198                 { NM_DEVICE_CAPABILITIES,      &priv->capabilities },
199                 { NM_DEVICE_REAL,              &priv->real },
200                 { NM_DEVICE_MANAGED,           &priv->managed },
201                 { NM_DEVICE_AUTOCONNECT,       &priv->autoconnect },
202                 { NM_DEVICE_FIRMWARE_MISSING,  &priv->firmware_missing },
203                 { NM_DEVICE_IP4_CONFIG,        &priv->ip4_config, NULL, NM_TYPE_IP4_CONFIG },
204                 { NM_DEVICE_DHCP4_CONFIG,      &priv->dhcp4_config, NULL, NM_TYPE_DHCP4_CONFIG },
205                 { NM_DEVICE_IP6_CONFIG,        &priv->ip6_config, NULL, NM_TYPE_IP6_CONFIG },
206                 { NM_DEVICE_DHCP6_CONFIG,      &priv->dhcp6_config, NULL, NM_TYPE_DHCP6_CONFIG },
207                 { NM_DEVICE_STATE,             &priv->state },
208                 { NM_DEVICE_STATE_REASON,      &priv->state, demarshal_state_reason },
209                 { NM_DEVICE_ACTIVE_CONNECTION, &priv->active_connection, NULL, NM_TYPE_ACTIVE_CONNECTION },
210                 { NM_DEVICE_AVAILABLE_CONNECTIONS, &priv->available_connections, NULL, NM_TYPE_REMOTE_CONNECTION },
211                 { NM_DEVICE_PHYSICAL_PORT_ID,  &priv->physical_port_id },
212                 { NM_DEVICE_MTU,               &priv->mtu },
213
214                 /* Properties that exist in D-Bus but that we don't track */
215                 { "ip4-address", NULL },
216                 { "device-type", NULL },
217
218                 { NULL },
219         };
220
221         _nm_object_register_properties (NM_OBJECT (device),
222                                         priv->proxy,
223                                         property_info);
224 }
225
226 typedef struct {
227         NMDeviceState old_state;
228         NMDeviceState new_state;
229         NMDeviceStateReason reason;
230 } StateChangeData;
231
232 static void
233 device_state_change_reloaded (GObject *object,
234                               GAsyncResult *result,
235                               gpointer user_data)
236 {
237         NMDevice *self = NM_DEVICE (object);
238         NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
239         StateChangeData *data = user_data;
240         NMDeviceState old_state = data->old_state;
241         NMDeviceState new_state = data->new_state;
242         NMDeviceStateReason reason = data->reason;
243
244         g_slice_free (StateChangeData, data);
245
246         _nm_object_reload_properties_finish (NM_OBJECT (object), result, NULL);
247
248         /* If the device changes state several times in rapid succession, then we'll
249          * queue several reload_properties() calls, and there's no guarantee that
250          * they'll finish in the right order. In that case, only emit the signal
251          * for the last one.
252          */
253         if (priv->last_seen_state != new_state)
254                 return;
255
256         /* Ensure that nm_device_get_state() will return the right value even if
257          * we haven't processed the corresponding PropertiesChanged yet.
258          */
259         priv->state = new_state;
260
261         g_signal_emit (self, signals[STATE_CHANGED], 0,
262                        new_state, old_state, reason);
263 }
264
265 static void
266 device_state_changed (DBusGProxy *proxy,
267                       NMDeviceState new_state,
268                       NMDeviceState old_state,
269                       NMDeviceStateReason reason,
270                       gpointer user_data)
271 {
272         NMDevice *self = NM_DEVICE (user_data);
273         NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
274
275         if (old_state != new_state) {
276                 StateChangeData *data;
277
278                 /* Our object-valued properties (eg, ip4_config) will still
279                  * have their old values at this point, because NMObject is
280                  * in the process of asynchronously reading the new values.
281                  * Wait for that to finish before emitting the signal.
282                  */
283                 priv->last_seen_state = new_state;
284
285                 data = g_slice_new (StateChangeData);
286                 data->old_state = old_state;
287                 data->new_state = new_state;
288                 data->reason = reason;
289                 _nm_object_reload_properties_async (NM_OBJECT (user_data),
290                                                     device_state_change_reloaded,
291                                                     data);
292         }
293 }
294
295 static GType
296 _nm_device_gtype_from_dtype (NMDeviceType dtype)
297 {
298         switch (dtype) {
299         case NM_DEVICE_TYPE_VETH:
300         case NM_DEVICE_TYPE_ETHERNET:
301                 return NM_TYPE_DEVICE_ETHERNET;
302         case NM_DEVICE_TYPE_WIFI:
303                 return NM_TYPE_DEVICE_WIFI;
304         case NM_DEVICE_TYPE_MODEM:
305                 return NM_TYPE_DEVICE_MODEM;
306         case NM_DEVICE_TYPE_BT:
307                 return NM_TYPE_DEVICE_BT;
308         case NM_DEVICE_TYPE_ADSL:
309                 return NM_TYPE_DEVICE_ADSL;
310         case NM_DEVICE_TYPE_OLPC_MESH:
311                 return NM_TYPE_DEVICE_OLPC_MESH;
312         case NM_DEVICE_TYPE_WIMAX:
313                 return NM_TYPE_DEVICE_WIMAX;
314         case NM_DEVICE_TYPE_INFINIBAND:
315                 return NM_TYPE_DEVICE_INFINIBAND;
316         case NM_DEVICE_TYPE_BOND:
317                 return NM_TYPE_DEVICE_BOND;
318         case NM_DEVICE_TYPE_TEAM:
319                 return NM_TYPE_DEVICE_TEAM;
320         case NM_DEVICE_TYPE_BRIDGE:
321                 return NM_TYPE_DEVICE_BRIDGE;
322         case NM_DEVICE_TYPE_VLAN:
323                 return NM_TYPE_DEVICE_VLAN;
324         case NM_DEVICE_TYPE_GENERIC:
325         case NM_DEVICE_TYPE_TUN:
326         case NM_DEVICE_TYPE_IP_TUNNEL:
327                 return NM_TYPE_DEVICE_GENERIC;
328         default:
329                 /* Fall back to NMDeviceGeneric for unknown devices */
330                 return NM_TYPE_DEVICE_GENERIC;
331         }
332 }
333
334 static void
335 constructed (GObject *object)
336 {
337         NMDevicePrivate *priv;
338
339         G_OBJECT_CLASS (nm_device_parent_class)->constructed (object);
340
341         priv = NM_DEVICE_GET_PRIVATE (object);
342         /* Catch failure of subclasses to call _nm_device_set_device_type() */
343         g_warn_if_fail (priv->device_type != NM_DEVICE_TYPE_UNKNOWN);
344         /* Catch a subclass setting the wrong type */
345         g_warn_if_fail (G_OBJECT_TYPE (object) == _nm_device_gtype_from_dtype (priv->device_type));
346
347         priv->proxy = _nm_object_new_proxy (NM_OBJECT (object), NULL, NM_DBUS_INTERFACE_DEVICE);
348
349         register_properties (NM_DEVICE (object));
350
351         dbus_g_object_register_marshaller (g_cclosure_marshal_generic,
352                                            G_TYPE_NONE,
353                                            G_TYPE_UINT, G_TYPE_UINT, G_TYPE_UINT,
354                                            G_TYPE_INVALID);
355
356         dbus_g_proxy_add_signal (priv->proxy,
357                                  "StateChanged",
358                                  G_TYPE_UINT, G_TYPE_UINT, G_TYPE_UINT,
359                                  G_TYPE_INVALID);
360
361         dbus_g_proxy_connect_signal (priv->proxy, "StateChanged",
362                                      G_CALLBACK (device_state_changed),
363                                      NM_DEVICE (object),
364                                      NULL);
365 }
366
367 static void
368 dispose (GObject *object)
369 {
370         NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (object);
371
372         g_clear_object (&priv->proxy);
373         g_clear_object (&priv->ip4_config);
374         g_clear_object (&priv->dhcp4_config);
375         g_clear_object (&priv->ip6_config);
376         g_clear_object (&priv->dhcp6_config);
377         g_clear_object (&priv->client);
378         g_clear_object (&priv->active_connection);
379
380         if (priv->available_connections) {
381                 int i;
382
383                 for (i = 0; i < priv->available_connections->len; i++)
384                         g_object_unref (priv->available_connections->pdata[i]);
385                 g_ptr_array_free (priv->available_connections, TRUE);
386                 priv->available_connections = NULL;
387         }
388
389         G_OBJECT_CLASS (nm_device_parent_class)->dispose (object);
390 }
391
392 static void
393 finalize (GObject *object)
394 {
395         NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (object);
396
397         g_free (priv->iface);
398         g_free (priv->ip_iface);
399         g_free (priv->udi);
400         g_free (priv->driver);
401         g_free (priv->driver_version);
402         g_free (priv->firmware_version);
403         g_free (priv->product);
404         g_free (priv->short_product);
405         g_free (priv->vendor);
406         g_free (priv->short_vendor);
407         g_free (priv->description);
408         g_free (priv->bus_name);
409         g_free (priv->type_description);
410         g_free (priv->physical_port_id);
411
412         G_OBJECT_CLASS (nm_device_parent_class)->finalize (object);
413 }
414
415 static void
416 get_property (GObject *object,
417               guint prop_id,
418               GValue *value,
419               GParamSpec *pspec)
420 {
421         NMDevice *device = NM_DEVICE (object);
422         NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device);
423
424         _nm_object_ensure_inited (NM_OBJECT (object));
425
426         switch (prop_id) {
427         case PROP_DEVICE_TYPE:
428                 g_value_set_uint (value, nm_device_get_device_type (device));
429                 break;
430         case PROP_UDI:
431                 g_value_set_string (value, nm_device_get_udi (device));
432                 break;
433         case PROP_INTERFACE:
434                 g_value_set_string (value, nm_device_get_iface (device));
435                 break;
436         case PROP_IP_INTERFACE:
437                 g_value_set_string (value, nm_device_get_ip_iface (device));
438                 break;
439         case PROP_DRIVER:
440                 g_value_set_string (value, nm_device_get_driver (device));
441                 break;
442         case PROP_DRIVER_VERSION:
443                 g_value_set_string (value, nm_device_get_driver_version (device));
444                 break;
445         case PROP_FIRMWARE_VERSION:
446                 g_value_set_string (value, nm_device_get_firmware_version (device));
447                 break;
448         case PROP_CAPABILITIES:
449                 g_value_set_uint (value, nm_device_get_capabilities (device));
450                 break;
451         case PROP_REAL:
452                 g_value_set_boolean (value, nm_device_is_real (device));
453                 break;
454         case PROP_MANAGED:
455                 g_value_set_boolean (value, nm_device_get_managed (device));
456                 break;
457         case PROP_AUTOCONNECT:
458                 g_value_set_boolean (value, nm_device_get_autoconnect (device));
459                 break;
460         case PROP_FIRMWARE_MISSING:
461                 g_value_set_boolean (value, nm_device_get_firmware_missing (device));
462                 break;
463         case PROP_IP4_CONFIG:
464                 g_value_set_object (value, nm_device_get_ip4_config (device));
465                 break;
466         case PROP_DHCP4_CONFIG:
467                 g_value_set_object (value, nm_device_get_dhcp4_config (device));
468                 break;
469         case PROP_IP6_CONFIG:
470                 g_value_set_object (value, nm_device_get_ip6_config (device));
471                 break;
472         case PROP_DHCP6_CONFIG:
473                 g_value_set_object (value, nm_device_get_dhcp6_config (device));
474                 break;
475         case PROP_STATE:
476                 g_value_set_uint (value, nm_device_get_state (device));
477                 break;
478         case PROP_STATE_REASON:
479                 g_value_set_boxed (value,
480                                    dbus_g_type_specialized_construct (DBUS_G_TYPE_UINT_STRUCT));
481                 dbus_g_type_struct_set (value,
482                                         0, priv->state,
483                                         1, priv->reason,
484                                         G_MAXUINT);
485                 break;
486         case PROP_ACTIVE_CONNECTION:
487                 g_value_set_object (value, nm_device_get_active_connection (device));
488                 break;
489         case PROP_AVAILABLE_CONNECTIONS:
490                 g_value_set_boxed (value, nm_device_get_available_connections (device));
491                 break;
492         case PROP_PRODUCT:
493                 g_value_set_string (value, nm_device_get_product (device));
494                 break;
495         case PROP_VENDOR:
496                 g_value_set_string (value, nm_device_get_vendor (device));
497                 break;
498         case PROP_PHYSICAL_PORT_ID:
499                 g_value_set_string (value, nm_device_get_physical_port_id (device));
500                 break;
501         case PROP_MTU:
502                 g_value_set_uint (value, nm_device_get_mtu (device));
503                 break;
504         default:
505                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
506                 break;
507         }
508 }
509
510 static void
511 set_property (GObject *object,
512               guint prop_id,
513               const GValue *value,
514               GParamSpec *pspec)
515 {
516         NMDevice *self = NM_DEVICE (object);
517         NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
518         gboolean b;
519
520         switch (prop_id) {
521         case PROP_DEVICE_TYPE:
522                 /* Construct only */
523                 priv->device_type = g_value_get_uint (value);
524                 break;
525         case PROP_MANAGED:
526                 b = g_value_get_boolean (value);
527                 if (priv->managed != b)
528                         nm_device_set_managed (NM_DEVICE (object), b);
529                 break;
530         case PROP_AUTOCONNECT:
531                 b = g_value_get_boolean (value);
532                 if (priv->autoconnect != b)
533                         nm_device_set_autoconnect (NM_DEVICE (object), b);
534                 break;
535         default:
536                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
537                 break;
538         }
539 }
540
541 static void
542 nm_device_class_init (NMDeviceClass *device_class)
543 {
544         GObjectClass *object_class = G_OBJECT_CLASS (device_class);
545
546         g_type_class_add_private (device_class, sizeof (NMDevicePrivate));
547
548         /* virtual methods */
549         object_class->constructed = constructed;
550         object_class->get_property = get_property;
551         object_class->set_property = set_property;
552         object_class->dispose = dispose;
553         object_class->finalize = finalize;
554
555         device_class->connection_compatible = connection_compatible;
556
557         /* properties */
558
559         /**
560          * NMDevice:interface:
561          *
562          * The interface of the device.
563          **/
564         g_object_class_install_property
565                 (object_class, PROP_INTERFACE,
566                  g_param_spec_string (NM_DEVICE_INTERFACE, "", "",
567                                       NULL,
568                                       G_PARAM_READABLE |
569                                       G_PARAM_STATIC_STRINGS));
570
571         /**
572          * NMDevice:ip-interface:
573          *
574          * The IP interface of the device which should be used for all IP-related
575          * operations like addressing and routing.
576          **/
577         g_object_class_install_property
578                 (object_class, PROP_IP_INTERFACE,
579                  g_param_spec_string (NM_DEVICE_IP_INTERFACE, "", "",
580                                       NULL,
581                                       G_PARAM_READABLE |
582                                       G_PARAM_STATIC_STRINGS));
583
584         /**
585          * NMDevice:device-type:
586          *
587          * The numeric type of the device.
588          **/
589         g_object_class_install_property
590                 (object_class, PROP_DEVICE_TYPE,
591                  g_param_spec_uint (NM_DEVICE_DEVICE_TYPE, "", "",
592                                     NM_DEVICE_TYPE_UNKNOWN, G_MAXUINT32, NM_DEVICE_TYPE_UNKNOWN,
593                                     G_PARAM_READABLE |
594                                     G_PARAM_STATIC_STRINGS));
595         /**
596          * NMDevice:udi:
597          *
598          * An operating-system specific device hardware identifier; this is not
599          * unique to a specific hardware device across reboots or hotplugs.  It
600          * is an opaque string which for some device types (Bluetooth, Modem)
601          * contains an identifier provided by the underlying hardware service daemon
602          * such as Bluez or ModemManager, and clients can use this property to
603          * request more information about the device from those services.
604          **/
605         g_object_class_install_property
606                 (object_class, PROP_UDI,
607                  g_param_spec_string (NM_DEVICE_UDI, "", "",
608                                       NULL,
609                                       G_PARAM_READABLE |
610                                       G_PARAM_STATIC_STRINGS));
611
612         /**
613          * NMDevice:driver:
614          *
615          * The driver of the device.
616          **/
617         g_object_class_install_property
618                 (object_class, PROP_DRIVER,
619                  g_param_spec_string (NM_DEVICE_DRIVER, "", "",
620                                       NULL,
621                                       G_PARAM_READABLE |
622                                       G_PARAM_STATIC_STRINGS));
623
624         /**
625          * NMDevice:driver-version:
626          *
627          * The version of the device driver.
628          **/
629         g_object_class_install_property
630                 (object_class, PROP_DRIVER_VERSION,
631                  g_param_spec_string (NM_DEVICE_DRIVER_VERSION, "", "",
632                                       NULL,
633                                       G_PARAM_READABLE |
634                                       G_PARAM_STATIC_STRINGS));
635
636         /**
637          * NMDevice:firmware-version:
638          *
639          * The firmware version of the device.
640          **/
641         g_object_class_install_property
642                 (object_class, PROP_FIRMWARE_VERSION,
643                  g_param_spec_string (NM_DEVICE_FIRMWARE_VERSION, "", "",
644                                       NULL,
645                                       G_PARAM_READABLE |
646                                       G_PARAM_STATIC_STRINGS));
647
648         /**
649          * NMDevice:capabilities:
650          *
651          * The capabilities of the device.
652          **/
653         g_object_class_install_property
654                 (object_class, PROP_CAPABILITIES,
655                  g_param_spec_uint (NM_DEVICE_CAPABILITIES, "", "",
656                                     0, G_MAXUINT32, 0,
657                                     G_PARAM_READABLE |
658                                     G_PARAM_STATIC_STRINGS));
659
660         /**
661          * NMDevice:real:
662          *
663          * Whether the device is real or is a placeholder device that could
664          * be created automatically by NetworkManager if one of its
665          * #NMDevice:available-connections was activated.
666          *
667          * Since: 1.2
668          **/
669         g_object_class_install_property
670                 (object_class, PROP_REAL,
671                  g_param_spec_boolean (NM_DEVICE_REAL, "", "",
672                                        FALSE,
673                                        G_PARAM_READABLE |
674                                        G_PARAM_STATIC_STRINGS));
675
676         /**
677          * NMDevice:managed:
678          *
679          * Whether the device is managed by NetworkManager.
680          **/
681         g_object_class_install_property
682                 (object_class, PROP_MANAGED,
683                  g_param_spec_boolean (NM_DEVICE_MANAGED, "", "",
684                                        FALSE,
685                                        G_PARAM_READABLE |
686                                        G_PARAM_STATIC_STRINGS));
687
688         /**
689          * NMDevice:autoconnect:
690          *
691          * Whether the device can auto-activate a connection.
692          **/
693         g_object_class_install_property
694                 (object_class, PROP_AUTOCONNECT,
695                  g_param_spec_boolean (NM_DEVICE_AUTOCONNECT, "", "",
696                                        TRUE,
697                                        G_PARAM_READWRITE |
698                                        G_PARAM_STATIC_STRINGS));
699
700         /**
701          * NMDevice:firmware-missing:
702          *
703          * When %TRUE indicates the device is likely missing firmware required
704          * for its operation.
705          **/
706         g_object_class_install_property
707                 (object_class, PROP_FIRMWARE_MISSING,
708                  g_param_spec_boolean (NM_DEVICE_FIRMWARE_MISSING, "", "",
709                                        FALSE,
710                                        G_PARAM_READABLE |
711                                        G_PARAM_STATIC_STRINGS));
712
713         /**
714          * NMDevice:ip4-config:
715          *
716          * The #NMIP4Config of the device.
717          **/
718         g_object_class_install_property
719                 (object_class, PROP_IP4_CONFIG,
720                  g_param_spec_object (NM_DEVICE_IP4_CONFIG, "", "",
721                                       NM_TYPE_IP4_CONFIG,
722                                       G_PARAM_READABLE |
723                                       G_PARAM_STATIC_STRINGS));
724
725         /**
726          * NMDevice:dhcp4-config:
727          *
728          * The #NMDHCP4Config of the device.
729          **/
730         g_object_class_install_property
731                 (object_class, PROP_DHCP4_CONFIG,
732                  g_param_spec_object (NM_DEVICE_DHCP4_CONFIG, "", "",
733                                       NM_TYPE_DHCP4_CONFIG,
734                                       G_PARAM_READABLE |
735                                       G_PARAM_STATIC_STRINGS));
736
737         /**
738          * NMDevice:ip6-config:
739          *
740          * The #NMIP6Config of the device.
741          **/
742         g_object_class_install_property
743                 (object_class, PROP_IP6_CONFIG,
744                  g_param_spec_object (NM_DEVICE_IP6_CONFIG, "", "",
745                                       NM_TYPE_IP6_CONFIG,
746                                       G_PARAM_READABLE |
747                                       G_PARAM_STATIC_STRINGS));
748
749         /**
750          * NMDevice:dhcp6-config:
751          *
752          * The #NMDHCP6Config of the device.
753          **/
754         g_object_class_install_property
755                 (object_class, PROP_DHCP6_CONFIG,
756                  g_param_spec_object (NM_DEVICE_DHCP6_CONFIG, "", "",
757                                       NM_TYPE_DHCP6_CONFIG,
758                                       G_PARAM_READABLE |
759                                       G_PARAM_STATIC_STRINGS));
760
761         /**
762          * NMDevice:state:
763          *
764          * The state of the device.
765          **/
766         g_object_class_install_property
767                 (object_class, PROP_STATE,
768                  g_param_spec_uint (NM_DEVICE_STATE, "", "",
769                                     0, G_MAXUINT32, 0,
770                                     G_PARAM_READABLE |
771                                     G_PARAM_STATIC_STRINGS));
772
773         /**
774          * NMDevice:state-reason:
775          *
776          * The state and reason of the device.
777          **/
778         g_object_class_install_property
779                 (object_class, PROP_STATE_REASON,
780                  g_param_spec_boxed (NM_DEVICE_STATE_REASON, "", "",
781                                      DBUS_G_TYPE_UINT_STRUCT,
782                                      G_PARAM_READABLE |
783                                      G_PARAM_STATIC_STRINGS));
784
785         /**
786          * NMDevice:active-connection:
787          *
788          * The #NMActiveConnection object that "owns" this device during activation.
789          **/
790         g_object_class_install_property
791                 (object_class, PROP_ACTIVE_CONNECTION,
792                  g_param_spec_object (NM_DEVICE_ACTIVE_CONNECTION, "", "",
793                                       NM_TYPE_ACTIVE_CONNECTION,
794                                       G_PARAM_READABLE |
795                                       G_PARAM_STATIC_STRINGS));
796
797         /**
798          * NMDevice:available-connections:
799          *
800          * The available connections (#NMRemoteConnection) of the device
801          *
802          * Since: 0.9.8
803          **/
804         g_object_class_install_property
805                 (object_class, PROP_AVAILABLE_CONNECTIONS,
806                  g_param_spec_boxed (NM_DEVICE_AVAILABLE_CONNECTIONS, "", "",
807                                      NM_TYPE_OBJECT_ARRAY,
808                                      G_PARAM_READABLE |
809                                      G_PARAM_STATIC_STRINGS));
810
811         /**
812          * NMDevice:vendor:
813          *
814          * The vendor string of the device.
815          **/
816         g_object_class_install_property
817                 (object_class, PROP_VENDOR,
818                  g_param_spec_string (NM_DEVICE_VENDOR, "", "",
819                                       NULL,
820                                       G_PARAM_READABLE |
821                                       G_PARAM_STATIC_STRINGS));
822
823         /**
824          * NMDevice:product:
825          *
826          * The product string of the device.
827          **/
828         g_object_class_install_property
829                 (object_class, PROP_PRODUCT,
830                  g_param_spec_string (NM_DEVICE_PRODUCT, "", "",
831                                       NULL,
832                                       G_PARAM_READABLE |
833                                       G_PARAM_STATIC_STRINGS));
834
835         /**
836          * NMDevice:physical-port-id:
837          *
838          * The physical port ID of the device. (See
839          * nm_device_get_physical_port_id().)
840          *
841          * Since: 0.9.10
842          **/
843         g_object_class_install_property
844                 (object_class, PROP_PHYSICAL_PORT_ID,
845                  g_param_spec_string (NM_DEVICE_PHYSICAL_PORT_ID, "", "",
846                                       NULL,
847                                       G_PARAM_READABLE |
848                                       G_PARAM_STATIC_STRINGS));
849
850         /**
851          * NMDevice:mtu:
852          *
853          * The MTU of the device.
854          *
855          * Since: 0.9.10
856          **/
857         g_object_class_install_property
858                 (object_class, PROP_MTU,
859                  g_param_spec_uint (NM_DEVICE_MTU, "", "",
860                                     0, G_MAXUINT32, 1500,
861                                     G_PARAM_READABLE |
862                                     G_PARAM_STATIC_STRINGS));
863
864         /* signals */
865
866         /**
867          * NMDevice::state-changed:
868          * @device: the device object that received the signal
869          * @new_state: the new state of the device
870          * @old_state: the previous state of the device
871          * @reason: the reason describing the state change
872          *
873          * Notifies the state change of a #NMDevice.
874          **/
875         signals[STATE_CHANGED] =
876                 g_signal_new ("state-changed",
877                               G_OBJECT_CLASS_TYPE (object_class),
878                               G_SIGNAL_RUN_FIRST,
879                               G_STRUCT_OFFSET (NMDeviceClass, state_changed),
880                               NULL, NULL, NULL,
881                               G_TYPE_NONE, 3,
882                               G_TYPE_UINT, G_TYPE_UINT, G_TYPE_UINT);
883 }
884
885 /**
886  * _nm_device_set_device_type:
887  * @device: the device
888  * @dtype: the NM device type
889  *
890  * Sets the NM device type if it wasn't set during construction.  INTERNAL
891  * ONLY METHOD.
892  **/
893 void
894 _nm_device_set_device_type (NMDevice *device, NMDeviceType dtype)
895 {
896         NMDevicePrivate *priv;
897
898         g_return_if_fail (device != NULL);
899         g_return_if_fail (dtype != NM_DEVICE_TYPE_UNKNOWN);
900
901         priv = NM_DEVICE_GET_PRIVATE (device);
902         if (priv->device_type == NM_DEVICE_TYPE_UNKNOWN)
903                 priv->device_type = dtype;
904         else
905                 g_warn_if_fail (dtype == priv->device_type);
906 }
907
908 NMDeviceType
909 _nm_device_type_for_path (DBusGConnection *connection, const char *path)
910 {
911         DBusGProxy *proxy;
912         GError *err = NULL;
913         GValue value = G_VALUE_INIT;
914
915         proxy = _nm_dbus_new_proxy_for_connection (connection, path, DBUS_INTERFACE_PROPERTIES);
916         if (!proxy) {
917                 g_warning ("%s: couldn't create D-Bus object proxy.", __func__);
918                 return G_TYPE_INVALID;
919         }
920
921         if (!dbus_g_proxy_call (proxy,
922                                 "Get", &err,
923                                 G_TYPE_STRING, NM_DBUS_INTERFACE_DEVICE,
924                                 G_TYPE_STRING, "DeviceType",
925                                 G_TYPE_INVALID,
926                                 G_TYPE_VALUE, &value, G_TYPE_INVALID)) {
927                 g_warning ("Error in get_property: %s\n", err->message);
928                 g_error_free (err);
929                 g_object_unref (proxy);
930                 return G_TYPE_INVALID;
931         }
932         g_object_unref (proxy);
933
934         return g_value_get_uint (&value);
935 }
936
937 static GType
938 _nm_device_gtype_for_path (DBusGConnection *connection,
939                            const char *path)
940 {
941         return _nm_device_gtype_from_dtype (_nm_device_type_for_path (connection, path));
942 }
943
944 /**
945  * nm_device_new:
946  * @connection: the #DBusGConnection
947  * @path: the DBus object path of the device
948  *
949  * Creates a new #NMDevice.
950  *
951  * Returns: (transfer full): a new device
952  **/
953 GObject *
954 nm_device_new (DBusGConnection *connection, const char *path)
955 {
956         GType dtype;
957         NMDevice *device = NULL;
958
959         g_return_val_if_fail (connection != NULL, NULL);
960         g_return_val_if_fail (path != NULL, NULL);
961
962         dtype = _nm_device_gtype_for_path (connection, path);
963         if (dtype == G_TYPE_INVALID)
964                 return NULL;
965
966         device = (NMDevice *) g_object_new (dtype,
967                                             NM_OBJECT_DBUS_CONNECTION, connection,
968                                             NM_OBJECT_DBUS_PATH, path,
969                                             NULL);
970         _nm_object_ensure_inited (NM_OBJECT (device));
971         return G_OBJECT (device);
972 }
973
974 typedef struct {
975         DBusGConnection *connection;
976         NMObjectTypeCallbackFunc callback;
977         gpointer user_data;
978 } NMDeviceAsyncData;
979
980 static void
981 async_got_type (DBusGProxy *proxy, DBusGProxyCall *call, gpointer user_data)
982 {
983         NMDeviceAsyncData *async_data = user_data;
984         GValue value = G_VALUE_INIT;
985         const char *path = dbus_g_proxy_get_path (proxy);
986         GError *error = NULL;
987         GType type;
988
989         if (dbus_g_proxy_end_call (proxy, call, &error,
990                                    G_TYPE_VALUE, &value,
991                                    G_TYPE_INVALID)) {
992                 NMDeviceType dtype;
993
994                 dtype = g_value_get_uint (&value);
995                 type = _nm_device_gtype_from_dtype (dtype);
996         } else {
997                 g_warning ("%s: could not read properties for %s: %s", __func__, path, error->message);
998                 g_error_free (error);
999                 type = G_TYPE_INVALID;
1000         }
1001
1002         async_data->callback (type, async_data->user_data);
1003         g_object_unref (proxy);
1004         g_slice_free (NMDeviceAsyncData, async_data);
1005 }
1006
1007 static void
1008 _nm_device_gtype_for_path_async (DBusGConnection *connection,
1009                                 const char *path,
1010                                 NMObjectTypeCallbackFunc callback,
1011                                 gpointer user_data)
1012 {
1013         NMDeviceAsyncData *async_data;
1014         DBusGProxy *proxy;
1015
1016         async_data = g_slice_new (NMDeviceAsyncData);
1017         async_data->connection = connection;
1018         async_data->callback = callback;
1019         async_data->user_data = user_data;
1020
1021         proxy = _nm_dbus_new_proxy_for_connection (connection, path, DBUS_INTERFACE_PROPERTIES);
1022         dbus_g_proxy_begin_call (proxy, "Get",
1023                                  async_got_type, async_data, NULL,
1024                                  G_TYPE_STRING, NM_DBUS_INTERFACE_DEVICE,
1025                                  G_TYPE_STRING, "DeviceType",
1026                                  G_TYPE_INVALID);
1027 }
1028
1029 /**
1030  * nm_device_get_iface:
1031  * @device: a #NMDevice
1032  *
1033  * Gets the interface name of the #NMDevice.
1034  *
1035  * Returns: the interface of the device. This is the internal string used by the
1036  * device, and must not be modified.
1037  **/
1038 const char *
1039 nm_device_get_iface (NMDevice *device)
1040 {
1041         g_return_val_if_fail (NM_IS_DEVICE (device), NULL);
1042
1043         _nm_object_ensure_inited (NM_OBJECT (device));
1044         return NM_DEVICE_GET_PRIVATE (device)->iface;
1045 }
1046
1047 /**
1048  * nm_device_get_ip_iface:
1049  * @device: a #NMDevice
1050  *
1051  * Gets the IP interface name of the #NMDevice over which IP traffic flows
1052  * when the device is in the ACTIVATED state.
1053  *
1054  * Returns: the IP traffic interface of the device. This is the internal string
1055  * used by the device, and must not be modified.
1056  **/
1057 const char *
1058 nm_device_get_ip_iface (NMDevice *device)
1059 {
1060         g_return_val_if_fail (NM_IS_DEVICE (device), NULL);
1061
1062         _nm_object_ensure_inited (NM_OBJECT (device));
1063         return NM_DEVICE_GET_PRIVATE (device)->ip_iface;
1064 }
1065
1066 /**
1067  * nm_device_get_device_type:
1068  * @device: a #NMDevice
1069  *
1070  * Returns the numeric type of the #NMDevice, ie Ethernet, Wi-Fi, etc.
1071  *
1072  * Returns: the device type
1073  **/
1074 NMDeviceType
1075 nm_device_get_device_type (NMDevice *self)
1076 {
1077         g_return_val_if_fail (NM_IS_DEVICE (self), NM_DEVICE_TYPE_UNKNOWN);
1078
1079         return NM_DEVICE_GET_PRIVATE (self)->device_type;
1080 }
1081
1082 /**
1083  * nm_device_get_udi:
1084  * @device: a #NMDevice
1085  *
1086  * Gets the Unique Device Identifier of the #NMDevice.
1087  *
1088  * Returns: the Unique Device Identifier of the device.  This identifier may be
1089  * used to gather more information about the device from various operating
1090  * system services like udev or sysfs.
1091  **/
1092 const char *
1093 nm_device_get_udi (NMDevice *device)
1094 {
1095         g_return_val_if_fail (NM_IS_DEVICE (device), NULL);
1096
1097         _nm_object_ensure_inited (NM_OBJECT (device));
1098         return NM_DEVICE_GET_PRIVATE (device)->udi;
1099 }
1100
1101 /**
1102  * nm_device_get_driver:
1103  * @device: a #NMDevice
1104  *
1105  * Gets the driver of the #NMDevice.
1106  *
1107  * Returns: the driver of the device. This is the internal string used by the
1108  * device, and must not be modified.
1109  **/
1110 const char *
1111 nm_device_get_driver (NMDevice *device)
1112 {
1113         g_return_val_if_fail (NM_IS_DEVICE (device), NULL);
1114
1115         _nm_object_ensure_inited (NM_OBJECT (device));
1116         return NM_DEVICE_GET_PRIVATE (device)->driver;
1117 }
1118
1119 /**
1120  * nm_device_get_driver_version:
1121  * @device: a #NMDevice
1122  *
1123  * Gets the driver version of the #NMDevice.
1124  *
1125  * Returns: the version of the device driver. This is the internal string used by the
1126  * device, and must not be modified.
1127  **/
1128 const char *
1129 nm_device_get_driver_version (NMDevice *device)
1130 {
1131         g_return_val_if_fail (NM_IS_DEVICE (device), NULL);
1132
1133         _nm_object_ensure_inited (NM_OBJECT (device));
1134         return NM_DEVICE_GET_PRIVATE (device)->driver_version;
1135 }
1136
1137 /**
1138  * nm_device_get_firmware_version:
1139  * @device: a #NMDevice
1140  *
1141  * Gets the firmware version of the #NMDevice.
1142  *
1143  * Returns: the firmware version of the device. This is the internal string used by the
1144  * device, and must not be modified.
1145  **/
1146 const char *
1147 nm_device_get_firmware_version (NMDevice *device)
1148 {
1149         g_return_val_if_fail (NM_IS_DEVICE (device), NULL);
1150
1151         _nm_object_ensure_inited (NM_OBJECT (device));
1152         return NM_DEVICE_GET_PRIVATE (device)->firmware_version;
1153 }
1154
1155 /**
1156  * nm_device_get_type_description:
1157  * @device: a #NMDevice
1158  *
1159  * Gets a (non-localized) description of the type of device that
1160  * @device is.
1161  *
1162  * Returns: the type description of the device. This is the internal
1163  * string used by the device, and must not be modified.
1164  *
1165  * Since: 0.9.10
1166  **/
1167 const char *
1168 nm_device_get_type_description (NMDevice *device)
1169 {
1170         NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device);
1171         const char *desc, *typename;
1172
1173         g_return_val_if_fail (NM_IS_DEVICE (device), NULL);
1174
1175         if (priv->type_description)
1176                 return priv->type_description;
1177
1178         if (NM_DEVICE_GET_CLASS (device)->get_type_description) {
1179                 desc = NM_DEVICE_GET_CLASS (device)->get_type_description (device);
1180                 if (desc)
1181                         return desc;
1182         }
1183
1184         typename = G_OBJECT_TYPE_NAME (device);
1185         if (g_str_has_prefix (typename, "NMDevice"))
1186                 typename += 8;
1187         priv->type_description = g_ascii_strdown (typename, -1);
1188
1189         return priv->type_description;
1190 }
1191
1192 /**
1193  * nm_device_get_hw_address:
1194  * @device: a #NMDevice
1195  *
1196  * Gets the current a hardware address (MAC) for the @device.
1197  *
1198  * Returns: the current MAC of the device, or %NULL.
1199  * This is the internal string used by the device, and must not be modified.
1200  *
1201  * Since: 0.9.10
1202  **/
1203 const char *
1204 nm_device_get_hw_address (NMDevice *device)
1205 {
1206         g_return_val_if_fail (NM_IS_DEVICE (device), NULL);
1207
1208         if (NM_DEVICE_GET_CLASS (device)->get_hw_address)
1209                 return NM_DEVICE_GET_CLASS (device)->get_hw_address (device);
1210
1211         return NULL;
1212 }
1213
1214 /**
1215  * nm_device_get_capabilities:
1216  * @device: a #NMDevice
1217  *
1218  * Gets the device' capabilities.
1219  *
1220  * Returns: the capabilities
1221  **/
1222 NMDeviceCapabilities
1223 nm_device_get_capabilities (NMDevice *device)
1224 {
1225         g_return_val_if_fail (NM_IS_DEVICE (device), 0);
1226
1227         _nm_object_ensure_inited (NM_OBJECT (device));
1228         return NM_DEVICE_GET_PRIVATE (device)->capabilities;
1229 }
1230
1231 /**
1232  * nm_device_get_managed:
1233  * @device: a #NMDevice
1234  *
1235  * Whether the #NMDevice is managed by NetworkManager.
1236  *
1237  * Returns: %TRUE if the device is managed by NetworkManager
1238  **/
1239 gboolean
1240 nm_device_get_managed (NMDevice *device)
1241 {
1242         g_return_val_if_fail (NM_IS_DEVICE (device), 0);
1243
1244         _nm_object_ensure_inited (NM_OBJECT (device));
1245         return NM_DEVICE_GET_PRIVATE (device)->managed;
1246 }
1247
1248 /**
1249  * nm_device_set_managed:
1250  * @device: a #NMDevice
1251  * @managed: %TRUE to make the device managed by NetworkManager.
1252  *
1253  * Enables or disables management of  #NMDevice by NetworkManager.
1254  *
1255  * Since: 1.2
1256  **/
1257 void
1258 nm_device_set_managed (NMDevice *device, gboolean managed)
1259 {
1260         GValue value = G_VALUE_INIT;
1261
1262         g_return_if_fail (NM_IS_DEVICE (device));
1263
1264         managed = !!managed;
1265
1266         g_value_init (&value, G_TYPE_BOOLEAN);
1267         g_value_set_boolean (&value, managed);
1268
1269         NM_DEVICE_GET_PRIVATE (device)->managed = managed;
1270
1271         _nm_object_set_property (NM_OBJECT (device),
1272                                  NM_DBUS_INTERFACE_DEVICE,
1273                                  "Managed",
1274                                  &value);
1275 }
1276
1277 /**
1278  * nm_device_get_autoconnect:
1279  * @device: a #NMDevice
1280  *
1281  * Whether the #NMDevice can be autoconnected.
1282  *
1283  * Returns: %TRUE if the device is allowed to be autoconnected
1284  **/
1285 gboolean
1286 nm_device_get_autoconnect (NMDevice *device)
1287 {
1288         g_return_val_if_fail (NM_IS_DEVICE (device), FALSE);
1289
1290         _nm_object_ensure_inited (NM_OBJECT (device));
1291         return NM_DEVICE_GET_PRIVATE (device)->autoconnect;
1292 }
1293
1294 /**
1295  * nm_device_set_autoconnect:
1296  * @device: a #NMDevice
1297  * @autoconnect: %TRUE to enable autoconnecting
1298  *
1299  * Enables or disables automatic activation of the #NMDevice.
1300  **/
1301 void
1302 nm_device_set_autoconnect (NMDevice *device, gboolean autoconnect)
1303 {
1304         GValue value = G_VALUE_INIT;
1305
1306         g_return_if_fail (NM_IS_DEVICE (device));
1307
1308         g_value_init (&value, G_TYPE_BOOLEAN);
1309         g_value_set_boolean (&value, autoconnect);
1310
1311
1312         NM_DEVICE_GET_PRIVATE (device)->autoconnect = autoconnect;
1313
1314         _nm_object_set_property (NM_OBJECT (device),
1315                                  NM_DBUS_INTERFACE_DEVICE,
1316                                  "Autoconnect",
1317                                  &value);
1318 }
1319
1320 /**
1321  * nm_device_get_firmware_missing:
1322  * @device: a #NMDevice
1323  *
1324  * Indicates that firmware required for the device's operation is likely
1325  * to be missing.
1326  *
1327  * Returns: %TRUE if firmware required for the device's operation is likely
1328  * to be missing.
1329  **/
1330 gboolean
1331 nm_device_get_firmware_missing (NMDevice *device)
1332 {
1333         g_return_val_if_fail (NM_IS_DEVICE (device), 0);
1334
1335         _nm_object_ensure_inited (NM_OBJECT (device));
1336         return NM_DEVICE_GET_PRIVATE (device)->firmware_missing;
1337 }
1338
1339 /**
1340  * nm_device_get_ip4_config:
1341  * @device: a #NMDevice
1342  *
1343  * Gets the current #NMIP4Config associated with the #NMDevice.
1344  *
1345  * Note that as of NetworkManager 0.9.10, you can alternatively use
1346  * nm_active_connection_get_ip4_config(), which also works with VPN
1347  * connections.
1348  *
1349  * Returns: (transfer none): the #NMIP4Config or %NULL if the device is not activated.
1350  **/
1351 NMIP4Config *
1352 nm_device_get_ip4_config (NMDevice *device)
1353 {
1354         g_return_val_if_fail (NM_IS_DEVICE (device), NULL);
1355
1356         _nm_object_ensure_inited (NM_OBJECT (device));
1357         return NM_DEVICE_GET_PRIVATE (device)->ip4_config;
1358 }
1359
1360 /**
1361  * nm_device_get_dhcp4_config:
1362  * @device: a #NMDevice
1363  *
1364  * Gets the current #NMDHCP4Config associated with the #NMDevice.
1365  *
1366  * Note that as of NetworkManager 0.9.10, you can alternatively use
1367  * nm_active_connection_get_dhcp4_config(), which also works with VPN
1368  * connections.
1369  *
1370  * Returns: (transfer none): the #NMDHCP4Config or %NULL if the device is not activated or not
1371  * using DHCP.
1372  **/
1373 NMDHCP4Config *
1374 nm_device_get_dhcp4_config (NMDevice *device)
1375 {
1376         g_return_val_if_fail (NM_IS_DEVICE (device), NULL);
1377
1378         _nm_object_ensure_inited (NM_OBJECT (device));
1379         return NM_DEVICE_GET_PRIVATE (device)->dhcp4_config;
1380 }
1381
1382 /**
1383  * nm_device_get_ip6_config:
1384  * @device: a #NMDevice
1385  *
1386  * Gets the current #NMIP6Config associated with the #NMDevice.
1387  *
1388  * Note that as of NetworkManager 0.9.10, you can alternatively use
1389  * nm_active_connection_get_ip6_config(), which also works with VPN
1390  * connections.
1391  *
1392  * Returns: (transfer none): the #NMIP6Config or %NULL if the device is not activated.
1393  **/
1394 NMIP6Config *
1395 nm_device_get_ip6_config (NMDevice *device)
1396 {
1397         g_return_val_if_fail (NM_IS_DEVICE (device), NULL);
1398
1399         _nm_object_ensure_inited (NM_OBJECT (device));
1400         return NM_DEVICE_GET_PRIVATE (device)->ip6_config;
1401 }
1402
1403 /**
1404  * nm_device_get_dhcp6_config:
1405  * @device: a #NMDevice
1406  *
1407  * Gets the current #NMDHCP6Config associated with the #NMDevice.
1408  *
1409  * Note that as of NetworkManager 0.9.10, you can alternatively use
1410  * nm_active_connection_get_dhcp6_config(), which also works with VPN
1411  * connections.
1412  *
1413  * Returns: (transfer none): the #NMDHCP6Config or %NULL if the device is not activated or not
1414  * using DHCP.
1415  **/
1416 NMDHCP6Config *
1417 nm_device_get_dhcp6_config (NMDevice *device)
1418 {
1419         g_return_val_if_fail (NM_IS_DEVICE (device), NULL);
1420
1421         _nm_object_ensure_inited (NM_OBJECT (device));
1422         return NM_DEVICE_GET_PRIVATE (device)->dhcp6_config;
1423 }
1424
1425 /**
1426  * nm_device_get_state:
1427  * @device: a #NMDevice
1428  *
1429  * Gets the current #NMDevice state.
1430  *
1431  * Returns: the current device state
1432  **/
1433 NMDeviceState
1434 nm_device_get_state (NMDevice *device)
1435 {
1436         g_return_val_if_fail (NM_IS_DEVICE (device), NM_DEVICE_STATE_UNKNOWN);
1437
1438         _nm_object_ensure_inited (NM_OBJECT (device));
1439         return NM_DEVICE_GET_PRIVATE (device)->state;
1440 }
1441
1442 /**
1443  * nm_device_get_state_reason:
1444  * @device: a #NMDevice
1445  * @reason: (out) (allow-none): location to store reason (#NMDeviceStateReason), or %NULL
1446  *
1447  * Gets the current #NMDevice state (return value) and the reason for entering
1448  * the state (@reason argument).
1449  *
1450  * Returns: the current device state
1451  **/
1452 NMDeviceState
1453 nm_device_get_state_reason (NMDevice *device, NMDeviceStateReason *reason)
1454 {
1455         g_return_val_if_fail (NM_IS_DEVICE (device), NM_DEVICE_STATE_UNKNOWN);
1456
1457         _nm_object_ensure_inited (NM_OBJECT (device));
1458         if (reason)
1459                 *reason = NM_DEVICE_GET_PRIVATE (device)->reason;
1460         return NM_DEVICE_GET_PRIVATE (device)->state;
1461 }
1462
1463 /**
1464  * nm_device_get_active_connection:
1465  * @device: a #NMDevice
1466  *
1467  * Gets the #NMActiveConnection object which owns this device during activation.
1468  *
1469  * Returns: (transfer none): the #NMActiveConnection or %NULL if the device is
1470  * not part of an active connection
1471  **/
1472 NMActiveConnection *
1473 nm_device_get_active_connection (NMDevice *device)
1474 {
1475         g_return_val_if_fail (NM_IS_DEVICE (device), NULL);
1476
1477         _nm_object_ensure_inited (NM_OBJECT (device));
1478         return NM_DEVICE_GET_PRIVATE (device)->active_connection;
1479 }
1480
1481 /**
1482  * nm_device_get_available_connections:
1483  * @device: a #NMDevice
1484  *
1485  * Gets the #NMRemoteConnections currently known to the daemon that could
1486  * be activated on @device.
1487  *
1488  * Returns: (element-type NMRemoteConnection): the #GPtrArray
1489  * containing #NMRemoteConnections. This is the internal copy used by
1490  * the connection, and must not be modified.
1491  *
1492  * Since: 0.9.8
1493  **/
1494 const GPtrArray *
1495 nm_device_get_available_connections (NMDevice *device)
1496 {
1497         g_return_val_if_fail (NM_IS_DEVICE (device), NULL);
1498
1499         _nm_object_ensure_inited (NM_OBJECT (device));
1500         return handle_ptr_array_return (NM_DEVICE_GET_PRIVATE (device)->available_connections);
1501 }
1502
1503 static char *
1504 get_decoded_property (GUdevDevice *device, const char *property)
1505 {
1506         const char *orig, *p;
1507         char *unescaped, *n;
1508         guint len;
1509
1510         p = orig = g_udev_device_get_property (device, property);
1511         if (!orig)
1512                 return NULL;
1513
1514         len = strlen (orig);
1515         n = unescaped = g_malloc0 (len + 1);
1516         while (*p) {
1517                 if ((len >= 4) && (*p == '\\') && (*(p+1) == 'x')) {
1518                         *n++ = (char) nm_utils_hex2byte (p + 2);
1519                         p += 4;
1520                         len -= 4;
1521                 } else {
1522                         *n++ = *p++;
1523                         len--;
1524                 }
1525         }
1526
1527         return unescaped;
1528 }
1529
1530 static gboolean
1531 ensure_udev_client (NMDevice *device)
1532 {
1533         static const char *const subsys[3] = { "net", "tty", NULL };
1534         NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device);
1535
1536         if (!priv->client)
1537                 priv->client = g_udev_client_new (subsys);
1538
1539         return priv->client != NULL;
1540 }
1541
1542 static char *
1543 _get_udev_property (NMDevice *device,
1544                     const char *enc_prop,  /* ID_XXX_ENC */
1545                     const char *db_prop)   /* ID_XXX_FROM_DATABASE */
1546 {
1547         NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device);
1548         GUdevDevice *udev_device = NULL, *tmpdev, *olddev;
1549         const char *ifname;
1550         guint32 count = 0;
1551         char *enc_value = NULL, *db_value = NULL;
1552
1553         if (!ensure_udev_client (device))
1554                 return NULL;
1555
1556         ifname = nm_device_get_iface (device);
1557         if (!ifname)
1558                 return NULL;
1559
1560         udev_device = g_udev_client_query_by_subsystem_and_name (priv->client, "net", ifname);
1561         if (!udev_device)
1562                 udev_device = g_udev_client_query_by_subsystem_and_name (priv->client, "tty", ifname);
1563         if (!udev_device)
1564                 return NULL;
1565
1566         /* Walk up the chain of the device and its parents a few steps to grab
1567          * vendor and device ID information off it.
1568          */
1569
1570         /* Ref the device again because we have to unref it each iteration,
1571          * as g_udev_device_get_parent() returns a ref-ed object.
1572          */
1573         tmpdev = g_object_ref (udev_device);
1574         while ((count++ < 3) && tmpdev && !enc_value) {
1575                 if (!enc_value)
1576                         enc_value = get_decoded_property (tmpdev, enc_prop);
1577                 if (!db_value)
1578                         db_value = g_strdup (g_udev_device_get_property (tmpdev, db_prop));
1579
1580                 olddev = tmpdev;
1581                 tmpdev = g_udev_device_get_parent (tmpdev);
1582                 g_object_unref (olddev);
1583         }
1584
1585         /* Unref the last device if we found what we needed before running out
1586          * of parents.
1587          */
1588         if (tmpdev)
1589                 g_object_unref (tmpdev);
1590
1591         /* Balance the initial g_udev_client_query_by_subsystem_and_name() */
1592         g_object_unref (udev_device);
1593
1594         /* Prefer the encoded value which comes directly from the device
1595          * over the hwdata database value.
1596          */
1597         if (enc_value) {
1598                 g_free (db_value);
1599                 return enc_value;
1600         }
1601
1602         return db_value;
1603 }
1604
1605 /**
1606  * nm_device_get_product:
1607  * @device: a #NMDevice
1608  *
1609  * Gets the product string of the #NMDevice.
1610  *
1611  * Returns: the product name of the device. This is the internal string used by the
1612  * device, and must not be modified.
1613  **/
1614 const char *
1615 nm_device_get_product (NMDevice *device)
1616 {
1617         NMDevicePrivate *priv;
1618
1619         g_return_val_if_fail (NM_IS_DEVICE (device), NULL);
1620
1621         priv = NM_DEVICE_GET_PRIVATE (device);
1622         if (!priv->product) {
1623                 priv->product = _get_udev_property (device, "ID_MODEL_ENC", "ID_MODEL_FROM_DATABASE");
1624                 if (!priv->product) {
1625                         /* Sometimes ID_PRODUCT_FROM_DATABASE is used? */
1626                         priv->product = _get_udev_property (device, "ID_MODEL_ENC", "ID_PRODUCT_FROM_DATABASE");
1627                 }
1628                 _nm_object_queue_notify (NM_OBJECT (device), NM_DEVICE_PRODUCT);
1629         }
1630         return priv->product;
1631 }
1632
1633 /**
1634  * nm_device_get_vendor:
1635  * @device: a #NMDevice
1636  *
1637  * Gets the vendor string of the #NMDevice.
1638  *
1639  * Returns: the vendor name of the device. This is the internal string used by the
1640  * device, and must not be modified.
1641  **/
1642 const char *
1643 nm_device_get_vendor (NMDevice *device)
1644 {
1645         NMDevicePrivate *priv;
1646
1647         g_return_val_if_fail (NM_IS_DEVICE (device), NULL);
1648
1649         priv = NM_DEVICE_GET_PRIVATE (device);
1650         if (!priv->vendor) {
1651                 priv->vendor = _get_udev_property (device, "ID_VENDOR_ENC", "ID_VENDOR_FROM_DATABASE");
1652                 _nm_object_queue_notify (NM_OBJECT (device), NM_DEVICE_VENDOR);
1653         }
1654         return priv->vendor;
1655 }
1656
1657 static const char * const ignored_words[] = {
1658         "Semiconductor",
1659         "Components",
1660         "Corporation",
1661         "Communications",
1662         "Company",
1663         "Corp.",
1664         "Corp",
1665         "Co.",
1666         "Inc.",
1667         "Inc",
1668         "Incorporated",
1669         "Ltd.",
1670         "Limited.",
1671         "Intel?",
1672         "chipset",
1673         "adapter",
1674         "[hex]",
1675         "NDIS",
1676         "Module",
1677         NULL
1678 };
1679
1680 static const char * const ignored_phrases[] = {
1681         "Multiprotocol MAC/baseband processor",
1682         "Wireless LAN Controller",
1683         "Wireless LAN Adapter",
1684         "Wireless Adapter",
1685         "Network Connection",
1686         "Wireless Cardbus Adapter",
1687         "Wireless CardBus Adapter",
1688         "54 Mbps Wireless PC Card",
1689         "Wireless PC Card",
1690         "Wireless PC",
1691         "PC Card with XJACK(r) Antenna",
1692         "Wireless cardbus",
1693         "Wireless LAN PC Card",
1694         "Technology Group Ltd.",
1695         "Communication S.p.A.",
1696         "Business Mobile Networks BV",
1697         "Mobile Broadband Minicard Composite Device",
1698         "Mobile Communications AB",
1699         "(PC-Suite Mode)",
1700         NULL
1701 };
1702
1703 static char *
1704 fixup_desc_string (const char *desc)
1705 {
1706         char *p, *temp;
1707         char **words, **item;
1708         GString *str;
1709         int i;
1710
1711         if (!desc)
1712                 return NULL;
1713
1714         p = temp = g_strdup (desc);
1715         while (*p) {
1716                 if (*p == '_' || *p == ',')
1717                         *p = ' ';
1718                 p++;
1719         }
1720
1721         /* Attempt to shorten ID by ignoring certain phrases */
1722         for (i = 0; ignored_phrases[i]; i++) {
1723                 p = strstr (temp, ignored_phrases[i]);
1724                 if (p) {
1725                         guint32 ignored_len = strlen (ignored_phrases[i]);
1726
1727                         memmove (p, p + ignored_len, strlen (p + ignored_len) + 1); /* +1 for the \0 */
1728                 }
1729         }
1730
1731         /* Attempt to shorten ID by ignoring certain individual words */
1732         words = g_strsplit (temp, " ", 0);
1733         str = g_string_new_len (NULL, strlen (temp));
1734         g_free (temp);
1735
1736         for (item = words; *item; item++) {
1737                 gboolean ignore = FALSE;
1738
1739                 if (**item == '\0')
1740                         continue;
1741
1742                 for (i = 0; ignored_words[i]; i++) {
1743                         if (!strcmp (*item, ignored_words[i])) {
1744                                 ignore = TRUE;
1745                                 break;
1746                         }
1747                 }
1748
1749                 if (!ignore) {
1750                         if (str->len)
1751                                 g_string_append_c (str, ' ');
1752                         g_string_append (str, *item);
1753                 }
1754         }
1755         g_strfreev (words);
1756
1757         temp = str->str;
1758         g_string_free (str, FALSE);
1759
1760         return temp;
1761 }
1762
1763 static void
1764 get_description (NMDevice *device)
1765 {
1766         NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device);
1767         const char *dev_product;
1768         const char *dev_vendor;
1769         char *pdown;
1770         char *vdown;
1771         GString *str;
1772
1773         dev_product = nm_device_get_product (device);
1774         priv->short_product = fixup_desc_string (dev_product);
1775
1776         dev_vendor = nm_device_get_vendor (device);
1777         priv->short_vendor = fixup_desc_string (dev_vendor);
1778
1779         if (!dev_product || !dev_vendor) {
1780                 priv->description = g_strdup (nm_device_get_iface (device));
1781                 return;
1782         }
1783
1784         str = g_string_new_len (NULL, strlen (priv->short_vendor) + strlen (priv->short_product) + 1);
1785
1786         /* Another quick hack; if all of the fixed up vendor string
1787          * is found in product, ignore the vendor.
1788          */
1789         pdown = g_ascii_strdown (priv->short_product, -1);
1790         vdown = g_ascii_strdown (priv->short_vendor, -1);
1791         if (!strstr (pdown, vdown)) {
1792                 g_string_append (str, priv->short_vendor);
1793                 g_string_append_c (str, ' ');
1794         }
1795         g_free (pdown);
1796         g_free (vdown);
1797
1798         g_string_append (str, priv->short_product);
1799
1800         priv->description = g_string_free (str, FALSE);
1801 }
1802
1803 static const char *
1804 get_short_vendor (NMDevice *device)
1805 {
1806         NMDevicePrivate *priv;
1807
1808         g_return_val_if_fail (NM_IS_DEVICE (device), NULL);
1809
1810         priv = NM_DEVICE_GET_PRIVATE (device);
1811
1812         if (!priv->description)
1813                 get_description (device);
1814
1815         return priv->short_vendor;
1816 }
1817
1818 /**
1819  * nm_device_get_description:
1820  * @device: an #NMDevice
1821  *
1822  * Gets a description of @device, based on its vendor and product names.
1823  *
1824  * Returns: a description of @device. If either the vendor or the
1825  *   product name is unknown, this returns the interface name.
1826  *
1827  * Since: 0.9.10
1828  */
1829 const char *
1830 nm_device_get_description (NMDevice *device)
1831 {
1832         NMDevicePrivate *priv;
1833
1834         g_return_val_if_fail (NM_IS_DEVICE (device), NULL);
1835
1836         priv = NM_DEVICE_GET_PRIVATE (device);
1837
1838         if (!priv->description)
1839                 get_description (device);
1840
1841         return priv->description;
1842 }
1843
1844 static const char *
1845 get_type_name (NMDevice *device)
1846 {
1847         switch (nm_device_get_device_type (device)) {
1848         case NM_DEVICE_TYPE_ETHERNET:
1849                 return _("Ethernet");
1850         case NM_DEVICE_TYPE_WIFI:
1851                 return _("Wi-Fi");
1852         case NM_DEVICE_TYPE_BT:
1853                 return _("Bluetooth");
1854         case NM_DEVICE_TYPE_OLPC_MESH:
1855                 return _("OLPC Mesh");
1856         case NM_DEVICE_TYPE_WIMAX:
1857                 return _("WiMAX");
1858         case NM_DEVICE_TYPE_MODEM:
1859                 return _("Mobile Broadband");
1860         case NM_DEVICE_TYPE_INFINIBAND:
1861                 return _("InfiniBand");
1862         case NM_DEVICE_TYPE_BOND:
1863                 return _("Bond");
1864         case NM_DEVICE_TYPE_TEAM:
1865                 return _("Team");
1866         case NM_DEVICE_TYPE_BRIDGE:
1867                 return _("Bridge");
1868         case NM_DEVICE_TYPE_VLAN:
1869                 return _("VLAN");
1870         case NM_DEVICE_TYPE_ADSL:
1871                 return _("ADSL");
1872         case NM_DEVICE_TYPE_MACVLAN:
1873                 return _("MACVLAN");
1874         case NM_DEVICE_TYPE_VXLAN:
1875                 return _("VXLAN");
1876         case NM_DEVICE_TYPE_IP_TUNNEL:
1877                 return _("IPTunnel");
1878         case NM_DEVICE_TYPE_TUN:
1879                 return _("Tun");
1880         case NM_DEVICE_TYPE_VETH:
1881                 return _("Veth");
1882         case NM_DEVICE_TYPE_GENERIC:
1883         case NM_DEVICE_TYPE_UNUSED1:
1884         case NM_DEVICE_TYPE_UNUSED2:
1885         case NM_DEVICE_TYPE_UNKNOWN:
1886                 break;
1887         }
1888         return _("Unknown");
1889 }
1890
1891 static char *
1892 get_device_type_name_with_iface (NMDevice *device)
1893 {
1894         const char *type_name = get_type_name (device);
1895
1896         switch (nm_device_get_device_type (device)) {
1897         case NM_DEVICE_TYPE_BOND:
1898         case NM_DEVICE_TYPE_TEAM:
1899         case NM_DEVICE_TYPE_BRIDGE:
1900         case NM_DEVICE_TYPE_VLAN:
1901                 return g_strdup_printf ("%s (%s)", type_name, nm_device_get_iface (device));
1902         default:
1903                 return g_strdup (type_name);
1904         }
1905 }
1906
1907 static char *
1908 get_device_generic_type_name_with_iface (NMDevice *device)
1909 {
1910         switch (nm_device_get_device_type (device)) {
1911         case NM_DEVICE_TYPE_ETHERNET:
1912         case NM_DEVICE_TYPE_INFINIBAND:
1913                 return g_strdup (_("Wired"));
1914         default:
1915                 return get_device_type_name_with_iface (device);
1916         }
1917 }
1918
1919 static const char *
1920 get_bus_name (NMDevice *device)
1921 {
1922         NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device);
1923         GUdevDevice *udevice;
1924         const char *ifname, *bus;
1925
1926         if (priv->bus_name)
1927                 goto out;
1928
1929         if (!ensure_udev_client (device))
1930                 return NULL;
1931
1932         ifname = nm_device_get_iface (device);
1933         if (!ifname)
1934                 return NULL;
1935
1936         udevice = g_udev_client_query_by_subsystem_and_name (priv->client, "net", ifname);
1937         if (!udevice)
1938                 udevice = g_udev_client_query_by_subsystem_and_name (priv->client, "tty", ifname);
1939         if (!udevice)
1940                 return NULL;
1941
1942         bus = g_udev_device_get_property (udevice, "ID_BUS");
1943         if (!g_strcmp0 (bus, "pci"))
1944                 priv->bus_name = g_strdup (_("PCI"));
1945         else if (!g_strcmp0 (bus, "usb"))
1946                 priv->bus_name = g_strdup (_("USB"));
1947         else {
1948                 /* Use "" instead of NULL so we can tell later that we've
1949                  * already tried.
1950                  */
1951                 priv->bus_name = g_strdup ("");
1952         }
1953
1954 out:
1955         if (*priv->bus_name)
1956                 return priv->bus_name;
1957         else
1958                 return NULL;
1959 }
1960
1961 static gboolean
1962 find_duplicates (char     **names,
1963                  gboolean  *duplicates,
1964                  int        num_devices)
1965 {
1966         int i, j;
1967         gboolean found_any = FALSE;
1968
1969         memset (duplicates, 0, num_devices * sizeof (gboolean));
1970         for (i = 0; i < num_devices; i++) {
1971                 if (duplicates[i])
1972                         continue;
1973                 for (j = i + 1; j < num_devices; j++) {
1974                         if (duplicates[j])
1975                                 continue;
1976                         if (!strcmp (names[i], names[j]))
1977                                 duplicates[i] = duplicates[j] = found_any = TRUE;
1978                 }
1979         }
1980
1981         return found_any;
1982 }
1983
1984 /**
1985  * nm_device_disambiguate_names:
1986  * @devices: (array length=num_devices): an array of #NMDevice
1987  * @num_devices: length of @devices
1988  *
1989  * Generates a list of short-ish unique presentation names for the
1990  * devices in @devices.
1991  *
1992  * Returns: (transfer full) (array zero-terminated=1): the device names
1993  *
1994  * Since: 0.9.10
1995  */
1996 char **
1997 nm_device_disambiguate_names (NMDevice **devices,
1998                               int        num_devices)
1999 {
2000         char **names;
2001         gboolean *duplicates;
2002         int i;
2003
2004         names = g_new (char *, num_devices + 1);
2005         duplicates = g_new (gboolean, num_devices);
2006
2007         /* Generic device name */
2008         for (i = 0; i < num_devices; i++)
2009                 names[i] = get_device_generic_type_name_with_iface (devices[i]);
2010         if (!find_duplicates (names, duplicates, num_devices))
2011                 goto done;
2012
2013         /* Try specific names (eg, "Ethernet" and "InfiniBand" rather
2014          * than "Wired")
2015          */
2016         for (i = 0; i < num_devices; i++) {
2017                 if (duplicates[i]) {
2018                         g_free (names[i]);
2019                         names[i] = get_device_type_name_with_iface (devices[i]);
2020                 }
2021         }
2022         if (!find_duplicates (names, duplicates, num_devices))
2023                 goto done;
2024
2025         /* Try prefixing bus name (eg, "PCI Ethernet" vs "USB Ethernet") */
2026         for (i = 0; i < num_devices; i++) {
2027                 if (duplicates[i]) {
2028                         const char *bus = get_bus_name (devices[i]);
2029                         char *name;
2030
2031                         if (!bus)
2032                                 continue;
2033
2034                         g_free (names[i]);
2035                         name = get_device_type_name_with_iface (devices[i]);
2036                         /* Translators: the first %s is a bus name (eg, "USB") or
2037                          * product name, the second is a device type (eg,
2038                          * "Ethernet"). You can change this to something like
2039                          * "%2$s (%1$s)" if there's no grammatical way to combine
2040                          * the strings otherwise.
2041                          */
2042                         names[i] = g_strdup_printf (C_("long device name", "%s %s"),
2043                                                     bus, name);
2044                         g_free (name);
2045                 }
2046         }
2047         if (!find_duplicates (names, duplicates, num_devices))
2048                 goto done;
2049
2050         /* Try prefixing vendor name */
2051         for (i = 0; i < num_devices; i++) {
2052                 if (duplicates[i]) {
2053                         const char *vendor = get_short_vendor (devices[i]);
2054                         char *name;
2055
2056                         if (!vendor)
2057                                 continue;
2058
2059                         g_free (names[i]);
2060                         name = get_device_type_name_with_iface (devices[i]);
2061                         names[i] = g_strdup_printf (C_("long device name", "%s %s"),
2062                                                     vendor,
2063                                                     get_type_name (devices[i]));
2064                         g_free (name);
2065                 }
2066         }
2067         if (!find_duplicates (names, duplicates, num_devices))
2068                 goto done;
2069
2070         /* We have multiple identical network cards, so we have to differentiate
2071          * them by interface name.
2072          */
2073         for (i = 0; i < num_devices; i++) {
2074                 if (duplicates[i]) {
2075                         const char *interface = nm_device_get_iface (devices[i]);
2076
2077                         if (!interface)
2078                                 continue;
2079
2080                         g_free (names[i]);
2081                         names[i] = g_strdup_printf ("%s (%s)",
2082                                                     get_type_name (devices[i]),
2083                                                     interface);
2084                 }
2085         }
2086
2087 done:
2088         g_free (duplicates);
2089         names[num_devices] = NULL;
2090         return names;
2091 }
2092
2093 /**
2094  * nm_device_get_physical_port_id:
2095  * @device: a #NMDevice
2096  *
2097  * Gets the physical port ID of the #NMDevice. If non-%NULL, this is
2098  * an opaque string that can be used to recognize when
2099  * seemingly-unrelated #NMDevices are actually just different virtual
2100  * ports on a single physical port. (Eg, NPAR / SR-IOV.)
2101  *
2102  * Returns: the physical port ID of the device, or %NULL if the port
2103  *   ID is unknown. This is the internal string used by the device and
2104  *   must not be modified.
2105  *
2106  * Since: 0.9.10
2107  **/
2108 const char *
2109 nm_device_get_physical_port_id (NMDevice *device)
2110 {
2111         NMDevicePrivate *priv;
2112
2113         g_return_val_if_fail (NM_IS_DEVICE (device), NULL);
2114
2115         priv = NM_DEVICE_GET_PRIVATE (device);
2116
2117         _nm_object_ensure_inited (NM_OBJECT (device));
2118         if (priv->physical_port_id && *priv->physical_port_id)
2119                 return priv->physical_port_id;
2120         else
2121                 return NULL;
2122 }
2123
2124 /**
2125  * nm_device_get_mtu:
2126  * @device: a #NMDevice
2127  *
2128  * Gets the  MTU of the #NMDevice.
2129  *
2130  * Returns: the MTU of the device.
2131  *
2132  * Since: 0.9.10
2133  **/
2134 guint32
2135 nm_device_get_mtu (NMDevice *device)
2136 {
2137         g_return_val_if_fail (NM_IS_DEVICE (device), 0);
2138
2139         _nm_object_ensure_inited (NM_OBJECT (device));
2140         return NM_DEVICE_GET_PRIVATE (device)->mtu;
2141 }
2142
2143 /**
2144  * nm_device_is_real:
2145  * @device: a #NMDevice
2146  *
2147  * Returns: %TRUE if the device exists, or %FALSE if it is a placeholder device
2148  * that could be automatically created by NetworkManager if one of its
2149  * #NMDevice:available-connections was activated.
2150  *
2151  * Since: 1.2
2152  **/
2153 gboolean
2154 nm_device_is_real (NMDevice *device)
2155 {
2156         g_return_val_if_fail (NM_IS_DEVICE (device), FALSE);
2157
2158         _nm_object_ensure_inited (NM_OBJECT (device));
2159         return NM_DEVICE_GET_PRIVATE (device)->real;
2160 }
2161
2162 /**
2163  * nm_device_is_software:
2164  * @device: a #NMDevice
2165  *
2166  * Whether the device is a software device.
2167  *
2168  * Returns: %TRUE if @device is a software device, %FALSE if it is a hardware device.
2169  *
2170  * Since: 1.0
2171  **/
2172 gboolean
2173 nm_device_is_software (NMDevice *device)
2174 {
2175         g_return_val_if_fail (NM_IS_DEVICE (device), FALSE);
2176
2177         _nm_object_ensure_inited (NM_OBJECT (device));
2178         return !!(NM_DEVICE_GET_PRIVATE (device)->capabilities & NM_DEVICE_CAP_IS_SOFTWARE);
2179 }
2180
2181 typedef struct {
2182         NMDevice *device;
2183         NMDeviceCallbackFn fn;
2184         gpointer user_data;
2185         const char *method;
2186 } DeviceCallbackInfo;
2187
2188 static void
2189 device_operation_cb (DBusGProxy *proxy,
2190                      DBusGProxyCall *call,
2191                      gpointer user_data)
2192 {
2193         DeviceCallbackInfo *info = user_data;
2194         GError *error = NULL;
2195
2196         dbus_g_proxy_end_call (proxy, call, &error,
2197                                G_TYPE_INVALID);
2198         if (info->fn)
2199                 info->fn (info->device, error, info->user_data);
2200         else if (error) {
2201                 g_warning ("%s: device %s %s failed: %s",
2202                            __func__,
2203                            nm_object_get_path (NM_OBJECT (info->device)),
2204                            info->method,
2205                            NM_G_ERROR_MSG (error));
2206         }
2207         g_clear_error (&error);
2208
2209         g_object_unref (info->device);
2210         g_slice_free (DeviceCallbackInfo, info);
2211 }
2212
2213 /**
2214  * nm_device_disconnect:
2215  * @device: a #NMDevice
2216  * @callback: (scope async) (allow-none): callback to be called when disconnect
2217  * operation completes
2218  * @user_data: (closure): caller-specific data passed to @callback
2219  *
2220  * Disconnects the device if currently connected, and prevents the device from
2221  * automatically connecting to networks until the next manual network connection
2222  * request.
2223  **/
2224 void
2225 nm_device_disconnect (NMDevice *device,
2226                       NMDeviceCallbackFn callback,
2227                       gpointer user_data)
2228 {
2229         DeviceCallbackInfo *info;
2230
2231         g_return_if_fail (NM_IS_DEVICE (device));
2232
2233         info = g_slice_new (DeviceCallbackInfo);
2234         info->fn = callback;
2235         info->user_data = user_data;
2236         info->method = "Disconnect";
2237         info->device = g_object_ref (device);
2238
2239         dbus_g_proxy_begin_call (NM_DEVICE_GET_PRIVATE (device)->proxy, "Disconnect",
2240                                  device_operation_cb, info, NULL,
2241                                  G_TYPE_INVALID);
2242 }
2243
2244 /**
2245  * nm_device_delete:
2246  * @device: a #NMDevice
2247  * @callback: (scope async) (allow-none): callback to be called when delete
2248  * operation completes
2249  * @user_data: (closure): caller-specific data passed to @callback
2250  *
2251  * Deletes the software device. Hardware devices can't be deleted.
2252  *
2253  * Since: 1.0
2254  **/
2255 void
2256 nm_device_delete (NMDevice *device,
2257                   NMDeviceCallbackFn callback,
2258                   gpointer user_data)
2259 {
2260         DeviceCallbackInfo *info;
2261
2262         g_return_if_fail (NM_IS_DEVICE (device));
2263
2264         info = g_slice_new (DeviceCallbackInfo);
2265         info->fn = callback;
2266         info->user_data = user_data;
2267         info->method = "Delete";
2268         info->device = g_object_ref (device);
2269
2270         dbus_g_proxy_begin_call (NM_DEVICE_GET_PRIVATE (device)->proxy, "Delete",
2271                                  device_operation_cb, info, NULL,
2272                                  G_TYPE_INVALID);
2273 }
2274
2275 /**
2276  * nm_device_connection_valid:
2277  * @device: an #NMDevice to validate @connection against
2278  * @connection: an #NMConnection to validate against @device
2279  *
2280  * Validates a given connection for a given #NMDevice object and returns
2281  * whether the connection may be activated with the device. For example if
2282  * @device is a Wi-Fi device that supports only WEP encryption, the connection
2283  * will only be valid if it is a Wi-Fi connection which describes a WEP or open
2284  * network, and will not be valid if it describes a WPA network, or if it is
2285  * an Ethernet, Bluetooth, WWAN, etc connection that is incompatible with the
2286  * device.
2287  *
2288  * Returns: %TRUE if the connection may be activated with this device, %FALSE
2289  * if is incompatible with the device's capabilities and characteristics.
2290  **/
2291 gboolean
2292 nm_device_connection_valid (NMDevice *device, NMConnection *connection)
2293 {
2294         return nm_device_connection_compatible (device, connection, NULL);
2295 }
2296
2297 gboolean
2298 connection_compatible (NMDevice *device, NMConnection *connection, GError **error)
2299 {
2300         NMSettingConnection *s_con;
2301         const char *config_iface, *device_iface;
2302
2303         s_con = nm_connection_get_setting_connection (connection);
2304         g_assert (s_con);
2305
2306         config_iface = nm_setting_connection_get_interface_name (s_con);
2307         device_iface = nm_device_get_iface (device);
2308         if (config_iface && g_strcmp0 (config_iface, device_iface) != 0) {
2309                 g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INTERFACE_MISMATCH,
2310                              "The interface names of the device and the connection didn't match.");
2311                 return FALSE;
2312         }
2313
2314         return TRUE;
2315 }
2316
2317 /**
2318  * nm_device_connection_compatible:
2319  * @device: an #NMDevice to validate @connection against
2320  * @connection: an #NMConnection to validate against @device
2321  * @error: return location for a #GError, or %NULL
2322  *
2323  * Validates a given connection for a given #NMDevice object and returns
2324  * whether the connection may be activated with the device. For example if
2325  * @device is a Wi-Fi device that supports only WEP encryption, the connection
2326  * will only be valid if it is a Wi-Fi connection which describes a WEP or open
2327  * network, and will not be valid if it describes a WPA network, or if it is
2328  * an Ethernet, Bluetooth, WWAN, etc connection that is incompatible with the
2329  * device.
2330  *
2331  * This function does the same as nm_device_connection_valid(), i.e. checking
2332  * compatibility of the given device and connection. But, in addition, it sets
2333  * GError when FALSE is returned.
2334  *
2335  * Returns: %TRUE if the connection may be activated with this device, %FALSE
2336  * if is incompatible with the device's capabilities and characteristics.
2337  **/
2338 gboolean
2339 nm_device_connection_compatible (NMDevice *device, NMConnection *connection, GError **error)
2340 {
2341         g_return_val_if_fail (NM_IS_DEVICE (device), FALSE);
2342         g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE);
2343         g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
2344
2345         return NM_DEVICE_GET_CLASS (device)->connection_compatible (device, connection, error);
2346 }
2347
2348 /**
2349  * nm_device_filter_connections:
2350  * @device: an #NMDevice to filter connections for
2351  * @connections: (element-type NMConnection): a list of #NMConnection objects to filter
2352  *
2353  * Filters a given list of connections for a given #NMDevice object and return
2354  * connections which may be activated with the device. For example if @device
2355  * is a Wi-Fi device that supports only WEP encryption, the returned list will
2356  * contain any Wi-Fi connections in @connections that allow connection to
2357  * unencrypted or WEP-enabled SSIDs.  The returned list will not contain
2358  * Ethernet, Bluetooth, Wi-Fi WPA connections, or any other connection that is
2359  * incompatible with the device. To get the full list of connections see
2360  * nm_remote_settings_list_connections().
2361  *
2362  * Returns: (transfer container) (element-type NMConnection): a
2363  * list of #NMConnection objects that could be activated with the given @device.
2364  * The elements of the list are owned by their creator and should not be freed
2365  * by the caller, but the returned list itself is owned by the caller and should
2366  * be freed with g_slist_free() when it is no longer required.
2367  **/
2368 GSList *
2369 nm_device_filter_connections (NMDevice *device, const GSList *connections)
2370 {
2371         GSList *filtered = NULL;
2372         const GSList *iter;
2373
2374         for (iter = connections; iter; iter = g_slist_next (iter)) {
2375                 NMConnection *candidate = NM_CONNECTION (iter->data);
2376
2377                 /* Connection applies to this device */
2378                 if (nm_device_connection_valid (device, candidate))
2379                         filtered = g_slist_prepend (filtered, candidate);
2380         }
2381
2382         return g_slist_reverse (filtered);
2383 }
2384
2385 /**
2386  * nm_device_get_setting_type:
2387  * @device: an #NMDevice
2388  *
2389  * Gets the (primary) #NMSetting subtype associated with connections
2390  * that can be used on @device.
2391  *
2392  * Returns: @device's associated #NMSetting type
2393  *
2394  * Since: 0.9.10
2395  */
2396 GType
2397 nm_device_get_setting_type (NMDevice *device)
2398 {
2399         g_return_val_if_fail (NM_IS_DEVICE (device), G_TYPE_INVALID);
2400         g_return_val_if_fail (NM_DEVICE_GET_CLASS (device)->get_setting_type != NULL, G_TYPE_INVALID);
2401
2402         return NM_DEVICE_GET_CLASS (device)->get_setting_type (device);
2403 }