1/*
2 *
3 *  BlueZ - Bluetooth protocol stack for Linux
4 *
5 *  Copyright (C) 2006-2010  Nokia Corporation
6 *  Copyright (C) 2004-2010  Marcel Holtmann <marcel@holtmann.org>
7 *
8 *
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.
13 *
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.
18 *
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
22 *
23 */
24
25#ifdef HAVE_CONFIG_H
26#include <config.h>
27#endif
28
29#include <errno.h>
30#include <stdlib.h>
31#include <string.h>
32
33#include <bluetooth/bluetooth.h>
34#include <bluetooth/sdp.h>
35#include <bluetooth/sdp_lib.h>
36
37#include <gdbus.h>
38
39#include "sdpd.h"
40#include "sdp-xml.h"
41#include "plugin.h"
42#include "adapter.h"
43#include "error.h"
44#include "log.h"
45
46#define SERVICE_INTERFACE "org.bluez.Service"
47
48static DBusConnection *connection;
49
50struct record_data {
51	uint32_t handle;
52	char *sender;
53	guint listener_id;
54	struct service_adapter *serv_adapter;
55};
56
57struct context_data {
58	sdp_record_t *record;
59	sdp_data_t attr_data;
60	struct sdp_xml_data *stack_head;
61	uint16_t attr_id;
62};
63
64struct pending_auth {
65	DBusConnection *conn;
66	DBusMessage *msg;
67	char *sender;
68	bdaddr_t dst;
69	char uuid[MAX_LEN_UUID_STR];
70};
71
72struct service_adapter {
73	struct btd_adapter *adapter;
74	GSList *pending_list;
75	GSList *records;
76};
77
78static struct service_adapter *serv_adapter_any = NULL;
79
80static int compute_seq_size(sdp_data_t *data)
81{
82	int unit_size = data->unitSize;
83	sdp_data_t *seq = data->val.dataseq;
84
85	for (; seq; seq = seq->next)
86		unit_size += seq->unitSize;
87
88	return unit_size;
89}
90
91static void element_start(GMarkupParseContext *context,
92		const gchar *element_name, const gchar **attribute_names,
93		const gchar **attribute_values, gpointer user_data, GError **err)
94{
95	struct context_data *ctx_data = user_data;
96
97	if (!strcmp(element_name, "record"))
98		return;
99
100	if (!strcmp(element_name, "attribute")) {
101		int i;
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);
105				break;
106			}
107		}
108		DBG("New attribute 0x%04x", ctx_data->attr_id);
109		return;
110	}
111
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;
116	} else {
117		ctx_data->stack_head = sdp_xml_data_alloc();
118		ctx_data->stack_head->next = NULL;
119	}
120
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);
125	else {
126		int i;
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]);
132
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);
136				}
137
138				memcpy(ctx_data->stack_head->text + curlen,
139						attribute_values[i], attrlen);
140				ctx_data->stack_head->text[curlen + attrlen] = '\0';
141			}
142
143			if (!strcmp(attribute_names[i], "encoding")) {
144				if (!strcmp(attribute_values[i], "hex"))
145					ctx_data->stack_head->type = 1;
146			}
147
148			if (!strcmp(attribute_names[i], "name")) {
149				ctx_data->stack_head->name = strdup(attribute_values[i]);
150			}
151		}
152
153		ctx_data->stack_head->data = sdp_xml_parse_datatype(element_name,
154				ctx_data->stack_head, ctx_data->record);
155
156		if (ctx_data->stack_head->data == NULL)
157			error("Can't parse element %s", element_name);
158	}
159}
160
161static void element_end(GMarkupParseContext *context,
162		const gchar *element_name, gpointer user_data, GError **err)
163{
164	struct context_data *ctx_data = user_data;
165	struct sdp_xml_data *elem;
166
167	if (!strcmp(element_name, "record"))
168		return;
169
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);
174			if (ret == -1)
175				DBG("Could not add attribute 0x%04x",
176							ctx_data->attr_id);
177
178			ctx_data->stack_head->data = NULL;
179			sdp_xml_data_free(ctx_data->stack_head);
180			ctx_data->stack_head = NULL;
181		} else {
182			DBG("No data for attribute 0x%04x", ctx_data->attr_id);
183		}
184		return;
185	}
186
187	if (!strcmp(element_name, "sequence")) {
188		ctx_data->stack_head->data->unitSize = compute_seq_size(ctx_data->stack_head->data);
189
190		if (ctx_data->stack_head->data->unitSize > USHRT_MAX) {
191			ctx_data->stack_head->data->unitSize += sizeof(uint32_t);
192			ctx_data->stack_head->data->dtd = SDP_SEQ32;
193		} else if (ctx_data->stack_head->data->unitSize > UCHAR_MAX) {
194			ctx_data->stack_head->data->unitSize += sizeof(uint16_t);
195			ctx_data->stack_head->data->dtd = SDP_SEQ16;
196		} else {
197			ctx_data->stack_head->data->unitSize += sizeof(uint8_t);
198		}
199	} else if (!strcmp(element_name, "alternate")) {
200		ctx_data->stack_head->data->unitSize = compute_seq_size(ctx_data->stack_head->data);
201
202		if (ctx_data->stack_head->data->unitSize > USHRT_MAX) {
203			ctx_data->stack_head->data->unitSize += sizeof(uint32_t);
204			ctx_data->stack_head->data->dtd = SDP_ALT32;
205		} else if (ctx_data->stack_head->data->unitSize > UCHAR_MAX) {
206			ctx_data->stack_head->data->unitSize += sizeof(uint16_t);
207			ctx_data->stack_head->data->dtd = SDP_ALT16;
208		} else {
209			ctx_data->stack_head->data->unitSize += sizeof(uint8_t);
210		}
211	}
212
213	if (ctx_data->stack_head->next && ctx_data->stack_head->data &&
214					ctx_data->stack_head->next->data) {
215		switch (ctx_data->stack_head->next->data->dtd) {
216		case SDP_SEQ8:
217		case SDP_SEQ16:
218		case SDP_SEQ32:
219		case SDP_ALT8:
220		case SDP_ALT16:
221		case SDP_ALT32:
222			ctx_data->stack_head->next->data->val.dataseq =
223				sdp_seq_append(ctx_data->stack_head->next->data->val.dataseq,
224								ctx_data->stack_head->data);
225			ctx_data->stack_head->data = NULL;
226			break;
227		}
228
229		elem = ctx_data->stack_head;
230		ctx_data->stack_head = ctx_data->stack_head->next;
231
232		sdp_xml_data_free(elem);
233	}
234}
235
236static GMarkupParser parser = {
237	element_start, element_end, NULL, NULL, NULL
238};
239
240static sdp_record_t *sdp_xml_parse_record(const char *data, int size)
241{
242	GMarkupParseContext *ctx;
243	struct context_data *ctx_data;
244	sdp_record_t *record;
245
246	ctx_data = malloc(sizeof(*ctx_data));
247	if (!ctx_data)
248		return NULL;
249
250	record = sdp_record_alloc();
251	if (!record) {
252		free(ctx_data);
253		return NULL;
254	}
255
256	memset(ctx_data, 0, sizeof(*ctx_data));
257	ctx_data->record = record;
258
259	ctx = g_markup_parse_context_new(&parser, 0, ctx_data, NULL);
260
261	if (g_markup_parse_context_parse(ctx, data, size, NULL) == FALSE) {
262		error("XML parsing error");
263		g_markup_parse_context_free(ctx);
264		sdp_record_free(record);
265		free(ctx_data);
266		return NULL;
267	}
268
269	g_markup_parse_context_free(ctx);
270
271	free(ctx_data);
272
273	return record;
274}
275
276static struct record_data *find_record(struct service_adapter *serv_adapter,
277					uint32_t handle, const char *sender)
278{
279	GSList *list;
280
281	for (list = serv_adapter->records; list; list = list->next) {
282		struct record_data *data = list->data;
283		if (handle == data->handle && !strcmp(sender, data->sender))
284			return data;
285	}
286
287	return NULL;
288}
289
290static struct pending_auth *next_pending(struct service_adapter *serv_adapter)
291{
292	GSList *l = serv_adapter->pending_list;
293
294	if (l) {
295		struct pending_auth *auth = l->data;
296		return auth;
297	}
298
299	return NULL;
300}
301
302static struct pending_auth *find_pending_by_sender(
303			struct service_adapter *serv_adapter,
304			const char *sender)
305{
306	GSList *l = serv_adapter->pending_list;
307
308	for (; l; l = l->next) {
309		struct pending_auth *auth = l->data;
310		if (g_str_equal(auth->sender, sender))
311			return auth;
312	}
313
314	return NULL;
315}
316
317static void exit_callback(DBusConnection *conn, void *user_data)
318{
319	struct record_data *user_record = user_data;
320	struct service_adapter *serv_adapter = user_record->serv_adapter;
321	struct pending_auth *auth;
322
323	DBG("remove record");
324
325	serv_adapter->records = g_slist_remove(serv_adapter->records,
326						user_record);
327
328	auth = find_pending_by_sender(serv_adapter, user_record->sender);
329	if (auth) {
330		serv_adapter->pending_list = g_slist_remove(serv_adapter->pending_list,
331							auth);
332		g_free(auth);
333	}
334
335	remove_record_from_server(user_record->handle);
336
337	g_free(user_record->sender);
338	g_free(user_record);
339}
340
341static int add_xml_record(DBusConnection *conn, const char *sender,
342			struct service_adapter *serv_adapter,
343			const char *record, dbus_uint32_t *handle)
344{
345	struct record_data *user_record;
346	sdp_record_t *sdp_record;
347	bdaddr_t src;
348
349	sdp_record = sdp_xml_parse_record(record, strlen(record));
350	if (!sdp_record) {
351		error("Parsing of XML service record failed");
352		return -EIO;
353	}
354
355	if (serv_adapter->adapter)
356		adapter_get_address(serv_adapter->adapter, &src);
357	else
358		bacpy(&src, BDADDR_ANY);
359
360	if (add_record_to_server(&src, sdp_record) < 0) {
361		error("Failed to register service record");
362		sdp_record_free(sdp_record);
363		return -EIO;
364	}
365
366	user_record = g_new0(struct record_data, 1);
367	user_record->handle = sdp_record->handle;
368	user_record->sender = g_strdup(sender);
369	user_record->serv_adapter = serv_adapter;
370	user_record->listener_id = g_dbus_add_disconnect_watch(conn, sender,
371					exit_callback, user_record, NULL);
372
373	serv_adapter->records = g_slist_append(serv_adapter->records,
374								user_record);
375
376	DBG("listener_id %d", user_record->listener_id);
377
378	*handle = user_record->handle;
379
380	return 0;
381}
382
383static DBusMessage *update_record(DBusConnection *conn, DBusMessage *msg,
384		struct service_adapter *serv_adapter,
385		dbus_uint32_t handle, sdp_record_t *sdp_record)
386{
387	bdaddr_t src;
388	int err;
389
390	if (remove_record_from_server(handle) < 0) {
391		sdp_record_free(sdp_record);
392		return btd_error_not_available(msg);
393	}
394
395	if (serv_adapter->adapter)
396		adapter_get_address(serv_adapter->adapter, &src);
397	else
398		bacpy(&src, BDADDR_ANY);
399
400	sdp_record->handle = handle;
401	err = add_record_to_server(&src, sdp_record);
402	if (err < 0) {
403		sdp_record_free(sdp_record);
404		error("Failed to update the service record");
405		return btd_error_failed(msg, strerror(-err));
406	}
407
408	return dbus_message_new_method_return(msg);
409}
410
411static DBusMessage *update_xml_record(DBusConnection *conn,
412				DBusMessage *msg,
413				struct service_adapter *serv_adapter)
414{
415	struct record_data *user_record;
416	sdp_record_t *sdp_record;
417	const char *record;
418	dbus_uint32_t handle;
419	int len;
420
421	if (dbus_message_get_args(msg, NULL,
422				DBUS_TYPE_UINT32, &handle,
423				DBUS_TYPE_STRING, &record,
424				DBUS_TYPE_INVALID) == FALSE)
425		return NULL;
426
427	len = (record ? strlen(record) : 0);
428	if (len == 0)
429		return btd_error_invalid_args(msg);
430
431	user_record = find_record(serv_adapter, handle,
432				dbus_message_get_sender(msg));
433	if (!user_record)
434		return btd_error_not_available(msg);
435
436	sdp_record = sdp_xml_parse_record(record, len);
437	if (!sdp_record) {
438		error("Parsing of XML service record failed");
439		sdp_record_free(sdp_record);
440		return btd_error_failed(msg,
441					"Parsing of XML service record failed");
442	}
443
444	return update_record(conn, msg, serv_adapter, handle, sdp_record);
445}
446
447static int remove_record(DBusConnection *conn, const char *sender,
448			struct service_adapter *serv_adapter,
449			dbus_uint32_t handle)
450{
451	struct record_data *user_record;
452
453	DBG("remove record 0x%x", handle);
454
455	user_record = find_record(serv_adapter, handle, sender);
456	if (!user_record)
457		return -1;
458
459	DBG("listner_id %d", user_record->listener_id);
460
461	g_dbus_remove_watch(conn, user_record->listener_id);
462
463	exit_callback(conn, user_record);
464
465	return 0;
466}
467
468static DBusMessage *add_service_record(DBusConnection *conn,
469					DBusMessage *msg, void *data)
470{
471	struct service_adapter *serv_adapter = data;
472	DBusMessage *reply;
473	const char *sender, *record;
474	dbus_uint32_t handle;
475	int err;
476
477	if (dbus_message_get_args(msg, NULL,
478			DBUS_TYPE_STRING, &record, DBUS_TYPE_INVALID) == FALSE)
479		return NULL;
480
481	sender = dbus_message_get_sender(msg);
482	err = add_xml_record(conn, sender, serv_adapter, record, &handle);
483	if (err < 0)
484		return btd_error_failed(msg, strerror(-err));
485
486	reply = dbus_message_new_method_return(msg);
487	if (!reply)
488		return NULL;
489
490	dbus_message_append_args(reply, DBUS_TYPE_UINT32, &handle,
491							DBUS_TYPE_INVALID);
492
493	return reply;
494}
495
496static DBusMessage *update_service_record(DBusConnection *conn,
497					DBusMessage *msg, void *data)
498{
499	struct service_adapter *serv_adapter = data;
500
501	return update_xml_record(conn, msg, serv_adapter);
502}
503
504static DBusMessage *remove_service_record(DBusConnection *conn,
505					DBusMessage *msg, void *data)
506{
507	struct service_adapter *serv_adapter = data;
508	dbus_uint32_t handle;
509	const char *sender;
510
511	if (dbus_message_get_args(msg, NULL, DBUS_TYPE_UINT32, &handle,
512						DBUS_TYPE_INVALID) == FALSE)
513		return NULL;
514
515	sender = dbus_message_get_sender(msg);
516
517	if (remove_record(conn, sender, serv_adapter, handle) < 0)
518		return btd_error_not_available(msg);
519
520	return dbus_message_new_method_return(msg);
521}
522
523static void auth_cb(DBusError *derr, void *user_data)
524{
525	struct service_adapter *serv_adapter = user_data;
526	DBusMessage *reply;
527	struct pending_auth *auth;
528	bdaddr_t src;
529
530	auth = next_pending(serv_adapter);
531	if (auth == NULL) {
532		info("Authorization cancelled: Client exited");
533		return;
534	}
535
536	if (derr) {
537		error("Access denied: %s", derr->message);
538
539		reply = btd_error_not_authorized(auth->msg);
540		dbus_message_unref(auth->msg);
541		g_dbus_send_message(auth->conn, reply);
542		goto done;
543	}
544
545	g_dbus_send_reply(auth->conn, auth->msg,
546			DBUS_TYPE_INVALID);
547
548done:
549	dbus_connection_unref(auth->conn);
550
551	serv_adapter->pending_list = g_slist_remove(serv_adapter->pending_list,
552									auth);
553	g_free(auth);
554
555	auth = next_pending(serv_adapter);
556	if (auth == NULL)
557		return;
558
559	if (serv_adapter->adapter)
560		adapter_get_address(serv_adapter->adapter, &src);
561	else
562		bacpy(&src, BDADDR_ANY);
563
564	btd_request_authorization(&src, &auth->dst,
565					auth->uuid, auth_cb, serv_adapter);
566}
567
568static DBusMessage *request_authorization(DBusConnection *conn,
569						DBusMessage *msg, void *data)
570{
571	struct record_data *user_record;
572	struct service_adapter *serv_adapter = data;
573	sdp_record_t *record;
574	sdp_list_t *services;
575	const char *sender;
576	dbus_uint32_t handle;
577	const char *address;
578	struct pending_auth *auth;
579	char uuid_str[MAX_LEN_UUID_STR];
580	uuid_t *uuid, *uuid128;
581	bdaddr_t src;
582
583	if (dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &address,
584					DBUS_TYPE_UINT32, &handle,
585					DBUS_TYPE_INVALID) == FALSE)
586		return NULL;
587
588	sender = dbus_message_get_sender(msg);
589	if (find_pending_by_sender(serv_adapter, sender))
590		return btd_error_does_not_exist(msg);
591
592	user_record = find_record(serv_adapter, handle, sender);
593	if (!user_record) {
594		user_record = find_record(serv_adapter_any, handle, sender);
595		if (!user_record)
596			return btd_error_not_authorized(msg);
597	}
598
599	record = sdp_record_find(user_record->handle);
600	if (record == NULL)
601		return btd_error_not_authorized(msg);
602
603	if (sdp_get_service_classes(record, &services) < 0) {
604		sdp_record_free(record);
605		return btd_error_not_authorized(msg);
606	}
607
608	if (services == NULL)
609		return btd_error_not_authorized(msg);
610
611	uuid = services->data;
612	uuid128 = sdp_uuid_to_uuid128(uuid);
613
614	sdp_list_free(services, bt_free);
615
616	if (sdp_uuid2strn(uuid128, uuid_str, MAX_LEN_UUID_STR) < 0) {
617		bt_free(uuid128);
618		return btd_error_not_authorized(msg);
619	}
620	bt_free(uuid128);
621
622	auth = g_new0(struct pending_auth, 1);
623	auth->msg = dbus_message_ref(msg);
624	auth->conn = dbus_connection_ref(connection);
625	auth->sender = user_record->sender;
626	memcpy(auth->uuid, uuid_str, MAX_LEN_UUID_STR);
627	str2ba(address, &auth->dst);
628
629	serv_adapter->pending_list = g_slist_append(serv_adapter->pending_list,
630									auth);
631
632	auth = next_pending(serv_adapter);
633	if (auth == NULL)
634		return btd_error_does_not_exist(msg);
635
636	if (serv_adapter->adapter)
637		adapter_get_address(serv_adapter->adapter, &src);
638	else
639		bacpy(&src, BDADDR_ANY);
640
641	if (btd_request_authorization(&src, &auth->dst, auth->uuid, auth_cb,
642							serv_adapter) < 0) {
643		serv_adapter->pending_list = g_slist_remove(serv_adapter->pending_list,
644									auth);
645		g_free(auth);
646		return btd_error_not_authorized(msg);
647	}
648
649	return NULL;
650}
651
652static DBusMessage *cancel_authorization(DBusConnection *conn,
653						DBusMessage *msg, void *data)
654{
655	DBusMessage *reply;
656	struct service_adapter *serv_adapter = data;
657	struct pending_auth *auth;
658	const gchar *sender;
659	bdaddr_t src;
660
661	sender = dbus_message_get_sender(msg);
662
663	auth = find_pending_by_sender(serv_adapter, sender);
664	if (auth == NULL)
665		return btd_error_does_not_exist(msg);
666
667	if (serv_adapter->adapter)
668		adapter_get_address(serv_adapter->adapter, &src);
669	else
670		bacpy(&src, BDADDR_ANY);
671
672	btd_cancel_authorization(&src, &auth->dst);
673
674	reply = btd_error_not_authorized(auth->msg);
675	dbus_message_unref(auth->msg);
676	g_dbus_send_message(auth->conn, reply);
677
678	dbus_connection_unref(auth->conn);
679
680	serv_adapter->pending_list = g_slist_remove(serv_adapter->pending_list,
681									auth);
682	g_free(auth);
683
684	auth = next_pending(serv_adapter);
685	if (auth == NULL)
686		goto done;
687
688	if (serv_adapter->adapter)
689		adapter_get_address(serv_adapter->adapter, &src);
690	else
691		bacpy(&src, BDADDR_ANY);
692
693	btd_request_authorization(&src, &auth->dst,
694					auth->uuid, auth_cb, serv_adapter);
695
696done:
697	return dbus_message_new_method_return(msg);
698}
699
700static GDBusMethodTable service_methods[] = {
701	{ "AddRecord",		"s",	"u",	add_service_record	},
702	{ "UpdateRecord",	"us",	"",	update_service_record	},
703	{ "RemoveRecord",	"u",	"",	remove_service_record	},
704	{ "RequestAuthorization","su",	"",	request_authorization,
705						G_DBUS_METHOD_FLAG_ASYNC},
706	{ "CancelAuthorization", "",	"",	cancel_authorization	},
707	{ }
708};
709
710static void path_unregister(void *data)
711{
712	struct service_adapter *serv_adapter = data;
713	GSList *l, *next = NULL;
714
715	for (l = serv_adapter->records; l != NULL; l = next) {
716		struct record_data *user_record = l->data;
717
718		next = l->next;
719
720		g_dbus_remove_watch(connection, user_record->listener_id);
721		exit_callback(connection, user_record);
722	}
723
724	g_free(serv_adapter);
725}
726
727static int register_interface(const char *path, struct btd_adapter *adapter)
728{
729	struct service_adapter *serv_adapter;
730
731	DBG("path %s", path);
732
733	serv_adapter = g_try_new0(struct service_adapter, 1);
734	if (serv_adapter == NULL)
735		return -ENOMEM;
736
737	serv_adapter->adapter = adapter;
738	serv_adapter->pending_list = NULL;
739
740	if (g_dbus_register_interface(connection, path, SERVICE_INTERFACE,
741				service_methods, NULL, NULL, serv_adapter,
742						path_unregister) == FALSE) {
743		error("D-Bus failed to register %s interface",
744							SERVICE_INTERFACE);
745		g_free(serv_adapter);
746		return -EIO;
747	}
748
749	DBG("Registered interface %s on path %s", SERVICE_INTERFACE, path);
750
751	if (serv_adapter->adapter == NULL)
752		serv_adapter_any = serv_adapter;
753
754	return 0;
755}
756
757static void unregister_interface(const char *path)
758{
759	DBG("path %s", path);
760
761	g_dbus_unregister_interface(connection, path, SERVICE_INTERFACE);
762}
763
764static int service_probe(struct btd_adapter *adapter)
765{
766	register_interface(adapter_get_path(adapter), adapter);
767
768	return 0;
769}
770
771static void service_remove(struct btd_adapter *adapter)
772{
773	unregister_interface(adapter_get_path(adapter));
774}
775
776static struct btd_adapter_driver service_driver = {
777	.name	= "service",
778	.probe	= service_probe,
779	.remove	= service_remove,
780};
781
782static const char *any_path;
783
784static int service_init(void)
785{
786	int err;
787
788	connection = dbus_bus_get(DBUS_BUS_SYSTEM, NULL);
789	if (connection == NULL)
790		return -EIO;
791
792	any_path = btd_adapter_any_request_path();
793	if (any_path != NULL) {
794		if (register_interface(any_path, NULL) < 0) {
795			btd_adapter_any_release_path();
796			any_path = NULL;
797		}
798	}
799
800	err = btd_register_adapter_driver(&service_driver);
801	if (err < 0) {
802		dbus_connection_unref(connection);
803		return err;
804	}
805
806	return 0;
807}
808
809static void service_exit(void)
810{
811	btd_unregister_adapter_driver(&service_driver);
812
813	if (any_path != NULL) {
814		unregister_interface(any_path);
815
816		btd_adapter_any_release_path();
817		any_path = NULL;
818	}
819
820	dbus_connection_unref(connection);
821}
822
823BLUETOOTH_PLUGIN_DEFINE(service, VERSION,
824		BLUETOOTH_PLUGIN_PRIORITY_HIGH, service_init, service_exit)
825