[network-manager-applet] applet: add VLAN, Bridge and Bond device support



commit 4e29760e240d57e886513113ff9b6e01f32afb36
Author: Dan Winship <danw gnome org>
Date:   Tue May 21 16:56:29 2013 -0300

    applet: add VLAN, Bridge and Bond device support
    
    For virtual device types (vlan, bridge, bond), the physical device may
    not be created until the connection is activated. Reorganize things so
    that these device types are represented by their NMConnections, not
    their NMDevices, with the connections grouped together according to
    their virtual interface name.
    
    Based on a patch by Dan Williams.

 po/POTFILES.in             |    3 +
 src/Makefile.am            |    6 +
 src/applet-device-bond.c   |  169 +++++++++++++++++++++
 src/applet-device-bond.h   |   31 ++++
 src/applet-device-bridge.c |  168 +++++++++++++++++++++
 src/applet-device-bridge.h |   31 ++++
 src/applet-device-vlan.c   |  282 +++++++++++++++++++++++++++++++++++
 src/applet-device-vlan.h   |   31 ++++
 src/applet.c               |  356 +++++++++++++++++++++++++++++--------------
 src/applet.h               |    3 +
 10 files changed, 964 insertions(+), 116 deletions(-)
---
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 9d63756..115e5c5 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -6,11 +6,14 @@ nm-connection-editor.desktop.in
 org.gnome.nm-applet.gschema.xml.in
 [type: gettext/glade]src/8021x.ui
 src/applet.c
+src/applet-device-bond.c
+src/applet-device-bridge.c
 src/applet-device-bt.c
 src/applet-device-cdma.c
 src/applet-device-ethernet.c
 src/applet-device-broadband.c
 src/applet-device-gsm.c
+src/applet-device-vlan.c
 src/applet-device-wifi.c
 src/applet-device-wimax.c
 src/applet-dialogs.c
diff --git a/src/Makefile.am b/src/Makefile.am
index eecd788..23bae47 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -57,6 +57,12 @@ nm_applet_SOURCES = \
        applet-device-bt.c \
        applet-device-wimax.h \
        applet-device-wimax.c \
+       applet-device-vlan.h \
+       applet-device-vlan.c \
+       applet-device-bond.h \
+       applet-device-bond.c \
+       applet-device-bridge.h \
+       applet-device-bridge.c \
        fallback-icon.h \
        shell-watcher.h \
        shell-watcher.c
diff --git a/src/applet-device-bond.c b/src/applet-device-bond.c
new file mode 100644
index 0000000..ac844b8
--- /dev/null
+++ b/src/applet-device-bond.c
@@ -0,0 +1,169 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Wireless Applet -- Display wireless access points and allow user control
+ *
+ * Dan Williams <dcbw redhat com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * (C) Copyright 2008 Red Hat, Inc.
+ * (C) Copyright 2008 Novell, Inc.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+
+#include <nm-device.h>
+#include <nm-setting-connection.h>
+#include <nm-setting-wired.h>
+#include <nm-setting-bond.h>
+#include <nm-device-bond.h>
+#include <nm-utils.h>
+
+#include "applet.h"
+#include "applet-device-bond.h"
+#include "utils.h"
+#include "nm-ui-utils.h"
+
+static void
+bond_add_menu_item (NMDevice *device,
+                    gboolean multiple_devices,
+                    GSList *connections,
+                    NMConnection *active,
+                    GtkWidget *menu,
+                    NMApplet *applet)
+{
+       char *text;
+       GtkWidget *item;
+
+       text = nma_utils_get_connection_device_name (connections->data);
+       item = applet_menu_item_create_device_item_helper (device, applet, text);
+       g_free (text);
+
+       gtk_widget_set_sensitive (item, FALSE);
+       gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+       gtk_widget_show (item);
+
+       if (g_slist_length (connections))
+               applet_add_connection_items (device, connections, TRUE, active, NMA_ADD_ACTIVE, menu, applet);
+
+       /* Notify user of unmanaged or unavailable device */
+       if (device) {
+               item = nma_menu_device_get_menu_item (device, applet, NULL);
+               if (item) {
+                       gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+                       gtk_widget_show (item);
+               }
+       }
+
+       if (!device || !nma_menu_device_check_unusable (device)) {
+               if ((!active && g_slist_length (connections)) || (active && g_slist_length (connections) > 1))
+                       applet_menu_item_add_complex_separator_helper (menu, applet, _("Available"), -1);
+
+               if (g_slist_length (connections))
+                       applet_add_connection_items (device, connections, TRUE, active, NMA_ADD_INACTIVE, 
menu, applet);
+       }
+}
+
+static void
+bond_notify_connected (NMDevice *device,
+                       const char *msg,
+                       NMApplet *applet)
+{
+       applet_do_notify_with_pref (applet,
+                                   _("Connection Established"),
+                                   msg ? msg : _("You are now connected to the bonded network."),
+                                   "nm-device-wired",
+                                   PREF_DISABLE_CONNECTED_NOTIFICATIONS);
+}
+
+static GdkPixbuf *
+bond_get_icon (NMDevice *device,
+               NMDeviceState state,
+               NMConnection *connection,
+               char **tip,
+               NMApplet *applet)
+{
+       NMSettingConnection *s_con;
+       GdkPixbuf *pixbuf = NULL;
+       const char *id;
+
+       id = nm_device_get_iface (NM_DEVICE (device));
+       if (connection) {
+               s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (connection, 
NM_TYPE_SETTING_CONNECTION));
+               id = nm_setting_connection_get_id (s_con);
+       }
+
+       switch (state) {
+       case NM_DEVICE_STATE_PREPARE:
+               *tip = g_strdup_printf (_("Preparing VLAN connection '%s'..."), id);
+               break;
+       case NM_DEVICE_STATE_CONFIG:
+               *tip = g_strdup_printf (_("Configuring VLAN connection '%s'..."), id);
+               break;
+       case NM_DEVICE_STATE_NEED_AUTH:
+               *tip = g_strdup_printf (_("User authentication required for VLAN connection '%s'..."), id);
+               break;
+       case NM_DEVICE_STATE_IP_CONFIG:
+               *tip = g_strdup_printf (_("Requesting address for '%s'..."), id);
+               break;
+       case NM_DEVICE_STATE_ACTIVATED:
+               pixbuf = nma_icon_check_and_load ("nm-device-wired", &applet->ethernet_icon, applet);
+               *tip = g_strdup_printf (_("VLAN connection '%s' active"), id);
+               break;
+       default:
+               break;
+       }
+
+       return pixbuf;
+}
+
+static gboolean
+bond_new_auto_connection (NMDevice *device,
+                          gpointer dclass_data,
+                          AppletNewAutoConnectionCallback callback,
+                          gpointer callback_data)
+{
+       return FALSE;
+}
+
+
+static gboolean
+bond_get_secrets (SecretsRequest *req, GError **error)
+{
+       /* No 802.1x or PPPoE possible yet on bonds */
+       return FALSE;
+}
+
+NMADeviceClass *
+applet_device_bond_get_class (NMApplet *applet)
+{
+       NMADeviceClass *dclass;
+
+       dclass = g_slice_new0 (NMADeviceClass);
+       if (!dclass)
+               return NULL;
+
+       dclass->new_auto_connection = bond_new_auto_connection;
+       dclass->add_menu_item = bond_add_menu_item;
+       dclass->notify_connected = bond_notify_connected;
+       dclass->get_icon = bond_get_icon;
+       dclass->get_secrets = bond_get_secrets;
+
+       return dclass;
+}
diff --git a/src/applet-device-bond.h b/src/applet-device-bond.h
new file mode 100644
index 0000000..227c951
--- /dev/null
+++ b/src/applet-device-bond.h
@@ -0,0 +1,31 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Wireless Applet -- Display wireless access points and allow user control
+ *
+ * Dan Williams <dcbw redhat com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * (C) Copyright 2008 Red Hat, Inc.
+ * (C) Copyright 2008 Novell, Inc.
+ */
+
+#ifndef __APPLET_DEVICE_BOND_H__
+#define __APPLET_DEVICE_BOND_H__
+
+#include "applet.h"
+
+NMADeviceClass *applet_device_bond_get_class (NMApplet *applet);
+
+#endif /* __APPLET_DEVICE_BOND_H__ */
diff --git a/src/applet-device-bridge.c b/src/applet-device-bridge.c
new file mode 100644
index 0000000..008a794
--- /dev/null
+++ b/src/applet-device-bridge.c
@@ -0,0 +1,168 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Wireless Applet -- Display wireless access points and allow user control
+ *
+ * Dan Williams <dcbw redhat com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * (C) Copyright 2008 Red Hat, Inc.
+ * (C) Copyright 2008 Novell, Inc.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+
+#include <nm-device.h>
+#include <nm-setting-connection.h>
+#include <nm-setting-wired.h>
+#include <nm-setting-bridge.h>
+#include <nm-device-bridge.h>
+#include <nm-utils.h>
+
+#include "applet.h"
+#include "applet-device-bridge.h"
+#include "utils.h"
+#include "nm-ui-utils.h"
+
+static void
+bridge_add_menu_item (NMDevice *device,
+                      gboolean multiple_devices,
+                      GSList *connections,
+                      NMConnection *active,
+                      GtkWidget *menu,
+                      NMApplet *applet)
+{
+       char *text;
+       GtkWidget *item;
+
+       text = nma_utils_get_connection_device_name (connections->data);
+       item = applet_menu_item_create_device_item_helper (device, applet, text);
+       g_free (text);
+
+       gtk_widget_set_sensitive (item, FALSE);
+       gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+       gtk_widget_show (item);
+
+       if (g_slist_length (connections))
+               applet_add_connection_items (device, connections, TRUE, active, NMA_ADD_ACTIVE, menu, applet);
+
+       /* Notify user of unmanaged or unavailable device */
+       if (device) {
+               item = nma_menu_device_get_menu_item (device, applet, NULL);
+               if (item) {
+                       gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+                       gtk_widget_show (item);
+               }
+       }
+
+       if (!device || !nma_menu_device_check_unusable (device)) {
+               if ((!active && g_slist_length (connections)) || (active && g_slist_length (connections) > 1))
+                       applet_menu_item_add_complex_separator_helper (menu, applet, _("Available"), -1);
+
+               if (g_slist_length (connections))
+                       applet_add_connection_items (device, connections, TRUE, active, NMA_ADD_INACTIVE, 
menu, applet);
+       }
+}
+
+static void
+bridge_notify_connected (NMDevice *device,
+                         const char *msg,
+                         NMApplet *applet)
+{
+       applet_do_notify_with_pref (applet,
+                                   _("Connection Established"),
+                                   msg ? msg : _("You are now connected to the bridged network."),
+                                   "nm-device-wired",
+                                   PREF_DISABLE_CONNECTED_NOTIFICATIONS);
+}
+
+static GdkPixbuf *
+bridge_get_icon (NMDevice *device,
+                 NMDeviceState state,
+                 NMConnection *connection,
+                 char **tip,
+                 NMApplet *applet)
+{
+       NMSettingConnection *s_con;
+       GdkPixbuf *pixbuf = NULL;
+       const char *id;
+
+       id = nm_device_get_iface (NM_DEVICE (device));
+       if (connection) {
+               s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (connection, 
NM_TYPE_SETTING_CONNECTION));
+               id = nm_setting_connection_get_id (s_con);
+       }
+
+       switch (state) {
+       case NM_DEVICE_STATE_PREPARE:
+               *tip = g_strdup_printf (_("Preparing VLAN connection '%s'..."), id);
+               break;
+       case NM_DEVICE_STATE_CONFIG:
+               *tip = g_strdup_printf (_("Configuring VLAN connection '%s'..."), id);
+               break;
+       case NM_DEVICE_STATE_NEED_AUTH:
+               *tip = g_strdup_printf (_("User authentication required for VLAN connection '%s'..."), id);
+               break;
+       case NM_DEVICE_STATE_IP_CONFIG:
+               *tip = g_strdup_printf (_("Requesting address for '%s'..."), id);
+               break;
+       case NM_DEVICE_STATE_ACTIVATED:
+               pixbuf = nma_icon_check_and_load ("nm-device-wired", &applet->ethernet_icon, applet);
+               *tip = g_strdup_printf (_("VLAN connection '%s' active"), id);
+               break;
+       default:
+               break;
+       }
+
+       return pixbuf;
+}
+
+static gboolean
+bridge_new_auto_connection (NMDevice *device,
+                            gpointer dclass_data,
+                            AppletNewAutoConnectionCallback callback,
+                            gpointer callback_data)
+{
+       return FALSE;
+}
+
+static gboolean
+bridge_get_secrets (SecretsRequest *req, GError **error)
+{
+       /* No 802.1x or PPPoE possible yet on bridges */
+       return FALSE;
+}
+
+NMADeviceClass *
+applet_device_bridge_get_class (NMApplet *applet)
+{
+       NMADeviceClass *dclass;
+
+       dclass = g_slice_new0 (NMADeviceClass);
+       if (!dclass)
+               return NULL;
+
+       dclass->new_auto_connection = bridge_new_auto_connection;
+       dclass->add_menu_item = bridge_add_menu_item;
+       dclass->notify_connected = bridge_notify_connected;
+       dclass->get_icon = bridge_get_icon;
+       dclass->get_secrets = bridge_get_secrets;
+
+       return dclass;
+}
diff --git a/src/applet-device-bridge.h b/src/applet-device-bridge.h
new file mode 100644
index 0000000..33dc49a
--- /dev/null
+++ b/src/applet-device-bridge.h
@@ -0,0 +1,31 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Wireless Applet -- Display wireless access points and allow user control
+ *
+ * Dan Williams <dcbw redhat com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * (C) Copyright 2008 Red Hat, Inc.
+ * (C) Copyright 2008 Novell, Inc.
+ */
+
+#ifndef __APPLET_DEVICE_BRIDGE_H__
+#define __APPLET_DEVICE_BRIDGE_H__
+
+#include "applet.h"
+
+NMADeviceClass *applet_device_bridge_get_class (NMApplet *applet);
+
+#endif /* __APPLET_DEVICE_BRIDGE_H__ */
diff --git a/src/applet-device-vlan.c b/src/applet-device-vlan.c
new file mode 100644
index 0000000..2f6aa3d
--- /dev/null
+++ b/src/applet-device-vlan.c
@@ -0,0 +1,282 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Wireless Applet -- Display wireless access points and allow user control
+ *
+ * Dan Williams <dcbw redhat com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * (C) Copyright 2008 Red Hat, Inc.
+ * (C) Copyright 2008 Novell, Inc.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+
+#include <nm-device.h>
+#include <nm-setting-connection.h>
+#include <nm-setting-wired.h>
+#include <nm-setting-vlan.h>
+#include <nm-device-ethernet.h>
+#include <nm-device-vlan.h>
+#include <nm-utils.h>
+
+#include "applet.h"
+#include "applet-device-vlan.h"
+#include "nm-ui-utils.h"
+
+static NMDevice *
+find_device_by_iface (const char *iface, const GPtrArray *devices)
+{
+       NMDevice *candidate;
+       int i;
+
+       for (i = 0; i < devices->len; i++) {
+               candidate = devices->pdata[i];
+
+               if (!g_strcmp0 (iface, nm_device_get_iface (candidate)))
+                       return candidate;
+       }
+       return NULL;
+}
+
+static NMDevice *
+find_device_by_mac (const GByteArray *mac, const GPtrArray *devices)
+{
+       NMDevice *candidate, *device = NULL;
+       char *vlan_hw_address, *candidate_hw_address;
+       int i;
+
+       vlan_hw_address = nm_utils_hwaddr_ntoa (mac->data, nm_utils_hwaddr_type (mac->len));
+
+       for (i = 0; i < devices->len && device == NULL; i++) {
+               candidate = devices->pdata[i];
+
+               if (!g_object_class_find_property (G_OBJECT_GET_CLASS (candidate),
+                                                  "hw-address"))
+                       continue;
+
+               g_object_get (G_OBJECT (candidate),
+                             "hw-address", &candidate_hw_address,
+                             NULL);
+               if (!g_strcmp0 (vlan_hw_address, candidate_hw_address))
+                       device = candidate;
+               g_free (candidate_hw_address);
+       }
+       g_free (vlan_hw_address);
+
+       return device;
+}
+
+static NMDevice *
+find_vlan_parent (GSList *connections, NMApplet *applet)
+{
+       const GPtrArray *devices;
+       NMDevice *parent_device;
+       GSList *iter;
+
+       devices = nm_client_get_devices (applet->nm_client);
+       if (!devices)
+               return NULL;
+
+       for (iter = connections; iter; iter = iter->next) {
+               NMConnection *connection = iter->data;
+               NMSettingVlan *s_vlan;
+               const char *parent;
+
+               s_vlan = nm_connection_get_setting_vlan (connection);
+               g_return_val_if_fail (s_vlan != NULL, NULL);
+
+               parent = nm_setting_vlan_get_parent (s_vlan);
+               if (parent && nm_utils_iface_valid_name (parent)) {
+                       parent_device = find_device_by_iface (parent, devices);
+               } else {
+                       NMSettingConnection *s_con;
+                       NMSetting *s_hw;
+                       const char *type;
+                       GByteArray *mac;
+
+                       s_con = nm_connection_get_setting_connection (connection);
+                       type = nm_setting_connection_get_connection_type (s_con);
+                       s_hw = nm_connection_get_setting_by_name (connection, type);
+                       if (!s_hw) {
+                               g_warn_if_reached ();
+                               continue;
+                       }
+
+                       if (!g_object_class_find_property (G_OBJECT_GET_CLASS (s_hw),
+                                                          "mac-address"))
+                               continue;
+
+                       g_object_get (G_OBJECT (s_hw),
+                                     "mac-address", &mac,
+                                     NULL);
+                       if (mac) {
+                               parent_device = find_device_by_mac (mac, devices);
+                               g_byte_array_unref (mac);
+                       } else
+                               parent_device = NULL;
+               }
+               
+               if (parent_device)
+                       return parent_device;
+       }
+
+       return NULL;
+}
+
+static void
+vlan_add_menu_item (NMDevice *device,
+                    gboolean multiple_devices,
+                    GSList *connections,
+                    NMConnection *active,
+                    GtkWidget *menu,
+                    NMApplet *applet)
+{
+       char *text;
+       GtkWidget *item;
+       gboolean carrier = TRUE;
+
+       text = nma_utils_get_connection_device_name (connections->data);
+       item = applet_menu_item_create_device_item_helper (device, applet, text);
+       g_free (text);
+
+       /* If the VLAN device exists, check its carrier */
+       if (device && nm_device_get_capabilities (device) & NM_DEVICE_CAP_CARRIER_DETECT)
+               carrier = nm_device_vlan_get_carrier (NM_DEVICE_VLAN (device));
+       else {
+               NMDevice *parent;
+
+               /* If we can find its parent, check the parent's carrier */
+               parent = find_vlan_parent (connections, applet);
+
+               if (parent && nm_device_get_capabilities (parent) & NM_DEVICE_CAP_CARRIER_DETECT)
+                       g_object_get (G_OBJECT (parent), "carrier", &carrier, NULL);
+       } /* else fall back to assuming carrier is present */           
+
+       gtk_widget_set_sensitive (item, FALSE);
+       gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+       gtk_widget_show (item);
+
+       if (g_slist_length (connections))
+               applet_add_connection_items (device, connections, carrier, active, NMA_ADD_ACTIVE, menu, 
applet);
+
+       /* Notify user of unmanaged or unavailable device */
+       if (device) {
+               item = nma_menu_device_get_menu_item (device, applet, carrier ? NULL : _("disconnected"));
+               if (item) {
+                       gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+                       gtk_widget_show (item);
+               }
+       }
+
+       if (!device || !nma_menu_device_check_unusable (device)) {
+               if ((!active && g_slist_length (connections)) || (active && g_slist_length (connections) > 1))
+                       applet_menu_item_add_complex_separator_helper (menu, applet, _("Available"), -1);
+
+               if (g_slist_length (connections))
+                       applet_add_connection_items (device, connections, carrier, active, NMA_ADD_INACTIVE, 
menu, applet);
+       }
+}
+
+static void
+vlan_notify_connected (NMDevice *device,
+                       const char *msg,
+                       NMApplet *applet)
+{
+       applet_do_notify_with_pref (applet,
+                                   _("Connection Established"),
+                                   msg ? msg : _("You are now connected to the VLAN."),
+                                   "nm-device-wired",
+                                   PREF_DISABLE_CONNECTED_NOTIFICATIONS);
+}
+
+static GdkPixbuf *
+vlan_get_icon (NMDevice *device,
+               NMDeviceState state,
+               NMConnection *connection,
+               char **tip,
+               NMApplet *applet)
+{
+       NMSettingConnection *s_con;
+       GdkPixbuf *pixbuf = NULL;
+       const char *id;
+
+       id = nm_device_get_iface (NM_DEVICE (device));
+       if (connection) {
+               s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (connection, 
NM_TYPE_SETTING_CONNECTION));
+               id = nm_setting_connection_get_id (s_con);
+       }
+
+       switch (state) {
+       case NM_DEVICE_STATE_PREPARE:
+               *tip = g_strdup_printf (_("Preparing VLAN connection '%s'..."), id);
+               break;
+       case NM_DEVICE_STATE_CONFIG:
+               *tip = g_strdup_printf (_("Configuring VLAN connection '%s'..."), id);
+               break;
+       case NM_DEVICE_STATE_NEED_AUTH:
+               *tip = g_strdup_printf (_("User authentication required for VLAN connection '%s'..."), id);
+               break;
+       case NM_DEVICE_STATE_IP_CONFIG:
+               *tip = g_strdup_printf (_("Requesting address for '%s'..."), id);
+               break;
+       case NM_DEVICE_STATE_ACTIVATED:
+               pixbuf = nma_icon_check_and_load ("nm-device-wired", &applet->ethernet_icon, applet);
+               *tip = g_strdup_printf (_("VLAN connection '%s' active"), id);
+               break;
+       default:
+               break;
+       }
+
+       return pixbuf;
+}
+
+static gboolean
+vlan_new_auto_connection (NMDevice *device,
+                          gpointer dclass_data,
+                          AppletNewAutoConnectionCallback callback,
+                          gpointer callback_data)
+{
+       return FALSE;
+}
+
+static gboolean
+vlan_get_secrets (SecretsRequest *req, GError **error)
+{
+       /* No 802.1x or PPPoE possible yet on VLANs */
+       return FALSE;
+}
+
+NMADeviceClass *
+applet_device_vlan_get_class (NMApplet *applet)
+{
+       NMADeviceClass *dclass;
+
+       dclass = g_slice_new0 (NMADeviceClass);
+       if (!dclass)
+               return NULL;
+
+       dclass->new_auto_connection = vlan_new_auto_connection;
+       dclass->add_menu_item = vlan_add_menu_item;
+       dclass->notify_connected = vlan_notify_connected;
+       dclass->get_icon = vlan_get_icon;
+       dclass->get_secrets = vlan_get_secrets;
+
+       return dclass;
+}
diff --git a/src/applet-device-vlan.h b/src/applet-device-vlan.h
new file mode 100644
index 0000000..e905f42
--- /dev/null
+++ b/src/applet-device-vlan.h
@@ -0,0 +1,31 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Wireless Applet -- Display wireless access points and allow user control
+ *
+ * Dan Williams <dcbw redhat com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * (C) Copyright 2008 Red Hat, Inc.
+ * (C) Copyright 2008 Novell, Inc.
+ */
+
+#ifndef __APPLET_DEVICE_VLAN_H__
+#define __APPLET_DEVICE_VLAN_H__
+
+#include "applet.h"
+
+NMADeviceClass *applet_device_vlan_get_class (NMApplet *applet);
+
+#endif /* __APPLET_DEVICE_VLAN_H__ */
diff --git a/src/applet.c b/src/applet.c
index 6f7e0b0..6c39509 100644
--- a/src/applet.c
+++ b/src/applet.c
@@ -45,10 +45,14 @@
 #include <dbus/dbus-glib-lowlevel.h>
 
 #include <NetworkManagerVPN.h>
+#include <nm-device-bond.h>
+#include <nm-device-bridge.h>
+#include <nm-device-bt.h>
 #include <nm-device-ethernet.h>
-#include <nm-device-wifi.h>
+#include <nm-device-infiniband.h>
 #include <nm-device-modem.h>
-#include <nm-device-bt.h>
+#include <nm-device-vlan.h>
+#include <nm-device-wifi.h>
 #include <nm-device-wimax.h>
 #include <nm-utils.h>
 #include <nm-connection.h>
@@ -67,11 +71,14 @@
 #include <libnotify/notify.h>
 
 #include "applet.h"
+#include "applet-device-bond.h"
+#include "applet-device-bridge.h"
+#include "applet-device-bt.h"
+#include "applet-device-cdma.h"
 #include "applet-device-ethernet.h"
-#include "applet-device-wifi.h"
 #include "applet-device-gsm.h"
-#include "applet-device-cdma.h"
-#include "applet-device-bt.h"
+#include "applet-device-vlan.h"
+#include "applet-device-wifi.h"
 #include "applet-device-wimax.h"
 #include "applet-dialogs.h"
 #include "nm-wifi-dialog.h"
@@ -258,6 +265,12 @@ get_device_class (NMDevice *device, NMApplet *applet)
                return applet->bt_class;
        else if (NM_IS_DEVICE_WIMAX (device))
                return applet->wimax_class;
+       else if (NM_IS_DEVICE_VLAN (device))
+               return applet->vlan_class;
+       else if (NM_IS_DEVICE_BOND (device))
+               return applet->bond_class;
+       else if (NM_IS_DEVICE_BRIDGE (device))
+               return applet->bridge_class;
        else
                g_debug ("%s: Unknown device type '%s'", __func__, G_OBJECT_TYPE_NAME (device));
        return NULL;
@@ -292,6 +305,12 @@ get_device_class_from_connection (NMConnection *connection, NMApplet *applet)
                return applet->cdma_class;
        else if (!strcmp (ctype, NM_SETTING_BLUETOOTH_SETTING_NAME))
                return applet->bt_class;
+       else if (!strcmp (ctype, NM_SETTING_BOND_SETTING_NAME))
+               return applet->bond_class;
+       else if (!strcmp (ctype, NM_SETTING_BRIDGE_SETTING_NAME))
+               return applet->bridge_class;
+       else if (!strcmp (ctype, NM_SETTING_VLAN_SETTING_NAME))
+               return applet->vlan_class;
        else
                g_warning ("%s: unhandled connection type '%s'", __func__, ctype);
        return NULL;
@@ -630,8 +649,6 @@ applet_menu_item_activate_helper (NMDevice *device,
        AppletItemActivateInfo *info;
        NMADeviceClass *dclass;
 
-       g_return_if_fail (NM_IS_DEVICE (device));
-
        if (connection) {
                /* If the menu item had an associated connection already, just tell
                 * NM to activate that connection.
@@ -645,6 +662,8 @@ applet_menu_item_activate_helper (NMDevice *device,
                return;
        }
 
+       g_return_if_fail (NM_IS_DEVICE (device));
+
        /* If no connection was given, ask the device class to create a new
         * default connection for this device type.  This could be a wizard,
         * and thus take a while.
@@ -659,10 +678,8 @@ applet_menu_item_activate_helper (NMDevice *device,
        g_assert (dclass);
        if (!dclass->new_auto_connection (device, dclass_data,
                                          applet_menu_item_activate_helper_new_connection,
-                                         info)) {
-               g_warning ("Couldn't create default connection.");
+                                         info))
                applet_item_activate_info_destroy (info);
-       }
 }
 
 void
@@ -1340,49 +1357,17 @@ static void nma_menu_add_text_item (GtkWidget *menu, char *text)
 }
 
 static gint
-sort_devices (gconstpointer a, gconstpointer b)
+sort_devices_by_description (gconstpointer a, gconstpointer b)
 {
        NMDevice *aa = NM_DEVICE (a);
        NMDevice *bb = NM_DEVICE (b);
-       GType aa_type = G_OBJECT_TYPE (G_OBJECT (aa));
-       GType bb_type = G_OBJECT_TYPE (G_OBJECT (bb));
-
-       if (aa_type == bb_type) {
-               const char *aa_desc = NULL;
-               const char *bb_desc = NULL;
+       const char *aa_desc;
+       const char *bb_desc;
 
-               aa_desc = nma_utils_get_device_description (aa);
-               bb_desc = nma_utils_get_device_description (bb);
-
-               return g_strcmp0 (aa_desc, bb_desc);
-       }
+       aa_desc = nma_utils_get_device_description (aa);
+       bb_desc = nma_utils_get_device_description (bb);
 
-       /* Ethernet always first */
-       if (aa_type == NM_TYPE_DEVICE_ETHERNET)
-               return -1;
-       if (bb_type == NM_TYPE_DEVICE_ETHERNET)
-               return 1;
-
-       /* Modems next */
-       if (aa_type == NM_TYPE_DEVICE_MODEM)
-               return -1;
-       if (bb_type == NM_TYPE_DEVICE_MODEM)
-               return 1;
-
-       /* Bluetooth next */
-       if (aa_type == NM_TYPE_DEVICE_BT)
-               return -1;
-       if (bb_type == NM_TYPE_DEVICE_BT)
-               return 1;
-
-       /* WiMAX next */
-       if (aa_type == NM_TYPE_DEVICE_WIMAX)
-               return -1;
-       if (bb_type == NM_TYPE_DEVICE_WIMAX)
-               return 1;
-
-       /* WiFi last because it has many menu items */
-       return 1;
+       return g_strcmp0 (aa_desc, bb_desc);
 }
 
 static gboolean
@@ -1440,6 +1425,47 @@ applet_find_active_connection_for_device (NMDevice *device,
        return connection;
 }
 
+static NMConnection *
+applet_find_active_connection_for_virtual_device (const char *iface,
+                                                  NMApplet *applet,
+                                                  NMActiveConnection **out_active)
+{
+       const GPtrArray *active_connections;
+       NMConnection *connection = NULL;
+       int i;
+
+       g_return_val_if_fail (iface != NULL, NULL);
+       g_return_val_if_fail (NM_IS_APPLET (applet), NULL);
+       if (out_active)
+               g_return_val_if_fail (*out_active == NULL, NULL);
+
+       active_connections = nm_client_get_active_connections (applet->nm_client);
+       for (i = 0; active_connections && (i < active_connections->len); i++) {
+               NMRemoteConnection *tmp;
+               NMActiveConnection *active;
+               const char *connection_path;
+
+               active = NM_ACTIVE_CONNECTION (g_ptr_array_index (active_connections, i));
+               connection_path = nm_active_connection_get_connection (active);
+
+               if (!connection_path)
+                       continue;
+
+               tmp = nm_remote_settings_get_connection_by_path (applet->settings, connection_path);
+               if (!tmp)
+                       continue;
+
+               if (!g_strcmp0 (nm_connection_get_virtual_iface_name (NM_CONNECTION (tmp)), iface)) {
+                       connection = NM_CONNECTION (tmp);
+                       if (out_active)
+                               *out_active = active;
+                       break;
+               }
+       }
+
+       return connection;
+}
+
 gboolean
 nma_menu_device_check_unusable (NMDevice *device)
 {
@@ -1539,89 +1565,154 @@ nma_menu_device_get_menu_item (NMDevice *device,
        return item;
 }
 
-static guint32
-nma_menu_add_devices (GtkWidget *menu, NMApplet *applet)
+static int
+add_device_items (NMDeviceType type, const GPtrArray *all_devices, GSList *all_connections,
+                  GtkWidget *menu, NMApplet *applet)
 {
-       const GPtrArray *temp = NULL;
-       GSList *devices = NULL, *iter = NULL;
-       gint n_wifi_devices = 0;
-       gint n_usable_wifi_devices = 0;
-       gint n_ethernet_devices = 0;
-       gint n_mb_devices = 0;
-       gint n_bt_devices = 0;
-       int i;
+       GSList *devices = NULL, *iter;
+       int i, n_devices = 0;
 
-       temp = nm_client_get_devices (applet->nm_client);
-       for (i = 0; temp && (i < temp->len); i++)
-               devices = g_slist_insert_sorted (devices, g_ptr_array_index (temp, i), sort_devices);
+       for (i = 0; all_devices && (i < all_devices->len); i++) {
+               NMDevice *device = all_devices->pdata[i];
+
+               if (nm_device_get_device_type (device) == type) {
+                       n_devices++;
+                       devices = g_slist_prepend (devices, device);
+               }
+       }
+       devices = g_slist_sort (devices, sort_devices_by_description);
 
        for (iter = devices; iter; iter = iter->next) {
-               NMDevice *device = NM_DEVICE (iter->data);
+               NMDevice *device = iter->data;
+               NMADeviceClass *dclass;
+               NMConnection *active;
+               GSList *connections;
+
+               dclass = get_device_class (device, applet);
+               g_assert (dclass != NULL);
+
+               connections = nm_device_filter_connections (device, all_connections);
+               active = applet_find_active_connection_for_device (device, applet, NULL);
+
+               dclass->add_menu_item (device, n_devices > 1, connections, active, menu, applet);
+
+               g_slist_free (connections);
+       }
+
+       g_slist_free (devices);
+       return n_devices;
+}
+
+static gint
+sort_devices_by_interface (gconstpointer a, gconstpointer b)
+{
+       NMConnection *aa = NM_CONNECTION (a);
+       NMConnection *bb = NM_CONNECTION (b);
+
+       return strcmp (nm_connection_get_virtual_iface_name (aa),
+                      nm_connection_get_virtual_iface_name (bb));
+}
 
-               /* Ignore unsupported devices */
-               if (!(nm_device_get_capabilities (device) & NM_DEVICE_CAP_NM_SUPPORTED))
+static int
+add_virtual_items (const char *type, const GPtrArray *all_devices,
+                   GSList *all_connections, GtkWidget *menu, NMApplet *applet)
+{
+       GSList *iter, *connections = NULL;
+       int n_devices = 0;
+
+       for (iter = all_connections; iter; iter = iter->next) {
+               NMConnection *connection = iter->data;
+
+               if (!nm_connection_get_virtual_iface_name (connection))
                        continue;
 
-               if (NM_IS_DEVICE_WIFI (device)) {
-                       n_wifi_devices++;
-                       if (   nm_client_wireless_get_enabled (applet->nm_client)
-                           && (nm_device_get_state (device) >= NM_DEVICE_STATE_DISCONNECTED))
-                               n_usable_wifi_devices++;
-               } else if (NM_IS_DEVICE_ETHERNET (device))
-                       n_ethernet_devices++;
-               else if (NM_IS_DEVICE_MODEM (device))
-                       n_mb_devices++;
-               else if (NM_IS_DEVICE_BT (device))
-                       n_bt_devices++;
+               if (nm_connection_is_type (connection, type))
+                       connections = g_slist_prepend (connections, connection);
        }
 
-       if (!n_ethernet_devices && !n_wifi_devices && !n_mb_devices && !n_bt_devices) {
-               nma_menu_add_text_item (menu, _("No network devices available"));
-               goto out;
+       if (!connections)
+               return 0;
+
+       connections = g_slist_sort (connections, sort_devices_by_interface);
+       /* Count the number of unique interface names */
+       iter = connections;
+       while (iter) {
+               NMConnection *connection = iter->data;
+
+               n_devices++;
+               while (iter && sort_devices_by_interface (connection, iter->data) == 0)
+                       iter = iter->next;
        }
 
-       /* Add all devices in our device list to the menu */
-       for (iter = devices; iter; iter = iter->next) {
-               NMDevice *device = NM_DEVICE (iter->data);
-               gint n_devices;
+
+       iter = connections;
+       while (iter) {
+               NMConnection *connection = iter->data;
+               NMDevice *device = NULL;
+               const char *iface = nm_connection_get_virtual_iface_name (connection);
+               GSList *iface_connections = NULL;
                NMADeviceClass *dclass;
                NMConnection *active;
-               GSList *all, *connections;
+               int i;
 
-               /* Ignore unsupported devices */
-               if (!(nm_device_get_capabilities (device) & NM_DEVICE_CAP_NM_SUPPORTED))
-                       continue;
-               dclass = get_device_class (device, applet);
-               if (!dclass)
-                       continue;
+               for (i = 0; all_devices && (i < all_devices->len); i++) {
+                       NMDevice *candidate = all_devices->pdata[i];
 
-               if (NM_IS_DEVICE_WIFI (device))
-                       n_devices = n_wifi_devices;
-               else if (NM_IS_DEVICE_ETHERNET (device))
-                       n_devices = n_ethernet_devices;
-               else if (NM_IS_DEVICE_MODEM (device))
-                       n_devices = n_mb_devices;
-               else
-                       n_devices = 0;
+                       if (!strcmp (nm_device_get_iface (candidate), iface)) {
+                               device = candidate;
+                               break;
+                       }
+               }
 
-               all = applet_get_all_connections (applet);
-               connections = nm_device_filter_connections (device, all);
-               g_slist_free (all);
+               while (iter && sort_devices_by_interface (connection, iter->data) == 0) {
+                       iface_connections = g_slist_prepend (iface_connections, connection);
+                       iter = iter->next;
+               }
 
-               active = applet_find_active_connection_for_device (device, applet, NULL);
+               active = applet_find_active_connection_for_virtual_device (iface, applet, NULL);
 
-               dclass->add_menu_item (device, n_devices > 1, connections, active, menu, applet);
+               dclass = get_device_class_from_connection (connection, applet);
+               dclass->add_menu_item (device, n_devices > 1, iface_connections, active, menu, applet);
 
-               g_slist_free (connections);
+               g_slist_free (iface_connections);
        }
 
- out:
-       g_slist_free (devices);
+       g_slist_free (connections);
+       return n_devices;
+}
 
-       /* Return # of usable wifi devices here for correct enable/disable state
-        * of things like Enable Wi-Fi, "Connect to other..." and such.
-        */
-       return n_usable_wifi_devices;
+static void
+nma_menu_add_devices (GtkWidget *menu, NMApplet *applet)
+{
+       const GPtrArray *all_devices;
+       GSList *all_connections;
+       gint n_items;
+
+       all_connections = applet_get_all_connections (applet);
+       all_devices = nm_client_get_devices (applet->nm_client);
+
+       n_items = 0;
+       n_items += add_virtual_items (NM_SETTING_BRIDGE_SETTING_NAME,
+                                     all_devices, all_connections, menu, applet);
+       n_items += add_virtual_items (NM_SETTING_BOND_SETTING_NAME,
+                                     all_devices, all_connections, menu, applet);
+       n_items += add_device_items  (NM_DEVICE_TYPE_ETHERNET,
+                                     all_devices, all_connections, menu, applet);
+       n_items += add_device_items  (NM_DEVICE_TYPE_INFINIBAND,
+                                     all_devices, all_connections, menu, applet);
+       n_items += add_virtual_items (NM_SETTING_VLAN_SETTING_NAME,
+                                     all_devices, all_connections, menu, applet);
+       n_items += add_device_items  (NM_DEVICE_TYPE_WIFI,
+                                     all_devices, all_connections, menu, applet);
+       n_items += add_device_items  (NM_DEVICE_TYPE_MODEM,
+                                     all_devices, all_connections, menu, applet);
+       n_items += add_device_items  (NM_DEVICE_TYPE_BT,
+                                     all_devices, all_connections, menu, applet);
+
+       g_slist_free (all_connections);
+
+       if (!n_items)
+               nma_menu_add_text_item (menu, _("No network devices available"));
 }
 
 static int
@@ -1813,6 +1904,30 @@ nma_set_notifications_enabled_cb (GtkWidget *widget, NMApplet *applet)
                                !state);
 }
 
+static gboolean
+has_usable_wifi (NMApplet *applet)
+{
+       const GPtrArray *devices;
+       int i;
+
+       if (!nm_client_wireless_get_enabled (applet->nm_client))
+               return FALSE;
+
+       devices = nm_client_get_devices (applet->nm_client);
+       if (!devices)
+               return FALSE;
+
+       for (i = 0; i < devices->len; i++) {
+               NMDevice *device = devices->pdata[i];
+
+               if (   NM_IS_DEVICE_WIFI (device)
+                   && (nm_device_get_state (device) >= NM_DEVICE_STATE_DISCONNECTED))
+                       return TRUE;
+       }
+
+       return FALSE;
+}
+
 /*
  * nma_menu_show_cb
  *
@@ -1821,8 +1936,6 @@ nma_set_notifications_enabled_cb (GtkWidget *widget, NMApplet *applet)
  */
 static void nma_menu_show_cb (GtkWidget *menu, NMApplet *applet)
 {
-       guint32 n_wifi;
-
        g_return_if_fail (menu != NULL);
        g_return_if_fail (applet != NULL);
 
@@ -1838,11 +1951,10 @@ static void nma_menu_show_cb (GtkWidget *menu, NMApplet *applet)
                return;
        }
 
-       n_wifi = nma_menu_add_devices (menu, applet);
-
+       nma_menu_add_devices (menu, applet);
        nma_menu_add_vpn_submenu (menu, applet);
 
-       if (n_wifi > 0 && nm_client_wireless_get_enabled (applet->nm_client)) {
+       if (has_usable_wifi (applet)) {
                /* Add the "Hidden Wi-Fi network..." entry */
                nma_menu_add_separator_item (menu);
                nma_menu_add_hidden_network_item (menu, applet);
@@ -2015,7 +2127,7 @@ ce_child_setup (gpointer user_data G_GNUC_UNUSED)
 }
 
 static void
-nma_edit_connections_cb (GtkMenuItem *mi, NMApplet *applet)
+nma_edit_connections_cb (void)
 {
        char *argv[2];
        GError *error = NULL;
@@ -2206,7 +2318,7 @@ applet_add_connection_items (NMDevice *device,
 
                info = g_slice_new0 (AppletMenuItemInfo);
                info->applet = applet;
-               info->device = g_object_ref (device);
+               info->device = device ? g_object_ref (device) : NULL;
                info->connection = g_object_ref (connection);
 
                g_signal_connect_data (item, "activate",
@@ -3598,6 +3710,15 @@ constructor (GType type,
        applet->wimax_class = applet_device_wimax_get_class (applet);
        g_assert (applet->wimax_class);
 
+       applet->vlan_class = applet_device_vlan_get_class (applet);
+       g_assert (applet->vlan_class);
+
+       applet->bond_class = applet_device_bond_get_class (applet);
+       g_assert (applet->bond_class);
+
+       applet->bridge_class = applet_device_bridge_get_class (applet);
+       g_assert (applet->bridge_class);
+
        foo_client_setup (applet);
 
 #if WITH_MODEM_MANAGER_1
@@ -3640,6 +3761,9 @@ static void finalize (GObject *object)
 #endif
        g_slice_free (NMADeviceClass, applet->bt_class);
        g_slice_free (NMADeviceClass, applet->wimax_class);
+       g_slice_free (NMADeviceClass, applet->vlan_class);
+       g_slice_free (NMADeviceClass, applet->bond_class);
+       g_slice_free (NMADeviceClass, applet->bridge_class);
 
        if (applet->update_icon_id)
                g_source_remove (applet->update_icon_id);
diff --git a/src/applet.h b/src/applet.h
index 45a9723..1040fe5 100644
--- a/src/applet.h
+++ b/src/applet.h
@@ -116,6 +116,9 @@ typedef struct
 #endif
        NMADeviceClass *bt_class;
        NMADeviceClass *wimax_class;
+       NMADeviceClass *vlan_class;
+       NMADeviceClass *bond_class;
+       NMADeviceClass *bridge_class;
 
        /* Data model elements */
        guint                   update_icon_id;



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]