[NetworkManager/f21] bluetooth: Restore DUN support (rh #1055628)

Lubomir Rintel lkundrak at fedoraproject.org
Thu Oct 16 12:24:40 UTC 2014


commit 335e63c781dc039b37a4ae045e9135fbc06b293c
Author: Lubomir Rintel <lkundrak at v3.sk>
Date:   Thu Oct 16 13:50:40 2014 +0200

    bluetooth: Restore DUN support (rh #1055628)

 ...dns1-dns2.patch => 0000-explain-dns1-dns2.patch |    0
 ...w-non-local-admin-sessions-to-control-the.patch |   14 +-
 0002-bluez-split-out-errors.patch                  |  171 ++++
 ...ez-track-adapter-address-in-NMBluezDevice.patch |  147 ++++
 0004-bluez-re-add-DUN-support-for-Bluez5.patch     |  810 ++++++++++++++++++++
 NetworkManager.spec                                |   31 +-
 6 files changed, 1160 insertions(+), 13 deletions(-)
---
diff --git a/0001-explain-dns1-dns2.patch b/0000-explain-dns1-dns2.patch
similarity index 100%
rename from 0001-explain-dns1-dns2.patch
rename to 0000-explain-dns1-dns2.patch
diff --git a/non-local-session-polkit.patch b/0001-policy-allow-non-local-admin-sessions-to-control-the.patch
similarity index 61%
rename from non-local-session-polkit.patch
rename to 0001-policy-allow-non-local-admin-sessions-to-control-the.patch
index 401a9a5..5086775 100644
--- a/non-local-session-polkit.patch
+++ b/0001-policy-allow-non-local-admin-sessions-to-control-the.patch
@@ -1,14 +1,16 @@
-From f044ff186b433ef3debab7651adc06115809afc6 Mon Sep 17 00:00:00 2001
+From 2a10b58fad810aca1a041cd37b00241ace9be0c7 Mon Sep 17 00:00:00 2001
 From: Marius Vollmer <mvollmer at redhat.com>
-Date: Mon, 6 Oct 2014 11:16:03 +0300
-Subject: [PATCH] policy: allow non-local admin sessions to control the network (rh #1145646)
+Date: Mon, 13 Oct 2014 15:58:46 -0500
+Subject: [PATCH 1/4] policy: allow non-local admin sessions to control the
+ network (rh #1145646)
 
+(cherry picked from commit 4f950ee5692e57bbc9737720adfd7ad6788dabb7)
 ---
- policy/org.freedesktop.NetworkManager.policy.in.in | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
+ policy/org.freedesktop.NetworkManager.policy.in.in | 1 +
+ 1 file changed, 1 insertion(+)
 
 diff --git a/policy/org.freedesktop.NetworkManager.policy.in.in b/policy/org.freedesktop.NetworkManager.policy.in.in
-index cb22999..e103cd9 100644
+index cb22999..daefd80 100644
 --- a/policy/org.freedesktop.NetworkManager.policy.in.in
 +++ b/policy/org.freedesktop.NetworkManager.policy.in.in
 @@ -58,6 +58,7 @@
diff --git a/0002-bluez-split-out-errors.patch b/0002-bluez-split-out-errors.patch
new file mode 100644
index 0000000..6d3d438
--- /dev/null
+++ b/0002-bluez-split-out-errors.patch
@@ -0,0 +1,171 @@
+From 616d032c62f0d02be7ec29ff012c45c284f397a8 Mon Sep 17 00:00:00 2001
+From: Dan Williams <dcbw at redhat.com>
+Date: Mon, 16 Jun 2014 11:04:06 -0500
+Subject: [PATCH 2/4] bluez: split out errors
+
+We'll use them from more places than nm nm-bt-device.c in the future.
+
+(cherry picked from commit 5254ac456ecd2f5ef76b0a1937f52b75e319f204)
+---
+ src/devices/bluetooth/Makefile.am    |  4 +++-
+ src/devices/bluetooth/nm-bt-error.c  | 33 +++++++++++++++++++++++++++++++++
+ src/devices/bluetooth/nm-bt-error.h  | 35 +++++++++++++++++++++++++++++++++++
+ src/devices/bluetooth/nm-device-bt.c | 13 ++-----------
+ src/devices/bluetooth/nm-device-bt.h |  6 ------
+ 5 files changed, 73 insertions(+), 18 deletions(-)
+ create mode 100644 src/devices/bluetooth/nm-bt-error.c
+ create mode 100644 src/devices/bluetooth/nm-bt-error.h
+
+diff --git a/src/devices/bluetooth/Makefile.am b/src/devices/bluetooth/Makefile.am
+index 639a1ad..4342d4b 100644
+--- a/src/devices/bluetooth/Makefile.am
++++ b/src/devices/bluetooth/Makefile.am
+@@ -24,7 +24,7 @@ AM_CPPFLAGS = \
+ GLIB_GENERATED = nm-bt-enum-types.h nm-bt-enum-types.c
+ GLIB_MKENUMS_H_FLAGS = --identifier-prefix NM
+ GLIB_MKENUMS_C_FLAGS = --identifier-prefix NM
+-nm_bt_enum_types_sources = $(srcdir)/nm-device-bt.h
++nm_bt_enum_types_sources = $(srcdir)/nm-bt-error.h
+ 
+ nm-device-bt-glue.h: $(top_srcdir)/introspection/nm-device-bt.xml
+ 	dbus-binding-tool --prefix=nm_device_bt --mode=glib-server --output=$@ $<
+@@ -47,6 +47,8 @@ libnm_device_plugin_bluetooth_la_SOURCES = \
+ 	nm-bluez4-manager.h \
+ 	nm-bluez5-manager.c \
+ 	nm-bluez5-manager.h \
++	nm-bt-error.h \
++	nm-bt-error.c \
+ 	\
+ 	nm-device-bt.c \
+ 	nm-device-bt.h \
+diff --git a/src/devices/bluetooth/nm-bt-error.c b/src/devices/bluetooth/nm-bt-error.c
+new file mode 100644
+index 0000000..d014a10
+--- /dev/null
++++ b/src/devices/bluetooth/nm-bt-error.c
+@@ -0,0 +1,33 @@
++/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
++/* NetworkManager -- Network link manager
++ *
++ * 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.
++ *
++ * Copyright (C) 2014 Red Hat, Inc.
++ */
++
++#include <glib.h>
++#include "nm-bt-error.h"
++
++GQuark
++nm_bt_error_quark (void)
++{
++	static GQuark quark = 0;
++	if (!quark)
++		quark = g_quark_from_static_string ("nm-bt-error");
++	return quark;
++}
++
++
+diff --git a/src/devices/bluetooth/nm-bt-error.h b/src/devices/bluetooth/nm-bt-error.h
+new file mode 100644
+index 0000000..fa3a957
+--- /dev/null
++++ b/src/devices/bluetooth/nm-bt-error.h
+@@ -0,0 +1,35 @@
++/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
++/* NetworkManager -- Network link manager
++ *
++ * 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.
++ *
++ * Copyright (C) 2014 Red Hat, Inc.
++ */
++
++#ifndef _NM_BLUEZ5_ERROR_H_
++#define _NM_BLUEZ5_ERROR_H_
++
++typedef enum {
++	NM_BT_ERROR_CONNECTION_NOT_BT = 0,   /*< nick=ConnectionNotBt >*/
++	NM_BT_ERROR_CONNECTION_INVALID,      /*< nick=ConnectionInvalid >*/
++	NM_BT_ERROR_CONNECTION_INCOMPATIBLE, /*< nick=ConnectionIncompatible >*/
++	NM_BT_ERROR_DUN_CONNECT_FAILED,      /*< nick=DunConnectFailed >*/
++} NMBtError;
++
++#define NM_BT_ERROR (nm_bt_error_quark ())
++GQuark nm_bt_error_quark (void);
++
++#endif  /* _NM_BT_ERROR_H_ */
++
+diff --git a/src/devices/bluetooth/nm-device-bt.c b/src/devices/bluetooth/nm-device-bt.c
+index 6e1a399..ca3deb2 100644
+--- a/src/devices/bluetooth/nm-device-bt.c
++++ b/src/devices/bluetooth/nm-device-bt.c
+@@ -46,6 +46,8 @@
+ #include "NetworkManagerUtils.h"
+ #include "nm-bt-enum-types.h"
+ #include "nm-utils.h"
++#include "nm-bt-error.h"
++#include "nm-bt-enum-types.h"
+ 
+ #define MM_OLD_DBUS_SERVICE  "org.freedesktop.ModemManager"
+ #define MM_NEW_DBUS_SERVICE  "org.freedesktop.ModemManager1"
+@@ -94,17 +96,6 @@ enum {
+ static guint signals[LAST_SIGNAL] = { 0 };
+ 
+ 
+-#define NM_BT_ERROR (nm_bt_error_quark ())
+-
+-static GQuark
+-nm_bt_error_quark (void)
+-{
+-	static GQuark quark = 0;
+-	if (!quark)
+-		quark = g_quark_from_static_string ("nm-bt-error");
+-	return quark;
+-}
+-
+ guint32 nm_device_bt_get_capabilities (NMDeviceBt *self)
+ {
+ 	g_return_val_if_fail (NM_IS_DEVICE_BT (self), NM_BT_CAPABILITY_NONE);
+diff --git a/src/devices/bluetooth/nm-device-bt.h b/src/devices/bluetooth/nm-device-bt.h
+index 83732bc..ac5b115 100644
+--- a/src/devices/bluetooth/nm-device-bt.h
++++ b/src/devices/bluetooth/nm-device-bt.h
+@@ -34,12 +34,6 @@ G_BEGIN_DECLS
+ #define NM_IS_DEVICE_BT_CLASS(klass)	(G_TYPE_CHECK_CLASS_TYPE ((klass),  NM_TYPE_DEVICE_BT))
+ #define NM_DEVICE_BT_GET_CLASS(obj)	(G_TYPE_INSTANCE_GET_CLASS ((obj),  NM_TYPE_DEVICE_BT, NMDeviceBtClass))
+ 
+-typedef enum {
+-	NM_BT_ERROR_CONNECTION_NOT_BT = 0,   /*< nick=ConnectionNotBt >*/
+-	NM_BT_ERROR_CONNECTION_INVALID,      /*< nick=ConnectionInvalid >*/
+-	NM_BT_ERROR_CONNECTION_INCOMPATIBLE, /*< nick=ConnectionIncompatible >*/
+-} NMBtError;
+-
+ #define NM_DEVICE_BT_NAME         "name"
+ #define NM_DEVICE_BT_CAPABILITIES "bt-capabilities"
+ #define NM_DEVICE_BT_DEVICE       "bt-device"
+-- 
+1.9.3
+
diff --git a/0003-bluez-track-adapter-address-in-NMBluezDevice.patch b/0003-bluez-track-adapter-address-in-NMBluezDevice.patch
new file mode 100644
index 0000000..a50219f
--- /dev/null
+++ b/0003-bluez-track-adapter-address-in-NMBluezDevice.patch
@@ -0,0 +1,147 @@
+From d59bd3c9b57e55b20fd4d2e4781a8da123546f4d Mon Sep 17 00:00:00 2001
+From: Dan Williams <dcbw at redhat.com>
+Date: Mon, 16 Jun 2014 10:20:29 -0500
+Subject: [PATCH 3/4] bluez: track adapter address in NMBluezDevice
+
+We'll need it for bluez5 DUN support.
+
+[lkundrak at v3.sk: Turn the addresses to strings from guint8[ETH_ALEN], as that
+is what rest of NetworkManager uses for MAC addresses and what Bluez utility
+functions expect as well.]
+
+(cherry picked from commit 384ec8606488e67433753eb52440b4846a3090e7)
+---
+ src/devices/bluetooth/nm-bluez-device.c   | 29 ++++++++++++++++++++++++++---
+ src/devices/bluetooth/nm-bluez-device.h   |  5 ++++-
+ src/devices/bluetooth/nm-bluez4-adapter.c |  2 +-
+ src/devices/bluetooth/nm-bluez5-manager.c |  2 +-
+ 4 files changed, 32 insertions(+), 6 deletions(-)
+
+diff --git a/src/devices/bluetooth/nm-bluez-device.c b/src/devices/bluetooth/nm-bluez-device.c
+index 4c448a3..edebb75 100644
+--- a/src/devices/bluetooth/nm-bluez-device.c
++++ b/src/devices/bluetooth/nm-bluez-device.c
+@@ -55,6 +55,7 @@ typedef struct {
+ 	gboolean usable;
+ 	NMBluetoothCapabilities connection_bt_type;
+ 
++	char *adapter_address;
+ 	char *address;
+ 	guint8 bin_address[ETH_ALEN];
+ 	char *name;
+@@ -270,7 +271,7 @@ check_emit_usable (NMBluezDevice *self)
+ 	new_usable = (priv->initialized && priv->capabilities && priv->name &&
+ 	              ((priv->bluez_version == 4) ||
+ 	               (priv->bluez_version == 5 && priv->adapter5 && priv->adapter_powered) ) &&
+-	              priv->dbus_connection && priv->address);
++	              priv->dbus_connection && priv->address && priv->adapter_address);
+ 
+ 	if (!new_usable)
+ 		goto END;
+@@ -558,6 +559,18 @@ nm_bluez_device_connect_finish (NMBluezDevice *self,
+ 
+ /***********************************************************/
+ 
++static void
++set_adapter_address (NMBluezDevice *self, const char *address)
++{
++	NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self);
++
++	g_return_if_fail (address);
++
++	if (priv->adapter_address)
++		g_free (priv->adapter_address);
++	priv->adapter_address = g_strdup (address);
++}
++
+ static guint32
+ convert_uuids_to_capabilities (const char **strings, int bluez_version)
+ {
+@@ -752,6 +765,10 @@ adapter5_on_acquired (GObject *object, GAsyncResult *res, NMBluezDevice *self)
+ 		if (v)
+ 			g_variant_unref (v);
+ 
++		v = g_dbus_proxy_get_cached_property (priv->adapter5, "Address");
++		if (VARIANT_IS_OF_TYPE_STRING (v))
++			set_adapter_address (self, g_variant_get_string (v, NULL));
++
+ 		priv->initialized = TRUE;
+ 		g_signal_emit (self, signals[INITIALIZED], 0, TRUE);
+ 
+@@ -957,7 +974,10 @@ on_bus_acquired (GObject *object, GAsyncResult *res, NMBluezDevice *self)
+ /********************************************************************/
+ 
+ NMBluezDevice *
+-nm_bluez_device_new (const char *path, NMConnectionProvider *provider, int bluez_version)
++nm_bluez_device_new (const char *path,
++                     const char *adapter_address,
++                     NMConnectionProvider *provider,
++                     int bluez_version)
+ {
+ 	NMBluezDevice *self;
+ 	NMBluezDevicePrivate *priv;
+@@ -978,8 +998,10 @@ nm_bluez_device_new (const char *path, NMConnectionProvider *provider, int bluez
+ 	priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self);
+ 
+ 	priv->bluez_version = bluez_version;
+-
+ 	priv->provider = provider;
++	g_return_val_if_fail (bluez_version == 5 || (bluez_version == 4 && adapter_address), NULL);
++	if (adapter_address)
++		set_adapter_address (self, adapter_address);
+ 
+ 	g_signal_connect (priv->provider,
+ 	                  NM_CP_SIGNAL_CONNECTION_ADDED,
+@@ -1073,6 +1095,7 @@ finalize (GObject *object)
+ 	nm_log_dbg (LOGD_BT, "bluez[%s]: finalize NMBluezDevice", priv->path);
+ 
+ 	g_free (priv->path);
++	g_free (priv->adapter_address);
+ 	g_free (priv->address);
+ 	g_free (priv->name);
+ 	g_free (priv->bt_iface);
+diff --git a/src/devices/bluetooth/nm-bluez-device.h b/src/devices/bluetooth/nm-bluez-device.h
+index 0bf7d89..25891a0 100644
+--- a/src/devices/bluetooth/nm-bluez-device.h
++++ b/src/devices/bluetooth/nm-bluez-device.h
+@@ -62,7 +62,10 @@ typedef struct {
+ 
+ GType nm_bluez_device_get_type (void);
+ 
+-NMBluezDevice *nm_bluez_device_new (const char *path, NMConnectionProvider *provider, int bluez_version);
++NMBluezDevice *nm_bluez_device_new (const char *path,
++                                    const char *adapter_address,
++                                    NMConnectionProvider *provider,
++                                    int bluez_version);
+ 
+ const char *nm_bluez_device_get_path (NMBluezDevice *self);
+ 
+diff --git a/src/devices/bluetooth/nm-bluez4-adapter.c b/src/devices/bluetooth/nm-bluez4-adapter.c
+index ad1786f..9c57d97 100644
+--- a/src/devices/bluetooth/nm-bluez4-adapter.c
++++ b/src/devices/bluetooth/nm-bluez4-adapter.c
+@@ -162,7 +162,7 @@ device_created (DBusGProxy *proxy, const char *path, gpointer user_data)
+ 	NMBluez4AdapterPrivate *priv = NM_BLUEZ4_ADAPTER_GET_PRIVATE (self);
+ 	NMBluezDevice *device;
+ 
+-	device = nm_bluez_device_new (path, priv->provider, 4);
++	device = nm_bluez_device_new (path, priv->address, priv->provider, 4);
+ 	g_signal_connect (device, "initialized", G_CALLBACK (device_initialized), self);
+ 	g_signal_connect (device, "notify::usable", G_CALLBACK (device_usable), self);
+ 	g_hash_table_insert (priv->devices, (gpointer) nm_bluez_device_get_path (device), device);
+diff --git a/src/devices/bluetooth/nm-bluez5-manager.c b/src/devices/bluetooth/nm-bluez5-manager.c
+index 63006b3..8653c28 100644
+--- a/src/devices/bluetooth/nm-bluez5-manager.c
++++ b/src/devices/bluetooth/nm-bluez5-manager.c
+@@ -143,7 +143,7 @@ device_added (GDBusProxy *proxy, const gchar *path, NMBluez5Manager *self)
+ 	NMBluez5ManagerPrivate *priv = NM_BLUEZ5_MANAGER_GET_PRIVATE (self);
+ 	NMBluezDevice *device;
+ 
+-	device = nm_bluez_device_new (path, priv->provider, 5);
++	device = nm_bluez_device_new (path, NULL, priv->provider, 5);
+ 	g_signal_connect (device, "initialized", G_CALLBACK (device_initialized), self);
+ 	g_signal_connect (device, "notify::usable", G_CALLBACK (device_usable), self);
+ 	g_hash_table_insert (priv->devices, (gpointer) nm_bluez_device_get_path (device), device);
+-- 
+1.9.3
+
diff --git a/0004-bluez-re-add-DUN-support-for-Bluez5.patch b/0004-bluez-re-add-DUN-support-for-Bluez5.patch
new file mode 100644
index 0000000..7797781
--- /dev/null
+++ b/0004-bluez-re-add-DUN-support-for-Bluez5.patch
@@ -0,0 +1,810 @@
+From 2ca59ef657b1f2a584807adea923589e5a4470a1 Mon Sep 17 00:00:00 2001
+From: Lubomir Rintel <lkundrak at v3.sk>
+Date: Wed, 1 Oct 2014 10:59:13 +0200
+Subject: [PATCH 4/4] bluez: re-add DUN support for Bluez5
+
+This adds service discovery via SDP and RFCOMM tty management to
+NetworkManager, as it was dropped from Bluez.
+
+Based on work by Dan Williams <dcbw at redhat.com>.
+The SDP discovery is based on code from Bluez project.
+
+(cherry picked from commit f1c9595311f52d8b79e8d2032e006005613a8fb1)
+---
+[lkundrak at v3.sk: contrib/fedora/rpm/NetworkManager.spec hunk removed for RPM]
+
+ configure.ac                            |  14 ++
+ contrib/fedora/rpm/NetworkManager.spec  |   3 +
+ src/devices/bluetooth/Makefile.am       |  10 +
+ src/devices/bluetooth/nm-bluez-device.c | 134 +++++++----
+ src/devices/bluetooth/nm-bluez5-dun.c   | 409 ++++++++++++++++++++++++++++++++
+ src/devices/bluetooth/nm-bluez5-dun.h   |  46 ++++
+ 6 files changed, 573 insertions(+), 43 deletions(-)
+ create mode 100644 src/devices/bluetooth/nm-bluez5-dun.c
+ create mode 100644 src/devices/bluetooth/nm-bluez5-dun.h
+
+diff --git a/configure.ac b/configure.ac
+index d4437a6..d1ba66a 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -586,6 +586,20 @@ else
+ fi
+ AM_CONDITIONAL(WITH_MODEM_MANAGER_1, test "${with_modem_manager_1}" = "yes")
+ 
++# Bluez5 DUN support
++PKG_CHECK_MODULES(BLUEZ5, [bluez >= 5], [have_bluez5=yes],[have_bluez5=no])
++AC_ARG_ENABLE(bluez5-dun, AS_HELP_STRING([--enable-bluez5-dun], [enable Bluez5 DUN support]),
++		[enable_bluez5_dun=${enableval}], [enable_bluez5_dun=${have_bluez5}])
++if (test "${enable_bluez5_dun}" = "yes"); then
++	if test x"$have_bluez5" = x"no"; then
++		AC_MSG_ERROR(Bluez 5.x development headers are required)
++	fi
++	AC_DEFINE(WITH_BLUEZ5_DUN, 1, [Define if you have Bluez 5 libraries])
++else
++	AC_DEFINE(HAVE_BLUEZ5_DUN, 0, [Define if you have Bluez 5 libraries])
++fi
++AM_CONDITIONAL(WITH_BLUEZ5_DUN, test "${enable_bluez5_dun}" = "yes")
++
+ # DHCP client support
+ AC_ARG_WITH([dhclient], AS_HELP_STRING([--with-dhclient=yes|no|path], [Enable dhclient 4.x support]))
+ AC_ARG_WITH([dhcpcd], AS_HELP_STRING([--with-dhcpcd=yes|no|path], [Enable dhcpcd 4.x support]))
+diff --git a/src/devices/bluetooth/Makefile.am b/src/devices/bluetooth/Makefile.am
+index 4342d4b..7840a21 100644
+--- a/src/devices/bluetooth/Makefile.am
++++ b/src/devices/bluetooth/Makefile.am
+@@ -64,6 +64,16 @@ libnm_device_plugin_bluetooth_la_LIBADD = \
+ 	$(DBUS_LIBS) \
+ 	$(GUDEV_LIBS)
+ 
++if WITH_BLUEZ5_DUN
++AM_CPPFLAGS += $(BLUEZ5_CFLAGS)
++
++libnm_device_plugin_bluetooth_la_SOURCES += \
++	nm-bluez5-dun.c \
++	nm-bluez5-dun.h
++
++libnm_device_plugin_bluetooth_la_LIBADD += $(BLUEZ5_LIBS)
++endif
++
+ CLEANFILES = $(BUILT_SOURCES)
+ EXTRA_DIST = $(SYMBOL_VIS_FILE)
+ 
+diff --git a/src/devices/bluetooth/nm-bluez-device.c b/src/devices/bluetooth/nm-bluez-device.c
+index edebb75..5ca370a 100644
+--- a/src/devices/bluetooth/nm-bluez-device.c
++++ b/src/devices/bluetooth/nm-bluez-device.c
+@@ -34,7 +34,8 @@
+ #include "nm-logging.h"
+ #include "nm-utils.h"
+ #include "nm-settings-connection.h"
+-
++#include "nm-bluez5-dun.h"
++#include "NetworkManagerUtils.h"
+ 
+ G_DEFINE_TYPE (NMBluezDevice, nm_bluez_device, G_TYPE_OBJECT)
+ 
+@@ -62,7 +63,8 @@ typedef struct {
+ 	guint32 capabilities;
+ 	gboolean connected;
+ 
+-	char *bt_iface;
++	char *b4_iface;
++	NMBluez5DunContext *b5_dun_context;
+ 
+ 	NMConnectionProvider *provider;
+ 	GSList *connections;
+@@ -157,9 +159,12 @@ nm_bluez_device_get_capabilities (NMBluezDevice *self)
+ gboolean
+ nm_bluez_device_get_connected (NMBluezDevice *self)
+ {
++	NMBluezDevicePrivate *priv;
++
+ 	g_return_val_if_fail (NM_IS_BLUEZ_DEVICE (self), FALSE);
+ 
+-	return NM_BLUEZ_DEVICE_GET_PRIVATE (self)->connected;
++	priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self);
++	return priv->connected;
+ }
+ 
+ static void
+@@ -265,8 +270,7 @@ check_emit_usable (NMBluezDevice *self)
+ 	gboolean new_usable;
+ 
+ 	/* only expect the supported capabilities set. */
+-	g_assert (priv->bluez_version != 4 || ((priv->capabilities & ~(NM_BT_CAPABILITY_NAP | NM_BT_CAPABILITY_DUN)) == NM_BT_CAPABILITY_NONE ));
+-	g_assert (priv->bluez_version != 5 || ((priv->capabilities & ~(NM_BT_CAPABILITY_NAP                       )) == NM_BT_CAPABILITY_NONE ));
++	g_assert ((priv->capabilities & ~(NM_BT_CAPABILITY_NAP | NM_BT_CAPABILITY_DUN)) == NM_BT_CAPABILITY_NONE );
+ 
+ 	new_usable = (priv->initialized && priv->capabilities && priv->name &&
+ 	              ((priv->bluez_version == 4) ||
+@@ -421,26 +425,33 @@ nm_bluez_device_disconnect (NMBluezDevice *self)
+ {
+ 	NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self);
+ 	GVariant *args = NULL;
+-	const char *dbus_iface;
++	const char *dbus_iface = NULL;
+ 
+ 	g_return_if_fail (priv->dbus_connection);
+ 
+-	if (priv->bluez_version == 5) {
+-		g_return_if_fail (priv->connection_bt_type == NM_BT_CAPABILITY_NAP);
+-		dbus_iface = BLUEZ5_NETWORK_INTERFACE;
+-	} else if (priv->bluez_version == 4 && priv->connection_bt_type == NM_BT_CAPABILITY_DUN) {
+-		/* Can't pass a NULL interface name through dbus to bluez, so just
+-		 * ignore the disconnect if the interface isn't known.
+-		 */
+-		if (!priv->bt_iface)
+-			return;
+-
+-		args = g_variant_new ("(s)", priv->bt_iface),
+-		dbus_iface = BLUEZ4_SERIAL_INTERFACE;
+-	} else {
+-		g_return_if_fail (priv->bluez_version == 4 && priv->connection_bt_type == NM_BT_CAPABILITY_NAP);
+-		dbus_iface = BLUEZ4_NETWORK_INTERFACE;
+-	}
++	if (priv->connection_bt_type == NM_BT_CAPABILITY_DUN) {
++		if (priv->bluez_version == 4) {
++			/* Can't pass a NULL interface name through dbus to bluez, so just
++			 * ignore the disconnect if the interface isn't known.
++			 */
++			if (!priv->b4_iface)
++				goto out;
++			args = g_variant_new ("(s)", priv->b4_iface),
++			dbus_iface = BLUEZ4_SERIAL_INTERFACE;
++		} else if (priv->bluez_version == 5) {
++			nm_bluez5_dun_cleanup (priv->b5_dun_context);
++			priv->connected = FALSE;
++			goto out;
++		}
++	} else if (priv->connection_bt_type == NM_BT_CAPABILITY_NAP) {
++		if (priv->bluez_version == 4)
++			dbus_iface = BLUEZ4_NETWORK_INTERFACE;
++		else if (priv->bluez_version == 5)
++			dbus_iface = BLUEZ5_NETWORK_INTERFACE;
++		else
++			g_assert_not_reached ();
++	} else
++		g_assert_not_reached ();
+ 
+ 	g_dbus_connection_call (priv->dbus_connection,
+ 	                        BLUEZ_SERVICE,
+@@ -455,6 +466,8 @@ nm_bluez_device_disconnect (NMBluezDevice *self)
+ 	                        (GAsyncReadyCallback) bluez_disconnect_cb,
+ 	                        g_object_ref (self));
+ 
++out:
++	g_clear_pointer (&priv->b4_iface, g_free);
+ 	priv->connection_bt_type = NM_BT_CAPABILITY_NONE;
+ }
+ 
+@@ -481,7 +494,7 @@ bluez_connect_cb (GDBusConnection *dbus_connection,
+ 		g_simple_async_result_set_op_res_gpointer (result,
+ 		                                           g_strdup (device),
+ 		                                           g_free);
+-		priv->bt_iface = device;
++		priv->b4_iface = device;
+ 		g_variant_unref (variant);
+ 	}
+ 
+@@ -490,6 +503,26 @@ bluez_connect_cb (GDBusConnection *dbus_connection,
+ 	g_object_unref (result_object);
+ }
+ 
++static void
++bluez5_dun_connect_cb (NMBluez5DunContext *context,
++                   const char *device,
++                   GError *error,
++                   gpointer user_data)
++{
++	GSimpleAsyncResult *result = G_SIMPLE_ASYNC_RESULT (user_data);
++
++	if (error) {
++		g_simple_async_result_take_error (result, error);
++	} else {
++		g_simple_async_result_set_op_res_gpointer (result,
++		                                           g_strdup (device),
++		                                           g_free);
++	}
++
++	g_simple_async_result_complete (result);
++	g_object_unref (result);
++}
++
+ void
+ nm_bluez_device_connect_async (NMBluezDevice *self,
+                                NMBluetoothCapabilities connection_bt_type,
+@@ -498,26 +531,35 @@ nm_bluez_device_connect_async (NMBluezDevice *self,
+ {
+ 	GSimpleAsyncResult *simple;
+ 	NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self);
+-	const char *dbus_iface;
+-	const char *connect_type = BLUETOOTH_CONNECT_NAP;
++	const char *dbus_iface = NULL;
++	const char *connect_type = NULL;
+ 
+ 	g_return_if_fail (priv->capabilities & connection_bt_type & (NM_BT_CAPABILITY_DUN | NM_BT_CAPABILITY_NAP));
+ 
+-	if (priv->bluez_version == 5) {
+-		g_return_if_fail (connection_bt_type == NM_BT_CAPABILITY_NAP);
+-		dbus_iface = BLUEZ5_NETWORK_INTERFACE;
+-	} else if (priv->bluez_version == 4 && connection_bt_type == NM_BT_CAPABILITY_DUN) {
+-		dbus_iface = BLUEZ4_SERIAL_INTERFACE;
+-		connect_type = BLUETOOTH_CONNECT_DUN;
+-	} else {
+-		g_return_if_fail (priv->bluez_version == 4 && connection_bt_type == NM_BT_CAPABILITY_NAP);
+-		dbus_iface = BLUEZ4_NETWORK_INTERFACE;
+-	}
+-
+ 	simple = g_simple_async_result_new (G_OBJECT (self),
+ 	                                    callback,
+ 	                                    user_data,
+ 	                                    nm_bluez_device_connect_async);
++	priv->connection_bt_type = connection_bt_type;
++
++	if (connection_bt_type == NM_BT_CAPABILITY_NAP) {
++		connect_type = BLUETOOTH_CONNECT_NAP;
++		if (priv->bluez_version == 4)
++			dbus_iface = BLUEZ4_NETWORK_INTERFACE;
++		else if (priv->bluez_version == 5)
++			dbus_iface = BLUEZ5_NETWORK_INTERFACE;
++	} else if (connection_bt_type == NM_BT_CAPABILITY_DUN) {
++		connect_type = BLUETOOTH_CONNECT_DUN;
++		if (priv->bluez_version == 4)
++			dbus_iface = BLUEZ4_SERIAL_INTERFACE;
++		else if (priv->bluez_version == 5) {
++			if (priv->b5_dun_context == NULL)
++				priv->b5_dun_context = nm_bluez5_dun_new (priv->adapter_address, priv->address);
++			nm_bluez5_dun_connect (priv->b5_dun_context, bluez5_dun_connect_cb, simple);
++			return;
++		}
++	} else
++		g_assert_not_reached ();
+ 
+ 	g_dbus_connection_call (priv->dbus_connection,
+ 	                        BLUEZ_SERVICE,
+@@ -531,8 +573,6 @@ nm_bluez_device_connect_async (NMBluezDevice *self,
+ 	                        NULL,
+ 	                        (GAsyncReadyCallback) bluez_connect_cb,
+ 	                        simple);
+-
+-	priv->connection_bt_type = connection_bt_type;
+ }
+ 
+ const char *
+@@ -540,6 +580,7 @@ nm_bluez_device_connect_finish (NMBluezDevice *self,
+                                 GAsyncResult *result,
+                                 GError **error)
+ {
++	NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self);
+ 	GSimpleAsyncResult *simple;
+ 	const char *device;
+ 
+@@ -554,6 +595,9 @@ nm_bluez_device_connect_finish (NMBluezDevice *self,
+ 		return NULL;
+ 
+ 	device = (const char *) g_simple_async_result_get_op_res_gpointer (simple);
++	if (device && priv->bluez_version == 5)
++		priv->connected = TRUE;
++
+ 	return device;
+ }
+ 
+@@ -572,7 +616,7 @@ set_adapter_address (NMBluezDevice *self, const char *address)
+ }
+ 
+ static guint32
+-convert_uuids_to_capabilities (const char **strings, int bluez_version)
++convert_uuids_to_capabilities (const char **strings)
+ {
+ 	const char **iter;
+ 	guint32 capabilities = 0;
+@@ -584,8 +628,7 @@ convert_uuids_to_capabilities (const char **strings, int bluez_version)
+ 		if (parts && parts[0]) {
+ 			switch (g_ascii_strtoull (parts[0], NULL, 16)) {
+ 			case 0x1103:
+-				if (bluez_version == 4)
+-					capabilities |= NM_BT_CAPABILITY_DUN;
++				capabilities |= NM_BT_CAPABILITY_DUN;
+ 				break;
+ 			case 0x1116:
+ 				capabilities |= NM_BT_CAPABILITY_NAP;
+@@ -606,7 +649,7 @@ _set_property_capabilities (NMBluezDevice *self, const char **uuids)
+ 	guint32 uint_val;
+ 	NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self);
+ 
+-	uint_val = convert_uuids_to_capabilities (uuids, priv->bluez_version);
++	uint_val = convert_uuids_to_capabilities (uuids);
+ 	if (priv->capabilities != uint_val) {
+ 		if (priv->capabilities) {
+ 			/* changing (relevant) capabilities is not supported and ignored -- except setting initially */
+@@ -1067,6 +1110,11 @@ dispose (GObject *object)
+ 		g_clear_object (&priv->pan_connection_original);
+ 	}
+ 
++	if (priv->b5_dun_context) {
++		nm_bluez5_dun_free (priv->b5_dun_context);
++		priv->b5_dun_context = NULL;
++	}
++
+ 	g_signal_handlers_disconnect_by_func (priv->provider, cp_connection_added, self);
+ 	g_signal_handlers_disconnect_by_func (priv->provider, cp_connection_removed, self);
+ 	g_signal_handlers_disconnect_by_func (priv->provider, cp_connection_updated, self);
+@@ -1098,7 +1146,7 @@ finalize (GObject *object)
+ 	g_free (priv->adapter_address);
+ 	g_free (priv->address);
+ 	g_free (priv->name);
+-	g_free (priv->bt_iface);
++	g_free (priv->b4_iface);
+ 
+ 	if (priv->proxy)
+ 		g_signal_handlers_disconnect_by_data (priv->proxy, object);
+diff --git a/src/devices/bluetooth/nm-bluez5-dun.c b/src/devices/bluetooth/nm-bluez5-dun.c
+new file mode 100644
+index 0000000..dcd3d73
+--- /dev/null
++++ b/src/devices/bluetooth/nm-bluez5-dun.c
+@@ -0,0 +1,409 @@
++/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
++/* NetworkManager -- Network link manager
++ *
++ * 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.
++ *
++ * Copyright (C) 2014 Red Hat, Inc.
++ */
++
++#include <config.h>
++#include <sys/socket.h>
++#include <bluetooth/sdp.h>
++#include <bluetooth/sdp_lib.h>
++#include <bluetooth/rfcomm.h>
++#include <net/ethernet.h>
++#include <sys/ioctl.h>
++#include <unistd.h>
++#include <errno.h>
++#include <fcntl.h>
++
++#include "nm-bluez5-dun.h"
++#include "nm-bt-error.h"
++#include "nm-logging.h"
++#include "NetworkManagerUtils.h"
++
++typedef struct _NMBluez5DunContext {
++	bdaddr_t src;
++	bdaddr_t dst;
++	char *src_str;
++	char *dst_str;
++	int rfcomm_channel;
++	int rfcomm_fd;
++	int rfcomm_tty_fd;
++	int rfcomm_id;
++	NMBluez5DunFunc callback;
++	gpointer user_data;
++	sdp_session_t *sdp_session;
++	guint sdp_watch_id;
++} NMBluez5DunContext;
++
++static void
++dun_connect (NMBluez5DunContext *context)
++{
++	struct sockaddr_rc sa;
++	int devid, try = 30;
++	char tty[100];
++	const int ttylen = sizeof (tty) - 1;
++	GError *error = NULL;
++
++	struct rfcomm_dev_req req = {
++		.flags = (1 << RFCOMM_REUSE_DLC) | (1 << RFCOMM_RELEASE_ONHUP),
++		.dev_id = -1,
++		.channel = context->rfcomm_channel
++	};
++
++	context->rfcomm_fd = socket (AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
++	if (context->rfcomm_fd < 0) {
++		int errsv = errno;
++		error = g_error_new (NM_BT_ERROR, NM_BT_ERROR_DUN_CONNECT_FAILED,
++		                     "Failed to create RFCOMM socket: (%d) %s",
++		                     errsv, strerror (errsv));
++		goto done;
++	}
++
++	/* Connect to the remote device */
++	sa.rc_family = AF_BLUETOOTH;
++	sa.rc_channel = 0;
++	memcpy (&sa.rc_bdaddr, &context->src, ETH_ALEN);
++	if (bind (context->rfcomm_fd, (struct sockaddr *) &sa, sizeof(sa))) {
++		int errsv = errno;
++		error = g_error_new (NM_BT_ERROR, NM_BT_ERROR_DUN_CONNECT_FAILED,
++		                     "Failed to bind socket: (%d) %s",
++		                     errsv, strerror (errsv));
++		goto done;
++	}
++
++	sa.rc_channel = context->rfcomm_channel;
++	memcpy (&sa.rc_bdaddr, &context->dst, ETH_ALEN);
++	if (connect (context->rfcomm_fd, (struct sockaddr *) &sa, sizeof (sa)) ) {
++		int errsv = errno;
++		error = g_error_new (NM_BT_ERROR, NM_BT_ERROR_DUN_CONNECT_FAILED,
++		                     "Failed to connect to remote device: (%d) %s",
++		                     errsv, strerror (errsv));
++		goto done;
++	}
++
++	nm_log_dbg (LOGD_BT, "(%s): connected to %s on channel %d",
++	            context->src_str, context->dst_str, context->rfcomm_channel);
++
++	/* Create an RFCOMM kernel device for the DUN channel */
++	memcpy (&req.src, &context->src, ETH_ALEN);
++	memcpy (&req.dst, &context->dst, ETH_ALEN);
++	devid = ioctl (context->rfcomm_fd, RFCOMMCREATEDEV, &req);
++	if (devid < 0) {
++		int errsv = errno;
++		error = g_error_new (NM_BT_ERROR, NM_BT_ERROR_DUN_CONNECT_FAILED,
++		                     "Failed to create rfcomm device: (%d) %s",
++		                     errsv, strerror (errsv));
++		goto done;
++	}
++	context->rfcomm_id = devid;
++
++	snprintf (tty, ttylen, "/dev/rfcomm%d", devid);
++	while ((context->rfcomm_tty_fd = open (tty, O_RDONLY | O_NOCTTY)) < 0 && try--) {
++		if (try) {
++			g_usleep (100 * 1000);
++			continue;
++		}
++
++		error = g_error_new (NM_BT_ERROR, NM_BT_ERROR_DUN_CONNECT_FAILED,
++		                     "Failed to find rfcomm device: %s",
++		                     tty);
++		break;
++	}
++
++done:
++	context->callback (context, tty, error, context->user_data);
++}
++
++static void
++sdp_search_cleanup (NMBluez5DunContext *context)
++{
++	if (context->sdp_session) {
++		sdp_close (context->sdp_session);
++		context->sdp_session = NULL;
++	}
++
++	if (context->sdp_watch_id) {
++		g_source_remove (context->sdp_watch_id);
++		context->sdp_watch_id = 0;
++	}
++}
++
++static void
++sdp_search_completed_cb (uint8_t type, uint16_t status, uint8_t *rsp, size_t size, void *user_data)
++{
++	NMBluez5DunContext *context = user_data;
++	int scanned, seqlen = 0, bytesleft = size;
++	uint8_t dataType;
++	int channel = -1;
++
++	nm_log_dbg (LOGD_BT, "(%s -> %s): SDP search finished with type=%d status=%d",
++	            context->src_str, context->dst_str, status, type);
++
++	/* SDP response received */
++	if (status || type != SDP_SVC_SEARCH_ATTR_RSP) {
++		GError *error = g_error_new (NM_BT_ERROR,
++		                             NM_BT_ERROR_DUN_CONNECT_FAILED,
++		                             "Did not get a Service Discovery response");
++		context->callback (context, NULL, error, context->user_data);
++		goto done;
++	}
++
++	scanned = sdp_extract_seqtype (rsp, bytesleft, &dataType, &seqlen);
++
++	nm_log_dbg (LOGD_BT, "(%s -> %s): SDP sequence type scanned=%d length=%d",
++	            context->src_str, context->dst_str, scanned, seqlen);
++
++	scanned = sdp_extract_seqtype (rsp, bytesleft, &dataType, &seqlen);
++	if (!scanned || !seqlen) {
++		/* Short read or unknown sequence type */
++		GError *error = g_error_new (NM_BT_ERROR,
++		                             NM_BT_ERROR_DUN_CONNECT_FAILED,
++		                             "Improper Service Discovery response");
++		context->callback (context, NULL, error, context->user_data);
++		goto done;
++	}
++
++	rsp += scanned;
++	bytesleft -= scanned;
++	do {
++		sdp_record_t *rec;
++		int recsize = 0;
++		sdp_list_t *protos;
++
++		rec = sdp_extract_pdu (rsp, bytesleft, &recsize);
++		if (!rec)
++			break;
++
++		if (!recsize) {
++			sdp_record_free (rec);
++			break;
++		}
++
++		if (sdp_get_access_protos (rec, &protos) == 0) {
++			/* Extract the DUN channel number */
++			channel = sdp_get_proto_port (protos, RFCOMM_UUID);
++			sdp_list_free (protos, NULL);
++
++			nm_log_dbg (LOGD_BT, "(%s -> %s): SDP channel=%d",
++			            context->src_str, context->dst_str, channel);
++		}
++		sdp_record_free (rec);
++
++		scanned += recsize;
++		rsp += recsize;
++		bytesleft -= recsize;
++	} while ((scanned < (ssize_t) size) && (bytesleft > 0) && (channel < 0));
++
++done:
++	if (channel != -1) {
++		context->rfcomm_channel = channel;
++		dun_connect (context);
++	}
++
++	sdp_search_cleanup (context);
++}
++
++static gboolean
++sdp_search_process_cb (GIOChannel *channel, GIOCondition condition, gpointer user_data)
++{
++	NMBluez5DunContext *context = user_data;
++
++	nm_log_dbg (LOGD_BT, "(%s -> %s): SDP search progressed with condition=%d",
++	            context->src_str, context->dst_str, condition);
++
++	if (condition & (G_IO_ERR | G_IO_HUP | G_IO_NVAL)) {
++		GError *error = g_error_new (NM_BT_ERROR,
++		                             NM_BT_ERROR_DUN_CONNECT_FAILED,
++		                             "Service Discovery interrupted");
++		context->callback (context, NULL, error, context->user_data);
++		sdp_search_cleanup (context);
++		return FALSE;
++	}
++
++	if (sdp_process (context->sdp_session) < 0) {
++		nm_log_dbg (LOGD_BT, "(%s -> %s): SDP search finished",
++		            context->src_str, context->dst_str);
++
++		/* Search finished successfully. */
++		return FALSE;
++	}
++
++	/* Search progressed successfully. */
++	return TRUE;
++}
++
++static gboolean
++sdp_connect_watch (GIOChannel *channel, GIOCondition condition, gpointer user_data)
++{
++	NMBluez5DunContext *context = user_data;
++	sdp_list_t *search, *attrs;
++	uuid_t svclass;
++	uint16_t attr;
++	int fd, err, fd_err = 0;
++	socklen_t len = sizeof (fd_err);
++	GError *error = NULL;
++
++	context->sdp_watch_id = 0;
++
++	fd = g_io_channel_unix_get_fd (channel);
++	if (getsockopt (fd, SOL_SOCKET, SO_ERROR, &fd_err, &len) < 0) {
++		nm_log_dbg (LOGD_BT, "(%s -> %s): getsockopt error=%d",
++		            context->src_str, context->dst_str, errno);
++		err = errno;
++	} else {
++		nm_log_dbg (LOGD_BT, "(%s -> %s): SO_ERROR error=%d",
++		            context->src_str, context->dst_str, fd_err);
++		err = fd_err;
++	}
++
++	if (err != 0) {
++		error = g_error_new (NM_BT_ERROR, NM_BT_ERROR_DUN_CONNECT_FAILED,
++		                     "Error on Service Discovery socket: (%d) %s",
++		                     err, strerror (err));
++		goto done;
++	}
++
++	if (sdp_set_notify (context->sdp_session, sdp_search_completed_cb, context) < 0) {
++		/* Should not be reached, only can fail if we passed bad sdp_session. */
++		error = g_error_new (NM_BT_ERROR, NM_BT_ERROR_DUN_CONNECT_FAILED,
++		                     "Could not request Service Discovery notification");
++		goto done;
++	}
++
++	sdp_uuid16_create (&svclass, DIALUP_NET_SVCLASS_ID);
++	search = sdp_list_append (NULL, &svclass);
++	attr = SDP_ATTR_PROTO_DESC_LIST;
++	attrs = sdp_list_append (NULL, &attr);
++
++	if (!sdp_service_search_attr_async (context->sdp_session, search, SDP_ATTR_REQ_INDIVIDUAL, attrs)) {
++		/* Set callback responsible for update the internal SDP transaction */
++		context->sdp_watch_id = g_io_add_watch (channel,
++		                                        G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
++		                                        sdp_search_process_cb,
++		                                        context);
++	} else {
++		err = sdp_get_error (context->sdp_session);
++		error = g_error_new (NM_BT_ERROR,
++		                     NM_BT_ERROR_DUN_CONNECT_FAILED,
++		                     "Error starting Service Discovery: (%d) %s",
++		                     err, strerror (err));
++	}
++
++	sdp_list_free (attrs, NULL);
++	sdp_list_free (search, NULL);
++
++done:
++	if (error) {
++		context->callback (context, NULL, error, context->user_data);
++		sdp_search_cleanup (context);
++	}
++
++	return G_SOURCE_REMOVE;
++}
++
++NMBluez5DunContext *
++nm_bluez5_dun_new (const char *adapter,
++                   const char *remote)
++
++{
++	NMBluez5DunContext *context;
++
++	context = g_slice_new0 (NMBluez5DunContext);
++	str2ba (adapter, &context->src);
++	str2ba (remote, &context->dst);
++	context->src_str = g_strdup (adapter);
++	context->dst_str = g_strdup (remote);
++	context->rfcomm_channel = -1;
++	context->rfcomm_id = -1;
++	context->rfcomm_fd = -1;
++	return context;
++}
++
++void
++nm_bluez5_dun_connect (NMBluez5DunContext *context,
++                       NMBluez5DunFunc callback,
++                       gpointer user_data)
++{
++	GIOChannel *channel;
++
++	context->callback = callback;
++	context->user_data = user_data;
++
++	if (context->rfcomm_channel != -1) {
++		nm_log_dbg (LOGD_BT, "(%s): channel number on device %s cached: %d",
++			    context->src_str, context->dst_str, context->rfcomm_channel);
++		dun_connect (context);
++		return;
++	}
++
++	nm_log_dbg (LOGD_BT, "(%s): starting channel number discovery for device %s",
++		    context->src_str, context->dst_str);
++
++	context->sdp_session = sdp_connect (&context->src, &context->dst, SDP_NON_BLOCKING);
++	if (!context->sdp_session) {
++		GError *error;
++		int err = sdp_get_error (context->sdp_session);
++
++		error = g_error_new (NM_BT_ERROR, NM_BT_ERROR_DUN_CONNECT_FAILED,
++		                     "Failed to connect to the SDP server: (%d) %s",
++		                      err, strerror (err));
++		context->callback (context, NULL, error, context->user_data);
++		return;
++	}
++
++	channel = g_io_channel_unix_new (sdp_get_socket (context->sdp_session));
++	context->sdp_watch_id = g_io_add_watch (channel,
++	                                        G_IO_OUT | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
++	                                        sdp_connect_watch,
++	                                        context);
++	g_io_channel_unref (channel);
++}
++
++/* Only clean up connection-related stuff to allow reconnect */
++void
++nm_bluez5_dun_cleanup (NMBluez5DunContext *context)
++{
++	g_return_if_fail (context != NULL);
++
++	sdp_search_cleanup (context);
++
++	if (context->rfcomm_fd >= 0) {
++		if (context->rfcomm_id >= 0) {
++			struct rfcomm_dev_req req = { 0 };
++
++			req.dev_id = context->rfcomm_id;
++			ioctl (context->rfcomm_fd, RFCOMMRELEASEDEV, &req);
++			context->rfcomm_id = -1;
++		}
++		close (context->rfcomm_fd);
++		context->rfcomm_fd = -1;
++	}
++
++	close (context->rfcomm_tty_fd);
++	context->rfcomm_tty_fd = -1;
++}
++
++void
++nm_bluez5_dun_free (NMBluez5DunContext *context)
++{
++	g_return_if_fail (context != NULL);
++
++	nm_bluez5_dun_cleanup (context);
++	g_clear_pointer (&context->src_str, g_free);
++	g_clear_pointer (&context->dst_str, g_free);
++	g_slice_free (NMBluez5DunContext, context);
++}
+diff --git a/src/devices/bluetooth/nm-bluez5-dun.h b/src/devices/bluetooth/nm-bluez5-dun.h
+new file mode 100644
+index 0000000..7e25972
+--- /dev/null
++++ b/src/devices/bluetooth/nm-bluez5-dun.h
+@@ -0,0 +1,46 @@
++/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
++/* NetworkManager -- Network link manager
++ *
++ * 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.
++ *
++ * Copyright (C) 2014 Red Hat, Inc.
++ */
++
++#ifndef _NM_BLUEZ5_UTILS_H_
++#define _NM_BLUEZ5_UTILS_H_
++
++#include <glib.h>
++#include <gio/gio.h>
++
++typedef struct _NMBluez5DunContext NMBluez5DunContext;
++
++typedef void (*NMBluez5DunFunc) (NMBluez5DunContext *context,
++                                 const char *rfcomm_dev,
++                                 GError *error,
++                                 gpointer user_data);
++
++NMBluez5DunContext *nm_bluez5_dun_new (const char *adapter,
++                                       const char *remote);
++
++void nm_bluez5_dun_connect (NMBluez5DunContext *context,
++                            NMBluez5DunFunc callback, gpointer user_data);
++
++/* Clean up connection resources */
++void nm_bluez5_dun_cleanup (NMBluez5DunContext *context);
++
++/* Clean up and dispose all resources */
++void nm_bluez5_dun_free (NMBluez5DunContext *context);
++
++#endif  /* _NM_BLUEZ5_UTILS_H_ */
+-- 
+1.9.3
+
diff --git a/NetworkManager.spec b/NetworkManager.spec
index 35d6b4f..1af5a26 100644
--- a/NetworkManager.spec
+++ b/NetworkManager.spec
@@ -13,7 +13,7 @@
 %define snapshot .git20140704
 %define git_sha 6eb82acd
 %define realversion 0.9.10.0
-%define release_version 7
+%define release_version 8
 %define epoch_version 1
 
 %define obsoletes_nmver 1:0.9.9.95-1
@@ -77,8 +77,15 @@ Source1: NetworkManager.conf
 Source2: 00-server.conf
 Source3: 20-connectivity-fedora.conf
 
-Patch1: 0001-explain-dns1-dns2.patch
-Patch2: non-local-session-polkit.patch
+# Not upstream.
+Patch0: 0000-explain-dns1-dns2.patch
+
+# Cherry-picks from upstream:
+# http://cgit.freedesktop.org/NetworkManager/NetworkManager/log/?h=nm-0-9-10
+Patch1: 0001-policy-allow-non-local-admin-sessions-to-control-the.patch
+Patch2: 0002-bluez-split-out-errors.patch
+Patch3: 0003-bluez-track-adapter-address-in-NMBluezDevice.patch
+Patch4: 0004-bluez-re-add-DUN-support-for-Bluez5.patch
 
 BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
 
@@ -140,6 +147,9 @@ BuildRequires: libuuid-devel
 BuildRequires: libgudev1-devel >= 143
 BuildRequires: vala-tools
 BuildRequires: iptables
+%if 0%{?with_bluetooth} && 0%{?fedora} > 19
+BuildRequires: bluez-libs-devel
+%endif
 %if 0%{?with_wimax}
 BuildRequires: wimax-devel
 %endif
@@ -314,8 +324,11 @@ by nm-connection-editor and nm-applet in a non-graphical environment.
 %prep
 %setup -q -n NetworkManager-%{realversion}
 
-%patch1 -p1 -b .0001.explain-dns1-dns2.orig
-%patch2 -p1 -b .non-local-session-polkit.orig
+%patch0 -p1 -b .explain-dns1-dns2.orig
+%patch1 -p1 -b .policy-allow-non-local-admin-sessions-to-control-the.orig
+%patch2 -p1 -b .bluez-split-out-errors.orig
+%patch3 -p1 -b .bluez-track-adapter-address-in-NMBluezDevice.orig
+%patch4 -p1 -b .bluez-re-add-DUN-support-for-Bluez5.orig
 
 %build
 
@@ -325,8 +338,9 @@ by nm-connection-editor and nm-applet in a non-graphical environment.
 %{__cp} -R docs ORIG-docs
 %endif
 
-#autopoint --force
-#intltoolize --force
+autoreconf -f -i
+autopoint --force
+intltoolize --force
 %configure \
 	--disable-static \
 	--with-dhclient=yes \
@@ -585,6 +599,9 @@ fi
 %endif
 
 %changelog
+* Thu Oct 16 2014 Lubomir Rintel <lkundrak at v3.sk> 1:0.9.10.0-8.git20140704
+- bluetooth: Restore DUN support (rh #1055628)
+
 * Mon Oct 06 2014 Stef Walter <stefw at redhat.com> - 1:0.9.10.0-7.git20140704
 - Allow non-local users network control after PolicyKit authentication (rh #1145646)
 


More information about the scm-commits mailing list