From: Abhinav Kumar Date: Thu, 19 Feb 2015 04:15:59 +0000 (+0530) Subject: Applied bluez patches present in Tizen branch. The following patches have been applied : X-Git-Tag: accepted/tizen/common/20150521.125355~2 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=7a63bb884b1e84ec510349114f0dfcea0506b0ac;p=platform%2Fupstream%2Fbluez.git Applied bluez patches present in Tizen branch. The following patches have been applied : 1> bluetooth player: add searchable value to show cmd 2> add property connected for input device 3> core/service: Add btd_service_get_version 4> core/profile: Add version information to btd_profile 5> core/service: Add btd_service_set_auto_connect 6> core/service: Add btd_service_get_auto_connect 7> core/device: Use service auto_connect flag 8> profiles: Add missing local_uuid 9> core/service: Add btd_service_set_blocked 10> core/service: Add btd_service_is_blocked 11> core/profile: Add authorization UUID information to btd_profile 12> core/device: Add device_is_service_blocked 13> core/adapter: Check if service is blocked before authorizing 14> plugins: Add initial code for service plugin 15> plugins/service: Add initial code 16> Fix bluetoothd core dumped if disable bt tethering 17> Fix Security Static Code Analysis 18> Add param fd into authorize service 19> Modify the param of authorize service 20> Fix the remaining Security Static Code Analysis 21> Fix the length of string 22> Fix the remaining Security Static Code Analysis Change-Id: I3191182d850b1252248de76d4bd8f70768230b93 --- diff --git a/Makefile.plugins b/Makefile.plugins index ddcbd3a..ce2d2e1 100644 --- a/Makefile.plugins +++ b/Makefile.plugins @@ -142,3 +142,11 @@ plugins_sixaxis_la_LDFLAGS = $(AM_LDFLAGS) -module -avoid-version \ -no-undefined @UDEV_LIBS@ plugins_sixaxis_la_CFLAGS = $(AM_CFLAGS) -fvisibility=hidden @UDEV_CFLAGS@ endif + +if SERVICE +plugin_LTLIBRARIES += plugins/service.la +plugins_service_la_SOURCES = plugins/service.c +plugins_service_la_LDFLAGS = $(AM_LDFLAGS) -module -avoid-version \ + -no-undefined +plugins_service_la_CFLAGS = $(AM_CFLAGS) -fvisibility=hidden +endif diff --git a/client/agent.c b/client/agent.c index eeabd5b..54c83fc 100644 --- a/client/agent.c +++ b/client/agent.c @@ -295,11 +295,13 @@ static DBusMessage *authorize_service(DBusConnection *conn, { const char *device, *uuid; char *str; + int fd; rl_printf("Authorize service\n"); dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &device, - DBUS_TYPE_STRING, &uuid, DBUS_TYPE_INVALID); + DBUS_TYPE_STRING, &uuid, + DBUS_TYPE_UNIX_FD, &fd, DBUS_TYPE_INVALID); str = g_strdup_printf("Authorize service %s (yes/no): ", uuid); agent_prompt(str); @@ -344,7 +346,8 @@ static const GDBusMethodTable methods[] = { GDBUS_ARGS({ "device", "o" }), NULL, request_authorization) }, { GDBUS_ASYNC_METHOD("AuthorizeService", - GDBUS_ARGS({ "device", "o" }, { "uuid", "s" }), + GDBUS_ARGS({ "device", "o" }, { "uuid", "s" }, + {"fd", "h"}), NULL, authorize_service) }, { GDBUS_METHOD("Cancel", NULL, NULL, cancel_request) }, { } diff --git a/configure.ac b/configure.ac index 8a4bae6..18e4ddb 100644 --- a/configure.ac +++ b/configure.ac @@ -245,6 +245,10 @@ AC_ARG_ENABLE(sixaxis, AC_HELP_STRING([--enable-sixaxis], AM_CONDITIONAL(SIXAXIS, test "${enable_sixaxis}" = "yes" && test "${enable_udev}" != "no") +AC_ARG_ENABLE(service, AC_HELP_STRING([--enable-service], + [enable service plugin]), [enable_service=${enableval}]) +AM_CONDITIONAL(SERVICE, test "${enable_service}" = "yes") + if (test "${prefix}" = "NONE"); then dnl no prefix and no localstatedir, so default to /var if (test "$localstatedir" = '${prefix}/var'); then diff --git a/obexd/plugins/pbap.c b/obexd/plugins/pbap.c index 2008f36..d9e9643 100644 --- a/obexd/plugins/pbap.c +++ b/obexd/plugins/pbap.c @@ -460,7 +460,7 @@ static void cache_entry_done(void *user_data) { struct pbap_session *pbap = user_data; const char *id; - int ret; + int ret = 0; DBG(""); diff --git a/plugins/service.c b/plugins/service.c new file mode 100644 index 0000000..25111f6 --- /dev/null +++ b/plugins/service.c @@ -0,0 +1,439 @@ +/* + * + * BlueZ - Bluetooth protocol stack for Linux + * + * Copyright (C) 2014 Intel Corporation. + * + * + * 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 St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + +#include +#include + +#include "lib/uuid.h" +#include "src/plugin.h" +#include "src/log.h" +#include "src/dbus-common.h" +#include "src/error.h" +#include "src/adapter.h" +#include "src/device.h" +#include "src/service.h" +#include "src/profile.h" + +#define SERVICE_INTERFACE "org.bluez.Service1" + +static unsigned int service_id = 0; +static GSList *services = NULL; + +struct service_data { + struct btd_service *service; + char *path; + DBusMessage *connect; + DBusMessage *disconnect; +}; + +static struct service_data *find_data(struct btd_service *service) +{ + GSList *l; + + for (l = services; l; l = l->next) { + struct service_data *data = l->data; + + if (data->service == service) + return data; + } + + return NULL; +} + +static void data_free(void *user_data) +{ + struct service_data *data = user_data; + + if (data->connect) + dbus_message_unref(data->connect); + + if (data->disconnect) + dbus_message_unref(data->disconnect); + + g_free(data->path); + g_free(data); +} + +static void data_remove(struct service_data *data) +{ + services = g_slist_remove(services, data); + g_dbus_unregister_interface(btd_get_dbus_connection(), data->path, + SERVICE_INTERFACE); +} + +static DBusMessage *service_disconnect(DBusConnection *conn, DBusMessage *msg, + void *user_data) +{ + struct service_data *data = user_data; + int err; + + if (data->disconnect) + return btd_error_in_progress(msg); + + data->disconnect = dbus_message_ref(msg); + + err = btd_service_disconnect(data->service); + if (err == 0) + return NULL; + + dbus_message_unref(data->disconnect); + data->disconnect = NULL; + + return btd_error_failed(msg, strerror(-err)); +} + +static DBusMessage *service_connect(DBusConnection *conn, DBusMessage *msg, + void *user_data) +{ + struct service_data *data = user_data; + int err; + + if (data->connect) + return btd_error_in_progress(msg); + + err = btd_service_connect(data->service); + if (err < 0) + return btd_error_failed(msg, strerror(-err)); + + data->connect = dbus_message_ref(msg); + + return NULL; +} + +static const char *data_get_state(struct service_data *data) +{ + btd_service_state_t state = btd_service_get_state(data->service); + int err; + + switch (state) { + case BTD_SERVICE_STATE_UNAVAILABLE: + return "unavailable"; + case BTD_SERVICE_STATE_DISCONNECTED: + err = btd_service_get_error(data->service); + return err < 0 ? "error" : "disconnected"; + case BTD_SERVICE_STATE_CONNECTING: + return "connecting"; + case BTD_SERVICE_STATE_CONNECTED: + return "connected"; + case BTD_SERVICE_STATE_DISCONNECTING: + return "disconnecting"; + } + + return "unknown"; +} + +static gboolean get_device(const GDBusPropertyTable *property, + DBusMessageIter *iter, void *user_data) +{ + struct service_data *data = user_data; + struct btd_device *dev = btd_service_get_device(data->service); + const char *path = btd_device_get_path(dev); + + dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH, &path); + + return TRUE; +} + +static gboolean get_state(const GDBusPropertyTable *property, + DBusMessageIter *iter, void *user_data) +{ + struct service_data *data = user_data; + const char *state; + + state = data_get_state(data); + + dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &state); + + return TRUE; +} + +static gboolean remote_uuid_exists(const GDBusPropertyTable *property, + void *user_data) +{ + struct service_data *data = user_data; + struct btd_profile *p = btd_service_get_profile(data->service); + + return p->remote_uuid != NULL; +} + +static gboolean get_remote_uuid(const GDBusPropertyTable *property, + DBusMessageIter *iter, void *user_data) +{ + struct service_data *data = user_data; + struct btd_profile *p = btd_service_get_profile(data->service); + + dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &p->remote_uuid); + + return TRUE; +} + + +static gboolean local_uuid_exists(const GDBusPropertyTable *property, + void *user_data) +{ + struct service_data *data = user_data; + struct btd_profile *p = btd_service_get_profile(data->service); + + return p->local_uuid != NULL; +} + +static gboolean get_local_uuid(const GDBusPropertyTable *property, + DBusMessageIter *iter, void *user_data) +{ + struct service_data *data = user_data; + struct btd_profile *p = btd_service_get_profile(data->service); + + dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &p->local_uuid); + + return TRUE; +} + +static gboolean version_exists(const GDBusPropertyTable *property, + void *user_data) +{ + struct service_data *data = user_data; + uint16_t version = btd_service_get_version(data->service); + + return version != 0x0000; +} + +static gboolean get_version(const GDBusPropertyTable *property, + DBusMessageIter *iter, void *user_data) +{ + struct service_data *data = user_data; + uint16_t version = btd_service_get_version(data->service); + + dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT16, &version); + + return TRUE; +} + +static gboolean get_auto_connect(const GDBusPropertyTable *property, + DBusMessageIter *iter, void *user_data) +{ + struct service_data *data = user_data; + dbus_bool_t value = btd_service_get_auto_connect(data->service); + + dbus_message_iter_append_basic(iter, DBUS_TYPE_BOOLEAN, &value); + + return TRUE; +} + +static void set_auto_connect(const GDBusPropertyTable *property, + DBusMessageIter *value, + GDBusPendingPropertySet id, + void *user_data) +{ + struct service_data *data = user_data; + dbus_bool_t b; + + if (dbus_message_iter_get_arg_type(value) != DBUS_TYPE_BOOLEAN) { + g_dbus_pending_property_error(id, + ERROR_INTERFACE ".InvalidArguments", + "Invalid arguments in method call"); + return; + } + + dbus_message_iter_get_basic(value, &b); + + btd_service_set_auto_connect(data->service, b); + + g_dbus_pending_property_success(id); +} + +static gboolean get_blocked(const GDBusPropertyTable *property, + DBusMessageIter *iter, void *user_data) +{ + struct service_data *data = user_data; + dbus_bool_t value = btd_service_is_blocked(data->service); + + dbus_message_iter_append_basic(iter, DBUS_TYPE_BOOLEAN, &value); + + return TRUE; +} + +static void set_blocked(const GDBusPropertyTable *property, + DBusMessageIter *value, + GDBusPendingPropertySet id, + void *user_data) +{ + struct service_data *data = user_data; + dbus_bool_t b; + + if (dbus_message_iter_get_arg_type(value) != DBUS_TYPE_BOOLEAN) { + g_dbus_pending_property_error(id, + ERROR_INTERFACE ".InvalidArguments", + "Invalid arguments in method call"); + return; + } + + dbus_message_iter_get_basic(value, &b); + + btd_service_set_blocked(data->service, b); + + g_dbus_pending_property_success(id); +} + +static const GDBusPropertyTable service_properties[] = { + { "Device", "o", get_device, NULL, NULL }, + { "State", "s", get_state, NULL, NULL }, + { "RemoteUUID", "s", get_remote_uuid, NULL, remote_uuid_exists }, + { "LocalUUID", "s", get_local_uuid, NULL, local_uuid_exists }, + { "Version", "q", get_version, NULL, version_exists }, + { "AutoConnect", "b", get_auto_connect, set_auto_connect, NULL }, + { "Blocked", "b", get_blocked, set_blocked, NULL }, + { } +}; + +static const GDBusMethodTable service_methods[] = { + { GDBUS_ASYNC_METHOD("Disconnect", NULL, NULL, service_disconnect) }, + { GDBUS_ASYNC_METHOD("Connect", NULL, NULL, service_connect) }, + {} +}; + +static struct service_data *service_get_data(struct btd_service *service) +{ + struct btd_device *dev = btd_service_get_device(service); + struct btd_profile *p = btd_service_get_profile(service); + struct service_data *data; + + data = find_data(service); + if (data != NULL) + return data; + + data = g_new0(struct service_data, 1); + data->path = g_strdup_printf("%s/%s", btd_device_get_path(dev), + p->remote_uuid); + data->path = g_strdelimit(data->path, "-", '_'); + data->service = service; + if (g_dbus_register_interface(btd_get_dbus_connection(), + data->path, SERVICE_INTERFACE, + service_methods, NULL, + service_properties, data, + data_free) == FALSE) { + error("Unable to register service interface for %s", + data->path); + data_free(data); + return NULL; + } + + services = g_slist_prepend(services, data); + + DBG("%s", data->path); + + return data; +} + +static void service_connected(struct service_data *data) +{ + DBusMessage *reply; + + if (!data->connect) + return; + + reply = dbus_message_new_method_return(data->connect); + g_dbus_send_message(btd_get_dbus_connection(), reply); + dbus_message_unref(data->connect); + data->connect = NULL; +} + +static void service_disconnected(struct service_data *data) +{ + DBusMessage *reply; + int err; + + if (data->disconnect) { + reply = dbus_message_new_method_return(data->disconnect); + g_dbus_send_message(btd_get_dbus_connection(), reply); + dbus_message_unref(data->disconnect); + data->connect = NULL; + } + + if (!data->connect) + return; + + err = btd_service_get_error(data->service); + + reply = btd_error_failed(data->connect, strerror(-err)); + g_dbus_send_message(btd_get_dbus_connection(), reply); + dbus_message_unref(data->connect); + data->connect = NULL; +} + +static void service_cb(struct btd_service *service, + btd_service_state_t old_state, + btd_service_state_t new_state, + void *user_data) +{ + struct service_data *data; + + data = service_get_data(service); + if (!data) + return; + + switch (new_state) { + case BTD_SERVICE_STATE_UNAVAILABLE: + data_remove(data); + return; + case BTD_SERVICE_STATE_CONNECTED: + service_connected(data); + break; + case BTD_SERVICE_STATE_DISCONNECTED: + service_disconnected(data); + break; + default: + break; + } + + g_dbus_emit_property_changed(btd_get_dbus_connection(), data->path, + SERVICE_INTERFACE, "State"); +} + +static int service_init(void) +{ + DBG(""); + + service_id = btd_service_add_state_cb(service_cb, NULL); + + return 0; +} + +static void service_exit(void) +{ + DBG(""); + + btd_service_remove_state_cb(service_id); + + g_slist_free_full(services, data_free); +} + +BLUETOOTH_PLUGIN_DEFINE(service, VERSION, BLUETOOTH_PLUGIN_PRIORITY_DEFAULT, + service_init, service_exit) diff --git a/profiles/audio/a2dp.c b/profiles/audio/a2dp.c index 96416b5..ffb482b 100644 --- a/profiles/audio/a2dp.c +++ b/profiles/audio/a2dp.c @@ -2071,8 +2071,12 @@ static void media_server_remove(struct btd_adapter *adapter) static struct btd_profile a2dp_source_profile = { .name = "a2dp-source", .priority = BTD_PROFILE_PRIORITY_MEDIUM, + .version = 0x0103, .remote_uuid = A2DP_SOURCE_UUID, + .local_uuid = A2DP_SINK_UUID, + .auth_uuid = ADVANCED_AUDIO_UUID, + .device_probe = a2dp_source_probe, .device_remove = a2dp_source_remove, @@ -2087,8 +2091,12 @@ static struct btd_profile a2dp_source_profile = { static struct btd_profile a2dp_sink_profile = { .name = "a2dp-sink", .priority = BTD_PROFILE_PRIORITY_MEDIUM, + .version = 0x0103, .remote_uuid = A2DP_SINK_UUID, + .local_uuid = A2DP_SOURCE_UUID, + .auth_uuid = ADVANCED_AUDIO_UUID, + .device_probe = a2dp_sink_probe, .device_remove = a2dp_sink_remove, diff --git a/profiles/audio/avctp.c b/profiles/audio/avctp.c index 3680400..4514d69 100644 --- a/profiles/audio/avctp.c +++ b/profiles/audio/avctp.c @@ -1351,11 +1351,11 @@ static void avctp_control_confirm(struct avctp *session, GIOChannel *chan, #ifdef __TIZEN_PATCH__ session->auth_id = btd_request_authorization(src, dst, AVRCP_TARGET_UUID, - auth_cb, session); + auth_cb, session, 0); #else session->auth_id = btd_request_authorization(src, dst, AVRCP_REMOTE_UUID, - auth_cb, session); + auth_cb, session, 0); #endif if (session->auth_id == 0) goto drop; diff --git a/profiles/audio/avdtp.c b/profiles/audio/avdtp.c index f6d810e..ef6979e 100644 --- a/profiles/audio/avdtp.c +++ b/profiles/audio/avdtp.c @@ -2722,7 +2722,7 @@ static void avdtp_confirm_cb(GIOChannel *chan, gpointer data) session->auth_id = btd_request_authorization(&src, &dst, ADVANCED_AUDIO_UUID, - auth_cb, session); + auth_cb, session, 0); if (session->auth_id == 0) { avdtp_set_state(session, AVDTP_SESSION_STATE_DISCONNECTED); goto drop; diff --git a/profiles/audio/avrcp.c b/profiles/audio/avrcp.c index f2817b7..90fd5d5 100644 --- a/profiles/audio/avrcp.c +++ b/profiles/audio/avrcp.c @@ -4031,8 +4031,12 @@ done: static struct btd_profile avrcp_target_profile = { .name = "audio-avrcp-target", + .version = 0x0105, .remote_uuid = AVRCP_TARGET_UUID, + .local_uuid = AVRCP_REMOTE_UUID, + .auth_uuid = AVRCP_REMOTE_UUID, + .device_probe = avrcp_target_probe, .device_remove = avrcp_target_remove, @@ -4114,8 +4118,12 @@ done: static struct btd_profile avrcp_controller_profile = { .name = "avrcp-controller", + .version = 0x0104, .remote_uuid = AVRCP_REMOTE_UUID, + .local_uuid = AVRCP_TARGET_UUID, + .auth_uuid = AVRCP_REMOTE_UUID, + .device_probe = avrcp_controller_probe, .device_remove = avrcp_controller_remove, diff --git a/profiles/health/hdp_manager.c b/profiles/health/hdp_manager.c index 1882043..95ee7ac 100644 --- a/profiles/health/hdp_manager.c +++ b/profiles/health/hdp_manager.c @@ -70,7 +70,10 @@ static void hdp_driver_remove(struct btd_service *service) static struct btd_profile hdp_source_profile = { .name = "hdp-source", + .version = 0x0100, + .remote_uuid = HDP_SOURCE_UUID, + .local_uuid = HDP_SINK_UUID, .device_probe = hdp_driver_probe, .device_remove = hdp_driver_remove, @@ -81,7 +84,10 @@ static struct btd_profile hdp_source_profile = { static struct btd_profile hdp_sink_profile = { .name = "hdp-sink", + .version = 0x0100, + .remote_uuid = HDP_SINK_UUID, + .local_uuid = HDP_SOURCE_UUID, .device_probe = hdp_driver_probe, .device_remove = hdp_driver_remove, diff --git a/profiles/input/device.c b/profiles/input/device.c index cfa5e23..277f8a5 100644 --- a/profiles/input/device.c +++ b/profiles/input/device.c @@ -1341,8 +1341,29 @@ static gboolean property_get_reconnect_mode( return TRUE; } +static gboolean property_get_connected(const GDBusPropertyTable *property, + DBusMessageIter *iter, void *data) +{ + struct input_device *idev = data; + dbus_bool_t connected; + + if (idev->service == NULL) + return FALSE; + + if (btd_service_get_state(idev->service) + == BTD_SERVICE_STATE_CONNECTED) { + connected = true; + } else + connected = false; + + dbus_message_iter_append_basic(iter, DBUS_TYPE_BOOLEAN, &connected); + + return TRUE; +} + static const GDBusPropertyTable input_properties[] = { { "ReconnectMode", "s", property_get_reconnect_mode }, + { "Connected", "b", property_get_connected }, { } }; diff --git a/profiles/input/manager.c b/profiles/input/manager.c index 9712d2c..cfc9f6a 100644 --- a/profiles/input/manager.c +++ b/profiles/input/manager.c @@ -57,6 +57,8 @@ static void hid_server_remove(struct btd_profile *p, static struct btd_profile input_profile = { .name = "input-hid", + .version = 0x0101, + .local_uuid = HID_UUID, .remote_uuid = HID_UUID, diff --git a/profiles/input/server.c b/profiles/input/server.c index 50a9074..95f7eeb 100644 --- a/profiles/input/server.c +++ b/profiles/input/server.c @@ -270,7 +270,7 @@ static void confirm_event_cb(GIOChannel *chan, gpointer user_data) bacpy(&server->confirm->dst, &dst); ret = btd_request_authorization(&src, &dst, HID_UUID, - auth_callback, server); + auth_callback, server, 0); if (ret != 0) return; diff --git a/profiles/network/manager.c b/profiles/network/manager.c index 0fe98a0..81b0ce0 100644 --- a/profiles/network/manager.c +++ b/profiles/network/manager.c @@ -135,8 +135,10 @@ static void nap_server_remove(struct btd_profile *p, static struct btd_profile panu_profile = { .name = "network-panu", + .version = 0x0100, .local_uuid = NAP_UUID, .remote_uuid = PANU_UUID, + .auth_uuid = BNEP_SVC_UUID, .device_probe = connection_register, .device_remove = connection_unregister, .connect = connection_connect, @@ -147,8 +149,10 @@ static struct btd_profile panu_profile = { static struct btd_profile gn_profile = { .name = "network-gn", + .version = 0x0100, .local_uuid = PANU_UUID, .remote_uuid = GN_UUID, + .auth_uuid = BNEP_SVC_UUID, .device_probe = connection_register, .device_remove = connection_unregister, .connect = connection_connect, @@ -159,8 +163,10 @@ static struct btd_profile gn_profile = { static struct btd_profile nap_profile = { .name = "network-nap", + .version = 0x0100, .local_uuid = PANU_UUID, .remote_uuid = NAP_UUID, + .auth_uuid = BNEP_SVC_UUID, .device_probe = connection_register, .device_remove = connection_unregister, .connect = connection_connect, diff --git a/profiles/network/server.c b/profiles/network/server.c index b010371..a1b4126 100644 --- a/profiles/network/server.c +++ b/profiles/network/server.c @@ -325,7 +325,7 @@ static gboolean server_disconnected_cb(GIOChannel *chan, { struct network_server *ns = NULL; struct network_session *session = NULL; - char address[20] = {0}; + char address[24] = {0}; const char* paddr = address; char *name_str = NULL; @@ -373,7 +373,7 @@ static gboolean bnep_setup(GIOChannel *chan, GIOCondition cond, gpointer user_data) { struct network_adapter *na = user_data; - struct network_server *ns; + struct network_server *ns = NULL; uint8_t packet[BNEP_MTU]; struct bnep_setup_conn_req *req = (void *) packet; uint16_t src_role, dst_role, rsp = BNEP_CONN_NOT_ALLOWED; @@ -564,7 +564,7 @@ static void confirm_event(GIOChannel *chan, gpointer user_data) na->setup->io = g_io_channel_ref(chan); ret = btd_request_authorization(&src, &dst, BNEP_SVC_UUID, - auth_cb, na); + auth_cb, na, 0); if (ret == 0) { error("Refusing connect from %s", address); setup_destroy(na); @@ -611,11 +611,26 @@ static void server_remove_sessions(struct network_server *ns) for (list = ns->sessions; list; list = list->next) { struct network_session *session = list->data; + char address[24] = {0}; + char *paddr = address; + const char *name_str = NULL; if (*session->dev == '\0') continue; bnep_server_delete(ns->bridge, session->dev, &session->dst); + + name_str = session->dev; + ba2str(&session->dst, paddr); + + DBG("send peerdisconnected signal"); + + g_dbus_emit_signal(btd_get_dbus_connection(), + adapter_get_path(ns->na->adapter), + NETWORK_SERVER_INTERFACE, "PeerDisconnected", + DBUS_TYPE_STRING, &name_str, + DBUS_TYPE_STRING, &paddr, + DBUS_TYPE_INVALID); } #ifndef __TIZEN_PATCH__ diff --git a/profiles/sap/server.c b/profiles/sap/server.c index 20c6cab..683d6f2 100644 --- a/profiles/sap/server.c +++ b/profiles/sap/server.c @@ -1253,7 +1253,7 @@ static void connect_confirm_cb(GIOChannel *io, gpointer data) ba2str(&dst, dstaddr); ret = btd_request_authorization(&src, &dst, SAP_UUID, connect_auth_cb, - server); + server, 0); if (ret == 0) { error("Authorization failure"); sap_server_remove_conn(server); diff --git a/src/adapter.c b/src/adapter.c index d7815e8..0066c76 100644 --- a/src/adapter.c +++ b/src/adapter.c @@ -173,6 +173,7 @@ struct service_auth { struct btd_device *device; struct btd_adapter *adapter; struct agent *agent; /* NULL for queued auths */ + int fd; }; struct btd_adapter_pin_cb_iter { @@ -7266,6 +7267,11 @@ static gboolean process_auth_queue(gpointer user_data) if (auth->svc_id > 0) return FALSE; + if (device_is_service_blocked(device, auth->uuid)) { + auth->cb(&err, auth->user_data); + goto next; + } + /* The below patch should be removed after we provide the API * to control autorization for the specific UUID. */ @@ -7288,7 +7294,7 @@ static gboolean process_auth_queue(gpointer user_data) dev_path = device_get_path(device); if (agent_authorize_service(auth->agent, dev_path, auth->uuid, - agent_auth_cb, adapter, NULL) < 0) { + agent_auth_cb, adapter, NULL, auth->fd) < 0) { auth->cb(&err, auth->user_data); goto next; } @@ -7324,7 +7330,7 @@ static void svc_complete(struct btd_device *dev, int err, void *user_data) static int adapter_authorize(struct btd_adapter *adapter, const bdaddr_t *dst, const char *uuid, service_auth_cb cb, - void *user_data) + void *user_data, int fd) { struct service_auth *auth; struct btd_device *device; @@ -7348,6 +7354,7 @@ static int adapter_authorize(struct btd_adapter *adapter, const bdaddr_t *dst, auth->device = device; auth->adapter = adapter; auth->id = ++id; + auth->fd = fd; auth->svc_id = device_wait_for_svc_complete(device, svc_complete, auth); g_queue_push_tail(adapter->auths, auth); @@ -7357,7 +7364,7 @@ static int adapter_authorize(struct btd_adapter *adapter, const bdaddr_t *dst, guint btd_request_authorization(const bdaddr_t *src, const bdaddr_t *dst, const char *uuid, service_auth_cb cb, - void *user_data) + void *user_data, int fd) { struct btd_adapter *adapter; GSList *l; @@ -7367,7 +7374,7 @@ guint btd_request_authorization(const bdaddr_t *src, const bdaddr_t *dst, if (!adapter) return 0; - return adapter_authorize(adapter, dst, uuid, cb, user_data); + return adapter_authorize(adapter, dst, uuid, cb, user_data, fd); } for (l = adapters; l != NULL; l = g_slist_next(l)) { @@ -7375,7 +7382,7 @@ guint btd_request_authorization(const bdaddr_t *src, const bdaddr_t *dst, adapter = l->data; - id = adapter_authorize(adapter, dst, uuid, cb, user_data); + id = adapter_authorize(adapter, dst, uuid, cb, user_data, fd); if (id != 0) return id; } diff --git a/src/adapter.h b/src/adapter.h index 8cb3009..0069c4b 100644 --- a/src/adapter.h +++ b/src/adapter.h @@ -127,7 +127,7 @@ void adapter_remove_profile(struct btd_adapter *adapter, gpointer p); int btd_register_adapter_driver(struct btd_adapter_driver *driver); void btd_unregister_adapter_driver(struct btd_adapter_driver *driver); guint btd_request_authorization(const bdaddr_t *src, const bdaddr_t *dst, - const char *uuid, service_auth_cb cb, void *user_data); + const char *uuid, service_auth_cb cb, void *user_data, int fd); int btd_cancel_authorization(guint id); int btd_adapter_restore_powered(struct btd_adapter *adapter); diff --git a/src/agent.c b/src/agent.c index 73b2fdd..bd88eb9 100644 --- a/src/agent.c +++ b/src/agent.c @@ -383,8 +383,9 @@ done: static int agent_call_authorize_service(struct agent_request *req, const char *device_path, - const char *uuid) + const char *uuid, const int fd) { + DBusMessageIter iter, dict; struct agent *agent = req->agent; req->msg = dbus_message_new_method_call(agent->owner, agent->path, @@ -394,10 +395,14 @@ static int agent_call_authorize_service(struct agent_request *req, return -ENOMEM; } - dbus_message_append_args(req->msg, - DBUS_TYPE_OBJECT_PATH, &device_path, - DBUS_TYPE_STRING, &uuid, - DBUS_TYPE_INVALID); + dbus_message_iter_init_append(req->msg, &iter); + + dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH, + &device_path); + + dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &uuid); + + dbus_message_iter_append_basic(&iter, DBUS_TYPE_UNIX_FD, &fd); if (g_dbus_send_message_with_reply(btd_get_dbus_connection(), req->msg, &req->call, @@ -412,7 +417,7 @@ static int agent_call_authorize_service(struct agent_request *req, int agent_authorize_service(struct agent *agent, const char *path, const char *uuid, agent_cb cb, - void *user_data, GDestroyNotify destroy) + void *user_data, GDestroyNotify destroy, int fd) { struct agent_request *req; int err; @@ -423,7 +428,7 @@ int agent_authorize_service(struct agent *agent, const char *path, req = agent_request_new(agent, AGENT_REQUEST_AUTHORIZE_SERVICE, cb, user_data, destroy); - err = agent_call_authorize_service(req, path, uuid); + err = agent_call_authorize_service(req, path, uuid, fd); if (err < 0) { agent_request_free(req, FALSE); return -ENOMEM; diff --git a/src/agent.h b/src/agent.h index 1e46920..dafee9c 100644 --- a/src/agent.h +++ b/src/agent.h @@ -40,7 +40,7 @@ struct agent *agent_get(const char *owner); int agent_authorize_service(struct agent *agent, const char *path, const char *uuid, agent_cb cb, - void *user_data, GDestroyNotify destroy); + void *user_data, GDestroyNotify destroy, int fd); int agent_request_pincode(struct agent *agent, struct btd_device *device, agent_pincode_cb cb, gboolean secure, diff --git a/src/bluetooth.conf b/src/bluetooth.conf index 70d9aa6..b575f78 100644 --- a/src/bluetooth.conf +++ b/src/bluetooth.conf @@ -8,6 +8,8 @@ + + @@ -38,6 +40,7 @@ + diff --git a/src/device.c b/src/device.c index f98e4a6..9a4f5f2 100644 --- a/src/device.c +++ b/src/device.c @@ -383,7 +383,7 @@ static GSList *find_service_with_gatt_handles(GSList *list, static void update_technologies(GKeyFile *file, struct btd_device *dev) { - const char *list[2]; + const char *list[2] = {NULL, NULL}; size_t len = 0; if (dev->bredr) @@ -810,6 +810,34 @@ gboolean device_is_trusted(struct btd_device *device) return device->trusted; } +bool device_is_service_blocked(struct btd_device *device, const char *uuid) +{ + GSList *l; + bool block = false; + + for (l = device->services; l; l = g_slist_next(l)) { + struct btd_service *service = l->data; + struct btd_profile *p = btd_service_get_profile(service); + const char *p_uuid; + + p_uuid = p->auth_uuid ? p->auth_uuid : p->local_uuid; + if (!p_uuid) + continue; + + if (strcasecmp(uuid, p_uuid)) + continue; + + if (!btd_service_is_blocked(service)) + return false; + + block = true; + } + + /* Every service matching is blocked + */ + return block; +} + static gboolean dev_property_get_address(const GDBusPropertyTable *property, DBusMessageIter *iter, void *data) { @@ -1811,6 +1839,10 @@ static GSList *create_pending_list(struct btd_device *dev, const char *uuid) for (l = dev->services; l != NULL; l = g_slist_next(l)) { service = l->data; + + if (!btd_service_get_auto_connect(service)) + continue; + p = btd_service_get_profile(service); #ifdef __TIZEN_PATCH__ diff --git a/src/device.h b/src/device.h index cc4ab4e..383f268 100644 --- a/src/device.h +++ b/src/device.h @@ -106,6 +106,7 @@ bool device_is_bonded(struct btd_device *device, uint8_t bdaddr_type); gboolean device_is_trusted(struct btd_device *device); void device_set_paired(struct btd_device *dev, uint8_t bdaddr_type); void device_set_unpaired(struct btd_device *dev, uint8_t bdaddr_type); +bool device_is_service_blocked(struct btd_device *device, const char *uuid); void btd_device_set_temporary(struct btd_device *device, gboolean temporary); void btd_device_set_trusted(struct btd_device *device, gboolean trusted); void device_set_bonded(struct btd_device *device, uint8_t bdaddr_type); diff --git a/src/org.bluez.service b/src/org.bluez.service index dd7ae8f..2a3b057 100644 --- a/src/org.bluez.service +++ b/src/org.bluez.service @@ -2,4 +2,4 @@ Name=org.bluez Exec=/bin/false User=root -SystemdService=dbus-org.bluez.service +SystemdService=bluetooth.service diff --git a/src/profile.c b/src/profile.c index 4634920..0874ecb 100644 --- a/src/profile.c +++ b/src/profile.c @@ -1253,6 +1253,7 @@ static void ext_confirm(GIOChannel *io, gpointer user_data) GError *gerr = NULL; bdaddr_t src, dst; char addr[18]; + int fd; bt_io_get(io, &gerr, BT_IO_OPT_SOURCE_BDADDR, &src, @@ -1272,8 +1273,9 @@ static void ext_confirm(GIOChannel *io, gpointer user_data) if (conn == NULL) return; + fd = g_io_channel_unix_get_fd(conn->io); conn->auth_id = btd_request_authorization(&src, &dst, uuid, ext_auth, - conn); + conn, fd); if (conn->auth_id == 0) { error("%s authorization failure", ext->name); ext_io_destroy(conn); diff --git a/src/profile.h b/src/profile.h index f5a3ded..254d85e 100644 --- a/src/profile.h +++ b/src/profile.h @@ -30,9 +30,11 @@ struct btd_service; struct btd_profile { const char *name; int priority; + uint16_t version; const char *local_uuid; const char *remote_uuid; + const char *auth_uuid; bool auto_connect; diff --git a/src/service.c b/src/service.c index 28e7169..8ecb7d4 100644 --- a/src/service.c +++ b/src/service.c @@ -36,6 +36,8 @@ #include #include +#include +#include #include @@ -55,6 +57,8 @@ struct btd_service { int err; uint16_t start_handle; uint16_t end_handle; + bool auto_connect; + bool blocked; }; struct service_state_callback { @@ -146,6 +150,7 @@ struct btd_service *service_create(struct btd_device *device, service->ref = 1; service->device = device; /* Weak ref */ service->profile = profile; + service->auto_connect = profile->auto_connect; service->state = BTD_SERVICE_STATE_UNAVAILABLE; return service; @@ -325,6 +330,51 @@ int btd_service_get_error(const struct btd_service *service) return service->err; } +uint16_t btd_service_get_version(const struct btd_service *service) +{ + const sdp_record_t *rec; + sdp_list_t *list; + sdp_profile_desc_t *desc; + uint16_t version; + + if (!service->profile->version) + return 0; + + rec = btd_device_get_record(service->device, + service->profile->remote_uuid); + if (rec == NULL) + return 0; + + if (sdp_get_profile_descs(rec, &list) < 0) + return 0; + + desc = list->data; + version = desc->version; + sdp_list_free(list, free); + + return MIN(version, service->profile->version); +} + +void btd_service_set_auto_connect(struct btd_service *service, bool value) +{ + service->auto_connect = value; +} + +bool btd_service_get_auto_connect(const struct btd_service *service) +{ + return service->auto_connect; +} + +void btd_service_set_blocked(struct btd_service *service, bool value) +{ + service->blocked = value; +} + +bool btd_service_is_blocked(const struct btd_service *service) +{ + return service->blocked; +} + bool btd_service_get_gatt_handles(const struct btd_service *service, uint16_t *start_handle, uint16_t *end_handle) diff --git a/src/service.h b/src/service.h index 3a0db6e..d092cc4 100644 --- a/src/service.h +++ b/src/service.h @@ -63,6 +63,11 @@ struct btd_device *btd_service_get_device(const struct btd_service *service); struct btd_profile *btd_service_get_profile(const struct btd_service *service); btd_service_state_t btd_service_get_state(const struct btd_service *service); int btd_service_get_error(const struct btd_service *service); +uint16_t btd_service_get_version(const struct btd_service *service); +void btd_service_set_auto_connect(struct btd_service *service, bool value); +bool btd_service_get_auto_connect(const struct btd_service *service); +void btd_service_set_blocked(struct btd_service *service, bool value); +bool btd_service_is_blocked(const struct btd_service *service); bool btd_service_get_gatt_handles(const struct btd_service *service, uint16_t *start_handle, uint16_t *end_handle); diff --git a/tools/bluetooth-player.c b/tools/bluetooth-player.c index f10d9be..f090e1b 100644 --- a/tools/bluetooth-player.c +++ b/tools/bluetooth-player.c @@ -654,6 +654,7 @@ static void cmd_show(int argc, char *argv[]) rl_printf("Player %s\n", g_dbus_proxy_get_path(proxy)); print_property(proxy, "Name"); + print_property(proxy, "Searchable"); print_property(proxy, "Repeat"); print_property(proxy, "Equalizer"); print_property(proxy, "Shuffle"); diff --git a/tools/hciattach.c b/tools/hciattach.c index db11f9a..3535faa 100644 --- a/tools/hciattach.c +++ b/tools/hciattach.c @@ -1530,7 +1530,7 @@ int main(int argc, char *argv[]) dev[0] = 0; if (!strchr(opt, '/')) strcpy(dev, "/dev/"); - strcat(dev, opt); + strncat(dev, opt, PATH_MAX); break; case 1: diff --git a/tools/hcitool.c b/tools/hcitool.c index 648a0f7..2c84dc7 100644 --- a/tools/hcitool.c +++ b/tools/hcitool.c @@ -2404,7 +2404,9 @@ failed: static int print_advertising_devices(int dd, uint8_t filter_type) { - unsigned char buf[HCI_MAX_EVENT_SIZE], *ptr; + unsigned char buf_array[HCI_MAX_EVENT_SIZE+1] = {0}; + unsigned char *buf = buf_array; + unsigned char *ptr = NULL; struct hci_filter nf, of; struct sigaction sa; socklen_t olen; @@ -2431,11 +2433,14 @@ static int print_advertising_devices(int dd, uint8_t filter_type) sigaction(SIGINT, &sa, NULL); while (1) { - evt_le_meta_event *meta; - le_advertising_info *info; - char addr[18]; + evt_le_meta_event *meta = NULL; + le_advertising_info *info = NULL; + char addr_array[18]; + char *addr = addr_array; + + buf[HCI_MAX_EVENT_SIZE] = 0; - while ((len = read(dd, buf, sizeof(buf))) < 0) { + while ((len = read(dd, buf, HCI_MAX_EVENT_SIZE)) < 0) { if (errno == EINTR && signal_received == SIGINT) { len = 0; goto done; @@ -2457,14 +2462,16 @@ static int print_advertising_devices(int dd, uint8_t filter_type) /* Ignoring multiple reports */ info = (le_advertising_info *) (meta->data + 1); if (check_report_filter(filter_type, info)) { - char name[30]; + char name_array[30]; + char *name = name_array; - memset(name, 0, sizeof(name)); + memset(name, 0, 30); ba2str(&info->bdaddr, addr); eir_parse_name(info->data, info->length, - name, sizeof(name) - 1); + name, 29); + name[29] = '\0'; printf("%s %s\n", addr, name); } }