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