libnm: add code comments to hint that NMConnection might not validate
[NetworkManager.git] / libnm / 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 "nm-device.h"
25
26 #include <string.h>
27 #include <gudev/gudev.h>
28
29 #include "nm-dbus-interface.h"
30 #include "nm-active-connection.h"
31 #include "nm-device-ethernet.h"
32 #include "nm-device-adsl.h"
33 #include "nm-device-wifi.h"
34 #include "nm-device-modem.h"
35 #include "nm-device-bt.h"
36 #include "nm-device-olpc-mesh.h"
37 #include "nm-device-wimax.h"
38 #include "nm-device-infiniband.h"
39 #include "nm-device-bond.h"
40 #include "nm-device-team.h"
41 #include "nm-device-bridge.h"
42 #include "nm-device-vlan.h"
43 #include "nm-device-vxlan.h"
44 #include "nm-device-generic.h"
45 #include "nm-device-ip-tunnel.h"
46 #include "nm-device-macvlan.h"
47 #include "nm-device-private.h"
48 #include "nm-dhcp4-config.h"
49 #include "nm-dhcp6-config.h"
50 #include "nm-ip4-config.h"
51 #include "nm-ip6-config.h"
52 #include "nm-object-private.h"
53 #include "nm-object-cache.h"
54 #include "nm-remote-connection.h"
55 #include "nm-core-internal.h"
56 #include "nm-utils.h"
57 #include "nm-dbus-helpers.h"
58 #include "nm-device-tun.h"
59 #include "nm-setting-connection.h"
60
61 #include "nmdbus-device.h"
62
63 static GType _nm_device_decide_type (GVariant *value);
64 static gboolean connection_compatible (NMDevice *device, NMConnection *connection, GError **error);
65 static NMLldpNeighbor *nm_lldp_neighbor_dup (NMLldpNeighbor *neighbor);
66
67 G_DEFINE_TYPE_WITH_CODE (NMDevice, nm_device, NM_TYPE_OBJECT,
68                          _nm_object_register_type_func (g_define_type_id,
69                                                         _nm_device_decide_type,
70                                                         NM_DBUS_INTERFACE_DEVICE,
71                                                         "DeviceType");
72                          )
73
74 #define NM_DEVICE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE, NMDevicePrivate))
75
76 typedef struct {
77         NMDBusDevice *proxy;
78
79         char *iface;
80         char *ip_iface;
81         NMDeviceType device_type;
82         char *udi;
83         char *driver;
84         char *driver_version;
85         char *firmware_version;
86         char *type_description;
87         NMMetered metered;
88         NMDeviceCapabilities capabilities;
89         gboolean real;
90         gboolean managed;
91         gboolean firmware_missing;
92         gboolean nm_plugin_missing;
93         gboolean autoconnect;
94         NMIPConfig *ip4_config;
95         NMDhcpConfig *dhcp4_config;
96         NMIPConfig *ip6_config;
97         NMDhcpConfig *dhcp6_config;
98         NMDeviceState state;
99         NMDeviceState last_seen_state;
100         NMDeviceStateReason reason;
101
102         NMActiveConnection *active_connection;
103         GPtrArray *available_connections;
104
105         GUdevClient *client;
106         char *product, *short_product;
107         char *vendor, *short_vendor;
108         char *description, *bus_name;
109
110         char *physical_port_id;
111         guint32 mtu;
112         GPtrArray *lldp_neighbors;
113 } NMDevicePrivate;
114
115 enum {
116         PROP_0,
117         PROP_INTERFACE,
118         PROP_UDI,
119         PROP_DRIVER,
120         PROP_DRIVER_VERSION,
121         PROP_FIRMWARE_VERSION,
122         PROP_CAPABILITIES,
123         PROP_REAL,
124         PROP_MANAGED,
125         PROP_AUTOCONNECT,
126         PROP_FIRMWARE_MISSING,
127         PROP_NM_PLUGIN_MISSING,
128         PROP_IP4_CONFIG,
129         PROP_DHCP4_CONFIG,
130         PROP_IP6_CONFIG,
131         PROP_STATE,
132         PROP_STATE_REASON,
133         PROP_PRODUCT,
134         PROP_VENDOR,
135         PROP_DHCP6_CONFIG,
136         PROP_IP_INTERFACE,
137         PROP_DEVICE_TYPE,
138         PROP_ACTIVE_CONNECTION,
139         PROP_AVAILABLE_CONNECTIONS,
140         PROP_PHYSICAL_PORT_ID,
141         PROP_MTU,
142         PROP_METERED,
143         PROP_LLDP_NEIGHBORS,
144
145         LAST_PROP
146 };
147
148 enum {
149         STATE_CHANGED,
150
151         LAST_SIGNAL
152 };
153
154 static guint signals[LAST_SIGNAL] = { 0 };
155
156 struct _NMLldpNeighbor {
157         guint refcount;
158         GHashTable *attrs;
159 };
160
161 G_DEFINE_BOXED_TYPE (NMLldpNeighbor, nm_lldp_neighbor, nm_lldp_neighbor_dup, nm_lldp_neighbor_unref)
162
163 static void
164 nm_device_init (NMDevice *device)
165 {
166         NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device);
167
168         priv->state = NM_DEVICE_STATE_UNKNOWN;
169         priv->reason = NM_DEVICE_STATE_REASON_NONE;
170         priv->lldp_neighbors = g_ptr_array_new ();
171 }
172
173 static gboolean
174 demarshal_state_reason (NMObject *object, GParamSpec *pspec, GVariant *value, gpointer field)
175 {
176         guint32 *reason_field = field;
177
178         g_variant_get (value, "(uu)", NULL, reason_field);
179         _nm_object_queue_notify (object, NM_DEVICE_STATE_REASON);
180         return TRUE;
181 }
182
183 static gboolean
184 demarshal_lldp_neighbors (NMObject *object, GParamSpec *pspec, GVariant *value, gpointer field)
185 {
186         NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (object);
187         GVariantIter iter, attrs_iter;
188         GVariant *variant, *attr_variant;
189         const char *attr_name;
190
191         g_return_val_if_fail (g_variant_is_of_type (value, G_VARIANT_TYPE ("aa{sv}")), FALSE);
192
193         g_ptr_array_unref (priv->lldp_neighbors);
194         priv->lldp_neighbors = g_ptr_array_new_with_free_func ((GDestroyNotify) nm_lldp_neighbor_unref);
195         g_variant_iter_init (&iter, value);
196
197         while (g_variant_iter_next (&iter, "@a{sv}", &variant)) {
198                 NMLldpNeighbor *neigh;
199
200                 neigh = nm_lldp_neighbor_new ();
201                 g_variant_iter_init (&attrs_iter, variant);
202
203                 while (g_variant_iter_next (&attrs_iter, "{&sv}", &attr_name, &attr_variant))
204                         g_hash_table_insert (neigh->attrs, g_strdup (attr_name), attr_variant);
205
206                 g_variant_unref (variant);
207                 g_ptr_array_add (priv->lldp_neighbors, neigh);
208         }
209
210         _nm_object_queue_notify (object, NM_DEVICE_LLDP_NEIGHBORS);
211
212         return TRUE;
213 }
214
215 static void
216 device_state_changed (NMDBusDevice *proxy,
217                       guint new_state,
218                       guint old_state,
219                       guint reason,
220                       gpointer user_data);
221
222 static void
223 init_dbus (NMObject *object)
224 {
225         NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (object);
226         const NMPropertiesInfo property_info[] = {
227                 { NM_DEVICE_UDI,               &priv->udi },
228                 { NM_DEVICE_INTERFACE,         &priv->iface },
229                 { NM_DEVICE_IP_INTERFACE,      &priv->ip_iface },
230                 { NM_DEVICE_DRIVER,            &priv->driver },
231                 { NM_DEVICE_DRIVER_VERSION,    &priv->driver_version },
232                 { NM_DEVICE_FIRMWARE_VERSION,  &priv->firmware_version },
233                 { NM_DEVICE_CAPABILITIES,      &priv->capabilities },
234                 { NM_DEVICE_REAL,              &priv->real },
235                 { NM_DEVICE_MANAGED,           &priv->managed },
236                 { NM_DEVICE_AUTOCONNECT,       &priv->autoconnect },
237                 { NM_DEVICE_FIRMWARE_MISSING,  &priv->firmware_missing },
238                 { NM_DEVICE_NM_PLUGIN_MISSING, &priv->nm_plugin_missing },
239                 { NM_DEVICE_IP4_CONFIG,        &priv->ip4_config, NULL, NM_TYPE_IP4_CONFIG },
240                 { NM_DEVICE_DHCP4_CONFIG,      &priv->dhcp4_config, NULL, NM_TYPE_DHCP4_CONFIG },
241                 { NM_DEVICE_IP6_CONFIG,        &priv->ip6_config, NULL, NM_TYPE_IP6_CONFIG },
242                 { NM_DEVICE_DHCP6_CONFIG,      &priv->dhcp6_config, NULL, NM_TYPE_DHCP6_CONFIG },
243                 { NM_DEVICE_STATE,             &priv->state },
244                 { NM_DEVICE_STATE_REASON,      &priv->reason, demarshal_state_reason },
245                 { NM_DEVICE_ACTIVE_CONNECTION, &priv->active_connection, NULL, NM_TYPE_ACTIVE_CONNECTION },
246                 { NM_DEVICE_AVAILABLE_CONNECTIONS, &priv->available_connections, NULL, NM_TYPE_REMOTE_CONNECTION },
247                 { NM_DEVICE_PHYSICAL_PORT_ID,  &priv->physical_port_id },
248                 { NM_DEVICE_MTU,               &priv->mtu },
249                 { NM_DEVICE_METERED,           &priv->metered },
250                 { NM_DEVICE_LLDP_NEIGHBORS,    &priv->lldp_neighbors, demarshal_lldp_neighbors },
251
252                 /* Properties that exist in D-Bus but that we don't track */
253                 { "ip4-address", NULL },
254                 { "device-type", NULL },
255
256                 { NULL },
257         };
258
259         NM_OBJECT_CLASS (nm_device_parent_class)->init_dbus (object);
260
261         priv->proxy = NMDBUS_DEVICE (_nm_object_get_proxy (object, NM_DBUS_INTERFACE_DEVICE));
262         _nm_object_register_properties (object,
263                                         NM_DBUS_INTERFACE_DEVICE,
264                                         property_info);
265
266         g_signal_connect (priv->proxy, "state-changed",
267                           G_CALLBACK (device_state_changed), object);
268 }
269
270 typedef struct {
271         NMDeviceState old_state;
272         NMDeviceState new_state;
273         NMDeviceStateReason reason;
274 } StateChangeData;
275
276 static void
277 device_state_change_reloaded (GObject *object,
278                               GAsyncResult *result,
279                               gpointer user_data)
280 {
281         NMDevice *self = NM_DEVICE (object);
282         NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
283         StateChangeData *data = user_data;
284         NMDeviceState old_state = data->old_state;
285         NMDeviceState new_state = data->new_state;
286         NMDeviceStateReason reason = data->reason;
287
288         g_slice_free (StateChangeData, data);
289
290         _nm_object_reload_properties_finish (NM_OBJECT (object), result, NULL);
291
292         /* If the device changes state several times in rapid succession, then we'll
293          * queue several reload_properties() calls, and there's no guarantee that
294          * they'll finish in the right order. In that case, only emit the signal
295          * for the last one.
296          */
297         if (priv->last_seen_state != new_state)
298                 return;
299
300         /* Ensure that nm_device_get_state() will return the right value even if
301          * we haven't processed the corresponding PropertiesChanged yet.
302          */
303         priv->state = new_state;
304
305         g_signal_emit (self, signals[STATE_CHANGED], 0,
306                        new_state, old_state, reason);
307 }
308
309 static void
310 device_state_changed (NMDBusDevice *proxy,
311                       guint new_state,
312                       guint old_state,
313                       guint reason,
314                       gpointer user_data)
315 {
316         NMDevice *self = NM_DEVICE (user_data);
317         NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
318         StateChangeData *data;
319
320         if (old_state == new_state)
321                 return;
322
323         /* Our object-valued properties (eg, ip4_config) will still
324          * have their old values at this point, because NMObject is
325          * in the process of asynchronously reading the new values.
326          * Wait for that to finish before emitting the signal.
327          */
328         priv->last_seen_state = new_state;
329
330         data = g_slice_new (StateChangeData);
331         data->old_state = old_state;
332         data->new_state = new_state;
333         data->reason = reason;
334         _nm_object_reload_properties_async (NM_OBJECT (user_data),
335                                             NULL,
336                                             device_state_change_reloaded,
337                                             data);
338 }
339
340 static GType
341 _nm_device_gtype_from_dtype (NMDeviceType dtype)
342 {
343         switch (dtype) {
344         case NM_DEVICE_TYPE_VETH:
345         case NM_DEVICE_TYPE_ETHERNET:
346                 return NM_TYPE_DEVICE_ETHERNET;
347         case NM_DEVICE_TYPE_WIFI:
348                 return NM_TYPE_DEVICE_WIFI;
349         case NM_DEVICE_TYPE_MODEM:
350                 return NM_TYPE_DEVICE_MODEM;
351         case NM_DEVICE_TYPE_BT:
352                 return NM_TYPE_DEVICE_BT;
353         case NM_DEVICE_TYPE_ADSL:
354                 return NM_TYPE_DEVICE_ADSL;
355         case NM_DEVICE_TYPE_OLPC_MESH:
356                 return NM_TYPE_DEVICE_OLPC_MESH;
357         case NM_DEVICE_TYPE_WIMAX:
358                 return NM_TYPE_DEVICE_WIMAX;
359         case NM_DEVICE_TYPE_INFINIBAND:
360                 return NM_TYPE_DEVICE_INFINIBAND;
361         case NM_DEVICE_TYPE_BOND:
362                 return NM_TYPE_DEVICE_BOND;
363         case NM_DEVICE_TYPE_TEAM:
364                 return NM_TYPE_DEVICE_TEAM;
365         case NM_DEVICE_TYPE_BRIDGE:
366                 return NM_TYPE_DEVICE_BRIDGE;
367         case NM_DEVICE_TYPE_VLAN:
368                 return NM_TYPE_DEVICE_VLAN;
369         case NM_DEVICE_TYPE_GENERIC:
370                 return NM_TYPE_DEVICE_GENERIC;
371         case NM_DEVICE_TYPE_TUN:
372                 return NM_TYPE_DEVICE_TUN;
373         case NM_DEVICE_TYPE_IP_TUNNEL:
374                 return NM_TYPE_DEVICE_IP_TUNNEL;
375         case NM_DEVICE_TYPE_MACVLAN:
376                 return NM_TYPE_DEVICE_MACVLAN;
377         case NM_DEVICE_TYPE_VXLAN:
378                 return NM_TYPE_DEVICE_VXLAN;
379         default:
380                 g_warning ("Unknown device type %d", dtype);
381                 return G_TYPE_INVALID;
382         }
383 }
384
385 static void
386 constructed (GObject *object)
387 {
388         NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (object);
389
390         G_OBJECT_CLASS (nm_device_parent_class)->constructed (object);
391
392         /* Catch failure of subclasses to call _nm_device_set_device_type() */
393         g_warn_if_fail (priv->device_type != NM_DEVICE_TYPE_UNKNOWN);
394         /* Catch a subclass setting the wrong type */
395         g_warn_if_fail (G_OBJECT_TYPE (object) == _nm_device_gtype_from_dtype (priv->device_type));
396 }
397
398 static void
399 dispose (GObject *object)
400 {
401         NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (object);
402
403         g_clear_object (&priv->ip4_config);
404         g_clear_object (&priv->dhcp4_config);
405         g_clear_object (&priv->ip6_config);
406         g_clear_object (&priv->dhcp6_config);
407         g_clear_object (&priv->client);
408         g_clear_object (&priv->active_connection);
409
410         g_clear_pointer (&priv->available_connections, g_ptr_array_unref);
411         g_clear_pointer (&priv->lldp_neighbors, g_ptr_array_unref);
412
413         G_OBJECT_CLASS (nm_device_parent_class)->dispose (object);
414 }
415
416 static void
417 finalize (GObject *object)
418 {
419         NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (object);
420
421         g_free (priv->iface);
422         g_free (priv->ip_iface);
423         g_free (priv->udi);
424         g_free (priv->driver);
425         g_free (priv->driver_version);
426         g_free (priv->firmware_version);
427         g_free (priv->product);
428         g_free (priv->short_product);
429         g_free (priv->vendor);
430         g_free (priv->short_vendor);
431         g_free (priv->description);
432         g_free (priv->bus_name);
433         g_free (priv->type_description);
434         g_free (priv->physical_port_id);
435
436         G_OBJECT_CLASS (nm_device_parent_class)->finalize (object);
437 }
438
439 static void
440 get_property (GObject *object,
441               guint prop_id,
442               GValue *value,
443               GParamSpec *pspec)
444 {
445         NMDevice *device = NM_DEVICE (object);
446
447         switch (prop_id) {
448         case PROP_DEVICE_TYPE:
449                 g_value_set_enum (value, nm_device_get_device_type (device));
450                 break;
451         case PROP_UDI:
452                 g_value_set_string (value, nm_device_get_udi (device));
453                 break;
454         case PROP_INTERFACE:
455                 g_value_set_string (value, nm_device_get_iface (device));
456                 break;
457         case PROP_IP_INTERFACE:
458                 g_value_set_string (value, nm_device_get_ip_iface (device));
459                 break;
460         case PROP_DRIVER:
461                 g_value_set_string (value, nm_device_get_driver (device));
462                 break;
463         case PROP_DRIVER_VERSION:
464                 g_value_set_string (value, nm_device_get_driver_version (device));
465                 break;
466         case PROP_FIRMWARE_VERSION:
467                 g_value_set_string (value, nm_device_get_firmware_version (device));
468                 break;
469         case PROP_CAPABILITIES:
470                 g_value_set_flags (value, nm_device_get_capabilities (device));
471                 break;
472         case PROP_REAL:
473                 g_value_set_boolean (value, nm_device_is_real (device));
474                 break;
475         case PROP_MANAGED:
476                 g_value_set_boolean (value, nm_device_get_managed (device));
477                 break;
478         case PROP_AUTOCONNECT:
479                 g_value_set_boolean (value, nm_device_get_autoconnect (device));
480                 break;
481         case PROP_FIRMWARE_MISSING:
482                 g_value_set_boolean (value, nm_device_get_firmware_missing (device));
483                 break;
484         case PROP_NM_PLUGIN_MISSING:
485                 g_value_set_boolean (value, nm_device_get_nm_plugin_missing (device));
486                 break;
487         case PROP_IP4_CONFIG:
488                 g_value_set_object (value, nm_device_get_ip4_config (device));
489                 break;
490         case PROP_DHCP4_CONFIG:
491                 g_value_set_object (value, nm_device_get_dhcp4_config (device));
492                 break;
493         case PROP_IP6_CONFIG:
494                 g_value_set_object (value, nm_device_get_ip6_config (device));
495                 break;
496         case PROP_DHCP6_CONFIG:
497                 g_value_set_object (value, nm_device_get_dhcp6_config (device));
498                 break;
499         case PROP_STATE:
500                 g_value_set_enum (value, nm_device_get_state (device));
501                 break;
502         case PROP_STATE_REASON:
503                 g_value_set_uint (value, nm_device_get_state_reason (device));
504                 break;
505         case PROP_ACTIVE_CONNECTION:
506                 g_value_set_object (value, nm_device_get_active_connection (device));
507                 break;
508         case PROP_AVAILABLE_CONNECTIONS:
509                 g_value_take_boxed (value, _nm_utils_copy_object_array (nm_device_get_available_connections (device)));
510                 break;
511         case PROP_PRODUCT:
512                 g_value_set_string (value, nm_device_get_product (device));
513                 break;
514         case PROP_VENDOR:
515                 g_value_set_string (value, nm_device_get_vendor (device));
516                 break;
517         case PROP_PHYSICAL_PORT_ID:
518                 g_value_set_string (value, nm_device_get_physical_port_id (device));
519                 break;
520         case PROP_MTU:
521                 g_value_set_uint (value, nm_device_get_mtu (device));
522                 break;
523         case PROP_METERED:
524                 g_value_set_uint (value, nm_device_get_metered (device));
525                 break;
526         case PROP_LLDP_NEIGHBORS:
527                 g_value_set_boxed (value, nm_device_get_lldp_neighbors (device));
528                 break;
529         default:
530                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
531                 break;
532         }
533 }
534
535 static void
536 set_property (GObject *object,
537               guint prop_id,
538               const GValue *value,
539               GParamSpec *pspec)
540 {
541         NMDevice *self = NM_DEVICE (object);
542         NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
543         gboolean b;
544
545         switch (prop_id) {
546         case PROP_DEVICE_TYPE:
547                 /* Construct only */
548                 priv->device_type = g_value_get_enum (value);
549                 break;
550         case PROP_MANAGED:
551                 b = g_value_get_boolean (value);
552                 if (priv->managed != b)
553                         nm_device_set_managed (NM_DEVICE (object), b);
554                 break;
555         case PROP_AUTOCONNECT:
556                 b = g_value_get_boolean (value);
557                 if (priv->autoconnect != b)
558                         nm_device_set_autoconnect (NM_DEVICE (object), b);
559                 break;
560         default:
561                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
562                 break;
563         }
564 }
565
566 static void
567 nm_device_class_init (NMDeviceClass *device_class)
568 {
569         GObjectClass *object_class = G_OBJECT_CLASS (device_class);
570         NMObjectClass *nm_object_class = NM_OBJECT_CLASS (device_class);
571
572         g_type_class_add_private (device_class, sizeof (NMDevicePrivate));
573
574         _nm_object_class_add_interface (nm_object_class, NM_DBUS_INTERFACE_DEVICE);
575         _nm_dbus_register_proxy_type (NM_DBUS_INTERFACE_DEVICE, NMDBUS_TYPE_DEVICE_PROXY);
576
577         /* virtual methods */
578         object_class->constructed = constructed;
579         object_class->get_property = get_property;
580         object_class->set_property = set_property;
581         object_class->dispose = dispose;
582         object_class->finalize = finalize;
583
584         nm_object_class->init_dbus = init_dbus;
585
586         device_class->connection_compatible = connection_compatible;
587
588         /* properties */
589
590         /**
591          * NMDevice:interface:
592          *
593          * The interface of the device.
594          **/
595         g_object_class_install_property
596                 (object_class, PROP_INTERFACE,
597                  g_param_spec_string (NM_DEVICE_INTERFACE, "", "",
598                                       NULL,
599                                       G_PARAM_READABLE |
600                                       G_PARAM_STATIC_STRINGS));
601
602         /**
603          * NMDevice:ip-interface:
604          *
605          * The IP interface of the device which should be used for all IP-related
606          * operations like addressing and routing.
607          **/
608         g_object_class_install_property
609                 (object_class, PROP_IP_INTERFACE,
610                  g_param_spec_string (NM_DEVICE_IP_INTERFACE, "", "",
611                                       NULL,
612                                       G_PARAM_READABLE |
613                                       G_PARAM_STATIC_STRINGS));
614
615         /**
616          * NMDevice:device-type:
617          *
618          * The numeric type of the device.
619          **/
620         g_object_class_install_property
621                 (object_class, PROP_DEVICE_TYPE,
622                  g_param_spec_enum (NM_DEVICE_DEVICE_TYPE, "", "",
623                                     NM_TYPE_DEVICE_TYPE,
624                                     NM_DEVICE_TYPE_UNKNOWN,
625                                     G_PARAM_READABLE |
626                                     G_PARAM_STATIC_STRINGS));
627         /**
628          * NMDevice:udi:
629          *
630          * An operating-system specific device hardware identifier; this is not
631          * unique to a specific hardware device across reboots or hotplugs.  It
632          * is an opaque string which for some device types (Bluetooth, Modem)
633          * contains an identifier provided by the underlying hardware service daemon
634          * such as Bluez or ModemManager, and clients can use this property to
635          * request more information about the device from those services.
636          **/
637         g_object_class_install_property
638                 (object_class, PROP_UDI,
639                  g_param_spec_string (NM_DEVICE_UDI, "", "",
640                                       NULL,
641                                       G_PARAM_READABLE |
642                                       G_PARAM_STATIC_STRINGS));
643
644         /**
645          * NMDevice:driver:
646          *
647          * The driver of the device.
648          **/
649         g_object_class_install_property
650                 (object_class, PROP_DRIVER,
651                  g_param_spec_string (NM_DEVICE_DRIVER, "", "",
652                                       NULL,
653                                       G_PARAM_READABLE |
654                                       G_PARAM_STATIC_STRINGS));
655
656         /**
657          * NMDevice:driver-version:
658          *
659          * The version of the device driver.
660          **/
661         g_object_class_install_property
662                 (object_class, PROP_DRIVER_VERSION,
663                  g_param_spec_string (NM_DEVICE_DRIVER_VERSION, "", "",
664                                       NULL,
665                                       G_PARAM_READABLE |
666                                       G_PARAM_STATIC_STRINGS));
667
668         /**
669          * NMDevice:firmware-version:
670          *
671          * The firmware version of the device.
672          **/
673         g_object_class_install_property
674                 (object_class, PROP_FIRMWARE_VERSION,
675                  g_param_spec_string (NM_DEVICE_FIRMWARE_VERSION, "", "",
676                                       NULL,
677                                       G_PARAM_READABLE |
678                                       G_PARAM_STATIC_STRINGS));
679
680         /**
681          * NMDevice:capabilities:
682          *
683          * The capabilities of the device.
684          **/
685         g_object_class_install_property
686                 (object_class, PROP_CAPABILITIES,
687                  g_param_spec_flags (NM_DEVICE_CAPABILITIES, "", "",
688                                      NM_TYPE_DEVICE_CAPABILITIES,
689                                      NM_DEVICE_CAP_NONE,
690                                      G_PARAM_READABLE |
691                                      G_PARAM_STATIC_STRINGS));
692
693         /**
694          * NMDevice:real:
695          *
696          * Whether the device is real or is a placeholder device that could
697          * be created automatically by NetworkManager if one of its
698          * #NMDevice:available-connections was activated.
699          *
700          * Since: 1.2
701          **/
702         g_object_class_install_property
703                 (object_class, PROP_REAL,
704                  g_param_spec_boolean (NM_DEVICE_REAL, "", "",
705                                        FALSE,
706                                        G_PARAM_READABLE |
707                                        G_PARAM_STATIC_STRINGS));
708
709         /**
710          * NMDevice:managed:
711          *
712          * Whether the device is managed by NetworkManager.
713          **/
714         g_object_class_install_property
715                 (object_class, PROP_MANAGED,
716                  g_param_spec_boolean (NM_DEVICE_MANAGED, "", "",
717                                        FALSE,
718                                        G_PARAM_READABLE |
719                                        G_PARAM_STATIC_STRINGS));
720
721         /**
722          * NMDevice:autoconnect:
723          *
724          * Whether the device can auto-activate a connection.
725          **/
726         g_object_class_install_property
727                 (object_class, PROP_AUTOCONNECT,
728                  g_param_spec_boolean (NM_DEVICE_AUTOCONNECT, "", "",
729                                        TRUE,
730                                        G_PARAM_READWRITE |
731                                        G_PARAM_STATIC_STRINGS));
732
733         /**
734          * NMDevice:firmware-missing:
735          *
736          * When %TRUE indicates the device is likely missing firmware required
737          * for its operation.
738          **/
739         g_object_class_install_property
740                 (object_class, PROP_FIRMWARE_MISSING,
741                  g_param_spec_boolean (NM_DEVICE_FIRMWARE_MISSING, "", "",
742                                        FALSE,
743                                        G_PARAM_READABLE |
744                                        G_PARAM_STATIC_STRINGS));
745
746         /**
747          * NMDevice:nm-plugin-missing:
748          *
749          * When %TRUE indicates that the NetworkManager plugin for the device
750          * is not installed.
751          *
752          * Since: 1.2
753          **/
754         g_object_class_install_property
755                 (object_class, PROP_NM_PLUGIN_MISSING,
756                  g_param_spec_boolean (NM_DEVICE_NM_PLUGIN_MISSING, "", "",
757                                        FALSE,
758                                        G_PARAM_READABLE |
759                                        G_PARAM_STATIC_STRINGS));
760
761         /**
762          * NMDevice:ip4-config:
763          *
764          * The #NMIP4Config of the device.
765          **/
766         g_object_class_install_property
767                 (object_class, PROP_IP4_CONFIG,
768                  g_param_spec_object (NM_DEVICE_IP4_CONFIG, "", "",
769                                       NM_TYPE_IP_CONFIG,
770                                       G_PARAM_READABLE |
771                                       G_PARAM_STATIC_STRINGS));
772
773         /**
774          * NMDevice:dhcp4-config:
775          *
776          * The IPv4 #NMDhcpConfig of the device.
777          **/
778         g_object_class_install_property
779                 (object_class, PROP_DHCP4_CONFIG,
780                  g_param_spec_object (NM_DEVICE_DHCP4_CONFIG, "", "",
781                                       NM_TYPE_DHCP_CONFIG,
782                                       G_PARAM_READABLE |
783                                       G_PARAM_STATIC_STRINGS));
784
785         /**
786          * NMDevice:ip6-config:
787          *
788          * The IPv6 #NMIPConfig of the device.
789          **/
790         g_object_class_install_property
791                 (object_class, PROP_IP6_CONFIG,
792                  g_param_spec_object (NM_DEVICE_IP6_CONFIG, "", "",
793                                       NM_TYPE_IP_CONFIG,
794                                       G_PARAM_READABLE |
795                                       G_PARAM_STATIC_STRINGS));
796
797         /**
798          * NMDevice:dhcp6-config:
799          *
800          * The IPv6 #NMDhcpConfig of the device.
801          **/
802         g_object_class_install_property
803                 (object_class, PROP_DHCP6_CONFIG,
804                  g_param_spec_object (NM_DEVICE_DHCP6_CONFIG, "", "",
805                                       NM_TYPE_DHCP_CONFIG,
806                                       G_PARAM_READABLE |
807                                       G_PARAM_STATIC_STRINGS));
808
809         /**
810          * NMDevice:state:
811          *
812          * The state of the device.
813          **/
814         g_object_class_install_property
815                 (object_class, PROP_STATE,
816                  g_param_spec_enum (NM_DEVICE_STATE, "", "",
817                                     NM_TYPE_DEVICE_STATE,
818                                     NM_DEVICE_STATE_UNKNOWN,
819                                     G_PARAM_READABLE |
820                                     G_PARAM_STATIC_STRINGS));
821
822         /**
823          * NMDevice:state-reason:
824          *
825          * The reason for the device state.
826          **/
827         g_object_class_install_property
828                 (object_class, PROP_STATE_REASON,
829                  g_param_spec_uint (NM_DEVICE_STATE_REASON, "", "",
830                                     0, G_MAXUINT32, 0,
831                                     G_PARAM_READABLE |
832                                     G_PARAM_STATIC_STRINGS));
833
834         /**
835          * NMDevice:active-connection:
836          *
837          * The #NMActiveConnection object that "owns" this device during activation.
838          **/
839         g_object_class_install_property
840                 (object_class, PROP_ACTIVE_CONNECTION,
841                  g_param_spec_object (NM_DEVICE_ACTIVE_CONNECTION, "", "",
842                                       NM_TYPE_ACTIVE_CONNECTION,
843                                       G_PARAM_READABLE |
844                                       G_PARAM_STATIC_STRINGS));
845
846         /**
847          * NMDevice:available-connections:
848          *
849          * The available connections of the device
850          *
851          * Element-type: NMRemoteConnection
852          **/
853         g_object_class_install_property
854                 (object_class, PROP_AVAILABLE_CONNECTIONS,
855                  g_param_spec_boxed (NM_DEVICE_AVAILABLE_CONNECTIONS, "", "",
856                                      G_TYPE_PTR_ARRAY,
857                                      G_PARAM_READABLE |
858                                      G_PARAM_STATIC_STRINGS));
859
860         /**
861          * NMDevice:vendor:
862          *
863          * The vendor string of the device.
864          **/
865         g_object_class_install_property
866                 (object_class, PROP_VENDOR,
867                  g_param_spec_string (NM_DEVICE_VENDOR, "", "",
868                                       NULL,
869                                       G_PARAM_READABLE |
870                                       G_PARAM_STATIC_STRINGS));
871
872         /**
873          * NMDevice:product:
874          *
875          * The product string of the device.
876          **/
877         g_object_class_install_property
878                 (object_class, PROP_PRODUCT,
879                  g_param_spec_string (NM_DEVICE_PRODUCT, "", "",
880                                       NULL,
881                                       G_PARAM_READABLE |
882                                       G_PARAM_STATIC_STRINGS));
883
884         /**
885          * NMDevice:physical-port-id:
886          *
887          * The physical port ID of the device. (See
888          * nm_device_get_physical_port_id().)
889          **/
890         g_object_class_install_property
891                 (object_class, PROP_PHYSICAL_PORT_ID,
892                  g_param_spec_string (NM_DEVICE_PHYSICAL_PORT_ID, "", "",
893                                       NULL,
894                                       G_PARAM_READABLE |
895                                       G_PARAM_STATIC_STRINGS));
896
897         /**
898          * NMDevice:mtu:
899          *
900          * The MTU of the device.
901          **/
902         g_object_class_install_property
903                 (object_class, PROP_MTU,
904                  g_param_spec_uint (NM_DEVICE_MTU, "", "",
905                                     0, G_MAXUINT32, 1500,
906                                     G_PARAM_READABLE |
907                                     G_PARAM_STATIC_STRINGS));
908
909         /**
910          * NMDevice:metered:
911          *
912          * Whether the device is metered.
913          *
914          * Since: 1.2
915          **/
916         g_object_class_install_property
917                 (object_class, PROP_METERED,
918                  g_param_spec_uint (NM_DEVICE_METERED, "", "",
919                                     0, G_MAXUINT32, NM_METERED_UNKNOWN,
920                                     G_PARAM_READABLE |
921                                     G_PARAM_STATIC_STRINGS));
922
923         /**
924          * NMDevice:lldp-neighbors:
925          *
926          * The LLDP neighbors.
927          **/
928         g_object_class_install_property
929             (object_class, PROP_LLDP_NEIGHBORS,
930              g_param_spec_boxed (NM_DEVICE_LLDP_NEIGHBORS, "", "",
931                                  G_TYPE_PTR_ARRAY,
932                                  G_PARAM_READABLE |
933                                  G_PARAM_STATIC_STRINGS));
934
935         /* signals */
936
937         /**
938          * NMDevice::state-changed:
939          * @device: the device object that received the signal
940          * @new_state: the new state of the device
941          * @old_state: the previous state of the device
942          * @reason: the reason describing the state change
943          *
944          * Notifies the state change of a #NMDevice.
945          **/
946         signals[STATE_CHANGED] =
947                 g_signal_new ("state-changed",
948                               G_OBJECT_CLASS_TYPE (object_class),
949                               G_SIGNAL_RUN_FIRST,
950                               G_STRUCT_OFFSET (NMDeviceClass, state_changed),
951                               NULL, NULL, NULL,
952                               G_TYPE_NONE, 3,
953                               G_TYPE_UINT, G_TYPE_UINT, G_TYPE_UINT);
954 }
955
956 /**
957  * _nm_device_set_device_type:
958  * @device: the device
959  * @dtype: the NM device type
960  *
961  * Sets the NM device type if it wasn't set during construction.  INTERNAL
962  * ONLY METHOD.
963  **/
964 void
965 _nm_device_set_device_type (NMDevice *device, NMDeviceType dtype)
966 {
967         NMDevicePrivate *priv;
968
969         g_return_if_fail (device != NULL);
970         g_return_if_fail (dtype != NM_DEVICE_TYPE_UNKNOWN);
971
972         priv = NM_DEVICE_GET_PRIVATE (device);
973         if (priv->device_type == NM_DEVICE_TYPE_UNKNOWN)
974                 priv->device_type = dtype;
975         else
976                 g_warn_if_fail (dtype == priv->device_type);
977 }
978
979 static GType
980 _nm_device_decide_type (GVariant *value)
981 {
982         return _nm_device_gtype_from_dtype (g_variant_get_uint32 (value));
983 }
984
985 /**
986  * nm_device_get_iface:
987  * @device: a #NMDevice
988  *
989  * Gets the interface name of the #NMDevice.
990  *
991  * Returns: the interface of the device. This is the internal string used by the
992  * device, and must not be modified.
993  **/
994 const char *
995 nm_device_get_iface (NMDevice *device)
996 {
997         g_return_val_if_fail (NM_IS_DEVICE (device), NULL);
998
999         return NM_DEVICE_GET_PRIVATE (device)->iface;
1000 }
1001
1002 /**
1003  * nm_device_get_ip_iface:
1004  * @device: a #NMDevice
1005  *
1006  * Gets the IP interface name of the #NMDevice over which IP traffic flows
1007  * when the device is in the ACTIVATED state.
1008  *
1009  * Returns: the IP traffic interface of the device. This is the internal string
1010  * used by the device, and must not be modified.
1011  **/
1012 const char *
1013 nm_device_get_ip_iface (NMDevice *device)
1014 {
1015         g_return_val_if_fail (NM_IS_DEVICE (device), NULL);
1016
1017         return NM_DEVICE_GET_PRIVATE (device)->ip_iface;
1018 }
1019
1020 /**
1021  * nm_device_get_device_type:
1022  * @device: a #NMDevice
1023  *
1024  * Returns the numeric type of the #NMDevice, ie Ethernet, Wi-Fi, etc.
1025  *
1026  * Returns: the device type
1027  **/
1028 NMDeviceType
1029 nm_device_get_device_type (NMDevice *self)
1030 {
1031         g_return_val_if_fail (NM_IS_DEVICE (self), NM_DEVICE_TYPE_UNKNOWN);
1032
1033         return NM_DEVICE_GET_PRIVATE (self)->device_type;
1034 }
1035
1036 /**
1037  * nm_device_get_udi:
1038  * @device: a #NMDevice
1039  *
1040  * Gets the Unique Device Identifier of the #NMDevice.
1041  *
1042  * Returns: the Unique Device Identifier of the device.  This identifier may be
1043  * used to gather more information about the device from various operating
1044  * system services like udev or sysfs.
1045  **/
1046 const char *
1047 nm_device_get_udi (NMDevice *device)
1048 {
1049         g_return_val_if_fail (NM_IS_DEVICE (device), NULL);
1050
1051         return NM_DEVICE_GET_PRIVATE (device)->udi;
1052 }
1053
1054 /**
1055  * nm_device_get_driver:
1056  * @device: a #NMDevice
1057  *
1058  * Gets the driver of the #NMDevice.
1059  *
1060  * Returns: the driver of the device. This is the internal string used by the
1061  * device, and must not be modified.
1062  **/
1063 const char *
1064 nm_device_get_driver (NMDevice *device)
1065 {
1066         g_return_val_if_fail (NM_IS_DEVICE (device), NULL);
1067
1068         return NM_DEVICE_GET_PRIVATE (device)->driver;
1069 }
1070
1071 /**
1072  * nm_device_get_driver_version:
1073  * @device: a #NMDevice
1074  *
1075  * Gets the driver version of the #NMDevice.
1076  *
1077  * Returns: the version of the device driver. This is the internal string used by the
1078  * device, and must not be modified.
1079  **/
1080 const char *
1081 nm_device_get_driver_version (NMDevice *device)
1082 {
1083         g_return_val_if_fail (NM_IS_DEVICE (device), NULL);
1084
1085         return NM_DEVICE_GET_PRIVATE (device)->driver_version;
1086 }
1087
1088 /**
1089  * nm_device_get_firmware_version:
1090  * @device: a #NMDevice
1091  *
1092  * Gets the firmware version of the #NMDevice.
1093  *
1094  * Returns: the firmware version of the device. This is the internal string used by the
1095  * device, and must not be modified.
1096  **/
1097 const char *
1098 nm_device_get_firmware_version (NMDevice *device)
1099 {
1100         g_return_val_if_fail (NM_IS_DEVICE (device), NULL);
1101
1102         return NM_DEVICE_GET_PRIVATE (device)->firmware_version;
1103 }
1104
1105 /**
1106  * nm_device_get_type_description:
1107  * @device: a #NMDevice
1108  *
1109  * Gets a (non-localized) description of the type of device that
1110  * @device is.
1111  *
1112  * Returns: the type description of the device. This is the internal
1113  * string used by the device, and must not be modified.
1114  **/
1115 const char *
1116 nm_device_get_type_description (NMDevice *device)
1117 {
1118         NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device);
1119         const char *desc, *typename;
1120
1121         /* BEWARE: this function should return the same value
1122          * as nm_device_get_type_description() in nm-core. */
1123
1124         g_return_val_if_fail (NM_IS_DEVICE (device), NULL);
1125
1126         if (priv->type_description)
1127                 return priv->type_description;
1128
1129         if (NM_DEVICE_GET_CLASS (device)->get_type_description) {
1130                 desc = NM_DEVICE_GET_CLASS (device)->get_type_description (device);
1131                 if (desc)
1132                         return desc;
1133         }
1134
1135         typename = G_OBJECT_TYPE_NAME (device);
1136         if (g_str_has_prefix (typename, "NMDevice"))
1137                 typename += 8;
1138         priv->type_description = g_ascii_strdown (typename, -1);
1139
1140         return priv->type_description;
1141 }
1142
1143 /**
1144  * nm_device_get_hw_address:
1145  * @device: a #NMDevice
1146  *
1147  * Gets the current a hardware address (MAC) for the @device.
1148  *
1149  * Returns: the current MAC of the device, or %NULL.
1150  * This is the internal string used by the device, and must not be modified.
1151  **/
1152 const char *
1153 nm_device_get_hw_address (NMDevice *device)
1154 {
1155         g_return_val_if_fail (NM_IS_DEVICE (device), NULL);
1156
1157         if (NM_DEVICE_GET_CLASS (device)->get_hw_address)
1158                 return NM_DEVICE_GET_CLASS (device)->get_hw_address (device);
1159
1160         return NULL;
1161 }
1162
1163 /**
1164  * nm_device_get_capabilities:
1165  * @device: a #NMDevice
1166  *
1167  * Gets the device' capabilities.
1168  *
1169  * Returns: the capabilities
1170  **/
1171 NMDeviceCapabilities
1172 nm_device_get_capabilities (NMDevice *device)
1173 {
1174         g_return_val_if_fail (NM_IS_DEVICE (device), 0);
1175
1176         return NM_DEVICE_GET_PRIVATE (device)->capabilities;
1177 }
1178
1179 /**
1180  * nm_device_get_managed:
1181  * @device: a #NMDevice
1182  *
1183  * Whether the #NMDevice is managed by NetworkManager.
1184  *
1185  * Returns: %TRUE if the device is managed by NetworkManager
1186  **/
1187 gboolean
1188 nm_device_get_managed (NMDevice *device)
1189 {
1190         g_return_val_if_fail (NM_IS_DEVICE (device), 0);
1191
1192         return NM_DEVICE_GET_PRIVATE (device)->managed;
1193 }
1194
1195 /**
1196  * nm_device_set_managed:
1197  * @device: a #NMDevice
1198  * @managed: %TRUE to make the device managed by NetworkManager.
1199  *
1200  * Enables or disables management of  #NMDevice by NetworkManager.
1201  *
1202  * Since: 1.2
1203  **/
1204 void
1205 nm_device_set_managed (NMDevice *device, gboolean managed)
1206 {
1207         g_return_if_fail (NM_IS_DEVICE (device));
1208
1209         managed = !!managed;
1210
1211         NM_DEVICE_GET_PRIVATE (device)->managed = managed;
1212
1213         _nm_object_set_property (NM_OBJECT (device),
1214                                  NM_DBUS_INTERFACE_DEVICE,
1215                                  "Managed",
1216                                  "b", managed);
1217 }
1218
1219 /**
1220  * nm_device_get_autoconnect:
1221  * @device: a #NMDevice
1222  *
1223  * Whether the #NMDevice can be autoconnected.
1224  *
1225  * Returns: %TRUE if the device is allowed to be autoconnected
1226  **/
1227 gboolean
1228 nm_device_get_autoconnect (NMDevice *device)
1229 {
1230         g_return_val_if_fail (NM_IS_DEVICE (device), FALSE);
1231
1232         return NM_DEVICE_GET_PRIVATE (device)->autoconnect;
1233 }
1234
1235 /**
1236  * nm_device_set_autoconnect:
1237  * @device: a #NMDevice
1238  * @autoconnect: %TRUE to enable autoconnecting
1239  *
1240  * Enables or disables automatic activation of the #NMDevice.
1241  **/
1242 void
1243 nm_device_set_autoconnect (NMDevice *device, gboolean autoconnect)
1244 {
1245         g_return_if_fail (NM_IS_DEVICE (device));
1246
1247         NM_DEVICE_GET_PRIVATE (device)->autoconnect = autoconnect;
1248
1249         _nm_object_set_property (NM_OBJECT (device),
1250                                  NM_DBUS_INTERFACE_DEVICE,
1251                                  "Autoconnect",
1252                                  "b", autoconnect);
1253 }
1254
1255 /**
1256  * nm_device_get_firmware_missing:
1257  * @device: a #NMDevice
1258  *
1259  * Indicates that firmware required for the device's operation is likely
1260  * to be missing.
1261  *
1262  * Returns: %TRUE if firmware required for the device's operation is likely
1263  * to be missing.
1264  **/
1265 gboolean
1266 nm_device_get_firmware_missing (NMDevice *device)
1267 {
1268         g_return_val_if_fail (NM_IS_DEVICE (device), 0);
1269
1270         return NM_DEVICE_GET_PRIVATE (device)->firmware_missing;
1271 }
1272
1273 /**
1274  * nm_device_get_nm_plugin_missing:
1275  * @device: a #NMDevice
1276  *
1277  * Indicates that the NetworkManager plugin for the device is not installed.
1278  *
1279  * Returns: %TRUE if the device plugin not installed.
1280  *
1281  * Since: 1.2
1282  **/
1283 gboolean
1284 nm_device_get_nm_plugin_missing (NMDevice *device)
1285 {
1286         g_return_val_if_fail (NM_IS_DEVICE (device), FALSE);
1287
1288         return NM_DEVICE_GET_PRIVATE (device)->nm_plugin_missing;
1289 }
1290
1291 /**
1292  * nm_device_get_ip4_config:
1293  * @device: a #NMDevice
1294  *
1295  * Gets the current IPv4 #NMIPConfig associated with the #NMDevice.
1296  *
1297  * You can alternatively use nm_active_connection_get_ip4_config(), which also
1298  * works with VPN connections.
1299  *
1300  * Returns: (transfer none): the IPv4 #NMIPConfig, or %NULL if the device is not
1301  * activated.
1302  **/
1303 NMIPConfig *
1304 nm_device_get_ip4_config (NMDevice *device)
1305 {
1306         g_return_val_if_fail (NM_IS_DEVICE (device), NULL);
1307
1308         return NM_DEVICE_GET_PRIVATE (device)->ip4_config;
1309 }
1310
1311 /**
1312  * nm_device_get_dhcp4_config:
1313  * @device: a #NMDevice
1314  *
1315  * Gets the current IPv4 #NMDhcpConfig associated with the #NMDevice.
1316  *
1317  * You can alternatively use nm_active_connection_get_dhcp4_config(), which also
1318  * works with VPN connections.
1319  *
1320  * Returns: (transfer none): the IPv4 #NMDhcpConfig, or %NULL if the device is
1321  * not activated or not using DHCP.
1322  **/
1323 NMDhcpConfig *
1324 nm_device_get_dhcp4_config (NMDevice *device)
1325 {
1326         g_return_val_if_fail (NM_IS_DEVICE (device), NULL);
1327
1328         return NM_DEVICE_GET_PRIVATE (device)->dhcp4_config;
1329 }
1330
1331 /**
1332  * nm_device_get_ip6_config:
1333  * @device: a #NMDevice
1334  *
1335  * Gets the current IPv6 #NMIPConfig associated with the #NMDevice.
1336  *
1337  * You can alternatively use nm_active_connection_get_ip6_config(), which also
1338  * works with VPN connections.
1339  *
1340  * Returns: (transfer none): the IPv6 #NMIPConfig or %NULL if the device is not activated.
1341  **/
1342 NMIPConfig *
1343 nm_device_get_ip6_config (NMDevice *device)
1344 {
1345         g_return_val_if_fail (NM_IS_DEVICE (device), NULL);
1346
1347         return NM_DEVICE_GET_PRIVATE (device)->ip6_config;
1348 }
1349
1350 /**
1351  * nm_device_get_dhcp6_config:
1352  * @device: a #NMDevice
1353  *
1354  * Gets the current IPv6 #NMDhcpConfig associated with the #NMDevice.
1355  *
1356  * You can alternatively use nm_active_connection_get_dhcp6_config(), which also
1357  * works with VPN connections.
1358  *
1359  * Returns: (transfer none): the IPv6 #NMDhcpConfig, or %NULL if the device is
1360  * not activated or not using DHCPv6.
1361  **/
1362 NMDhcpConfig *
1363 nm_device_get_dhcp6_config (NMDevice *device)
1364 {
1365         g_return_val_if_fail (NM_IS_DEVICE (device), NULL);
1366
1367         return NM_DEVICE_GET_PRIVATE (device)->dhcp6_config;
1368 }
1369
1370 /**
1371  * nm_device_get_state:
1372  * @device: a #NMDevice
1373  *
1374  * Gets the current #NMDevice state.
1375  *
1376  * Returns: the current device state
1377  **/
1378 NMDeviceState
1379 nm_device_get_state (NMDevice *device)
1380 {
1381         g_return_val_if_fail (NM_IS_DEVICE (device), NM_DEVICE_STATE_UNKNOWN);
1382
1383         return NM_DEVICE_GET_PRIVATE (device)->state;
1384 }
1385
1386 /**
1387  * nm_device_get_state_reason:
1388  * @device: a #NMDevice
1389  *
1390  * Gets the reason for entering the current #NMDevice state.
1391  *
1392  * Returns: the reason for entering the current device state
1393  **/
1394 NMDeviceStateReason
1395 nm_device_get_state_reason (NMDevice *device)
1396 {
1397         g_return_val_if_fail (NM_IS_DEVICE (device), NM_DEVICE_STATE_REASON_UNKNOWN);
1398
1399         return NM_DEVICE_GET_PRIVATE (device)->reason;
1400 }
1401
1402 /**
1403  * nm_device_get_active_connection:
1404  * @device: a #NMDevice
1405  *
1406  * Gets the #NMActiveConnection object which owns this device during activation.
1407  *
1408  * Returns: (transfer none): the #NMActiveConnection or %NULL if the device is
1409  * not part of an active connection
1410  **/
1411 NMActiveConnection *
1412 nm_device_get_active_connection (NMDevice *device)
1413 {
1414         g_return_val_if_fail (NM_IS_DEVICE (device), NULL);
1415
1416         return NM_DEVICE_GET_PRIVATE (device)->active_connection;
1417 }
1418
1419 /**
1420  * nm_device_get_available_connections:
1421  * @device: a #NMDevice
1422  *
1423  * Gets the #NMRemoteConnections currently known to the daemon that could
1424  * be activated on @device.
1425  *
1426  * Returns: (element-type NMRemoteConnection): the #GPtrArray
1427  * containing #NMRemoteConnections. This is the internal copy used by
1428  * the connection, and must not be modified.
1429  **/
1430 const GPtrArray *
1431 nm_device_get_available_connections (NMDevice *device)
1432 {
1433         g_return_val_if_fail (NM_IS_DEVICE (device), NULL);
1434
1435         return NM_DEVICE_GET_PRIVATE (device)->available_connections;
1436 }
1437
1438 static inline guint8
1439 hex2byte (const char *hex)
1440 {
1441         int a, b;
1442         a = g_ascii_xdigit_value (*hex++);
1443         if (a < 0)
1444                 return -1;
1445         b = g_ascii_xdigit_value (*hex++);
1446         if (b < 0)
1447                 return -1;
1448         return (a << 4) | b;
1449 }
1450
1451 static char *
1452 get_decoded_property (GUdevDevice *device, const char *property)
1453 {
1454         const char *orig, *p;
1455         char *unescaped, *n;
1456         guint len;
1457
1458         p = orig = g_udev_device_get_property (device, property);
1459         if (!orig)
1460                 return NULL;
1461
1462         len = strlen (orig);
1463         n = unescaped = g_malloc0 (len + 1);
1464         while (*p) {
1465                 if ((len >= 4) && (*p == '\\') && (*(p+1) == 'x')) {
1466                         *n++ = (char) hex2byte (p + 2);
1467                         p += 4;
1468                         len -= 4;
1469                 } else {
1470                         *n++ = *p++;
1471                         len--;
1472                 }
1473         }
1474
1475         return unescaped;
1476 }
1477
1478 static gboolean
1479 ensure_udev_client (NMDevice *device)
1480 {
1481         static const char *const subsys[3] = { "net", "tty", NULL };
1482         NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device);
1483
1484         if (!priv->client)
1485                 priv->client = g_udev_client_new (subsys);
1486
1487         return priv->client != NULL;
1488 }
1489
1490 static char *
1491 _get_udev_property (NMDevice *device,
1492                     const char *enc_prop,  /* ID_XXX_ENC */
1493                     const char *db_prop)   /* ID_XXX_FROM_DATABASE */
1494 {
1495         NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device);
1496         GUdevDevice *udev_device = NULL, *tmpdev, *olddev;
1497         const char *ifname;
1498         guint32 count = 0;
1499         char *enc_value = NULL, *db_value = NULL;
1500
1501         if (!ensure_udev_client (device))
1502                 return NULL;
1503
1504         ifname = nm_device_get_iface (device);
1505         if (!ifname)
1506                 return NULL;
1507
1508         udev_device = g_udev_client_query_by_subsystem_and_name (priv->client, "net", ifname);
1509         if (!udev_device)
1510                 udev_device = g_udev_client_query_by_subsystem_and_name (priv->client, "tty", ifname);
1511         if (!udev_device)
1512                 return NULL;
1513
1514         /* Walk up the chain of the device and its parents a few steps to grab
1515          * vendor and device ID information off it.
1516          */
1517
1518         /* Ref the device again because we have to unref it each iteration,
1519          * as g_udev_device_get_parent() returns a ref-ed object.
1520          */
1521         tmpdev = g_object_ref (udev_device);
1522         while ((count++ < 3) && tmpdev && !enc_value) {
1523                 if (!enc_value)
1524                         enc_value = get_decoded_property (tmpdev, enc_prop);
1525                 if (!db_value)
1526                         db_value = g_strdup (g_udev_device_get_property (tmpdev, db_prop));
1527
1528                 olddev = tmpdev;
1529                 tmpdev = g_udev_device_get_parent (tmpdev);
1530                 g_object_unref (olddev);
1531         }
1532
1533         /* Unref the last device if we found what we needed before running out
1534          * of parents.
1535          */
1536         if (tmpdev)
1537                 g_object_unref (tmpdev);
1538
1539         /* Balance the initial g_udev_client_query_by_subsystem_and_name() */
1540         g_object_unref (udev_device);
1541
1542         /* Prefer the encoded value which comes directly from the device
1543          * over the hwdata database value.
1544          */
1545         if (enc_value) {
1546                 g_free (db_value);
1547                 return enc_value;
1548         }
1549
1550         return db_value;
1551 }
1552
1553 /**
1554  * nm_device_get_product:
1555  * @device: a #NMDevice
1556  *
1557  * Gets the product string of the #NMDevice.
1558  *
1559  * Returns: the product name of the device. This is the internal string used by the
1560  * device, and must not be modified.
1561  **/
1562 const char *
1563 nm_device_get_product (NMDevice *device)
1564 {
1565         NMDevicePrivate *priv;
1566
1567         g_return_val_if_fail (NM_IS_DEVICE (device), NULL);
1568
1569         priv = NM_DEVICE_GET_PRIVATE (device);
1570         if (!priv->product)
1571                 priv->product = _get_udev_property (device, "ID_MODEL_ENC", "ID_MODEL_FROM_DATABASE");
1572
1573         /* Sometimes ID_PRODUCT_FROM_DATABASE is used? */
1574         if (!priv->product)
1575                 priv->product = _get_udev_property (device, "ID_MODEL_ENC", "ID_PRODUCT_FROM_DATABASE");
1576
1577         if (!priv->product)
1578                 priv->product = g_strdup ("");
1579
1580         return priv->product;
1581 }
1582
1583 /**
1584  * nm_device_get_vendor:
1585  * @device: a #NMDevice
1586  *
1587  * Gets the vendor string of the #NMDevice.
1588  *
1589  * Returns: the vendor name of the device. This is the internal string used by the
1590  * device, and must not be modified.
1591  **/
1592 const char *
1593 nm_device_get_vendor (NMDevice *device)
1594 {
1595         NMDevicePrivate *priv;
1596
1597         g_return_val_if_fail (NM_IS_DEVICE (device), NULL);
1598
1599         priv = NM_DEVICE_GET_PRIVATE (device);
1600
1601         if (!priv->vendor)
1602                 priv->vendor = _get_udev_property (device, "ID_VENDOR_ENC", "ID_VENDOR_FROM_DATABASE");
1603
1604         if (!priv->vendor)
1605                 priv->vendor = g_strdup ("");
1606
1607         return priv->vendor;
1608 }
1609
1610 static const char * const ignored_words[] = {
1611         "Semiconductor",
1612         "Components",
1613         "Corporation",
1614         "Communications",
1615         "Company",
1616         "Corp.",
1617         "Corp",
1618         "Co.",
1619         "Inc.",
1620         "Inc",
1621         "Incorporated",
1622         "Ltd.",
1623         "Limited.",
1624         "Intel?",
1625         "chipset",
1626         "adapter",
1627         "[hex]",
1628         "NDIS",
1629         "Module",
1630         NULL
1631 };
1632
1633 static const char * const ignored_phrases[] = {
1634         "Multiprotocol MAC/baseband processor",
1635         "Wireless LAN Controller",
1636         "Wireless LAN Adapter",
1637         "Wireless Adapter",
1638         "Network Connection",
1639         "Wireless Cardbus Adapter",
1640         "Wireless CardBus Adapter",
1641         "54 Mbps Wireless PC Card",
1642         "Wireless PC Card",
1643         "Wireless PC",
1644         "PC Card with XJACK(r) Antenna",
1645         "Wireless cardbus",
1646         "Wireless LAN PC Card",
1647         "Technology Group Ltd.",
1648         "Communication S.p.A.",
1649         "Business Mobile Networks BV",
1650         "Mobile Broadband Minicard Composite Device",
1651         "Mobile Communications AB",
1652         "(PC-Suite Mode)",
1653         NULL
1654 };
1655
1656 static char *
1657 fixup_desc_string (const char *desc)
1658 {
1659         char *p, *temp;
1660         char **words, **item;
1661         GString *str;
1662         int i;
1663
1664         if (!desc)
1665                 return NULL;
1666
1667         p = temp = g_strdup (desc);
1668         while (*p) {
1669                 if (*p == '_' || *p == ',')
1670                         *p = ' ';
1671                 p++;
1672         }
1673
1674         /* Attempt to shorten ID by ignoring certain phrases */
1675         for (i = 0; ignored_phrases[i]; i++) {
1676                 p = strstr (temp, ignored_phrases[i]);
1677                 if (p) {
1678                         guint32 ignored_len = strlen (ignored_phrases[i]);
1679
1680                         memmove (p, p + ignored_len, strlen (p + ignored_len) + 1); /* +1 for the \0 */
1681                 }
1682         }
1683
1684         /* Attempt to shorten ID by ignoring certain individual words */
1685         words = g_strsplit (temp, " ", 0);
1686         str = g_string_new_len (NULL, strlen (temp));
1687         g_free (temp);
1688
1689         for (item = words; *item; item++) {
1690                 gboolean ignore = FALSE;
1691
1692                 if (**item == '\0')
1693                         continue;
1694
1695                 for (i = 0; ignored_words[i]; i++) {
1696                         if (!strcmp (*item, ignored_words[i])) {
1697                                 ignore = TRUE;
1698                                 break;
1699                         }
1700                 }
1701
1702                 if (!ignore) {
1703                         if (str->len)
1704                                 g_string_append_c (str, ' ');
1705                         g_string_append (str, *item);
1706                 }
1707         }
1708         g_strfreev (words);
1709
1710         temp = str->str;
1711         g_string_free (str, FALSE);
1712
1713         return temp;
1714 }
1715
1716 static void
1717 get_description (NMDevice *device)
1718 {
1719         NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device);
1720         const char *dev_product;
1721         const char *dev_vendor;
1722         char *pdown;
1723         char *vdown;
1724         GString *str;
1725
1726         dev_product = nm_device_get_product (device);
1727         priv->short_product = fixup_desc_string (dev_product);
1728
1729         dev_vendor = nm_device_get_vendor (device);
1730         priv->short_vendor = fixup_desc_string (dev_vendor);
1731
1732         if (!dev_product || !dev_vendor) {
1733                 priv->description = g_strdup (nm_device_get_iface (device));
1734                 return;
1735         }
1736
1737         str = g_string_new_len (NULL, strlen (priv->short_vendor) + strlen (priv->short_product) + 1);
1738
1739         /* Another quick hack; if all of the fixed up vendor string
1740          * is found in product, ignore the vendor.
1741          */
1742         pdown = g_ascii_strdown (priv->short_product, -1);
1743         vdown = g_ascii_strdown (priv->short_vendor, -1);
1744         if (!strstr (pdown, vdown)) {
1745                 g_string_append (str, priv->short_vendor);
1746                 g_string_append_c (str, ' ');
1747         }
1748         g_free (pdown);
1749         g_free (vdown);
1750
1751         g_string_append (str, priv->short_product);
1752
1753         priv->description = g_string_free (str, FALSE);
1754 }
1755
1756 static const char *
1757 get_short_vendor (NMDevice *device)
1758 {
1759         NMDevicePrivate *priv;
1760
1761         g_return_val_if_fail (NM_IS_DEVICE (device), NULL);
1762
1763         priv = NM_DEVICE_GET_PRIVATE (device);
1764
1765         if (!priv->description)
1766                 get_description (device);
1767
1768         return priv->short_vendor;
1769 }
1770
1771 /**
1772  * nm_device_get_description:
1773  * @device: an #NMDevice
1774  *
1775  * Gets a description of @device, based on its vendor and product names.
1776  *
1777  * Returns: a description of @device. If either the vendor or the
1778  *   product name is unknown, this returns the interface name.
1779  */
1780 const char *
1781 nm_device_get_description (NMDevice *device)
1782 {
1783         NMDevicePrivate *priv;
1784
1785         g_return_val_if_fail (NM_IS_DEVICE (device), NULL);
1786
1787         priv = NM_DEVICE_GET_PRIVATE (device);
1788
1789         if (!priv->description)
1790                 get_description (device);
1791
1792         return priv->description;
1793 }
1794
1795 static const char *
1796 get_type_name (NMDevice *device)
1797 {
1798         switch (nm_device_get_device_type (device)) {
1799         case NM_DEVICE_TYPE_ETHERNET:
1800                 return _("Ethernet");
1801         case NM_DEVICE_TYPE_WIFI:
1802                 return _("Wi-Fi");
1803         case NM_DEVICE_TYPE_BT:
1804                 return _("Bluetooth");
1805         case NM_DEVICE_TYPE_OLPC_MESH:
1806                 return _("OLPC Mesh");
1807         case NM_DEVICE_TYPE_WIMAX:
1808                 return _("WiMAX");
1809         case NM_DEVICE_TYPE_MODEM:
1810                 return _("Mobile Broadband");
1811         case NM_DEVICE_TYPE_INFINIBAND:
1812                 return _("InfiniBand");
1813         case NM_DEVICE_TYPE_BOND:
1814                 return _("Bond");
1815         case NM_DEVICE_TYPE_TEAM:
1816                 return _("Team");
1817         case NM_DEVICE_TYPE_BRIDGE:
1818                 return _("Bridge");
1819         case NM_DEVICE_TYPE_VLAN:
1820                 return _("VLAN");
1821         case NM_DEVICE_TYPE_ADSL:
1822                 return _("ADSL");
1823         case NM_DEVICE_TYPE_MACVLAN:
1824                 return _("MACVLAN");
1825         case NM_DEVICE_TYPE_VXLAN:
1826                 return _("VXLAN");
1827         case NM_DEVICE_TYPE_IP_TUNNEL:
1828                 return _("IPTunnel");
1829         case NM_DEVICE_TYPE_TUN:
1830                 return _("Tun");
1831         case NM_DEVICE_TYPE_VETH:
1832                 return _("Veth");
1833         case NM_DEVICE_TYPE_GENERIC:
1834         case NM_DEVICE_TYPE_UNUSED1:
1835         case NM_DEVICE_TYPE_UNUSED2:
1836         case NM_DEVICE_TYPE_UNKNOWN:
1837                 break;
1838         }
1839         return _("Unknown");
1840 }
1841
1842 static char *
1843 get_device_type_name_with_iface (NMDevice *device)
1844 {
1845         const char *type_name = get_type_name (device);
1846
1847         switch (nm_device_get_device_type (device)) {
1848         case NM_DEVICE_TYPE_BOND:
1849         case NM_DEVICE_TYPE_TEAM:
1850         case NM_DEVICE_TYPE_BRIDGE:
1851         case NM_DEVICE_TYPE_VLAN:
1852                 return g_strdup_printf ("%s (%s)", type_name, nm_device_get_iface (device));
1853         default:
1854                 return g_strdup (type_name);
1855         }
1856 }
1857
1858 static char *
1859 get_device_generic_type_name_with_iface (NMDevice *device)
1860 {
1861         switch (nm_device_get_device_type (device)) {
1862         case NM_DEVICE_TYPE_ETHERNET:
1863         case NM_DEVICE_TYPE_INFINIBAND:
1864                 return g_strdup (_("Wired"));
1865         default:
1866                 return get_device_type_name_with_iface (device);
1867         }
1868 }
1869
1870 static const char *
1871 get_bus_name (NMDevice *device)
1872 {
1873         NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device);
1874         GUdevDevice *udevice;
1875         const char *ifname, *bus;
1876
1877         if (priv->bus_name)
1878                 goto out;
1879
1880         if (!ensure_udev_client (device))
1881                 return NULL;
1882
1883         ifname = nm_device_get_iface (device);
1884         if (!ifname)
1885                 return NULL;
1886
1887         udevice = g_udev_client_query_by_subsystem_and_name (priv->client, "net", ifname);
1888         if (!udevice)
1889                 udevice = g_udev_client_query_by_subsystem_and_name (priv->client, "tty", ifname);
1890         if (!udevice)
1891                 return NULL;
1892
1893         bus = g_udev_device_get_property (udevice, "ID_BUS");
1894         if (!g_strcmp0 (bus, "pci"))
1895                 priv->bus_name = g_strdup (_("PCI"));
1896         else if (!g_strcmp0 (bus, "usb"))
1897                 priv->bus_name = g_strdup (_("USB"));
1898         else {
1899                 /* Use "" instead of NULL so we can tell later that we've
1900                  * already tried.
1901                  */
1902                 priv->bus_name = g_strdup ("");
1903         }
1904
1905 out:
1906         if (*priv->bus_name)
1907                 return priv->bus_name;
1908         else
1909                 return NULL;
1910 }
1911
1912 static gboolean
1913 find_duplicates (char     **names,
1914                  gboolean  *duplicates,
1915                  int        num_devices)
1916 {
1917         int i, j;
1918         gboolean found_any = FALSE;
1919
1920         memset (duplicates, 0, num_devices * sizeof (gboolean));
1921         for (i = 0; i < num_devices; i++) {
1922                 if (duplicates[i])
1923                         continue;
1924                 for (j = i + 1; j < num_devices; j++) {
1925                         if (duplicates[j])
1926                                 continue;
1927                         if (!strcmp (names[i], names[j]))
1928                                 duplicates[i] = duplicates[j] = found_any = TRUE;
1929                 }
1930         }
1931
1932         return found_any;
1933 }
1934
1935 /**
1936  * nm_device_disambiguate_names:
1937  * @devices: (array length=num_devices): an array of #NMDevice
1938  * @num_devices: length of @devices
1939  *
1940  * Generates a list of short-ish unique presentation names for the
1941  * devices in @devices.
1942  *
1943  * Returns: (transfer full) (array zero-terminated=1): the device names
1944  */
1945 char **
1946 nm_device_disambiguate_names (NMDevice **devices,
1947                               int        num_devices)
1948 {
1949         char **names;
1950         gboolean *duplicates;
1951         int i;
1952
1953         names = g_new (char *, num_devices + 1);
1954         duplicates = g_new (gboolean, num_devices);
1955
1956         /* Generic device name */
1957         for (i = 0; i < num_devices; i++)
1958                 names[i] = get_device_generic_type_name_with_iface (devices[i]);
1959         if (!find_duplicates (names, duplicates, num_devices))
1960                 goto done;
1961
1962         /* Try specific names (eg, "Ethernet" and "InfiniBand" rather
1963          * than "Wired")
1964          */
1965         for (i = 0; i < num_devices; i++) {
1966                 if (duplicates[i]) {
1967                         g_free (names[i]);
1968                         names[i] = get_device_type_name_with_iface (devices[i]);
1969                 }
1970         }
1971         if (!find_duplicates (names, duplicates, num_devices))
1972                 goto done;
1973
1974         /* Try prefixing bus name (eg, "PCI Ethernet" vs "USB Ethernet") */
1975         for (i = 0; i < num_devices; i++) {
1976                 if (duplicates[i]) {
1977                         const char *bus = get_bus_name (devices[i]);
1978                         char *name;
1979
1980                         if (!bus)
1981                                 continue;
1982
1983                         g_free (names[i]);
1984                         name = get_device_type_name_with_iface (devices[i]);
1985                         /* Translators: the first %s is a bus name (eg, "USB") or
1986                          * product name, the second is a device type (eg,
1987                          * "Ethernet"). You can change this to something like
1988                          * "%2$s (%1$s)" if there's no grammatical way to combine
1989                          * the strings otherwise.
1990                          */
1991                         names[i] = g_strdup_printf (C_("long device name", "%s %s"),
1992                                                     bus, name);
1993                         g_free (name);
1994                 }
1995         }
1996         if (!find_duplicates (names, duplicates, num_devices))
1997                 goto done;
1998
1999         /* Try prefixing vendor name */
2000         for (i = 0; i < num_devices; i++) {
2001                 if (duplicates[i]) {
2002                         const char *vendor = get_short_vendor (devices[i]);
2003                         char *name;
2004
2005                         if (!vendor)
2006                                 continue;
2007
2008                         g_free (names[i]);
2009                         name = get_device_type_name_with_iface (devices[i]);
2010                         names[i] = g_strdup_printf (C_("long device name", "%s %s"),
2011                                                     vendor,
2012                                                     get_type_name (devices[i]));
2013                         g_free (name);
2014                 }
2015         }
2016         if (!find_duplicates (names, duplicates, num_devices))
2017                 goto done;
2018
2019         /* If dealing with Bluetooth devices, try to distinguish them by
2020          * device name.
2021          */
2022         for (i = 0; i < num_devices; i++) {
2023                 if (duplicates[i] && NM_IS_DEVICE_BT (devices[i])) {
2024                         const char *devname = nm_device_bt_get_name (NM_DEVICE_BT (devices[i]));
2025
2026                         if (!devname)
2027                                 continue;
2028
2029                         g_free (names[i]);
2030                         names[i] = g_strdup_printf ("%s (%s)",
2031                                                     get_device_type_name_with_iface (devices[i]),
2032                                                     devname);
2033                 }
2034         }
2035         if (!find_duplicates (names, duplicates, num_devices))
2036                 goto done;
2037
2038         /* We have multiple identical network cards, so we have to differentiate
2039          * them by interface name.
2040          */
2041         for (i = 0; i < num_devices; i++) {
2042                 if (duplicates[i]) {
2043                         const char *interface = nm_device_get_iface (devices[i]);
2044
2045                         if (!interface)
2046                                 continue;
2047
2048                         g_free (names[i]);
2049                         names[i] = g_strdup_printf ("%s (%s)",
2050                                                     get_type_name (devices[i]),
2051                                                     interface);
2052                 }
2053         }
2054
2055 done:
2056         g_free (duplicates);
2057         names[num_devices] = NULL;
2058         return names;
2059 }
2060
2061 /**
2062  * nm_device_get_physical_port_id:
2063  * @device: a #NMDevice
2064  *
2065  * Gets the physical port ID of the #NMDevice. If non-%NULL, this is
2066  * an opaque string that can be used to recognize when
2067  * seemingly-unrelated #NMDevices are actually just different virtual
2068  * ports on a single physical port. (Eg, NPAR / SR-IOV.)
2069  *
2070  * Returns: the physical port ID of the device, or %NULL if the port
2071  *   ID is unknown. This is the internal string used by the device and
2072  *   must not be modified.
2073  **/
2074 const char *
2075 nm_device_get_physical_port_id (NMDevice *device)
2076 {
2077         NMDevicePrivate *priv;
2078
2079         g_return_val_if_fail (NM_IS_DEVICE (device), NULL);
2080
2081         priv = NM_DEVICE_GET_PRIVATE (device);
2082
2083         if (priv->physical_port_id && *priv->physical_port_id)
2084                 return priv->physical_port_id;
2085         else
2086                 return NULL;
2087 }
2088
2089 /**
2090  * nm_device_get_mtu:
2091  * @device: a #NMDevice
2092  *
2093  * Gets the  MTU of the #NMDevice.
2094  *
2095  * Returns: the MTU of the device.
2096  **/
2097 guint32
2098 nm_device_get_mtu (NMDevice *device)
2099 {
2100         g_return_val_if_fail (NM_IS_DEVICE (device), 0);
2101
2102         return NM_DEVICE_GET_PRIVATE (device)->mtu;
2103 }
2104
2105 /**
2106  * nm_device_get_metered:
2107  * @device: a #NMDevice
2108  *
2109  * Gets the metered setting of a #NMDevice.
2110  *
2111  * Returns: the metered setting.
2112  *
2113  * Since: 1.2
2114  **/
2115 NMMetered
2116 nm_device_get_metered (NMDevice *device)
2117 {
2118         g_return_val_if_fail (NM_IS_DEVICE (device), NM_METERED_UNKNOWN);
2119
2120         return NM_DEVICE_GET_PRIVATE (device)->metered;
2121 }
2122
2123 NM_BACKPORT_SYMBOL (libnm_1_0_6, NMMetered, nm_device_get_metered, (NMDevice *device), (device));
2124
2125 /**
2126  * nm_device_get_lldp_neighbors:
2127  * @device: a #NMDevice
2128  *
2129  * Gets the list of neighbors discovered through LLDP.
2130  *
2131  * Returns: (element-type NMLldpNeighbor) (transfer none): the #GPtrArray
2132  * containing #NMLldpNeighbor<!-- -->s. This is the internal copy used by the
2133  * device and must not be modified. The library never modifies the returned
2134  * array and thus it is safe for callers to reference and keep using it.
2135  *
2136  * Since: 1.2
2137  **/
2138 GPtrArray *
2139 nm_device_get_lldp_neighbors (NMDevice *device)
2140 {
2141        g_return_val_if_fail (NM_IS_DEVICE (device), NULL);
2142
2143        return NM_DEVICE_GET_PRIVATE (device)->lldp_neighbors;
2144 }
2145
2146 /**
2147  * nm_device_is_real:
2148  * @device: a #NMDevice
2149  *
2150  * Returns: %TRUE if the device exists, or %FALSE if it is a placeholder device
2151  * that could be automatically created by NetworkManager if one of its
2152  * #NMDevice:available-connections was activated.
2153  *
2154  * Since: 1.2
2155  **/
2156 gboolean
2157 nm_device_is_real (NMDevice *device)
2158 {
2159         g_return_val_if_fail (NM_IS_DEVICE (device), FALSE);
2160
2161         return NM_DEVICE_GET_PRIVATE (device)->real;
2162 }
2163
2164 /**
2165  * nm_device_is_software:
2166  * @device: a #NMDevice
2167  *
2168  * Whether the device is a software device.
2169  *
2170  * Returns: %TRUE if @device is a software device, %FALSE if it is a hardware device.
2171  **/
2172 gboolean
2173 nm_device_is_software (NMDevice *device)
2174 {
2175         g_return_val_if_fail (NM_IS_DEVICE (device), FALSE);
2176
2177         return !!(NM_DEVICE_GET_PRIVATE (device)->capabilities & NM_DEVICE_CAP_IS_SOFTWARE);
2178 }
2179
2180 /**
2181  * nm_device_reapply:
2182  * @device: a #NMDevice
2183  * @connection: the #NMConnection to replace the applied settings with or %NULL to reuse existing
2184  * @version_id: zero or the expected version id of the applied connection. If specified
2185  *   and the version id mismatches, the call fails without modification. This allows to
2186  *   catch concurrent accesses.
2187  * @flags: always set this to zero
2188  * @cancellable: a #GCancellable, or %NULL
2189  * @error: location for a #GError, or %NULL
2190  *
2191  * Attempts to update device with changes to the currently active connection
2192  * made since it was last applied.
2193  *
2194  * Returns: %TRUE on success, %FALSE on error, in which case @error will be set.
2195  *
2196  * Since: 1.2
2197  **/
2198 gboolean
2199 nm_device_reapply (NMDevice *device,
2200                    NMConnection *connection,
2201                    guint64 version_id,
2202                    guint32 flags,
2203                    GCancellable *cancellable,
2204                    GError **error)
2205 {
2206         GVariant *dict = NULL;
2207         gboolean ret;
2208
2209         g_return_val_if_fail (NM_IS_DEVICE (device), FALSE);
2210
2211         if (connection)
2212                 dict = nm_connection_to_dbus (connection, NM_CONNECTION_SERIALIZE_ALL);
2213         if (!dict)
2214                 dict = g_variant_new_array (G_VARIANT_TYPE ("{sa{sv}}"), NULL, 0);
2215
2216
2217         ret = nmdbus_device_call_reapply_sync (NM_DEVICE_GET_PRIVATE (device)->proxy,
2218                                                dict, version_id, flags, cancellable, error);
2219         if (error && *error)
2220                 g_dbus_error_strip_remote_error (*error);
2221         return ret;
2222 }
2223
2224 static void
2225 device_reapply_cb (GObject *proxy,
2226                    GAsyncResult *result,
2227                    gpointer user_data)
2228 {
2229         GSimpleAsyncResult *simple = user_data;
2230         GError *error = NULL;
2231
2232         if (nmdbus_device_call_reapply_finish (NMDBUS_DEVICE (proxy), result, &error))
2233                 g_simple_async_result_set_op_res_gboolean (simple, TRUE);
2234         else {
2235                 g_dbus_error_strip_remote_error (error);
2236                 g_simple_async_result_take_error (simple, error);
2237         }
2238
2239         g_simple_async_result_complete (simple);
2240         g_object_unref (simple);
2241 }
2242
2243 /**
2244  * nm_device_reapply_async:
2245  * @device: a #NMDevice
2246  * @connection: the #NMConnection to replace the applied settings with or %NULL to reuse existing
2247  * @version_id: zero or the expected version id of the applied connection. If specified
2248  *   and the version id mismatches, the call fails without modification. This allows to
2249  *   catch concurrent accesses.
2250  * @flags: always set this to zero
2251  * @cancellable: a #GCancellable, or %NULL
2252  * @callback: callback to be called when the reapply operation completes
2253  * @user_data: caller-specific data passed to @callback
2254  *
2255  * Asynchronously begins an attempt to update device with changes to the
2256  * currently active connection made since it was last applied.
2257  *
2258  * Since: 1.2
2259  **/
2260 void
2261 nm_device_reapply_async (NMDevice *device,
2262                          NMConnection *connection,
2263                          guint64 version_id,
2264                          guint32 flags,
2265                          GCancellable *cancellable,
2266                          GAsyncReadyCallback callback,
2267                          gpointer user_data)
2268 {
2269         GVariant *dict = NULL;
2270         GSimpleAsyncResult *simple;
2271
2272         g_return_if_fail (NM_IS_DEVICE (device));
2273
2274         if (connection)
2275                 dict = nm_connection_to_dbus (connection, NM_CONNECTION_SERIALIZE_ALL);
2276         if (!dict)
2277                 dict = g_variant_new_array (G_VARIANT_TYPE ("{sa{sv}}"), NULL, 0);
2278
2279         simple = g_simple_async_result_new (G_OBJECT (device), callback, user_data,
2280                                             nm_device_reapply_async);
2281
2282         nmdbus_device_call_reapply (NM_DEVICE_GET_PRIVATE (device)->proxy,
2283                                     dict, version_id, flags, cancellable,
2284                                     device_reapply_cb, simple);
2285 }
2286
2287 /**
2288  * nm_device_reapply_finish:
2289  * @device: a #NMDevice
2290  * @result: the result passed to the #GAsyncReadyCallback
2291  * @error: location for a #GError, or %NULL
2292  *
2293  * Gets the result of a call to nm_device_reapply_async().
2294  *
2295  * Returns: %TRUE on success, %FALSE on error, in which case @error
2296  * will be set.
2297  *
2298  * Since: 1.2
2299  **/
2300 gboolean
2301 nm_device_reapply_finish (NMDevice *device,
2302                           GAsyncResult *result,
2303                           GError **error)
2304 {
2305         GSimpleAsyncResult *simple;
2306
2307         g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (device), nm_device_reapply_async), FALSE);
2308
2309         simple = G_SIMPLE_ASYNC_RESULT (result);
2310         if (g_simple_async_result_propagate_error (simple, error))
2311                 return FALSE;
2312         else
2313                 return g_simple_async_result_get_op_res_gboolean (simple);
2314 }
2315
2316 /*****************************************************************************/
2317
2318 /**
2319  * nm_device_get_applied_connection:
2320  * @device: a #NMDevice
2321  * @flags: the flags argument. Currently this value must always be zero.
2322  * @version_id: (out): (allow-none): returns the current version id of
2323  *   the applied connection
2324  * @cancellable: a #GCancellable, or %NULL
2325  * @error: location for a #GError, or %NULL
2326  *
2327  * Fetch the currently applied connection on the device.
2328  *
2329  * Returns: (transfer full): a %NMConnection with the currently applied settings
2330  *   or %NULL on error.
2331  *
2332  * The connection is as received from D-Bus and might not validate according
2333  * to nm_connection_verify().
2334  *
2335  * Since: 1.2
2336  **/
2337 NMConnection *
2338 nm_device_get_applied_connection (NMDevice *device,
2339                                   guint32 flags,
2340                                   guint64 *version_id,
2341                                   GCancellable *cancellable,
2342                                   GError **error)
2343 {
2344         gs_unref_variant GVariant *dict = NULL;
2345         guint64 my_version_id;
2346         gboolean success;
2347         NMConnection *connection;
2348
2349         g_return_val_if_fail (NM_IS_DEVICE (device), NULL);
2350         g_return_val_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable), NULL);
2351         g_return_val_if_fail (!error || !*error, NULL);
2352
2353         success = nmdbus_device_call_get_applied_connection_sync (NM_DEVICE_GET_PRIVATE (device)->proxy,
2354                                                                   flags, &dict, &my_version_id, cancellable, error);
2355         if (!success) {
2356                 if (error && *error)
2357                         g_dbus_error_strip_remote_error (*error);
2358                 return NULL;
2359         }
2360
2361         connection = _nm_simple_connection_new_from_dbus (dict, NM_SETTING_PARSE_FLAGS_BEST_EFFORT, error);
2362         if (!connection)
2363                 return NULL;
2364
2365         NM_SET_OUT (version_id, my_version_id);
2366         return connection;
2367 }
2368
2369 typedef struct {
2370         NMConnection *connection;
2371         guint64 version_id;
2372 } GetAppliedConnectionData;
2373
2374 static void
2375 device_get_applied_connection_data_free (gpointer user_data)
2376 {
2377         GetAppliedConnectionData *data = user_data;
2378
2379         g_return_if_fail (data);
2380
2381         g_object_unref (data->connection);
2382         g_slice_free (GetAppliedConnectionData, data);
2383 }
2384
2385 static void
2386 device_get_applied_connection_cb (GObject *proxy,
2387                                   GAsyncResult *result,
2388                                   gpointer user_data)
2389 {
2390         gs_unref_object GSimpleAsyncResult *simple = user_data;
2391         gs_unref_variant GVariant *dict = NULL;
2392         guint64 my_version_id;
2393         GError *error = NULL;
2394         NMConnection *connection;
2395         GetAppliedConnectionData *data;
2396
2397         if (!nmdbus_device_call_get_applied_connection_finish (NMDBUS_DEVICE (proxy), &dict, &my_version_id, result, &error)) {
2398                 g_dbus_error_strip_remote_error (error);
2399                 g_simple_async_result_take_error (simple, error);
2400                 goto out;
2401         }
2402
2403         connection = _nm_simple_connection_new_from_dbus (dict, NM_SETTING_PARSE_FLAGS_BEST_EFFORT, &error);
2404         if (!connection) {
2405                 g_simple_async_result_take_error (simple, error);
2406                 goto out;
2407         }
2408
2409         data = g_slice_new (GetAppliedConnectionData);
2410         data->connection = connection;
2411         data->version_id = my_version_id;
2412         g_simple_async_result_set_op_res_gpointer (simple, data, device_get_applied_connection_data_free);
2413
2414 out:
2415         g_simple_async_result_complete (simple);
2416 }
2417
2418 /**
2419  * nm_device_get_applied_connection_async:
2420  * @device: a #NMDevice
2421  * @flags: the flags argument. Currently this value must always be zero.
2422  * @cancellable: a #GCancellable, or %NULL
2423  * @callback: callback to be called when the reapply operation completes
2424  * @user_data: caller-specific data passed to @callback
2425  *
2426  * Asynchronously begins an get the a currently applied connection.
2427  *
2428  * Since: 1.2
2429  **/
2430 void
2431 nm_device_get_applied_connection_async  (NMDevice *device,
2432                                          guint32 flags,
2433                                          GCancellable *cancellable,
2434                                          GAsyncReadyCallback callback,
2435                                          gpointer user_data)
2436 {
2437         GSimpleAsyncResult *simple;
2438
2439         g_return_if_fail (NM_IS_DEVICE (device));
2440         g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
2441
2442         simple = g_simple_async_result_new (G_OBJECT (device), callback, user_data,
2443                                             nm_device_get_applied_connection_async);
2444
2445         nmdbus_device_call_get_applied_connection (NM_DEVICE_GET_PRIVATE (device)->proxy,
2446                                                    flags, cancellable,
2447                                                    device_get_applied_connection_cb, simple);
2448 }
2449
2450 /**
2451  * nm_device_get_applied_connection_finish:
2452  * @device: a #NMDevice
2453  * @result: the result passed to the #GAsyncReadyCallback
2454  * @version_id: (out): (allow-none): the current version id of the applied
2455  *   connection.
2456  * @error: location for a #GError, or %NULL
2457  *
2458  * Gets the result of a call to nm_device_get_applied_connection_async().
2459  *
2460  * Returns: (transfer full): a currently applied %NMConnection or %NULL in case
2461  *   of error.
2462  *
2463  * The connection is as received from D-Bus and might not validate according
2464  * to nm_connection_verify().
2465  *
2466  * Since: 1.2
2467  **/
2468 NMConnection *
2469 nm_device_get_applied_connection_finish (NMDevice *device,
2470                                          GAsyncResult *result,
2471                                          guint64 *version_id,
2472                                          GError **error)
2473 {
2474         GSimpleAsyncResult *simple;
2475         GetAppliedConnectionData *data;
2476
2477         g_return_val_if_fail (NM_IS_DEVICE (device), NULL);
2478         g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (device), nm_device_get_applied_connection_async), NULL);
2479         g_return_val_if_fail (!error || !*error, NULL);
2480
2481         simple = G_SIMPLE_ASYNC_RESULT (result);
2482         if (g_simple_async_result_propagate_error (simple, error))
2483                 return NULL;
2484
2485         data = g_simple_async_result_get_op_res_gpointer (simple);
2486         g_return_val_if_fail (data, NULL);
2487         g_return_val_if_fail (NM_IS_CONNECTION (data->connection), NULL);
2488
2489         NM_SET_OUT (version_id, data->version_id);
2490         return g_object_ref (data->connection);
2491 }
2492
2493 /*****************************************************************************/
2494
2495 /**
2496  * nm_device_disconnect:
2497  * @device: a #NMDevice
2498  * @cancellable: a #GCancellable, or %NULL
2499  * @error: location for a #GError, or %NULL
2500  *
2501  * Disconnects the device if currently connected, and prevents the device from
2502  * automatically connecting to networks until the next manual network connection
2503  * request.
2504  *
2505  * Returns: %TRUE on success, %FALSE on error, in which case @error will be set.
2506  **/
2507 gboolean
2508 nm_device_disconnect (NMDevice *device,
2509                       GCancellable *cancellable,
2510                       GError **error)
2511 {
2512         gboolean ret;
2513
2514         g_return_val_if_fail (NM_IS_DEVICE (device), FALSE);
2515
2516         ret = nmdbus_device_call_disconnect_sync (NM_DEVICE_GET_PRIVATE (device)->proxy,
2517                                                   cancellable, error);
2518         if (error && *error)
2519                 g_dbus_error_strip_remote_error (*error);
2520         return ret;
2521 }
2522
2523 static void
2524 device_disconnect_cb (GObject *proxy,
2525                       GAsyncResult *result,
2526                       gpointer user_data)
2527 {
2528         GSimpleAsyncResult *simple = user_data;
2529         GError *error = NULL;
2530
2531         if (nmdbus_device_call_disconnect_finish (NMDBUS_DEVICE (proxy), result, &error))
2532                 g_simple_async_result_set_op_res_gboolean (simple, TRUE);
2533         else {
2534                 g_dbus_error_strip_remote_error (error);
2535                 g_simple_async_result_take_error (simple, error);
2536         }
2537
2538         g_simple_async_result_complete (simple);
2539         g_object_unref (simple);
2540 }
2541
2542 /**
2543  * nm_device_disconnect_async:
2544  * @device: a #NMDevice
2545  * @cancellable: a #GCancellable, or %NULL
2546  * @callback: callback to be called when the disconnect operation completes
2547  * @user_data: caller-specific data passed to @callback
2548  *
2549  * Asynchronously begins disconnecting the device if currently connected, and
2550  * prevents the device from automatically connecting to networks until the next
2551  * manual network connection request.
2552  **/
2553 void
2554 nm_device_disconnect_async (NMDevice *device,
2555                             GCancellable *cancellable,
2556                             GAsyncReadyCallback callback,
2557                             gpointer user_data)
2558 {
2559         GSimpleAsyncResult *simple;
2560
2561         g_return_if_fail (NM_IS_DEVICE (device));
2562
2563         simple = g_simple_async_result_new (G_OBJECT (device), callback, user_data,
2564                                             nm_device_disconnect_async);
2565
2566         nmdbus_device_call_disconnect (NM_DEVICE_GET_PRIVATE (device)->proxy,
2567                                        cancellable,
2568                                        device_disconnect_cb, simple);
2569 }
2570
2571 /**
2572  * nm_device_disconnect_finish:
2573  * @device: a #NMDevice
2574  * @result: the result passed to the #GAsyncReadyCallback
2575  * @error: location for a #GError, or %NULL
2576  *
2577  * Gets the result of a call to nm_device_disconnect_async().
2578  *
2579  * Returns: %TRUE on success, %FALSE on error, in which case @error
2580  * will be set.
2581  **/
2582 gboolean
2583 nm_device_disconnect_finish (NMDevice *device,
2584                              GAsyncResult *result,
2585                              GError **error)
2586 {
2587         GSimpleAsyncResult *simple;
2588
2589         g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (device), nm_device_disconnect_async), FALSE);
2590
2591         simple = G_SIMPLE_ASYNC_RESULT (result);
2592         if (g_simple_async_result_propagate_error (simple, error))
2593                 return FALSE;
2594         else
2595                 return g_simple_async_result_get_op_res_gboolean (simple);
2596 }
2597
2598 /**
2599  * nm_device_delete:
2600  * @device: a #NMDevice
2601  * @cancellable: a #GCancellable, or %NULL
2602  * @error: location for a #GError, or %NULL
2603  *
2604  * Deletes the software device. Hardware devices can't be deleted.
2605  *
2606  * Returns: %TRUE on success, %FALSE on error, in which case @error
2607  * will be set.
2608  **/
2609 gboolean
2610 nm_device_delete (NMDevice *device,
2611                   GCancellable *cancellable,
2612                   GError **error)
2613 {
2614         gboolean ret;
2615
2616         g_return_val_if_fail (NM_IS_DEVICE (device), FALSE);
2617
2618         ret = nmdbus_device_call_delete_sync (NM_DEVICE_GET_PRIVATE (device)->proxy,
2619                                               cancellable, error);
2620         if (error && *error)
2621                 g_dbus_error_strip_remote_error (*error);
2622         return ret;
2623 }
2624
2625 static void
2626 device_delete_cb (GObject *proxy,
2627                   GAsyncResult *result,
2628                   gpointer user_data)
2629 {
2630         GSimpleAsyncResult *simple = user_data;
2631         GError *error = NULL;
2632
2633         if (nmdbus_device_call_delete_finish (NMDBUS_DEVICE (proxy), result, &error))
2634                 g_simple_async_result_set_op_res_gboolean (simple, TRUE);
2635         else {
2636                 g_dbus_error_strip_remote_error (error);
2637                 g_simple_async_result_take_error (simple, error);
2638         }
2639
2640         g_simple_async_result_complete (simple);
2641         g_object_unref (simple);
2642 }
2643
2644 /**
2645  * nm_device_delete_async:
2646  * @device: a #NMDevice
2647  * @cancellable: a #GCancellable, or %NULL
2648  * @callback: callback to be called when delete operation completes
2649  * @user_data: caller-specific data passed to @callback
2650  *
2651  * Asynchronously begins deleteing the software device. Hardware devices can't
2652  * be deleted.
2653  **/
2654 void
2655 nm_device_delete_async (NMDevice *device,
2656                         GCancellable *cancellable,
2657                         GAsyncReadyCallback callback,
2658                         gpointer user_data)
2659 {
2660         GSimpleAsyncResult *simple;
2661
2662         g_return_if_fail (NM_IS_DEVICE (device));
2663
2664         simple = g_simple_async_result_new (G_OBJECT (device), callback, user_data,
2665                                             nm_device_delete_async);
2666
2667         nmdbus_device_call_delete (NM_DEVICE_GET_PRIVATE (device)->proxy,
2668                                    cancellable,
2669                                    device_delete_cb, simple);
2670 }
2671
2672 /**
2673  * nm_device_delete_finish:
2674  * @device: a #NMDevice
2675  * @result: the result passed to the #GAsyncReadyCallback
2676  * @error: location for a #GError, or %NULL
2677  *
2678  * Gets the result of a call to nm_device_delete_async().
2679  *
2680  * Returns: %TRUE on success, %FALSE on error, in which case @error
2681  * will be set.
2682  **/
2683 gboolean
2684 nm_device_delete_finish (NMDevice *device,
2685                          GAsyncResult *result,
2686                          GError **error)
2687 {
2688         GSimpleAsyncResult *simple;
2689
2690         g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (device), nm_device_delete_async), FALSE);
2691
2692         simple = G_SIMPLE_ASYNC_RESULT (result);
2693         if (g_simple_async_result_propagate_error (simple, error))
2694                 return FALSE;
2695         else
2696                 return g_simple_async_result_get_op_res_gboolean (simple);
2697 }
2698
2699 /**
2700  * nm_device_connection_valid:
2701  * @device: an #NMDevice to validate @connection against
2702  * @connection: an #NMConnection to validate against @device
2703  *
2704  * Validates a given connection for a given #NMDevice object and returns
2705  * whether the connection may be activated with the device. For example if
2706  * @device is a Wi-Fi device that supports only WEP encryption, the connection
2707  * will only be valid if it is a Wi-Fi connection which describes a WEP or open
2708  * network, and will not be valid if it describes a WPA network, or if it is
2709  * an Ethernet, Bluetooth, WWAN, etc connection that is incompatible with the
2710  * device.
2711  *
2712  * Returns: %TRUE if the connection may be activated with this device, %FALSE
2713  * if is incompatible with the device's capabilities and characteristics.
2714  **/
2715 gboolean
2716 nm_device_connection_valid (NMDevice *device, NMConnection *connection)
2717 {
2718         return nm_device_connection_compatible (device, connection, NULL);
2719 }
2720
2721 static gboolean
2722 connection_compatible (NMDevice *device, NMConnection *connection, GError **error)
2723 {
2724         const char *config_iface, *device_iface;
2725         GError *local = NULL;
2726
2727         if (!nm_connection_verify (connection, &local)) {
2728                 g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INVALID_CONNECTION,
2729                              _("The connection was not valid: %s"), local->message);
2730                 g_error_free (local);
2731                 return FALSE;
2732         }
2733
2734         config_iface = nm_connection_get_interface_name (connection);
2735         device_iface = nm_device_get_iface (device);
2736         if (config_iface && g_strcmp0 (config_iface, device_iface) != 0) {
2737                 g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION,
2738                              _("The interface names of the device and the connection didn't match."));
2739                 return FALSE;
2740         }
2741
2742         return TRUE;
2743 }
2744
2745 /**
2746  * nm_device_connection_compatible:
2747  * @device: an #NMDevice to validate @connection against
2748  * @connection: an #NMConnection to validate against @device
2749  * @error: return location for a #GError, or %NULL
2750  *
2751  * Validates a given connection for a given #NMDevice object and returns
2752  * whether the connection may be activated with the device. For example if
2753  * @device is a Wi-Fi device that supports only WEP encryption, the connection
2754  * will only be valid if it is a Wi-Fi connection which describes a WEP or open
2755  * network, and will not be valid if it describes a WPA network, or if it is
2756  * an Ethernet, Bluetooth, WWAN, etc connection that is incompatible with the
2757  * device.
2758  *
2759  * This function does the same as nm_device_connection_valid(), i.e. checking
2760  * compatibility of the given device and connection. But, in addition, it sets
2761  * GError when FALSE is returned.
2762  *
2763  * Returns: %TRUE if the connection may be activated with this device, %FALSE
2764  * if is incompatible with the device's capabilities and characteristics.
2765  **/
2766 gboolean
2767 nm_device_connection_compatible (NMDevice *device, NMConnection *connection, GError **error)
2768 {
2769         g_return_val_if_fail (NM_IS_DEVICE (device), FALSE);
2770         g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE);
2771         g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
2772
2773         return NM_DEVICE_GET_CLASS (device)->connection_compatible (device, connection, error);
2774 }
2775
2776 /**
2777  * nm_device_filter_connections:
2778  * @device: an #NMDevice to filter connections for
2779  * @connections: (element-type NMConnection): an array of #NMConnections to filter
2780  *
2781  * Filters a given array of connections for a given #NMDevice object and returns
2782  * connections which may be activated with the device. For example if @device
2783  * is a Wi-Fi device that supports only WEP encryption, the returned array will
2784  * contain any Wi-Fi connections in @connections that allow connection to
2785  * unencrypted or WEP-enabled SSIDs.  The returned array will not contain
2786  * Ethernet, Bluetooth, Wi-Fi WPA connections, or any other connection that is
2787  * incompatible with the device. To get the full list of connections see
2788  * nm_client_get_connections().
2789  *
2790  * Returns: (transfer container) (element-type NMConnection): an array of
2791  * #NMConnections that could be activated with the given @device.  The array
2792  * should be freed with g_ptr_array_unref() when it is no longer required.
2793  **/
2794 GPtrArray *
2795 nm_device_filter_connections (NMDevice *device, const GPtrArray *connections)
2796 {
2797         GPtrArray *filtered;
2798         int i;
2799
2800         filtered = g_ptr_array_new_with_free_func (g_object_unref);
2801         for (i = 0; i < connections->len; i++) {
2802                 NMConnection *candidate = connections->pdata[i];
2803
2804                 /* Connection applies to this device */
2805                 if (nm_device_connection_valid (device, candidate))
2806                         g_ptr_array_add (filtered, g_object_ref (candidate));
2807         }
2808
2809         return filtered;
2810 }
2811
2812 /**
2813  * nm_device_get_setting_type:
2814  * @device: an #NMDevice
2815  *
2816  * Gets the (primary) #NMSetting subtype associated with connections
2817  * that can be used on @device.
2818  *
2819  * Returns: @device's associated #NMSetting type
2820  */
2821 GType
2822 nm_device_get_setting_type (NMDevice *device)
2823 {
2824         g_return_val_if_fail (NM_IS_DEVICE (device), G_TYPE_INVALID);
2825         g_return_val_if_fail (NM_DEVICE_GET_CLASS (device)->get_setting_type != NULL, G_TYPE_INVALID);
2826
2827         return NM_DEVICE_GET_CLASS (device)->get_setting_type (device);
2828 }
2829
2830 /**
2831  * nm_lldp_neighbor_new:
2832  *
2833  * Creates a new #NMLldpNeighbor object.
2834  *
2835  * Returns: (transfer full): the new #NMLldpNeighbor object.
2836  *
2837  * Since: 1.2
2838  **/
2839 NMLldpNeighbor *
2840 nm_lldp_neighbor_new (void)
2841 {
2842         NMLldpNeighbor *neigh;
2843
2844         neigh = g_new0 (NMLldpNeighbor, 1);
2845         neigh->refcount = 1;
2846         neigh->attrs = g_hash_table_new_full (g_str_hash, g_str_equal, g_free,
2847                                               (GDestroyNotify) g_variant_unref);
2848
2849         return neigh;
2850 }
2851
2852 static NMLldpNeighbor *
2853 nm_lldp_neighbor_dup (NMLldpNeighbor *neighbor)
2854 {
2855         NMLldpNeighbor *copy;
2856
2857         copy = nm_lldp_neighbor_new ();
2858         copy->attrs = g_hash_table_ref (neighbor->attrs);
2859
2860         return copy;
2861 }
2862
2863 /**
2864  * nm_lldp_neighbor_ref:
2865  * @neighbor: the #NMLldpNeighbor
2866  *
2867  * Increases the reference count of the object.
2868  *
2869  * Since: 1.2
2870  **/
2871 void
2872 nm_lldp_neighbor_ref (NMLldpNeighbor *neighbor)
2873 {
2874         g_return_if_fail (neighbor);
2875         g_return_if_fail (neighbor->refcount > 0);
2876
2877         neighbor->refcount++;
2878 }
2879
2880 /**
2881  * nm_lldp_neighbor_unref:
2882  * @neighbor: the #NMLldpNeighbor
2883  *
2884  * Decreases the reference count of the object.  If the reference count
2885  * reaches zero, the object will be destroyed.
2886  *
2887  * Since: 1.2
2888  **/
2889 void
2890 nm_lldp_neighbor_unref (NMLldpNeighbor *neighbor)
2891 {
2892         g_return_if_fail (neighbor);
2893         g_return_if_fail (neighbor->refcount > 0);
2894
2895         if (--neighbor->refcount == 0) {
2896                 g_return_if_fail (neighbor->attrs);
2897                 g_hash_table_unref (neighbor->attrs);
2898                 g_free (neighbor);
2899         }
2900 }
2901
2902 /**
2903  * nm_lldp_neighbor_get_attr_names:
2904  * @neighbor: the #NMLldpNeighbor
2905  *
2906  * Gets an array of attribute names available for @neighbor.
2907  *
2908  * Returns: (transfer full): a %NULL-terminated array of attribute names.
2909  *
2910  * Since: 1.2
2911  **/
2912 char **
2913 nm_lldp_neighbor_get_attr_names (NMLldpNeighbor *neighbor)
2914 {
2915         GHashTableIter iter;
2916         const char *key;
2917         GPtrArray *names;
2918
2919         g_return_val_if_fail (neighbor, NULL);
2920         g_return_val_if_fail (neighbor->attrs, NULL);
2921
2922         names = g_ptr_array_new ();
2923
2924         g_hash_table_iter_init (&iter, neighbor->attrs);
2925         while (g_hash_table_iter_next (&iter, (gpointer *) &key, NULL))
2926                 g_ptr_array_add (names, g_strdup (key));
2927
2928         g_ptr_array_add (names, NULL);
2929
2930         return (char **) g_ptr_array_free (names, FALSE);
2931 }
2932
2933 /**
2934  * nm_lldp_neighbor_get_attr_string_value:
2935  * @neighbor: the #NMLldpNeighbor
2936  * @name: the attribute name
2937  * @out_value: (out) (allow-none) (transfer none): on return, the attribute value
2938  *
2939  * Gets the string value of attribute with name @name on @neighbor
2940  *
2941  * Returns: %TRUE if a string attribute with name @name was found, %FALSE otherwise
2942  *
2943  * Since: 1.2
2944  **/
2945 gboolean
2946 nm_lldp_neighbor_get_attr_string_value (NMLldpNeighbor *neighbor, char *name,
2947                                         const char **out_value)
2948 {
2949         GVariant *variant;
2950
2951         g_return_val_if_fail (neighbor, FALSE);
2952         g_return_val_if_fail (name && name[0], FALSE);
2953
2954         variant = g_hash_table_lookup (neighbor->attrs, name);
2955         if (variant && g_variant_is_of_type (variant, G_VARIANT_TYPE_STRING)) {
2956                 if (out_value)
2957                         *out_value = g_variant_get_string (variant, NULL);
2958                 return TRUE;
2959         } else
2960                 return FALSE;
2961 }
2962
2963 /**
2964  * nm_lldp_neighbor_get_attr_uint_value:
2965  * @neighbor: the #NMLldpNeighbor
2966  * @name: the attribute name
2967  * @out_value: (out) (allow-none): on return, the attribute value
2968  *
2969  * Gets the uint value of attribute with name @name on @neighbor
2970  *
2971  * Returns: %TRUE if a uint attribute with name @name was found, %FALSE otherwise
2972  *
2973  * Since: 1.2
2974  **/
2975 gboolean
2976 nm_lldp_neighbor_get_attr_uint_value (NMLldpNeighbor *neighbor, char *name,
2977                                       guint *out_value)
2978 {
2979         GVariant *variant;
2980
2981         g_return_val_if_fail (neighbor, FALSE);
2982         g_return_val_if_fail (name && name[0], FALSE);
2983
2984         variant = g_hash_table_lookup (neighbor->attrs, name);
2985         if (variant && g_variant_is_of_type (variant, G_VARIANT_TYPE_UINT32)) {
2986                 if (out_value)
2987                         *out_value = g_variant_get_uint32 (variant);
2988                 return TRUE;
2989         } else
2990                 return FALSE;
2991 }
2992
2993 /**
2994  * nm_lldp_neighbor_get_attr_type:
2995  * @neighbor: the #NMLldpNeighbor
2996  * @name: the attribute name
2997  *
2998  * Get the type of an attribute.
2999  *
3000  * Returns: the #GVariantType of the attribute with name @name
3001  *
3002  * Since: 1.2
3003  **/
3004 const GVariantType *
3005 nm_lldp_neighbor_get_attr_type (NMLldpNeighbor *neighbor, char *name)
3006 {
3007         GVariant *variant;
3008
3009         g_return_val_if_fail (neighbor, NULL);
3010         g_return_val_if_fail (name && name[0], NULL);
3011
3012         variant = g_hash_table_lookup (neighbor->attrs, name);
3013         if (variant)
3014                 return g_variant_get_type (variant);
3015         else
3016                 return NULL;
3017
3018 }