libnm: don't normalize connection for nm_device_get_applied_connection()
[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  * Since: 1.2
2333  **/
2334 NMConnection *
2335 nm_device_get_applied_connection (NMDevice *device,
2336                                   guint32 flags,
2337                                   guint64 *version_id,
2338                                   GCancellable *cancellable,
2339                                   GError **error)
2340 {
2341         gs_unref_variant GVariant *dict = NULL;
2342         guint64 my_version_id;
2343         gboolean success;
2344         NMConnection *connection;
2345
2346         g_return_val_if_fail (NM_IS_DEVICE (device), NULL);
2347         g_return_val_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable), NULL);
2348         g_return_val_if_fail (!error || !*error, NULL);
2349
2350         success = nmdbus_device_call_get_applied_connection_sync (NM_DEVICE_GET_PRIVATE (device)->proxy,
2351                                                                   flags, &dict, &my_version_id, cancellable, error);
2352         if (!success) {
2353                 if (error && *error)
2354                         g_dbus_error_strip_remote_error (*error);
2355                 return NULL;
2356         }
2357
2358         connection = _nm_simple_connection_new_from_dbus (dict, NM_SETTING_PARSE_FLAGS_BEST_EFFORT, error);
2359         if (!connection)
2360                 return NULL;
2361
2362         NM_SET_OUT (version_id, my_version_id);
2363         return connection;
2364 }
2365
2366 typedef struct {
2367         NMConnection *connection;
2368         guint64 version_id;
2369 } GetAppliedConnectionData;
2370
2371 static void
2372 device_get_applied_connection_data_free (gpointer user_data)
2373 {
2374         GetAppliedConnectionData *data = user_data;
2375
2376         g_return_if_fail (data);
2377
2378         g_object_unref (data->connection);
2379         g_slice_free (GetAppliedConnectionData, data);
2380 }
2381
2382 static void
2383 device_get_applied_connection_cb (GObject *proxy,
2384                                   GAsyncResult *result,
2385                                   gpointer user_data)
2386 {
2387         gs_unref_object GSimpleAsyncResult *simple = user_data;
2388         gs_unref_variant GVariant *dict = NULL;
2389         guint64 my_version_id;
2390         GError *error = NULL;
2391         NMConnection *connection;
2392         GetAppliedConnectionData *data;
2393
2394         if (!nmdbus_device_call_get_applied_connection_finish (NMDBUS_DEVICE (proxy), &dict, &my_version_id, result, &error)) {
2395                 g_dbus_error_strip_remote_error (error);
2396                 g_simple_async_result_take_error (simple, error);
2397                 goto out;
2398         }
2399
2400         connection = _nm_simple_connection_new_from_dbus (dict, NM_SETTING_PARSE_FLAGS_BEST_EFFORT, &error);
2401         if (!connection) {
2402                 g_simple_async_result_take_error (simple, error);
2403                 goto out;
2404         }
2405
2406         data = g_slice_new (GetAppliedConnectionData);
2407         data->connection = connection;
2408         data->version_id = my_version_id;
2409         g_simple_async_result_set_op_res_gpointer (simple, data, device_get_applied_connection_data_free);
2410
2411 out:
2412         g_simple_async_result_complete (simple);
2413 }
2414
2415 /**
2416  * nm_device_get_applied_connection_async:
2417  * @device: a #NMDevice
2418  * @flags: the flags argument. Currently this value must always be zero.
2419  * @cancellable: a #GCancellable, or %NULL
2420  * @callback: callback to be called when the reapply operation completes
2421  * @user_data: caller-specific data passed to @callback
2422  *
2423  * Asynchronously begins an get the a currently applied connection.
2424  *
2425  * Since: 1.2
2426  **/
2427 void
2428 nm_device_get_applied_connection_async  (NMDevice *device,
2429                                          guint32 flags,
2430                                          GCancellable *cancellable,
2431                                          GAsyncReadyCallback callback,
2432                                          gpointer user_data)
2433 {
2434         GSimpleAsyncResult *simple;
2435
2436         g_return_if_fail (NM_IS_DEVICE (device));
2437         g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
2438
2439         simple = g_simple_async_result_new (G_OBJECT (device), callback, user_data,
2440                                             nm_device_get_applied_connection_async);
2441
2442         nmdbus_device_call_get_applied_connection (NM_DEVICE_GET_PRIVATE (device)->proxy,
2443                                                    flags, cancellable,
2444                                                    device_get_applied_connection_cb, simple);
2445 }
2446
2447 /**
2448  * nm_device_get_applied_connection_finish:
2449  * @device: a #NMDevice
2450  * @result: the result passed to the #GAsyncReadyCallback
2451  * @version_id: (out): (allow-none): the current version id of the applied
2452  *   connection.
2453  * @error: location for a #GError, or %NULL
2454  *
2455  * Gets the result of a call to nm_device_get_applied_connection_async().
2456  *
2457  * Returns: (transfer full): a currently applied %NMConnection or %NULL in case
2458  *   of error.
2459  *
2460  * Since: 1.2
2461  **/
2462 NMConnection *
2463 nm_device_get_applied_connection_finish (NMDevice *device,
2464                                          GAsyncResult *result,
2465                                          guint64 *version_id,
2466                                          GError **error)
2467 {
2468         GSimpleAsyncResult *simple;
2469         GetAppliedConnectionData *data;
2470
2471         g_return_val_if_fail (NM_IS_DEVICE (device), NULL);
2472         g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (device), nm_device_get_applied_connection_async), NULL);
2473         g_return_val_if_fail (!error || !*error, NULL);
2474
2475         simple = G_SIMPLE_ASYNC_RESULT (result);
2476         if (g_simple_async_result_propagate_error (simple, error))
2477                 return NULL;
2478
2479         data = g_simple_async_result_get_op_res_gpointer (simple);
2480         g_return_val_if_fail (data, NULL);
2481         g_return_val_if_fail (NM_IS_CONNECTION (data->connection), NULL);
2482
2483         NM_SET_OUT (version_id, data->version_id);
2484         return g_object_ref (data->connection);
2485 }
2486
2487 /*****************************************************************************/
2488
2489 /**
2490  * nm_device_disconnect:
2491  * @device: a #NMDevice
2492  * @cancellable: a #GCancellable, or %NULL
2493  * @error: location for a #GError, or %NULL
2494  *
2495  * Disconnects the device if currently connected, and prevents the device from
2496  * automatically connecting to networks until the next manual network connection
2497  * request.
2498  *
2499  * Returns: %TRUE on success, %FALSE on error, in which case @error will be set.
2500  **/
2501 gboolean
2502 nm_device_disconnect (NMDevice *device,
2503                       GCancellable *cancellable,
2504                       GError **error)
2505 {
2506         gboolean ret;
2507
2508         g_return_val_if_fail (NM_IS_DEVICE (device), FALSE);
2509
2510         ret = nmdbus_device_call_disconnect_sync (NM_DEVICE_GET_PRIVATE (device)->proxy,
2511                                                   cancellable, error);
2512         if (error && *error)
2513                 g_dbus_error_strip_remote_error (*error);
2514         return ret;
2515 }
2516
2517 static void
2518 device_disconnect_cb (GObject *proxy,
2519                       GAsyncResult *result,
2520                       gpointer user_data)
2521 {
2522         GSimpleAsyncResult *simple = user_data;
2523         GError *error = NULL;
2524
2525         if (nmdbus_device_call_disconnect_finish (NMDBUS_DEVICE (proxy), result, &error))
2526                 g_simple_async_result_set_op_res_gboolean (simple, TRUE);
2527         else {
2528                 g_dbus_error_strip_remote_error (error);
2529                 g_simple_async_result_take_error (simple, error);
2530         }
2531
2532         g_simple_async_result_complete (simple);
2533         g_object_unref (simple);
2534 }
2535
2536 /**
2537  * nm_device_disconnect_async:
2538  * @device: a #NMDevice
2539  * @cancellable: a #GCancellable, or %NULL
2540  * @callback: callback to be called when the disconnect operation completes
2541  * @user_data: caller-specific data passed to @callback
2542  *
2543  * Asynchronously begins disconnecting the device if currently connected, and
2544  * prevents the device from automatically connecting to networks until the next
2545  * manual network connection request.
2546  **/
2547 void
2548 nm_device_disconnect_async (NMDevice *device,
2549                             GCancellable *cancellable,
2550                             GAsyncReadyCallback callback,
2551                             gpointer user_data)
2552 {
2553         GSimpleAsyncResult *simple;
2554
2555         g_return_if_fail (NM_IS_DEVICE (device));
2556
2557         simple = g_simple_async_result_new (G_OBJECT (device), callback, user_data,
2558                                             nm_device_disconnect_async);
2559
2560         nmdbus_device_call_disconnect (NM_DEVICE_GET_PRIVATE (device)->proxy,
2561                                        cancellable,
2562                                        device_disconnect_cb, simple);
2563 }
2564
2565 /**
2566  * nm_device_disconnect_finish:
2567  * @device: a #NMDevice
2568  * @result: the result passed to the #GAsyncReadyCallback
2569  * @error: location for a #GError, or %NULL
2570  *
2571  * Gets the result of a call to nm_device_disconnect_async().
2572  *
2573  * Returns: %TRUE on success, %FALSE on error, in which case @error
2574  * will be set.
2575  **/
2576 gboolean
2577 nm_device_disconnect_finish (NMDevice *device,
2578                              GAsyncResult *result,
2579                              GError **error)
2580 {
2581         GSimpleAsyncResult *simple;
2582
2583         g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (device), nm_device_disconnect_async), FALSE);
2584
2585         simple = G_SIMPLE_ASYNC_RESULT (result);
2586         if (g_simple_async_result_propagate_error (simple, error))
2587                 return FALSE;
2588         else
2589                 return g_simple_async_result_get_op_res_gboolean (simple);
2590 }
2591
2592 /**
2593  * nm_device_delete:
2594  * @device: a #NMDevice
2595  * @cancellable: a #GCancellable, or %NULL
2596  * @error: location for a #GError, or %NULL
2597  *
2598  * Deletes the software device. Hardware devices can't be deleted.
2599  *
2600  * Returns: %TRUE on success, %FALSE on error, in which case @error
2601  * will be set.
2602  **/
2603 gboolean
2604 nm_device_delete (NMDevice *device,
2605                   GCancellable *cancellable,
2606                   GError **error)
2607 {
2608         gboolean ret;
2609
2610         g_return_val_if_fail (NM_IS_DEVICE (device), FALSE);
2611
2612         ret = nmdbus_device_call_delete_sync (NM_DEVICE_GET_PRIVATE (device)->proxy,
2613                                               cancellable, error);
2614         if (error && *error)
2615                 g_dbus_error_strip_remote_error (*error);
2616         return ret;
2617 }
2618
2619 static void
2620 device_delete_cb (GObject *proxy,
2621                   GAsyncResult *result,
2622                   gpointer user_data)
2623 {
2624         GSimpleAsyncResult *simple = user_data;
2625         GError *error = NULL;
2626
2627         if (nmdbus_device_call_delete_finish (NMDBUS_DEVICE (proxy), result, &error))
2628                 g_simple_async_result_set_op_res_gboolean (simple, TRUE);
2629         else {
2630                 g_dbus_error_strip_remote_error (error);
2631                 g_simple_async_result_take_error (simple, error);
2632         }
2633
2634         g_simple_async_result_complete (simple);
2635         g_object_unref (simple);
2636 }
2637
2638 /**
2639  * nm_device_delete_async:
2640  * @device: a #NMDevice
2641  * @cancellable: a #GCancellable, or %NULL
2642  * @callback: callback to be called when delete operation completes
2643  * @user_data: caller-specific data passed to @callback
2644  *
2645  * Asynchronously begins deleteing the software device. Hardware devices can't
2646  * be deleted.
2647  **/
2648 void
2649 nm_device_delete_async (NMDevice *device,
2650                         GCancellable *cancellable,
2651                         GAsyncReadyCallback callback,
2652                         gpointer user_data)
2653 {
2654         GSimpleAsyncResult *simple;
2655
2656         g_return_if_fail (NM_IS_DEVICE (device));
2657
2658         simple = g_simple_async_result_new (G_OBJECT (device), callback, user_data,
2659                                             nm_device_delete_async);
2660
2661         nmdbus_device_call_delete (NM_DEVICE_GET_PRIVATE (device)->proxy,
2662                                    cancellable,
2663                                    device_delete_cb, simple);
2664 }
2665
2666 /**
2667  * nm_device_delete_finish:
2668  * @device: a #NMDevice
2669  * @result: the result passed to the #GAsyncReadyCallback
2670  * @error: location for a #GError, or %NULL
2671  *
2672  * Gets the result of a call to nm_device_delete_async().
2673  *
2674  * Returns: %TRUE on success, %FALSE on error, in which case @error
2675  * will be set.
2676  **/
2677 gboolean
2678 nm_device_delete_finish (NMDevice *device,
2679                          GAsyncResult *result,
2680                          GError **error)
2681 {
2682         GSimpleAsyncResult *simple;
2683
2684         g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (device), nm_device_delete_async), FALSE);
2685
2686         simple = G_SIMPLE_ASYNC_RESULT (result);
2687         if (g_simple_async_result_propagate_error (simple, error))
2688                 return FALSE;
2689         else
2690                 return g_simple_async_result_get_op_res_gboolean (simple);
2691 }
2692
2693 /**
2694  * nm_device_connection_valid:
2695  * @device: an #NMDevice to validate @connection against
2696  * @connection: an #NMConnection to validate against @device
2697  *
2698  * Validates a given connection for a given #NMDevice object and returns
2699  * whether the connection may be activated with the device. For example if
2700  * @device is a Wi-Fi device that supports only WEP encryption, the connection
2701  * will only be valid if it is a Wi-Fi connection which describes a WEP or open
2702  * network, and will not be valid if it describes a WPA network, or if it is
2703  * an Ethernet, Bluetooth, WWAN, etc connection that is incompatible with the
2704  * device.
2705  *
2706  * Returns: %TRUE if the connection may be activated with this device, %FALSE
2707  * if is incompatible with the device's capabilities and characteristics.
2708  **/
2709 gboolean
2710 nm_device_connection_valid (NMDevice *device, NMConnection *connection)
2711 {
2712         return nm_device_connection_compatible (device, connection, NULL);
2713 }
2714
2715 static gboolean
2716 connection_compatible (NMDevice *device, NMConnection *connection, GError **error)
2717 {
2718         const char *config_iface, *device_iface;
2719         GError *local = NULL;
2720
2721         if (!nm_connection_verify (connection, &local)) {
2722                 g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INVALID_CONNECTION,
2723                              _("The connection was not valid: %s"), local->message);
2724                 g_error_free (local);
2725                 return FALSE;
2726         }
2727
2728         config_iface = nm_connection_get_interface_name (connection);
2729         device_iface = nm_device_get_iface (device);
2730         if (config_iface && g_strcmp0 (config_iface, device_iface) != 0) {
2731                 g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION,
2732                              _("The interface names of the device and the connection didn't match."));
2733                 return FALSE;
2734         }
2735
2736         return TRUE;
2737 }
2738
2739 /**
2740  * nm_device_connection_compatible:
2741  * @device: an #NMDevice to validate @connection against
2742  * @connection: an #NMConnection to validate against @device
2743  * @error: return location for a #GError, or %NULL
2744  *
2745  * Validates a given connection for a given #NMDevice object and returns
2746  * whether the connection may be activated with the device. For example if
2747  * @device is a Wi-Fi device that supports only WEP encryption, the connection
2748  * will only be valid if it is a Wi-Fi connection which describes a WEP or open
2749  * network, and will not be valid if it describes a WPA network, or if it is
2750  * an Ethernet, Bluetooth, WWAN, etc connection that is incompatible with the
2751  * device.
2752  *
2753  * This function does the same as nm_device_connection_valid(), i.e. checking
2754  * compatibility of the given device and connection. But, in addition, it sets
2755  * GError when FALSE is returned.
2756  *
2757  * Returns: %TRUE if the connection may be activated with this device, %FALSE
2758  * if is incompatible with the device's capabilities and characteristics.
2759  **/
2760 gboolean
2761 nm_device_connection_compatible (NMDevice *device, NMConnection *connection, GError **error)
2762 {
2763         g_return_val_if_fail (NM_IS_DEVICE (device), FALSE);
2764         g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE);
2765         g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
2766
2767         return NM_DEVICE_GET_CLASS (device)->connection_compatible (device, connection, error);
2768 }
2769
2770 /**
2771  * nm_device_filter_connections:
2772  * @device: an #NMDevice to filter connections for
2773  * @connections: (element-type NMConnection): an array of #NMConnections to filter
2774  *
2775  * Filters a given array of connections for a given #NMDevice object and returns
2776  * connections which may be activated with the device. For example if @device
2777  * is a Wi-Fi device that supports only WEP encryption, the returned array will
2778  * contain any Wi-Fi connections in @connections that allow connection to
2779  * unencrypted or WEP-enabled SSIDs.  The returned array will not contain
2780  * Ethernet, Bluetooth, Wi-Fi WPA connections, or any other connection that is
2781  * incompatible with the device. To get the full list of connections see
2782  * nm_client_get_connections().
2783  *
2784  * Returns: (transfer container) (element-type NMConnection): an array of
2785  * #NMConnections that could be activated with the given @device.  The array
2786  * should be freed with g_ptr_array_unref() when it is no longer required.
2787  **/
2788 GPtrArray *
2789 nm_device_filter_connections (NMDevice *device, const GPtrArray *connections)
2790 {
2791         GPtrArray *filtered;
2792         int i;
2793
2794         filtered = g_ptr_array_new_with_free_func (g_object_unref);
2795         for (i = 0; i < connections->len; i++) {
2796                 NMConnection *candidate = connections->pdata[i];
2797
2798                 /* Connection applies to this device */
2799                 if (nm_device_connection_valid (device, candidate))
2800                         g_ptr_array_add (filtered, g_object_ref (candidate));
2801         }
2802
2803         return filtered;
2804 }
2805
2806 /**
2807  * nm_device_get_setting_type:
2808  * @device: an #NMDevice
2809  *
2810  * Gets the (primary) #NMSetting subtype associated with connections
2811  * that can be used on @device.
2812  *
2813  * Returns: @device's associated #NMSetting type
2814  */
2815 GType
2816 nm_device_get_setting_type (NMDevice *device)
2817 {
2818         g_return_val_if_fail (NM_IS_DEVICE (device), G_TYPE_INVALID);
2819         g_return_val_if_fail (NM_DEVICE_GET_CLASS (device)->get_setting_type != NULL, G_TYPE_INVALID);
2820
2821         return NM_DEVICE_GET_CLASS (device)->get_setting_type (device);
2822 }
2823
2824 /**
2825  * nm_lldp_neighbor_new:
2826  *
2827  * Creates a new #NMLldpNeighbor object.
2828  *
2829  * Returns: (transfer full): the new #NMLldpNeighbor object.
2830  *
2831  * Since: 1.2
2832  **/
2833 NMLldpNeighbor *
2834 nm_lldp_neighbor_new (void)
2835 {
2836         NMLldpNeighbor *neigh;
2837
2838         neigh = g_new0 (NMLldpNeighbor, 1);
2839         neigh->refcount = 1;
2840         neigh->attrs = g_hash_table_new_full (g_str_hash, g_str_equal, g_free,
2841                                               (GDestroyNotify) g_variant_unref);
2842
2843         return neigh;
2844 }
2845
2846 static NMLldpNeighbor *
2847 nm_lldp_neighbor_dup (NMLldpNeighbor *neighbor)
2848 {
2849         NMLldpNeighbor *copy;
2850
2851         copy = nm_lldp_neighbor_new ();
2852         copy->attrs = g_hash_table_ref (neighbor->attrs);
2853
2854         return copy;
2855 }
2856
2857 /**
2858  * nm_lldp_neighbor_ref:
2859  * @neighbor: the #NMLldpNeighbor
2860  *
2861  * Increases the reference count of the object.
2862  *
2863  * Since: 1.2
2864  **/
2865 void
2866 nm_lldp_neighbor_ref (NMLldpNeighbor *neighbor)
2867 {
2868         g_return_if_fail (neighbor);
2869         g_return_if_fail (neighbor->refcount > 0);
2870
2871         neighbor->refcount++;
2872 }
2873
2874 /**
2875  * nm_lldp_neighbor_unref:
2876  * @neighbor: the #NMLldpNeighbor
2877  *
2878  * Decreases the reference count of the object.  If the reference count
2879  * reaches zero, the object will be destroyed.
2880  *
2881  * Since: 1.2
2882  **/
2883 void
2884 nm_lldp_neighbor_unref (NMLldpNeighbor *neighbor)
2885 {
2886         g_return_if_fail (neighbor);
2887         g_return_if_fail (neighbor->refcount > 0);
2888
2889         if (--neighbor->refcount == 0) {
2890                 g_return_if_fail (neighbor->attrs);
2891                 g_hash_table_unref (neighbor->attrs);
2892                 g_free (neighbor);
2893         }
2894 }
2895
2896 /**
2897  * nm_lldp_neighbor_get_attr_names:
2898  * @neighbor: the #NMLldpNeighbor
2899  *
2900  * Gets an array of attribute names available for @neighbor.
2901  *
2902  * Returns: (transfer full): a %NULL-terminated array of attribute names.
2903  *
2904  * Since: 1.2
2905  **/
2906 char **
2907 nm_lldp_neighbor_get_attr_names (NMLldpNeighbor *neighbor)
2908 {
2909         GHashTableIter iter;
2910         const char *key;
2911         GPtrArray *names;
2912
2913         g_return_val_if_fail (neighbor, NULL);
2914         g_return_val_if_fail (neighbor->attrs, NULL);
2915
2916         names = g_ptr_array_new ();
2917
2918         g_hash_table_iter_init (&iter, neighbor->attrs);
2919         while (g_hash_table_iter_next (&iter, (gpointer *) &key, NULL))
2920                 g_ptr_array_add (names, g_strdup (key));
2921
2922         g_ptr_array_add (names, NULL);
2923
2924         return (char **) g_ptr_array_free (names, FALSE);
2925 }
2926
2927 /**
2928  * nm_lldp_neighbor_get_attr_string_value:
2929  * @neighbor: the #NMLldpNeighbor
2930  * @name: the attribute name
2931  * @out_value: (out) (allow-none) (transfer none): on return, the attribute value
2932  *
2933  * Gets the string value of attribute with name @name on @neighbor
2934  *
2935  * Returns: %TRUE if a string attribute with name @name was found, %FALSE otherwise
2936  *
2937  * Since: 1.2
2938  **/
2939 gboolean
2940 nm_lldp_neighbor_get_attr_string_value (NMLldpNeighbor *neighbor, char *name,
2941                                         const char **out_value)
2942 {
2943         GVariant *variant;
2944
2945         g_return_val_if_fail (neighbor, FALSE);
2946         g_return_val_if_fail (name && name[0], FALSE);
2947
2948         variant = g_hash_table_lookup (neighbor->attrs, name);
2949         if (variant && g_variant_is_of_type (variant, G_VARIANT_TYPE_STRING)) {
2950                 if (out_value)
2951                         *out_value = g_variant_get_string (variant, NULL);
2952                 return TRUE;
2953         } else
2954                 return FALSE;
2955 }
2956
2957 /**
2958  * nm_lldp_neighbor_get_attr_uint_value:
2959  * @neighbor: the #NMLldpNeighbor
2960  * @name: the attribute name
2961  * @out_value: (out) (allow-none): on return, the attribute value
2962  *
2963  * Gets the uint value of attribute with name @name on @neighbor
2964  *
2965  * Returns: %TRUE if a uint attribute with name @name was found, %FALSE otherwise
2966  *
2967  * Since: 1.2
2968  **/
2969 gboolean
2970 nm_lldp_neighbor_get_attr_uint_value (NMLldpNeighbor *neighbor, char *name,
2971                                       guint *out_value)
2972 {
2973         GVariant *variant;
2974
2975         g_return_val_if_fail (neighbor, FALSE);
2976         g_return_val_if_fail (name && name[0], FALSE);
2977
2978         variant = g_hash_table_lookup (neighbor->attrs, name);
2979         if (variant && g_variant_is_of_type (variant, G_VARIANT_TYPE_UINT32)) {
2980                 if (out_value)
2981                         *out_value = g_variant_get_uint32 (variant);
2982                 return TRUE;
2983         } else
2984                 return FALSE;
2985 }
2986
2987 /**
2988  * nm_lldp_neighbor_get_attr_type:
2989  * @neighbor: the #NMLldpNeighbor
2990  * @name: the attribute name
2991  *
2992  * Get the type of an attribute.
2993  *
2994  * Returns: the #GVariantType of the attribute with name @name
2995  *
2996  * Since: 1.2
2997  **/
2998 const GVariantType *
2999 nm_lldp_neighbor_get_attr_type (NMLldpNeighbor *neighbor, char *name)
3000 {
3001         GVariant *variant;
3002
3003         g_return_val_if_fail (neighbor, NULL);
3004         g_return_val_if_fail (name && name[0], NULL);
3005
3006         variant = g_hash_table_lookup (neighbor->attrs, name);
3007         if (variant)
3008                 return g_variant_get_type (variant);
3009         else
3010                 return NULL;
3011
3012 }