3
* BlueZ - Bluetooth protocol stack for Linux
5
* Copyright (C) 2006-2007 Nokia Corporation
6
* Copyright (C) 2004-2008 Marcel Holtmann <marcel@holtmann.org>
9
* This program is free software; you can redistribute it and/or modify
10
* it under the terms of the GNU General Public License as published by
11
* the Free Software Foundation; either version 2 of the License, or
12
* (at your option) any later version.
14
* This program is distributed in the hope that it will be useful,
15
* but WITHOUT ANY WARRANTY; without even the implied warranty of
16
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
* GNU General Public License for more details.
19
* You should have received a copy of the GNU General Public License
20
* along with this program; if not, write to the Free Software
21
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
33
#include <bluetooth/bluetooth.h>
34
#include <bluetooth/hci.h>
35
#include <bluetooth/hci_lib.h>
36
#include <bluetooth/sdp.h>
37
#include <bluetooth/sdp_lib.h>
48
#define SERVICE_INTERFACE "org.bluez.Service"
50
static DBusConnection *connection = NULL;
56
struct service_adapter *serv_adapter;
62
struct sdp_xml_data *stack_head;
71
char uuid[MAX_LEN_UUID_STR];
74
struct service_adapter {
75
struct btd_adapter *adapter;
80
static int compute_seq_size(sdp_data_t *data)
82
int unit_size = data->unitSize;
83
sdp_data_t *seq = data->val.dataseq;
85
for (; seq; seq = seq->next)
86
unit_size += seq->unitSize;
91
static void element_start(GMarkupParseContext *context,
92
const gchar *element_name, const gchar **attribute_names,
93
const gchar **attribute_values, gpointer user_data, GError **err)
95
struct context_data *ctx_data = user_data;
97
if (!strcmp(element_name, "record"))
100
if (!strcmp(element_name, "attribute")) {
102
for (i = 0; attribute_names[i]; i++) {
103
if (!strcmp(attribute_names[i], "id")) {
104
ctx_data->attr_id = strtol(attribute_values[i], 0, 0);
108
debug("New attribute 0x%04x", ctx_data->attr_id);
112
if (ctx_data->stack_head) {
113
struct sdp_xml_data *newelem = sdp_xml_data_alloc();
114
newelem->next = ctx_data->stack_head;
115
ctx_data->stack_head = newelem;
117
ctx_data->stack_head = sdp_xml_data_alloc();
118
ctx_data->stack_head->next = NULL;
121
if (!strcmp(element_name, "sequence"))
122
ctx_data->stack_head->data = sdp_data_alloc(SDP_SEQ8, NULL);
123
else if (!strcmp(element_name, "alternate"))
124
ctx_data->stack_head->data = sdp_data_alloc(SDP_ALT8, NULL);
127
/* Parse value, name, encoding */
128
for (i = 0; attribute_names[i]; i++) {
129
if (!strcmp(attribute_names[i], "value")) {
130
int curlen = strlen(ctx_data->stack_head->text);
131
int attrlen = strlen(attribute_values[i]);
133
/* Ensure we're big enough */
134
while ((curlen + 1 + attrlen) > ctx_data->stack_head->size) {
135
sdp_xml_data_expand(ctx_data->stack_head);
138
memcpy(ctx_data->stack_head->text + curlen,
139
attribute_values[i], attrlen);
140
ctx_data->stack_head->text[curlen + attrlen] = '\0';
143
if (!strcmp(attribute_names[i], "encoding")) {
144
if (!strcmp(attribute_values[i], "hex"))
145
ctx_data->stack_head->type = 1;
148
if (!strcmp(attribute_names[i], "name")) {
149
ctx_data->stack_head->name = strdup(attribute_values[i]);
153
ctx_data->stack_head->data = sdp_xml_parse_datatype(element_name,
154
ctx_data->stack_head, ctx_data->record);
156
if (ctx_data->stack_head->data == NULL)
157
error("Can't parse element %s", element_name);
161
static void element_end(GMarkupParseContext *context,
162
const gchar *element_name, gpointer user_data, GError **err)
164
struct context_data *ctx_data = user_data;
165
struct sdp_xml_data *elem;
167
if (!strcmp(element_name, "record"))
170
if (!strcmp(element_name, "attribute")) {
171
if (ctx_data->stack_head && ctx_data->stack_head->data) {
172
int ret = sdp_attr_add(ctx_data->record, ctx_data->attr_id,
173
ctx_data->stack_head->data);
175
debug("Trouble adding attribute\n");
177
ctx_data->stack_head->data = NULL;
178
sdp_xml_data_free(ctx_data->stack_head);
179
ctx_data->stack_head = NULL;
181
debug("No data for attribute 0x%04x\n", ctx_data->attr_id);
186
if (!strcmp(element_name, "sequence")) {
187
ctx_data->stack_head->data->unitSize = compute_seq_size(ctx_data->stack_head->data);
189
if (ctx_data->stack_head->data->unitSize > USHRT_MAX) {
190
ctx_data->stack_head->data->unitSize += sizeof(uint32_t);
191
ctx_data->stack_head->data->dtd = SDP_SEQ32;
192
} else if (ctx_data->stack_head->data->unitSize > UCHAR_MAX) {
193
ctx_data->stack_head->data->unitSize += sizeof(uint16_t);
194
ctx_data->stack_head->data->dtd = SDP_SEQ16;
196
ctx_data->stack_head->data->unitSize += sizeof(uint8_t);
198
} else if (!strcmp(element_name, "alternate")) {
199
ctx_data->stack_head->data->unitSize = compute_seq_size(ctx_data->stack_head->data);
201
if (ctx_data->stack_head->data->unitSize > USHRT_MAX) {
202
ctx_data->stack_head->data->unitSize += sizeof(uint32_t);
203
ctx_data->stack_head->data->dtd = SDP_ALT32;
204
} else if (ctx_data->stack_head->data->unitSize > UCHAR_MAX) {
205
ctx_data->stack_head->data->unitSize += sizeof(uint16_t);
206
ctx_data->stack_head->data->dtd = SDP_ALT16;
208
ctx_data->stack_head->data->unitSize += sizeof(uint8_t);
212
if (ctx_data->stack_head->next && ctx_data->stack_head->data &&
213
ctx_data->stack_head->next->data) {
214
switch (ctx_data->stack_head->next->data->dtd) {
221
ctx_data->stack_head->next->data->val.dataseq =
222
sdp_seq_append(ctx_data->stack_head->next->data->val.dataseq,
223
ctx_data->stack_head->data);
224
ctx_data->stack_head->data = NULL;
228
elem = ctx_data->stack_head;
229
ctx_data->stack_head = ctx_data->stack_head->next;
231
sdp_xml_data_free(elem);
235
static GMarkupParser parser = {
236
element_start, element_end, NULL, NULL, NULL
239
static sdp_record_t *sdp_xml_parse_record(const char *data, int size)
241
GMarkupParseContext *ctx;
242
struct context_data *ctx_data;
243
sdp_record_t *record;
245
ctx_data = malloc(sizeof(*ctx_data));
249
record = sdp_record_alloc();
255
memset(ctx_data, 0, sizeof(*ctx_data));
256
ctx_data->record = record;
258
ctx = g_markup_parse_context_new(&parser, 0, ctx_data, NULL);
260
if (g_markup_parse_context_parse(ctx, data, size, NULL) == FALSE) {
261
error("XML parsing error");
262
g_markup_parse_context_free(ctx);
263
sdp_record_free(record);
268
g_markup_parse_context_free(ctx);
275
static struct record_data *find_record(struct service_adapter *serv_adapter,
276
uint32_t handle, const char *sender)
280
for (list = serv_adapter->records; list; list = list->next) {
281
struct record_data *data = list->data;
282
if (handle == data->handle && !strcmp(sender, data->sender))
289
static struct pending_auth *next_pending(struct service_adapter *serv_adapter)
291
GSList *l = serv_adapter->pending_list;
294
struct pending_auth *auth = l->data;
301
static struct pending_auth *find_pending_by_sender(
302
struct service_adapter *serv_adapter,
305
GSList *l = serv_adapter->pending_list;
307
for (; l; l = l->next) {
308
struct pending_auth *auth = l->data;
309
if (g_str_equal(auth->sender, sender))
316
static void exit_callback(void *user_data)
318
struct record_data *user_record = user_data;
319
struct service_adapter *serv_adapter = user_record->serv_adapter;
320
struct pending_auth *auth;
322
debug("remove record");
324
serv_adapter->records = g_slist_remove(serv_adapter->records,
327
auth = find_pending_by_sender(serv_adapter, user_record->sender);
329
serv_adapter->pending_list = g_slist_remove(serv_adapter->pending_list,
334
remove_record_from_server(user_record->handle);
336
g_free(user_record->sender);
340
static inline DBusMessage *invalid_arguments(DBusMessage *msg)
342
return g_dbus_create_error(msg, ERROR_INTERFACE ".InvalidArguments",
343
"Invalid arguments in method call");
346
static inline DBusMessage *not_available(DBusMessage *msg)
348
return g_dbus_create_error(msg, ERROR_INTERFACE ".NotAvailable",
352
static inline DBusMessage *failed(DBusMessage *msg)
354
return g_dbus_create_error(msg, ERROR_INTERFACE ".Failed", "Failed");
357
static inline DBusMessage *failed_strerror(DBusMessage *msg, int err)
359
return g_dbus_create_error(msg, ERROR_INTERFACE ".Failed",
363
static inline DBusMessage *not_authorized(DBusMessage *msg)
365
return g_dbus_create_error(msg, ERROR_INTERFACE ".NotAuthorized",
369
static inline DBusMessage *does_not_exist(DBusMessage *msg)
371
return g_dbus_create_error(msg, ERROR_INTERFACE ".DoesNotExist",
375
static int add_xml_record(DBusConnection *conn, const char *sender,
376
struct service_adapter *serv_adapter,
377
const char *record, dbus_uint32_t *handle)
379
struct record_data *user_record;
380
sdp_record_t *sdp_record;
383
sdp_record = sdp_xml_parse_record(record, strlen(record));
385
error("Parsing of XML service record failed");
389
adapter_get_address(serv_adapter->adapter, &src);
390
if (add_record_to_server(&src, sdp_record) < 0) {
391
error("Failed to register service record");
392
sdp_record_free(sdp_record);
396
user_record = g_new0(struct record_data, 1);
397
user_record->handle = sdp_record->handle;
398
user_record->sender = g_strdup(sender);
399
user_record->serv_adapter = serv_adapter;
400
user_record->listener_id = g_dbus_add_disconnect_watch(conn, sender,
401
exit_callback, user_record, NULL);
403
serv_adapter->records = g_slist_append(serv_adapter->records,
406
debug("listener_id %d", user_record->listener_id);
408
*handle = user_record->handle;
413
static DBusMessage *update_record(DBusConnection *conn, DBusMessage *msg,
414
struct service_adapter *serv_adapter,
415
dbus_uint32_t handle, sdp_record_t *sdp_record)
420
if (remove_record_from_server(handle) < 0) {
421
sdp_record_free(sdp_record);
422
return g_dbus_create_error(msg,
423
ERROR_INTERFACE ".NotAvailable",
427
adapter_get_address(serv_adapter->adapter, &src);
429
sdp_record->handle = handle;
430
err = add_record_to_server(&src, sdp_record);
432
sdp_record_free(sdp_record);
433
error("Failed to update the service record");
434
return g_dbus_create_error(msg,
435
ERROR_INTERFACE ".Failed",
439
return dbus_message_new_method_return(msg);
442
static DBusMessage *update_xml_record(DBusConnection *conn,
444
struct service_adapter *serv_adapter)
446
struct record_data *user_record;
447
sdp_record_t *sdp_record;
449
dbus_uint32_t handle;
452
if (dbus_message_get_args(msg, NULL,
453
DBUS_TYPE_UINT32, &handle,
454
DBUS_TYPE_STRING, &record,
455
DBUS_TYPE_INVALID) == FALSE)
458
len = (record ? strlen(record) : 0);
460
return invalid_arguments(msg);
462
user_record = find_record(serv_adapter, handle,
463
dbus_message_get_sender(msg));
465
return g_dbus_create_error(msg,
466
ERROR_INTERFACE ".NotAvailable",
469
sdp_record = sdp_xml_parse_record(record, len);
471
error("Parsing of XML service record failed");
472
sdp_record_free(sdp_record);
473
return g_dbus_create_error(msg,
474
ERROR_INTERFACE ".Failed",
478
return update_record(conn, msg, serv_adapter, handle, sdp_record);
481
static int remove_record(DBusConnection *conn, const char *sender,
482
struct service_adapter *serv_adapter,
483
dbus_uint32_t handle)
485
struct record_data *user_record;
487
debug("remove record 0x%x", handle);
489
user_record = find_record(serv_adapter, handle, sender);
493
debug("listner_id %d", user_record->listener_id);
495
g_dbus_remove_watch(conn, user_record->listener_id);
497
exit_callback(user_record);
502
static DBusMessage *add_service_record(DBusConnection *conn,
503
DBusMessage *msg, void *data)
505
struct service_adapter *serv_adapter = data;
507
const char *sender, *record;
508
dbus_uint32_t handle;
511
if (dbus_message_get_args(msg, NULL,
512
DBUS_TYPE_STRING, &record, DBUS_TYPE_INVALID) == FALSE)
515
sender = dbus_message_get_sender(msg);
516
err = add_xml_record(conn, sender, serv_adapter, record, &handle);
518
return failed_strerror(msg, err);
520
reply = dbus_message_new_method_return(msg);
524
dbus_message_append_args(reply, DBUS_TYPE_UINT32, &handle,
530
static DBusMessage *update_service_record(DBusConnection *conn,
531
DBusMessage *msg, void *data)
533
struct service_adapter *serv_adapter = data;
535
return update_xml_record(conn, msg, serv_adapter);
538
static DBusMessage *remove_service_record(DBusConnection *conn,
539
DBusMessage *msg, void *data)
541
struct service_adapter *serv_adapter = data;
542
dbus_uint32_t handle;
545
if (dbus_message_get_args(msg, NULL, DBUS_TYPE_UINT32, &handle,
546
DBUS_TYPE_INVALID) == FALSE)
549
sender = dbus_message_get_sender(msg);
551
if (remove_record(conn, sender, serv_adapter, handle) < 0)
552
return not_available(msg);
554
return dbus_message_new_method_return(msg);
557
static void auth_cb(DBusError *derr, void *user_data)
559
struct service_adapter *serv_adapter = user_data;
561
struct pending_auth *auth;
564
auth = next_pending(serv_adapter);
566
info("Authorization cancelled: Client exited");
571
adapter_get_address(serv_adapter->adapter, &src);
572
error("Access denied: %s", derr->message);
574
reply = not_authorized(auth->msg);
575
dbus_message_unref(auth->msg);
576
g_dbus_send_message(auth->conn, reply);
580
g_dbus_send_reply(auth->conn, auth->msg,
584
dbus_connection_unref(auth->conn);
586
serv_adapter->pending_list = g_slist_remove(serv_adapter->pending_list,
590
auth = next_pending(serv_adapter);
594
adapter_get_address(serv_adapter->adapter, &src);
595
btd_request_authorization(&src, &auth->dst,
596
auth->uuid, auth_cb, serv_adapter);
599
static DBusMessage *request_authorization(DBusConnection *conn,
600
DBusMessage *msg, void *data)
602
struct record_data *user_record;
603
struct service_adapter *serv_adapter = data;
604
struct btd_adapter *adapter = serv_adapter->adapter;
605
sdp_record_t *record;
606
sdp_list_t *services;
608
dbus_uint32_t handle;
610
struct pending_auth *auth;
611
char uuid_str[MAX_LEN_UUID_STR];
612
uuid_t *uuid, *uuid128;
615
if (dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &address,
616
DBUS_TYPE_UINT32, &handle,
617
DBUS_TYPE_INVALID) == FALSE)
620
sender = dbus_message_get_sender(msg);
621
if (find_pending_by_sender(serv_adapter, sender))
624
user_record = find_record(serv_adapter, handle, sender);
626
return not_authorized(msg);
628
record = sdp_record_find(user_record->handle);
630
if (sdp_get_service_classes(record, &services) < 0) {
631
sdp_record_free(record);
632
return not_authorized(msg);
635
if (services == NULL)
636
return not_authorized(msg);
638
uuid = services->data;
639
uuid128 = sdp_uuid_to_uuid128(uuid);
641
sdp_list_free(services, bt_free);
643
if (sdp_uuid2strn(uuid128, uuid_str, MAX_LEN_UUID_STR) < 0) {
645
return not_authorized(msg);
649
auth = g_new0(struct pending_auth, 1);
650
auth->msg = dbus_message_ref(msg);
651
auth->conn = dbus_connection_ref(connection);
652
auth->sender = user_record->sender;
653
memcpy(auth->uuid, uuid_str, MAX_LEN_UUID_STR);
654
str2ba(address, &auth->dst);
656
serv_adapter->pending_list = g_slist_append(serv_adapter->pending_list,
659
auth = next_pending(serv_adapter);
661
return does_not_exist(msg);
663
adapter_get_address(adapter, &src);
664
if (btd_request_authorization(&src, &auth->dst, auth->uuid, auth_cb,
666
serv_adapter->pending_list = g_slist_remove(serv_adapter->pending_list, auth);
668
return not_authorized(msg);
674
static DBusMessage *cancel_authorization(DBusConnection *conn,
675
DBusMessage *msg, void *data)
678
struct service_adapter *serv_adapter = data;
679
struct btd_adapter *adapter = serv_adapter->adapter;
680
struct pending_auth *auth;
684
sender = dbus_message_get_sender(msg);
686
auth = find_pending_by_sender(serv_adapter, sender);
688
return does_not_exist(msg);
690
adapter_get_address(adapter, &src);
691
btd_cancel_authorization(&src, &auth->dst);
693
reply = not_authorized(auth->msg);
694
dbus_message_unref(auth->msg);
695
g_dbus_send_message(auth->conn, reply);
697
dbus_connection_unref(auth->conn);
699
serv_adapter->pending_list = g_slist_remove(serv_adapter->pending_list,
703
auth = next_pending(serv_adapter);
707
adapter_get_address(adapter, &src);
708
btd_request_authorization(&src, &auth->dst,
709
auth->uuid, auth_cb, serv_adapter);
712
return dbus_message_new_method_return(msg);
715
static GDBusMethodTable service_methods[] = {
716
{ "AddRecord", "s", "u", add_service_record },
717
{ "UpdateRecord", "us", "", update_service_record },
718
{ "RemoveRecord", "u", "", remove_service_record },
719
{ "RequestAuthorization","su", "", request_authorization,
720
G_DBUS_METHOD_FLAG_ASYNC},
721
{ "CancelAuthorization", "", "", cancel_authorization },
725
static void path_unregister(void *data)
727
struct service_adapter *serv_adapter = data;
729
g_slist_foreach(serv_adapter->records, (GFunc) exit_callback, NULL);
732
static int service_probe(struct btd_adapter *adapter)
734
const char *path = adapter_get_path(adapter);
735
struct service_adapter *serv_adapter;
737
DBG("path %s", path);
739
serv_adapter = g_new0(struct service_adapter, 1);
740
serv_adapter->adapter = adapter;
741
serv_adapter->pending_list = NULL;
743
if (!g_dbus_register_interface(connection, path,
745
service_methods, NULL, NULL,
746
serv_adapter, path_unregister)) {
747
error("D-Bus failed to register %s interface",
752
info("Registered interface %s on path %s", SERVICE_INTERFACE, path);
757
static void service_remove(struct btd_adapter *adapter)
759
const char *path = adapter_get_path(adapter);
761
DBG("path %s", path);
763
g_dbus_unregister_interface(connection, path, SERVICE_INTERFACE);
766
static struct btd_adapter_driver service_driver = {
768
.probe = service_probe,
769
.remove = service_remove,
772
static int service_init(void)
774
connection = dbus_bus_get(DBUS_BUS_SYSTEM, NULL);
775
if (connection == NULL)
778
return btd_register_adapter_driver(&service_driver);
781
static void service_exit(void)
783
btd_unregister_adapter_driver(&service_driver);
785
dbus_connection_unref(connection);
788
BLUETOOTH_PLUGIN_DEFINE("service", service_init, service_exit)