• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *
3  *  BlueZ - Bluetooth protocol stack for Linux
4  *
5  *  Copyright (C) 2011  ST-Ericsson SA
6  *
7  *  Author: Szymon Janc <szymon.janc@tieto.com> for ST-Ericsson
8  *
9  *
10  *  This program is free software; you can redistribute it and/or modify
11  *  it under the terms of the GNU General Public License as published by
12  *  the Free Software Foundation; either version 2 of the License, or
13  *  (at your option) any later version.
14  *
15  *  This program is distributed in the hope that it will be useful,
16  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  *  GNU General Public License for more details.
19  *
20  *  You should have received a copy of the GNU General Public License
21  *  along with this program; if not, write to the Free Software
22  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
23  *
24  */
25 
26 #ifdef HAVE_CONFIG_H
27 #include <config.h>
28 #endif
29 
30 #include <errno.h>
31 #include <gdbus.h>
32 
33 #include <bluetooth/bluetooth.h>
34 #include <bluetooth/hci.h>
35 #include <bluetooth/sdp.h>
36 
37 #include "plugin.h"
38 #include "log.h"
39 #include "adapter.h"
40 #include "device.h"
41 #include "manager.h"
42 #include "dbus-common.h"
43 #include "event.h"
44 #include "error.h"
45 #include "oob.h"
46 
47 #define OOB_INTERFACE	"org.bluez.OutOfBand"
48 
49 struct oob_request {
50 	struct btd_adapter *adapter;
51 	DBusMessage *msg;
52 };
53 
54 static GSList *oob_requests = NULL;
55 static DBusConnection *connection = NULL;
56 
oob_request_cmp(gconstpointer a,gconstpointer b)57 static gint oob_request_cmp(gconstpointer a, gconstpointer b)
58 {
59 	const struct oob_request *data = a;
60 	const struct btd_adapter *adapter = b;
61 
62 	return data->adapter != adapter;
63 }
64 
find_oob_request(struct btd_adapter * adapter)65 static struct oob_request *find_oob_request(struct btd_adapter *adapter)
66 {
67 	GSList *match;
68 
69 	match = g_slist_find_custom(oob_requests, adapter, oob_request_cmp);
70 
71 	if (match)
72 		return match->data;
73 
74 	return NULL;
75 }
76 
read_local_data_complete(struct btd_adapter * adapter,uint8_t * hash,uint8_t * randomizer)77 static void read_local_data_complete(struct btd_adapter *adapter, uint8_t *hash,
78 				uint8_t *randomizer)
79 {
80 	struct DBusMessage *reply;
81 	struct oob_request *oob_request;
82 
83 	oob_request = find_oob_request(adapter);
84 	if (!oob_request)
85 		return;
86 
87 	if (hash && randomizer)
88 		reply = g_dbus_create_reply(oob_request->msg,
89 			DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &hash, 16,
90 			DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &randomizer, 16,
91 			DBUS_TYPE_INVALID);
92 	else
93 		reply = btd_error_failed(oob_request->msg,
94 					"Failed to read local OOB data.");
95 
96 	oob_requests = g_slist_remove(oob_requests, oob_request);
97 	dbus_message_unref(oob_request->msg);
98 	g_free(oob_request);
99 
100 	if (!reply) {
101 		error("Couldn't allocate D-Bus message");
102 		return;
103 	}
104 
105 	if (!g_dbus_send_message(connection, reply))
106 		error("D-Bus send failed");
107 }
108 
read_local_data(DBusConnection * conn,DBusMessage * msg,void * data)109 static DBusMessage *read_local_data(DBusConnection *conn, DBusMessage *msg,
110 								void *data)
111 {
112 	struct btd_adapter *adapter = data;
113 	struct oob_request *oob_request;
114 
115 	if (find_oob_request(adapter))
116 		return btd_error_in_progress(msg);
117 
118 	if (btd_adapter_read_local_oob_data(adapter))
119 		return btd_error_failed(msg, "Request failed.");
120 
121 	oob_request = g_new(struct oob_request, 1);
122 	oob_request->adapter = adapter;
123 	oob_requests = g_slist_append(oob_requests, oob_request);
124 	oob_request->msg = dbus_message_ref(msg);
125 
126 	return NULL;
127 }
128 
add_remote_data(DBusConnection * conn,DBusMessage * msg,void * data)129 static DBusMessage *add_remote_data(DBusConnection *conn, DBusMessage *msg,
130 								void *data)
131 {
132 	struct btd_adapter *adapter = data;
133 	uint8_t *hash, *randomizer;
134 	int32_t hlen, rlen;
135 	const char *addr;
136 	bdaddr_t bdaddr;
137 
138 	if (!dbus_message_get_args(msg, NULL,
139 			DBUS_TYPE_STRING, &addr,
140 			DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &hash, &hlen,
141 			DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &randomizer, &rlen,
142 			DBUS_TYPE_INVALID))
143 		return btd_error_invalid_args(msg);
144 
145 	if (hlen != 16 || rlen != 16 || bachk(addr))
146 		return btd_error_invalid_args(msg);
147 
148 	str2ba(addr, &bdaddr);
149 
150 	if (btd_adapter_add_remote_oob_data(adapter, &bdaddr, hash, randomizer))
151 		return btd_error_failed(msg, "Request failed");
152 
153 	return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
154 }
155 
remove_remote_data(DBusConnection * conn,DBusMessage * msg,void * data)156 static DBusMessage *remove_remote_data(DBusConnection *conn, DBusMessage *msg,
157 								void *data)
158 {
159 	struct btd_adapter *adapter = data;
160 	const char *addr;
161 	bdaddr_t bdaddr;
162 
163 	if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &addr,
164 			DBUS_TYPE_INVALID))
165 		return btd_error_invalid_args(msg);
166 
167 	if (bachk(addr))
168 		return btd_error_invalid_args(msg);
169 
170 	str2ba(addr, &bdaddr);
171 
172 	if (btd_adapter_remove_remote_oob_data(adapter, &bdaddr))
173 		return btd_error_failed(msg, "Request failed");
174 
175 	return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
176 }
177 
178 static GDBusMethodTable oob_methods[] = {
179 	{"AddRemoteData",	"sayay",	"",	add_remote_data},
180 	{"RemoveRemoteData",	"s",		"",	remove_remote_data},
181 	{"ReadLocalData",	"",		"ayay",	read_local_data,
182 						G_DBUS_METHOD_FLAG_ASYNC},
183 	{}
184 };
185 
oob_probe(struct btd_adapter * adapter)186 static int oob_probe(struct btd_adapter *adapter)
187 {
188 	const char *path = adapter_get_path(adapter);
189 
190 	if (!g_dbus_register_interface(connection, path, OOB_INTERFACE,
191 				oob_methods, NULL, NULL, adapter, NULL)) {
192 			error("OOB interface init failed on path %s", path);
193 			return -EIO;
194 		}
195 
196 	return 0;
197 }
198 
oob_remove(struct btd_adapter * adapter)199 static void oob_remove(struct btd_adapter *adapter)
200 {
201 	read_local_data_complete(adapter, NULL, NULL);
202 
203 	g_dbus_unregister_interface(connection, adapter_get_path(adapter),
204 							OOB_INTERFACE);
205 }
206 
207 static struct btd_adapter_driver oob_driver = {
208 	.name	= "oob",
209 	.probe	= oob_probe,
210 	.remove	= oob_remove,
211 };
212 
dbusoob_init(void)213 static int dbusoob_init(void)
214 {
215 	DBG("Setup dbusoob plugin");
216 
217 	connection = get_dbus_connection();
218 
219 	oob_register_cb(read_local_data_complete);
220 
221 	return btd_register_adapter_driver(&oob_driver);
222 }
223 
dbusoob_exit(void)224 static void dbusoob_exit(void)
225 {
226 	DBG("Cleanup dbusoob plugin");
227 
228 	manager_foreach_adapter((adapter_cb) oob_remove, NULL);
229 
230 	btd_unregister_adapter_driver(&oob_driver);
231 }
232 
233 BLUETOOTH_PLUGIN_DEFINE(dbusoob, VERSION, BLUETOOTH_PLUGIN_PRIORITY_DEFAULT,
234 						dbusoob_init, dbusoob_exit)
235