1/*
2 *
3 *  BlueZ - Bluetooth protocol stack for Linux
4 *
5 *  Copyright (C) 2004-2009  Marcel Holtmann <marcel@holtmann.org>
6 *
7 *
8 *  This program is free software; you can redistribute it and/or modify
9 *  it under the terms of the GNU General Public License as published by
10 *  the Free Software Foundation; either version 2 of the License, or
11 *  (at your option) any later version.
12 *
13 *  This program is distributed in the hope that it will be useful,
14 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 *  GNU General Public License for more details.
17 *
18 *  You should have received a copy of the GNU General Public License
19 *  along with this program; if not, write to the Free Software
20 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
21 *
22 */
23
24#ifdef HAVE_CONFIG_H
25#include <config.h>
26#endif
27
28#include <stdlib.h>
29#include <errno.h>
30#include <fcntl.h>
31#include <unistd.h>
32#include <sys/ioctl.h>
33#include <sys/socket.h>
34
35#include <bluetooth/bluetooth.h>
36#include <bluetooth/hci.h>
37#include <bluetooth/hci_lib.h>
38#include <bluetooth/rfcomm.h>
39#include <bluetooth/l2cap.h>
40#include <bluetooth/sco.h>
41#include <bluetooth/sdp.h>
42#include <bluetooth/sdp_lib.h>
43
44#include <glib.h>
45
46#include "glib-helper.h"
47
48/* Number of seconds to keep a sdp_session_t in the cache */
49#define CACHE_TIMEOUT 2
50
51struct cached_sdp_session {
52	bdaddr_t src;
53	bdaddr_t dst;
54	sdp_session_t *session;
55	guint timer;
56};
57
58static GSList *cached_sdp_sessions = NULL;
59
60struct hci_cmd_data {
61	bt_hci_result_t		cb;
62	uint16_t		handle;
63	uint16_t		ocf;
64	gpointer		caller_data;
65};
66
67static gboolean cached_session_expired(gpointer user_data)
68{
69	struct cached_sdp_session *cached = user_data;
70
71	cached_sdp_sessions = g_slist_remove(cached_sdp_sessions, cached);
72
73	sdp_close(cached->session);
74
75	g_free(cached);
76
77	return FALSE;
78}
79
80static sdp_session_t *get_sdp_session(const bdaddr_t *src, const bdaddr_t *dst)
81{
82	GSList *l;
83
84	for (l = cached_sdp_sessions; l != NULL; l = l->next) {
85		struct cached_sdp_session *c = l->data;
86		sdp_session_t *session;
87
88		if (bacmp(&c->src, src) || bacmp(&c->dst, dst))
89			continue;
90
91		g_source_remove(c->timer);
92
93		session = c->session;
94
95		cached_sdp_sessions = g_slist_remove(cached_sdp_sessions, c);
96		g_free(c);
97
98		return session;
99	}
100
101	return sdp_connect(src, dst, SDP_NON_BLOCKING);
102}
103
104static void cache_sdp_session(bdaddr_t *src, bdaddr_t *dst,
105				sdp_session_t *session)
106{
107	struct cached_sdp_session *cached;
108
109	cached = g_new0(struct cached_sdp_session, 1);
110
111	bacpy(&cached->src, src);
112	bacpy(&cached->dst, dst);
113
114	cached->session = session;
115
116	cached_sdp_sessions = g_slist_append(cached_sdp_sessions, cached);
117
118	cached->timer = g_timeout_add_seconds(CACHE_TIMEOUT,
119						cached_session_expired,
120						cached);
121}
122
123int set_nonblocking(int fd)
124{
125	long arg;
126
127	arg = fcntl(fd, F_GETFL);
128	if (arg < 0)
129		return -errno;
130
131	/* Return if already nonblocking */
132	if (arg & O_NONBLOCK)
133		return 0;
134
135	arg |= O_NONBLOCK;
136	if (fcntl(fd, F_SETFL, arg) < 0)
137		return -errno;
138
139	return 0;
140}
141
142struct search_context {
143	bdaddr_t		src;
144	bdaddr_t		dst;
145	sdp_session_t		*session;
146	bt_callback_t		cb;
147	bt_destroy_t		destroy;
148	gpointer		user_data;
149	uuid_t			uuid;
150	guint			io_id;
151};
152
153static GSList *context_list = NULL;
154
155static void search_context_cleanup(struct search_context *ctxt)
156{
157	context_list = g_slist_remove(context_list, ctxt);
158
159	if (ctxt->destroy)
160		ctxt->destroy(ctxt->user_data);
161
162	g_free(ctxt);
163}
164
165static void search_completed_cb(uint8_t type, uint16_t status,
166			uint8_t *rsp, size_t size, void *user_data)
167{
168	struct search_context *ctxt = user_data;
169	sdp_list_t *recs = NULL;
170	int scanned, seqlen = 0, bytesleft = size;
171	uint8_t dataType;
172	int err = 0;
173
174	if (status || type != SDP_SVC_SEARCH_ATTR_RSP) {
175		err = -EPROTO;
176		goto done;
177	}
178
179	scanned = sdp_extract_seqtype(rsp, bytesleft, &dataType, &seqlen);
180	if (!scanned || !seqlen)
181		goto done;
182
183	rsp += scanned;
184	bytesleft -= scanned;
185	do {
186		sdp_record_t *rec;
187		int recsize;
188
189		recsize = 0;
190		rec = sdp_extract_pdu(rsp, bytesleft, &recsize);
191		if (!rec)
192			break;
193
194		if (!recsize) {
195			sdp_record_free(rec);
196			break;
197		}
198
199		scanned += recsize;
200		rsp += recsize;
201		bytesleft -= recsize;
202
203		recs = sdp_list_append(recs, rec);
204	} while (scanned < (ssize_t) size && bytesleft > 0);
205
206done:
207	cache_sdp_session(&ctxt->src, &ctxt->dst, ctxt->session);
208
209	if (ctxt->cb)
210		ctxt->cb(recs, err, ctxt->user_data);
211
212	if (recs)
213		sdp_list_free(recs, (sdp_free_func_t) sdp_record_free);
214
215	search_context_cleanup(ctxt);
216}
217
218static gboolean search_process_cb(GIOChannel *chan,
219			GIOCondition cond, void *user_data)
220{
221	struct search_context *ctxt = user_data;
222	int err = 0;
223
224	if (cond & (G_IO_ERR | G_IO_HUP | G_IO_NVAL)) {
225		err = EIO;
226		goto failed;
227	}
228
229	if (sdp_process(ctxt->session) < 0)
230		goto failed;
231
232	return TRUE;
233
234failed:
235	if (err) {
236		sdp_close(ctxt->session);
237		ctxt->session = NULL;
238
239		if (ctxt->cb)
240			ctxt->cb(NULL, err, ctxt->user_data);
241
242		search_context_cleanup(ctxt);
243	}
244
245	return FALSE;
246}
247
248static gboolean connect_watch(GIOChannel *chan, GIOCondition cond, gpointer user_data)
249{
250	struct search_context *ctxt = user_data;
251	sdp_list_t *search, *attrids;
252	uint32_t range = 0x0000ffff;
253	socklen_t len;
254	int sk, err = 0;
255
256	sk = g_io_channel_unix_get_fd(chan);
257	ctxt->io_id = 0;
258
259	len = sizeof(err);
260	if (getsockopt(sk, SOL_SOCKET, SO_ERROR, &err, &len) < 0) {
261		err = errno;
262		goto failed;
263	}
264
265	if (err != 0)
266		goto failed;
267
268	if (sdp_set_notify(ctxt->session, search_completed_cb, ctxt) < 0) {
269		err = EIO;
270		goto failed;
271	}
272
273	search = sdp_list_append(NULL, &ctxt->uuid);
274	attrids = sdp_list_append(NULL, &range);
275	if (sdp_service_search_attr_async(ctxt->session,
276				search, SDP_ATTR_REQ_RANGE, attrids) < 0) {
277		sdp_list_free(attrids, NULL);
278		sdp_list_free(search, NULL);
279		err = EIO;
280		goto failed;
281	}
282
283	sdp_list_free(attrids, NULL);
284	sdp_list_free(search, NULL);
285
286	/* Set callback responsible for update the internal SDP transaction */
287	ctxt->io_id = g_io_add_watch(chan,
288				G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
289				search_process_cb, ctxt);
290	return FALSE;
291
292failed:
293	sdp_close(ctxt->session);
294	ctxt->session = NULL;
295
296	if (ctxt->cb)
297		ctxt->cb(NULL, -err, ctxt->user_data);
298
299	search_context_cleanup(ctxt);
300
301	return FALSE;
302}
303
304static int create_search_context(struct search_context **ctxt,
305				const bdaddr_t *src, const bdaddr_t *dst,
306				uuid_t *uuid)
307{
308	sdp_session_t *s;
309	GIOChannel *chan;
310
311	if (!ctxt)
312		return -EINVAL;
313
314	s = get_sdp_session(src, dst);
315	if (!s)
316		return -errno;
317
318	*ctxt = g_try_malloc0(sizeof(struct search_context));
319	if (!*ctxt) {
320		sdp_close(s);
321		return -ENOMEM;
322	}
323
324	bacpy(&(*ctxt)->src, src);
325	bacpy(&(*ctxt)->dst, dst);
326	(*ctxt)->session = s;
327	(*ctxt)->uuid = *uuid;
328
329	chan = g_io_channel_unix_new(sdp_get_socket(s));
330	(*ctxt)->io_id = g_io_add_watch(chan,
331				G_IO_OUT | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
332				connect_watch, *ctxt);
333	g_io_channel_unref(chan);
334
335	return 0;
336}
337
338int bt_search_service(const bdaddr_t *src, const bdaddr_t *dst,
339			uuid_t *uuid, bt_callback_t cb, void *user_data,
340			bt_destroy_t destroy)
341{
342	struct search_context *ctxt = NULL;
343	int err;
344
345	if (!cb)
346		return -EINVAL;
347
348	err = create_search_context(&ctxt, src, dst, uuid);
349	if (err < 0)
350		return err;
351
352	ctxt->cb	= cb;
353	ctxt->destroy	= destroy;
354	ctxt->user_data	= user_data;
355
356	context_list = g_slist_append(context_list, ctxt);
357
358	return 0;
359}
360
361int bt_discover_services(const bdaddr_t *src, const bdaddr_t *dst,
362		bt_callback_t cb, void *user_data, bt_destroy_t destroy)
363{
364	uuid_t uuid;
365
366	sdp_uuid16_create(&uuid, PUBLIC_BROWSE_GROUP);
367
368	return bt_search_service(src, dst, &uuid, cb, user_data, destroy);
369}
370
371static int find_by_bdaddr(const void *data, const void *user_data)
372{
373	const struct search_context *ctxt = data, *search = user_data;
374
375	return (bacmp(&ctxt->dst, &search->dst) &&
376					bacmp(&ctxt->src, &search->src));
377}
378
379int bt_cancel_discovery(const bdaddr_t *src, const bdaddr_t *dst)
380{
381	struct search_context search, *ctxt;
382	GSList *match;
383
384	memset(&search, 0, sizeof(search));
385	bacpy(&search.src, src);
386	bacpy(&search.dst, dst);
387
388	/* Ongoing SDP Discovery */
389	match = g_slist_find_custom(context_list, &search, find_by_bdaddr);
390	if (!match)
391		return -ENODATA;
392
393	ctxt = match->data;
394	if (!ctxt->session)
395		return -ENOTCONN;
396
397	if (ctxt->io_id)
398		g_source_remove(ctxt->io_id);
399
400	if (ctxt->session)
401		sdp_close(ctxt->session);
402
403	search_context_cleanup(ctxt);
404	return 0;
405}
406
407char *bt_uuid2string(uuid_t *uuid)
408{
409	gchar *str;
410	uuid_t uuid128;
411	unsigned int data0;
412	unsigned short data1;
413	unsigned short data2;
414	unsigned short data3;
415	unsigned int data4;
416	unsigned short data5;
417
418	if (!uuid)
419		return NULL;
420
421	switch (uuid->type) {
422	case SDP_UUID16:
423		sdp_uuid16_to_uuid128(&uuid128, uuid);
424		break;
425	case SDP_UUID32:
426		sdp_uuid32_to_uuid128(&uuid128, uuid);
427		break;
428	case SDP_UUID128:
429		memcpy(&uuid128, uuid, sizeof(uuid_t));
430		break;
431	default:
432		/* Type of UUID unknown */
433		return NULL;
434	}
435
436	memcpy(&data0, &uuid128.value.uuid128.data[0], 4);
437	memcpy(&data1, &uuid128.value.uuid128.data[4], 2);
438	memcpy(&data2, &uuid128.value.uuid128.data[6], 2);
439	memcpy(&data3, &uuid128.value.uuid128.data[8], 2);
440	memcpy(&data4, &uuid128.value.uuid128.data[10], 4);
441	memcpy(&data5, &uuid128.value.uuid128.data[14], 2);
442
443	str = g_try_malloc0(MAX_LEN_UUID_STR);
444	if (!str)
445		return NULL;
446
447	sprintf(str, "%.8x-%.4x-%.4x-%.4x-%.8x%.4x",
448			g_ntohl(data0), g_ntohs(data1),
449			g_ntohs(data2), g_ntohs(data3),
450			g_ntohl(data4), g_ntohs(data5));
451
452	return str;
453}
454
455static struct {
456	const char	*name;
457	uint16_t	class;
458} bt_services[] = {
459	{ "vcp",	VIDEO_CONF_SVCLASS_ID		},
460	{ "pbap",	PBAP_SVCLASS_ID			},
461	{ "sap",	SAP_SVCLASS_ID			},
462	{ "ftp",	OBEX_FILETRANS_SVCLASS_ID	},
463	{ "bpp",	BASIC_PRINTING_SVCLASS_ID	},
464	{ "bip",	IMAGING_SVCLASS_ID		},
465	{ "synch",	IRMC_SYNC_SVCLASS_ID		},
466	{ "dun",	DIALUP_NET_SVCLASS_ID		},
467	{ "opp",	OBEX_OBJPUSH_SVCLASS_ID		},
468	{ "fax",	FAX_SVCLASS_ID			},
469	{ "spp",	SERIAL_PORT_SVCLASS_ID		},
470	{ "hsp",	HEADSET_SVCLASS_ID		},
471	{ "hfp",	HANDSFREE_SVCLASS_ID		},
472	{ }
473};
474
475uint16_t bt_name2class(const char *pattern)
476{
477	int i;
478
479	for (i = 0; bt_services[i].name; i++) {
480		if (strcasecmp(bt_services[i].name, pattern) == 0)
481			return bt_services[i].class;
482	}
483
484	return 0;
485}
486
487static inline gboolean is_uuid128(const char *string)
488{
489	return (strlen(string) == 36 &&
490			string[8] == '-' &&
491			string[13] == '-' &&
492			string[18] == '-' &&
493			string[23] == '-');
494}
495
496char *bt_name2string(const char *pattern)
497{
498	uuid_t uuid;
499	uint16_t uuid16;
500	int i;
501
502	/* UUID 128 string format */
503	if (is_uuid128(pattern))
504		return g_strdup(pattern);
505
506	/* Friendly service name format */
507	uuid16 = bt_name2class(pattern);
508	if (uuid16)
509		goto proceed;
510
511	/* HEX format */
512	uuid16 = strtol(pattern, NULL, 16);
513	for (i = 0; bt_services[i].class; i++) {
514		if (bt_services[i].class == uuid16)
515			goto proceed;
516	}
517
518	return NULL;
519
520proceed:
521	sdp_uuid16_create(&uuid, uuid16);
522
523	return bt_uuid2string(&uuid);
524}
525
526int bt_string2uuid(uuid_t *uuid, const char *string)
527{
528	uint32_t data0, data4;
529	uint16_t data1, data2, data3, data5;
530
531	if (is_uuid128(string) &&
532			sscanf(string, "%08x-%04hx-%04hx-%04hx-%08x%04hx",
533				&data0, &data1, &data2, &data3, &data4, &data5) == 6) {
534		uint8_t val[16];
535
536		data0 = g_htonl(data0);
537		data1 = g_htons(data1);
538		data2 = g_htons(data2);
539		data3 = g_htons(data3);
540		data4 = g_htonl(data4);
541		data5 = g_htons(data5);
542
543		memcpy(&val[0], &data0, 4);
544		memcpy(&val[4], &data1, 2);
545		memcpy(&val[6], &data2, 2);
546		memcpy(&val[8], &data3, 2);
547		memcpy(&val[10], &data4, 4);
548		memcpy(&val[14], &data5, 2);
549
550		sdp_uuid128_create(uuid, val);
551
552		return 0;
553	} else {
554		uint16_t class = bt_name2class(string);
555		if (class) {
556			sdp_uuid16_create(uuid, class);
557			return 0;
558		}
559	}
560
561	return -1;
562}
563
564gchar *bt_list2string(GSList *list)
565{
566	GSList *l;
567	gchar *str, *tmp;
568
569	if (!list)
570		return NULL;
571
572	str = g_strdup((const gchar *) list->data);
573
574	for (l = list->next; l; l = l->next) {
575		tmp = g_strconcat(str, " " , (const gchar *) l->data, NULL);
576		g_free(str);
577		str = tmp;
578	}
579
580	return str;
581}
582
583GSList *bt_string2list(const gchar *str)
584{
585	GSList *l = NULL;
586	gchar **uuids;
587	int i = 0;
588
589	if (!str)
590		return NULL;
591
592	/* FIXME: eglib doesn't support g_strsplit */
593	uuids = g_strsplit(str, " ", 0);
594	if (!uuids)
595		return NULL;
596
597	while (uuids[i]) {
598		l = g_slist_append(l, uuids[i]);
599		i++;
600	}
601
602	g_free(uuids);
603
604	return l;
605}
606
607static gboolean hci_event_watch(GIOChannel *io,
608			GIOCondition cond, gpointer user_data)
609{
610	unsigned char buf[HCI_MAX_EVENT_SIZE], *body;
611	struct hci_cmd_data *cmd = user_data;
612	evt_cmd_status *evt_status;
613	evt_auth_complete *evt_auth;
614	evt_encrypt_change *evt_enc;
615	hci_event_hdr *hdr;
616	set_conn_encrypt_cp cp;
617	int dd;
618	uint16_t ocf;
619	uint8_t status = HCI_OE_POWER_OFF;
620
621	if (cond & G_IO_NVAL) {
622		cmd->cb(status, cmd->caller_data);
623		return FALSE;
624	}
625
626	if (cond & (G_IO_ERR | G_IO_HUP))
627		goto failed;
628
629	dd = g_io_channel_unix_get_fd(io);
630
631	if (read(dd, buf, sizeof(buf)) < 0)
632		goto failed;
633
634	hdr = (hci_event_hdr *) (buf + 1);
635	body = buf + (1 + HCI_EVENT_HDR_SIZE);
636
637	switch (hdr->evt) {
638	case EVT_CMD_STATUS:
639		evt_status = (evt_cmd_status *) body;
640		ocf = cmd_opcode_ocf(evt_status->opcode);
641		if (ocf != cmd->ocf)
642			return TRUE;
643		switch (ocf) {
644		case OCF_AUTH_REQUESTED:
645		case OCF_SET_CONN_ENCRYPT:
646			if (evt_status->status != 0) {
647				/* Baseband rejected command */
648				status = evt_status->status;
649				goto failed;
650			}
651			break;
652		default:
653			return TRUE;
654		}
655		/* Wait for the next event */
656		return TRUE;
657	case EVT_AUTH_COMPLETE:
658		evt_auth = (evt_auth_complete *) body;
659		if (evt_auth->handle != cmd->handle) {
660			/* Skipping */
661			return TRUE;
662		}
663
664		if (evt_auth->status != 0x00) {
665			status = evt_auth->status;
666			/* Abort encryption */
667			goto failed;
668		}
669
670		memset(&cp, 0, sizeof(cp));
671		cp.handle  = cmd->handle;
672		cp.encrypt = 1;
673
674		cmd->ocf = OCF_SET_CONN_ENCRYPT;
675
676		if (hci_send_cmd(dd, OGF_LINK_CTL, OCF_SET_CONN_ENCRYPT,
677					SET_CONN_ENCRYPT_CP_SIZE, &cp) < 0) {
678			status = HCI_COMMAND_DISALLOWED;
679			goto failed;
680		}
681		/* Wait for encrypt change event */
682		return TRUE;
683	case EVT_ENCRYPT_CHANGE:
684		evt_enc = (evt_encrypt_change *) body;
685		if (evt_enc->handle != cmd->handle)
686			return TRUE;
687
688		/* Procedure finished: reporting status */
689		status = evt_enc->status;
690		break;
691	default:
692		/* Skipping */
693		return TRUE;
694	}
695
696failed:
697	cmd->cb(status, cmd->caller_data);
698	g_io_channel_shutdown(io, TRUE, NULL);
699
700	return FALSE;
701}
702
703int bt_acl_encrypt(const bdaddr_t *src, const bdaddr_t *dst,
704			bt_hci_result_t cb, gpointer user_data)
705{
706	GIOChannel *io;
707	struct hci_cmd_data *cmd;
708	struct hci_conn_info_req *cr;
709	auth_requested_cp cp;
710	struct hci_filter nf;
711	int dd, dev_id, err;
712	char src_addr[18];
713	uint32_t link_mode;
714	uint16_t handle;
715
716	ba2str(src, src_addr);
717	dev_id = hci_devid(src_addr);
718	if (dev_id < 0)
719		return -errno;
720
721	dd = hci_open_dev(dev_id);
722	if (dd < 0)
723		return -errno;
724
725	cr = g_malloc0(sizeof(*cr) + sizeof(struct hci_conn_info));
726	cr->type = ACL_LINK;
727	bacpy(&cr->bdaddr, dst);
728
729	err = ioctl(dd, HCIGETCONNINFO, cr);
730	link_mode = cr->conn_info->link_mode;
731	handle = cr->conn_info->handle;
732	g_free(cr);
733
734	if (err < 0) {
735		err = errno;
736		goto failed;
737	}
738
739	if (link_mode & HCI_LM_ENCRYPT) {
740		/* Already encrypted */
741		err = EALREADY;
742		goto failed;
743	}
744
745	memset(&cp, 0, sizeof(cp));
746	cp.handle = htobs(handle);
747
748	if (hci_send_cmd(dd, OGF_LINK_CTL, OCF_AUTH_REQUESTED,
749				AUTH_REQUESTED_CP_SIZE, &cp) < 0) {
750		err = errno;
751		goto failed;
752	}
753
754	cmd = g_new0(struct hci_cmd_data, 1);
755	cmd->handle = handle;
756	cmd->ocf = OCF_AUTH_REQUESTED;
757	cmd->cb	= cb;
758	cmd->caller_data = user_data;
759
760	hci_filter_clear(&nf);
761	hci_filter_set_ptype(HCI_EVENT_PKT, &nf);
762	hci_filter_set_event(EVT_CMD_STATUS, &nf);
763	hci_filter_set_event(EVT_AUTH_COMPLETE, &nf);
764	hci_filter_set_event(EVT_ENCRYPT_CHANGE, &nf);
765
766	if (setsockopt(dd, SOL_HCI, HCI_FILTER, &nf, sizeof(nf)) < 0) {
767		err = errno;
768		goto failed;
769	}
770
771	io = g_io_channel_unix_new(dd);
772	g_io_channel_set_close_on_unref(io, FALSE);
773	g_io_add_watch_full(io, G_PRIORITY_DEFAULT,
774			G_IO_HUP | G_IO_ERR | G_IO_NVAL | G_IO_IN,
775			hci_event_watch, cmd, g_free);
776	g_io_channel_unref(io);
777
778	return 0;
779
780failed:
781	close(dd);
782
783	return -err;
784}
785