• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <stdio.h>
30 #include <errno.h>
31 #include <ctype.h>
32 #include <fcntl.h>
33 #include <unistd.h>
34 #include <stdlib.h>
35 #include <time.h>
36 #include <sys/file.h>
37 #include <sys/stat.h>
38 #include <sys/param.h>
39 #include <sys/socket.h>
40 
41 #include <glib.h>
42 
43 #include <bluetooth/bluetooth.h>
44 #include <bluetooth/sdp.h>
45 #include <bluetooth/sdp_lib.h>
46 
47 #include "textfile.h"
48 #include "adapter.h"
49 #include "device.h"
50 #include "glib-helper.h"
51 #include "storage.h"
52 
53 struct match {
54 	GSList *keys;
55 	char *pattern;
56 };
57 
create_filename(char * buf,size_t size,const bdaddr_t * bdaddr,const char * name)58 static inline int create_filename(char *buf, size_t size,
59 				const bdaddr_t *bdaddr, const char *name)
60 {
61 	char addr[18];
62 
63 	ba2str(bdaddr, addr);
64 
65 	return create_name(buf, size, STORAGEDIR, addr, name);
66 }
67 
read_device_alias(const char * src,const char * dst,char * alias,size_t size)68 int read_device_alias(const char *src, const char *dst, char *alias, size_t size)
69 {
70 	char filename[PATH_MAX + 1], *tmp;
71 	int err;
72 
73 	create_name(filename, PATH_MAX, STORAGEDIR, src, "aliases");
74 
75 	tmp = textfile_get(filename, dst);
76 	if (!tmp)
77 		return -ENXIO;
78 
79 	err = snprintf(alias, size, "%s", tmp);
80 
81 	free(tmp);
82 
83 	return err < 0 ? -EIO : 0;
84 }
85 
write_device_alias(const char * src,const char * dst,const char * alias)86 int write_device_alias(const char *src, const char *dst, const char *alias)
87 {
88 	char filename[PATH_MAX + 1];
89 
90 	create_name(filename, PATH_MAX, STORAGEDIR, src, "aliases");
91 
92 	create_file(filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
93 
94 	return textfile_put(filename, dst, alias);
95 }
96 
write_discoverable_timeout(bdaddr_t * bdaddr,int timeout)97 int write_discoverable_timeout(bdaddr_t *bdaddr, int timeout)
98 {
99 	char filename[PATH_MAX + 1], str[32];
100 
101 	snprintf(str, sizeof(str), "%d", timeout);
102 
103 	create_filename(filename, PATH_MAX, bdaddr, "config");
104 
105 	create_file(filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
106 
107 	return textfile_put(filename, "discovto", str);
108 }
109 
read_discoverable_timeout(const char * src,int * timeout)110 int read_discoverable_timeout(const char *src, int *timeout)
111 {
112 	char filename[PATH_MAX + 1], *str;
113 
114 	create_name(filename, PATH_MAX, STORAGEDIR, src, "config");
115 
116 	str = textfile_get(filename, "discovto");
117 	if (!str)
118 		return -ENOENT;
119 
120 	if (sscanf(str, "%d", timeout) != 1) {
121 		free(str);
122 		return -ENOENT;
123 	}
124 
125 	free(str);
126 
127 	return 0;
128 }
129 
write_pairable_timeout(bdaddr_t * bdaddr,int timeout)130 int write_pairable_timeout(bdaddr_t *bdaddr, int timeout)
131 {
132 	char filename[PATH_MAX + 1], str[32];
133 
134 	snprintf(str, sizeof(str), "%d", timeout);
135 
136 	create_filename(filename, PATH_MAX, bdaddr, "config");
137 
138 	create_file(filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
139 
140 	return textfile_put(filename, "pairto", str);
141 }
142 
read_pairable_timeout(const char * src,int * timeout)143 int read_pairable_timeout(const char *src, int *timeout)
144 {
145 	char filename[PATH_MAX + 1], *str;
146 
147 	create_name(filename, PATH_MAX, STORAGEDIR, src, "config");
148 
149 	str = textfile_get(filename, "pairto");
150 	if (!str)
151 		return -ENOENT;
152 
153 	if (sscanf(str, "%d", timeout) != 1) {
154 		free(str);
155 		return -ENOENT;
156 	}
157 
158 	free(str);
159 
160 	return 0;
161 }
162 
write_device_mode(bdaddr_t * bdaddr,const char * mode)163 int write_device_mode(bdaddr_t *bdaddr, const char *mode)
164 {
165 	char filename[PATH_MAX + 1];
166 
167 	create_filename(filename, PATH_MAX, bdaddr, "config");
168 
169 	create_file(filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
170 
171 	if (strcmp(mode, "off") != 0)
172 		textfile_put(filename, "onmode", mode);
173 
174 	return textfile_put(filename, "mode", mode);
175 }
176 
read_device_mode(const char * src,char * mode,int length)177 int read_device_mode(const char *src, char *mode, int length)
178 {
179 	char filename[PATH_MAX + 1], *str;
180 
181 	create_name(filename, PATH_MAX, STORAGEDIR, src, "config");
182 
183 	str = textfile_get(filename, "mode");
184 	if (!str)
185 		return -ENOENT;
186 
187 	strncpy(mode, str, length);
188 	mode[length - 1] = '\0';
189 
190 	free(str);
191 
192 	return 0;
193 }
194 
read_on_mode(const char * src,char * mode,int length)195 int read_on_mode(const char *src, char *mode, int length)
196 {
197 	char filename[PATH_MAX + 1], *str;
198 
199 	create_name(filename, PATH_MAX, STORAGEDIR, src, "config");
200 
201 	str = textfile_get(filename, "onmode");
202 	if (!str)
203 		return -ENOENT;
204 
205 	strncpy(mode, str, length);
206 	mode[length - 1] = '\0';
207 
208 	free(str);
209 
210 	return 0;
211 }
212 
write_local_name(bdaddr_t * bdaddr,const char * name)213 int write_local_name(bdaddr_t *bdaddr, const char *name)
214 {
215 	char filename[PATH_MAX + 1], str[249];
216 	int i;
217 
218 	memset(str, 0, sizeof(str));
219 	for (i = 0; i < 248 && name[i]; i++)
220 		if ((unsigned char) name[i] < 32 || name[i] == 127)
221 			str[i] = '.';
222 		else
223 			str[i] = name[i];
224 
225 	create_filename(filename, PATH_MAX, bdaddr, "config");
226 
227 	create_file(filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
228 
229 	return textfile_put(filename, "name", str);
230 }
231 
read_local_name(bdaddr_t * bdaddr,char * name)232 int read_local_name(bdaddr_t *bdaddr, char *name)
233 {
234 	char filename[PATH_MAX + 1], *str;
235 	int len;
236 
237 	create_filename(filename, PATH_MAX, bdaddr, "config");
238 
239 	str = textfile_get(filename, "name");
240 	if (!str)
241 		return -ENOENT;
242 
243 	len = strlen(str);
244 	if (len > 248)
245 		str[248] = '\0';
246 	strcpy(name, str);
247 
248 	free(str);
249 
250 	return 0;
251 }
252 
write_local_class(bdaddr_t * bdaddr,uint8_t * class)253 int write_local_class(bdaddr_t *bdaddr, uint8_t *class)
254 {
255 	char filename[PATH_MAX + 1], str[9];
256 
257 	sprintf(str, "0x%2.2x%2.2x%2.2x", class[2], class[1], class[0]);
258 
259 	create_filename(filename, PATH_MAX, bdaddr, "config");
260 
261 	create_file(filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
262 
263 	return textfile_put(filename, "class", str);
264 }
265 
read_local_class(bdaddr_t * bdaddr,uint8_t * class)266 int read_local_class(bdaddr_t *bdaddr, uint8_t *class)
267 {
268 	char filename[PATH_MAX + 1], tmp[3], *str;
269 	int i;
270 
271 	create_filename(filename, PATH_MAX, bdaddr, "config");
272 
273 	str = textfile_get(filename, "class");
274 	if (!str)
275 		return -ENOENT;
276 
277 	memset(tmp, 0, sizeof(tmp));
278 	for (i = 0; i < 3; i++) {
279 		memcpy(tmp, str + (i * 2) + 2, 2);
280 		class[2 - i] = (uint8_t) strtol(tmp, NULL, 16);
281 	}
282 
283 	free(str);
284 
285 	return 0;
286 }
287 
write_remote_class(bdaddr_t * local,bdaddr_t * peer,uint32_t class)288 int write_remote_class(bdaddr_t *local, bdaddr_t *peer, uint32_t class)
289 {
290 	char filename[PATH_MAX + 1], addr[18], str[9];
291 
292 	create_filename(filename, PATH_MAX, local, "classes");
293 
294 	create_file(filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
295 
296 	ba2str(peer, addr);
297 	sprintf(str, "0x%6.6x", class);
298 
299 	return textfile_put(filename, addr, str);
300 }
301 
read_remote_class(bdaddr_t * local,bdaddr_t * peer,uint32_t * class)302 int read_remote_class(bdaddr_t *local, bdaddr_t *peer, uint32_t *class)
303 {
304 	char filename[PATH_MAX + 1], addr[18], *str;
305 
306 	create_filename(filename, PATH_MAX, local, "classes");
307 
308 	ba2str(peer, addr);
309 
310 	str = textfile_get(filename, addr);
311 	if (!str)
312 		return -ENOENT;
313 
314 	if (sscanf(str, "%x", class) != 1) {
315 		free(str);
316 		return -ENOENT;
317 	}
318 
319 	free(str);
320 
321 	return 0;
322 }
323 
write_device_name(bdaddr_t * local,bdaddr_t * peer,char * name)324 int write_device_name(bdaddr_t *local, bdaddr_t *peer, char *name)
325 {
326 	char filename[PATH_MAX + 1], addr[18], str[249];
327 	int i;
328 
329 	memset(str, 0, sizeof(str));
330 	for (i = 0; i < 248 && name[i]; i++)
331 		if ((unsigned char) name[i] < 32 || name[i] == 127)
332 			str[i] = '.';
333 		else
334 			str[i] = name[i];
335 
336 	create_filename(filename, PATH_MAX, local, "names");
337 
338 	create_file(filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
339 
340 	ba2str(peer, addr);
341 	return textfile_put(filename, addr, str);
342 }
343 
read_device_name(const char * src,const char * dst,char * name)344 int read_device_name(const char *src, const char *dst, char *name)
345 {
346 	char filename[PATH_MAX + 1], *str;
347 	int len;
348 
349 	create_name(filename, PATH_MAX, STORAGEDIR, src, "names");
350 
351 	str = textfile_get(filename, dst);
352 	if (!str)
353 		return -ENOENT;
354 
355 	len = strlen(str);
356 	if (len > 248)
357 		str[248] = '\0';
358 	strcpy(name, str);
359 
360 	free(str);
361 
362 	return 0;
363 }
364 
write_remote_eir(bdaddr_t * local,bdaddr_t * peer,uint8_t * data)365 int write_remote_eir(bdaddr_t *local, bdaddr_t *peer, uint8_t *data)
366 {
367 	char filename[PATH_MAX + 1], addr[18], str[481];
368 	int i;
369 
370 	memset(str, 0, sizeof(str));
371 	for (i = 0; i < HCI_MAX_EIR_LENGTH; i++)
372 		sprintf(str + (i * 2), "%2.2X", data[i]);
373 
374 	create_filename(filename, PATH_MAX, local, "eir");
375 
376 	create_file(filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
377 
378 	ba2str(peer, addr);
379 	return textfile_put(filename, addr, str);
380 }
381 
read_remote_eir(bdaddr_t * local,bdaddr_t * peer,uint8_t * data)382 int read_remote_eir(bdaddr_t *local, bdaddr_t *peer, uint8_t *data)
383 {
384 	char filename[PATH_MAX + 1], addr[18], *str;
385 	int i;
386 
387 	create_filename(filename, PATH_MAX, local, "eir");
388 
389 	ba2str(peer, addr);
390 
391 	str = textfile_get(filename, addr);
392 	if (!str)
393 		return -ENOENT;
394 
395 	if (!data) {
396 		free(str);
397 		return 0;
398 	}
399 
400 	if (strlen(str) < 480) {
401 		free(str);
402 		return -EIO;
403 	}
404 
405 	for (i = 0; i < HCI_MAX_EIR_LENGTH; i++)
406 		sscanf(str + (i * 2), "%02hhX", &data[i]);
407 
408 	free(str);
409 
410 	return 0;
411 }
412 
write_version_info(bdaddr_t * local,bdaddr_t * peer,uint16_t manufacturer,uint8_t lmp_ver,uint16_t lmp_subver)413 int write_version_info(bdaddr_t *local, bdaddr_t *peer, uint16_t manufacturer,
414 					uint8_t lmp_ver, uint16_t lmp_subver)
415 {
416 	char filename[PATH_MAX + 1], addr[18], str[16];
417 
418 	memset(str, 0, sizeof(str));
419 	sprintf(str, "%d %d %d", manufacturer, lmp_ver, lmp_subver);
420 
421 	create_filename(filename, PATH_MAX, local, "manufacturers");
422 
423 	create_file(filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
424 
425 	ba2str(peer, addr);
426 	return textfile_put(filename, addr, str);
427 }
428 
write_features_info(bdaddr_t * local,bdaddr_t * peer,unsigned char * page1,unsigned char * page2)429 int write_features_info(bdaddr_t *local, bdaddr_t *peer,
430 				unsigned char *page1, unsigned char *page2)
431 {
432 	char filename[PATH_MAX + 1], addr[18];
433 	char str[] = "0000000000000000 0000000000000000";
434 	char *old_value;
435 	int i;
436 
437 	ba2str(peer, addr);
438 
439 	create_filename(filename, PATH_MAX, local, "features");
440 	create_file(filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
441 
442 	old_value = textfile_get(filename, addr);
443 
444 	if (page1)
445 		for (i = 0; i < 8; i++)
446 			sprintf(str + (i * 2), "%2.2X", page1[i]);
447 	else if (old_value && strlen(old_value) >= 16)
448 		strncpy(str, old_value, 16);
449 
450 	if (page2)
451 		for (i = 0; i < 8; i++)
452 			sprintf(str + 17 + (i * 2), "%2.2X", page2[i]);
453 	else if (old_value && strlen(old_value) >= 33)
454 		strncpy(str + 17, old_value + 17, 16);
455 
456 	free(old_value);
457 
458 	return textfile_put(filename, addr, str);
459 }
460 
decode_bytes(const char * str,unsigned char * bytes,size_t len)461 static int decode_bytes(const char *str, unsigned char *bytes, size_t len)
462 {
463 	unsigned int i;
464 
465 	for (i = 0; i < len; i++) {
466 		if (sscanf(str + (i * 2), "%02hhX", &bytes[i]) != 1)
467 			return -EINVAL;
468 	}
469 
470 	return 0;
471 }
472 
read_remote_features(bdaddr_t * local,bdaddr_t * peer,unsigned char * page1,unsigned char * page2)473 int read_remote_features(bdaddr_t *local, bdaddr_t *peer,
474 				unsigned char *page1, unsigned char *page2)
475 {
476 	char filename[PATH_MAX + 1], addr[18], *str;
477 	size_t len;
478 	int err;
479 
480 	if (page1 == NULL && page2 == NULL)
481 		return -EINVAL;
482 
483 	create_filename(filename, PATH_MAX, local, "features");
484 
485 	ba2str(peer, addr);
486 
487 	str = textfile_get(filename, addr);
488 	if (!str)
489 		return -ENOENT;
490 
491 	len = strlen(str);
492 
493 	err = -ENOENT;
494 
495 	if (page1 && len >= 16)
496 		err = decode_bytes(str, page1, 8);
497 
498 	if (page2 && len >= 33)
499 		err = decode_bytes(str + 17, page2, 8);
500 
501 	free(str);
502 
503 	return err;
504 }
505 
write_lastseen_info(bdaddr_t * local,bdaddr_t * peer,struct tm * tm)506 int write_lastseen_info(bdaddr_t *local, bdaddr_t *peer, struct tm *tm)
507 {
508 	char filename[PATH_MAX + 1], addr[18], str[24];
509 
510 	memset(str, 0, sizeof(str));
511 	strftime(str, sizeof(str), "%Y-%m-%d %H:%M:%S %Z", tm);
512 
513 	create_filename(filename, PATH_MAX, local, "lastseen");
514 
515 	create_file(filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
516 
517 	ba2str(peer, addr);
518 	return textfile_put(filename, addr, str);
519 }
520 
write_lastused_info(bdaddr_t * local,bdaddr_t * peer,struct tm * tm)521 int write_lastused_info(bdaddr_t *local, bdaddr_t *peer, struct tm *tm)
522 {
523 	char filename[PATH_MAX + 1], addr[18], str[24];
524 
525 	memset(str, 0, sizeof(str));
526 	strftime(str, sizeof(str), "%Y-%m-%d %H:%M:%S %Z", tm);
527 
528 	create_filename(filename, PATH_MAX, local, "lastused");
529 
530 	create_file(filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
531 
532 	ba2str(peer, addr);
533 	return textfile_put(filename, addr, str);
534 }
535 
write_link_key(bdaddr_t * local,bdaddr_t * peer,unsigned char * key,uint8_t type,int length)536 int write_link_key(bdaddr_t *local, bdaddr_t *peer, unsigned char *key, uint8_t type, int length)
537 {
538 	char filename[PATH_MAX + 1], addr[18], str[38];
539 	int i;
540 
541 	memset(str, 0, sizeof(str));
542 	for (i = 0; i < 16; i++)
543 		sprintf(str + (i * 2), "%2.2X", key[i]);
544 	sprintf(str + 32, " %d %d", type, length);
545 
546 	create_filename(filename, PATH_MAX, local, "linkkeys");
547 
548 	create_file(filename, S_IRUSR | S_IWUSR);
549 
550 	ba2str(peer, addr);
551 
552 	if (length < 0) {
553 		char *tmp = textfile_get(filename, addr);
554 		if (tmp) {
555 			if (strlen(tmp) > 34)
556 				memcpy(str + 34, tmp + 34, 3);
557 			free(tmp);
558 		}
559 	}
560 
561 	return textfile_put(filename, addr, str);
562 }
563 
read_link_key(bdaddr_t * local,bdaddr_t * peer,unsigned char * key,uint8_t * type)564 int read_link_key(bdaddr_t *local, bdaddr_t *peer, unsigned char *key, uint8_t *type)
565 {
566 	char filename[PATH_MAX + 1], addr[18], tmp[3], *str;
567 	int i;
568 
569 	create_filename(filename, PATH_MAX, local, "linkkeys");
570 
571 	ba2str(peer, addr);
572 	str = textfile_get(filename, addr);
573 	if (!str)
574 		return -ENOENT;
575 
576 	if (!key) {
577 		free(str);
578 		return 0;
579 	}
580 
581 	memset(tmp, 0, sizeof(tmp));
582 	for (i = 0; i < 16; i++) {
583 		memcpy(tmp, str + (i * 2), 2);
584 		key[i] = (uint8_t) strtol(tmp, NULL, 16);
585 	}
586 
587 	if (type) {
588 		memcpy(tmp, str + 33, 2);
589 		*type = (uint8_t) strtol(tmp, NULL, 10);
590 	}
591 
592 	free(str);
593 
594 	return 0;
595 }
596 
read_pin_code(bdaddr_t * local,bdaddr_t * peer,char * pin)597 int read_pin_code(bdaddr_t *local, bdaddr_t *peer, char *pin)
598 {
599 	char filename[PATH_MAX + 1], addr[18], *str;
600 	int len;
601 
602 	create_filename(filename, PATH_MAX, local, "pincodes");
603 
604 	ba2str(peer, addr);
605 	str = textfile_get(filename, addr);
606 	if (!str)
607 		return -ENOENT;
608 
609 	strncpy(pin, str, 16);
610 	len = strlen(pin);
611 
612 	free(str);
613 
614 	return len;
615 }
616 
service_string_to_list(char * services)617 static GSList *service_string_to_list(char *services)
618 {
619 	GSList *l = NULL;
620 	char *start = services;
621 	int i, finished = 0;
622 
623 	for (i = 0; !finished; i++) {
624 		if (services[i] == '\0')
625 			finished = 1;
626 
627 		if (services[i] == ' ' || services[i] == '\0') {
628 			services[i] = '\0';
629 			l = g_slist_append(l, start);
630 			start = services + i + 1;
631 		}
632 	}
633 
634 	return l;
635 }
636 
service_list_to_string(GSList * services)637 static char *service_list_to_string(GSList *services)
638 {
639 	char str[1024];
640 	int len = 0;
641 
642 	if (!services)
643 		return g_strdup("");
644 
645 	memset(str, 0, sizeof(str));
646 
647 	while (services) {
648 		int ret;
649 		char *ident = services->data;
650 
651 		ret = snprintf(str + len, sizeof(str) - len - 1, "%s%s",
652 				ident, services->next ? " " : "");
653 
654 		if (ret > 0)
655 			len += ret;
656 
657 		services = services->next;
658 	}
659 
660 	return g_strdup(str);
661 }
662 
write_trust(const char * src,const char * addr,const char * service,gboolean trust)663 int write_trust(const char *src, const char *addr, const char *service,
664 		gboolean trust)
665 {
666 	char filename[PATH_MAX + 1], *str;
667 	GSList *services = NULL, *match;
668 	gboolean trusted;
669 	int ret;
670 
671 	create_name(filename, PATH_MAX, STORAGEDIR, src, "trusts");
672 
673 	create_file(filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
674 
675 	str = textfile_caseget(filename, addr);
676 	if (str)
677 		services = service_string_to_list(str);
678 
679 	match = g_slist_find_custom(services, service, (GCompareFunc) strcmp);
680 	trusted = match ? TRUE : FALSE;
681 
682 	/* If the old setting is the same as the requested one, we're done */
683 	if (trusted == trust) {
684 		g_slist_free(services);
685 		free(str);
686 		return 0;
687 	}
688 
689 	if (trust)
690 		services = g_slist_append(services, (void *) service);
691 	else
692 		services = g_slist_remove(services, match->data);
693 
694 	/* Remove the entry if the last trusted service was removed */
695 	if (!trust && !services)
696 		ret = textfile_casedel(filename, addr);
697 	else {
698 		char *new_str = service_list_to_string(services);
699 		ret = textfile_caseput(filename, addr, new_str);
700 		free(new_str);
701 	}
702 
703 	g_slist_free(services);
704 
705 	free(str);
706 
707 	return ret;
708 }
709 
read_trust(const bdaddr_t * local,const char * addr,const char * service)710 gboolean read_trust(const bdaddr_t *local, const char *addr, const char *service)
711 {
712 	char filename[PATH_MAX + 1], *str;
713 	GSList *services;
714 	gboolean ret;
715 
716 	create_filename(filename, PATH_MAX, local, "trusts");
717 
718 	str = textfile_caseget(filename, addr);
719 	if (!str)
720 		return FALSE;
721 
722 	services = service_string_to_list(str);
723 
724 	if (g_slist_find_custom(services, service, (GCompareFunc) strcmp))
725 		ret = TRUE;
726 	else
727 		ret = FALSE;
728 
729 	g_slist_free(services);
730 	free(str);
731 
732 	return ret;
733 }
734 
735 struct trust_list {
736 	GSList *trusts;
737 	const char *service;
738 };
739 
append_trust(char * key,char * value,void * data)740 static void append_trust(char *key, char *value, void *data)
741 {
742 	struct trust_list *list = data;
743 
744 	if (strstr(value, list->service))
745 		list->trusts = g_slist_append(list->trusts, g_strdup(key));
746 }
747 
list_trusts(bdaddr_t * local,const char * service)748 GSList *list_trusts(bdaddr_t *local, const char *service)
749 {
750 	char filename[PATH_MAX + 1];
751 	struct trust_list list;
752 
753 	create_filename(filename, PATH_MAX, local, "trusts");
754 
755 	list.trusts = NULL;
756 	list.service = service;
757 
758 	if (textfile_foreach(filename, append_trust, &list) < 0)
759 		return NULL;
760 
761 	return list.trusts;
762 }
763 
write_device_profiles(bdaddr_t * src,bdaddr_t * dst,const char * profiles)764 int write_device_profiles(bdaddr_t *src, bdaddr_t *dst, const char *profiles)
765 {
766 	char filename[PATH_MAX + 1], addr[18];
767 
768 	if (!profiles)
769 		return -EINVAL;
770 
771 	create_filename(filename, PATH_MAX, src, "profiles");
772 
773 	create_file(filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
774 
775 	ba2str(dst, addr);
776 	return textfile_put(filename, addr, profiles);
777 }
778 
delete_entry(bdaddr_t * src,const char * storage,const char * key)779 int delete_entry(bdaddr_t *src, const char *storage, const char *key)
780 {
781 	char filename[PATH_MAX + 1];
782 
783 	create_filename(filename, PATH_MAX, src, storage);
784 
785 	return textfile_del(filename, key);
786 }
787 
store_record(const gchar * src,const gchar * dst,sdp_record_t * rec)788 int store_record(const gchar *src, const gchar *dst, sdp_record_t *rec)
789 {
790 	char filename[PATH_MAX + 1], key[28];
791 	sdp_buf_t buf;
792 	int err, size, i;
793 	char *str;
794 
795 	create_name(filename, PATH_MAX, STORAGEDIR, src, "sdp");
796 
797 	create_file(filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
798 
799 	snprintf(key, sizeof(key), "%17s#%08X", dst, rec->handle);
800 
801 	if (sdp_gen_record_pdu(rec, &buf) < 0)
802 		return -1;
803 
804 	size = buf.data_size;
805 
806 	str = g_malloc0(size*2+1);
807 
808 	for (i = 0; i < size; i++)
809 		sprintf(str + (i * 2), "%02X", buf.data[i]);
810 
811 	err = textfile_put(filename, key, str);
812 
813 	free(buf.data);
814 	free(str);
815 
816 	return err;
817 }
818 
record_from_string(const gchar * str)819 sdp_record_t *record_from_string(const gchar *str)
820 {
821 	sdp_record_t *rec;
822 	int size, i, len;
823 	uint8_t *pdata;
824 	char tmp[3];
825 
826 	size = strlen(str)/2;
827 	pdata = g_malloc0(size);
828 
829 	tmp[2] = 0;
830 	for (i = 0; i < size; i++) {
831 		memcpy(tmp, str + (i * 2), 2);
832 		pdata[i] = (uint8_t) strtol(tmp, NULL, 16);
833 	}
834 
835 	rec = sdp_extract_pdu(pdata, size, &len);
836 	free(pdata);
837 
838 	return rec;
839 }
840 
841 
fetch_record(const gchar * src,const gchar * dst,const uint32_t handle)842 sdp_record_t *fetch_record(const gchar *src, const gchar *dst,
843 						const uint32_t handle)
844 {
845 	char filename[PATH_MAX + 1], key[28], *str;
846 	sdp_record_t *rec;
847 
848 	create_name(filename, PATH_MAX, STORAGEDIR, src, "sdp");
849 
850 	snprintf(key, sizeof(key), "%17s#%08X", dst, handle);
851 
852 	str = textfile_get(filename, key);
853 	if (!str)
854 		return NULL;
855 
856 	rec = record_from_string(str);
857 	free(str);
858 
859 	return rec;
860 }
861 
delete_record(const gchar * src,const gchar * dst,const uint32_t handle)862 int delete_record(const gchar *src, const gchar *dst, const uint32_t handle)
863 {
864 	char filename[PATH_MAX + 1], key[28];
865 
866 	create_name(filename, PATH_MAX, STORAGEDIR, src, "sdp");
867 
868 	snprintf(key, sizeof(key), "%17s#%08X", dst, handle);
869 
870 	return textfile_del(filename, key);
871 }
872 
873 struct record_list {
874 	sdp_list_t *recs;
875 	const gchar *addr;
876 };
877 
create_stored_records_from_keys(char * key,char * value,void * user_data)878 static void create_stored_records_from_keys(char *key, char *value,
879 							void *user_data)
880 {
881 	struct record_list *rec_list = user_data;
882 	const gchar *addr = rec_list->addr;
883 	sdp_record_t *rec;
884 
885 	if (strncmp(key, addr, 17))
886 		return;
887 
888 	rec = record_from_string(value);
889 
890 	rec_list->recs = sdp_list_append(rec_list->recs, rec);
891 }
892 
delete_all_records(const bdaddr_t * src,const bdaddr_t * dst)893 void delete_all_records(const bdaddr_t *src, const bdaddr_t *dst)
894 {
895 	sdp_list_t *records, *seq;
896 	char srcaddr[18], dstaddr[18];
897 
898 	ba2str(src, srcaddr);
899 	ba2str(dst, dstaddr);
900 
901 	records = read_records(src, dst);
902 
903 	for (seq = records; seq; seq = seq->next) {
904 		sdp_record_t *rec = seq->data;
905 		delete_record(srcaddr, dstaddr, rec->handle);
906 	}
907 
908 	if (records)
909 		sdp_list_free(records, (sdp_free_func_t) sdp_record_free);
910 }
911 
read_records(const bdaddr_t * src,const bdaddr_t * dst)912 sdp_list_t *read_records(const bdaddr_t *src, const bdaddr_t *dst)
913 {
914 	char filename[PATH_MAX + 1];
915 	struct record_list rec_list;
916 	char srcaddr[18], dstaddr[18];
917 
918 	ba2str(src, srcaddr);
919 	ba2str(dst, dstaddr);
920 
921 	rec_list.addr = dstaddr;
922 	rec_list.recs = NULL;
923 
924 	create_name(filename, PATH_MAX, STORAGEDIR, srcaddr, "sdp");
925 	textfile_foreach(filename, create_stored_records_from_keys, &rec_list);
926 
927 	return rec_list.recs;
928 }
929 
find_record_in_list(sdp_list_t * recs,const char * uuid)930 sdp_record_t *find_record_in_list(sdp_list_t *recs, const char *uuid)
931 {
932 	sdp_list_t *seq;
933 
934 	for (seq = recs; seq; seq = seq->next) {
935 		sdp_record_t *rec = (sdp_record_t *) seq->data;
936 		sdp_list_t *svcclass = NULL;
937 		char *uuid_str;
938 
939 		if (sdp_get_service_classes(rec, &svcclass) < 0)
940 			continue;
941 
942 		/* Extract the uuid */
943 		uuid_str = bt_uuid2string(svcclass->data);
944 		if (!uuid_str)
945 			continue;
946 
947 		if (!strcasecmp(uuid_str, uuid)) {
948 			sdp_list_free(svcclass, free);
949 			free(uuid_str);
950 			return rec;
951 		}
952 
953 		sdp_list_free(svcclass, free);
954 		free(uuid_str);
955 	}
956 	return NULL;
957 }
958 
store_device_id(const gchar * src,const gchar * dst,const uint16_t source,const uint16_t vendor,const uint16_t product,const uint16_t version)959 int store_device_id(const gchar *src, const gchar *dst,
960 				const uint16_t source, const uint16_t vendor,
961 				const uint16_t product, const uint16_t version)
962 {
963 	char filename[PATH_MAX + 1], str[20];
964 
965 	create_name(filename, PATH_MAX, STORAGEDIR, src, "did");
966 
967 	create_file(filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
968 
969 	snprintf(str, sizeof(str), "%04X %04X %04X %04X", source,
970 						vendor, product, version);
971 
972 	return textfile_put(filename, dst, str);
973 }
974 
read_device_id_from_did(const gchar * src,const gchar * dst,uint16_t * source,uint16_t * vendor,uint16_t * product,uint16_t * version)975 static int read_device_id_from_did(const gchar *src, const gchar *dst,
976 					uint16_t *source, uint16_t *vendor,
977 					uint16_t *product, uint16_t *version)
978 {
979 	char filename[PATH_MAX + 1];
980 	char *str, *vendor_str, *product_str, *version_str;
981 
982 	create_name(filename, PATH_MAX, STORAGEDIR, src, "did");
983 
984 	str = textfile_get(filename, dst);
985 	if (!str)
986 		return -ENOENT;
987 
988 	vendor_str = strchr(str, ' ');
989 	if (!vendor_str) {
990 		free(str);
991 		return -ENOENT;
992 	}
993 	*(vendor_str++) = 0;
994 
995 	product_str = strchr(vendor_str, ' ');
996 	if (!product_str) {
997 		free(str);
998 		return -ENOENT;
999 	}
1000 	*(product_str++) = 0;
1001 
1002 	version_str = strchr(product_str, ' ');
1003 	if (!version_str) {
1004 		free(str);
1005 		return -ENOENT;
1006 	}
1007 	*(version_str++) = 0;
1008 
1009 	if (source)
1010 		*source = (uint16_t) strtol(str, NULL, 16);
1011 	if (vendor)
1012 		*vendor = (uint16_t) strtol(vendor_str, NULL, 16);
1013 	if (product)
1014 		*product = (uint16_t) strtol(product_str, NULL, 16);
1015 	if (version)
1016 		*version = (uint16_t) strtol(version_str, NULL, 16);
1017 
1018 	free(str);
1019 
1020 	return 0;
1021 }
1022 
read_device_id(const gchar * srcaddr,const gchar * dstaddr,uint16_t * source,uint16_t * vendor,uint16_t * product,uint16_t * version)1023 int read_device_id(const gchar *srcaddr, const gchar *dstaddr,
1024 					uint16_t *source, uint16_t *vendor,
1025 					uint16_t *product, uint16_t *version)
1026 {
1027 	uint16_t lsource, lvendor, lproduct, lversion;
1028 	sdp_list_t *recs;
1029 	sdp_record_t *rec;
1030 	bdaddr_t src, dst;
1031 	int err;
1032 
1033 	err = read_device_id_from_did(srcaddr, dstaddr, &lsource,
1034 						vendor, product, version);
1035 	if (!err) {
1036 		if (lsource == 0xffff)
1037 			err = -ENOENT;
1038 
1039 		return err;
1040 	}
1041 
1042 	str2ba(srcaddr, &src);
1043 	str2ba(dstaddr, &dst);
1044 
1045 	recs = read_records(&src, &dst);
1046 	rec = find_record_in_list(recs, PNP_UUID);
1047 
1048 	if (rec) {
1049 		sdp_data_t *pdlist;
1050 
1051 		pdlist = sdp_data_get(rec, SDP_ATTR_VENDOR_ID_SOURCE);
1052 		lsource = pdlist ? pdlist->val.uint16 : 0x0000;
1053 
1054 		pdlist = sdp_data_get(rec, SDP_ATTR_VENDOR_ID);
1055 		lvendor = pdlist ? pdlist->val.uint16 : 0x0000;
1056 
1057 		pdlist = sdp_data_get(rec, SDP_ATTR_PRODUCT_ID);
1058 		lproduct = pdlist ? pdlist->val.uint16 : 0x0000;
1059 
1060 		pdlist = sdp_data_get(rec, SDP_ATTR_VERSION);
1061 		lversion = pdlist ? pdlist->val.uint16 : 0x0000;
1062 
1063 		err = 0;
1064 	}
1065 
1066 	sdp_list_free(recs, (sdp_free_func_t)sdp_record_free);
1067 
1068 	if (err) {
1069 		/* FIXME: We should try EIR data if we have it, too */
1070 
1071 		/* If we don't have the data, we don't want to go through the
1072 		 * above search every time. */
1073 		lsource = 0xffff;
1074 		lvendor = 0x0000;
1075 		lproduct = 0x0000;
1076 		lversion = 0x0000;
1077 	}
1078 
1079 	store_device_id(srcaddr, dstaddr, lsource, lvendor, lproduct, lversion);
1080 
1081 	if (err)
1082 		return err;
1083 
1084 	if (source)
1085 		*source = lsource;
1086 	if (vendor)
1087 		*vendor = lvendor;
1088 	if (product)
1089 		*product = lproduct;
1090 	if (version)
1091 		*version = lversion;
1092 
1093 	return 0;
1094 }
1095 
write_device_pairable(bdaddr_t * bdaddr,gboolean mode)1096 int write_device_pairable(bdaddr_t *bdaddr, gboolean mode)
1097 {
1098 	char filename[PATH_MAX + 1];
1099 
1100 	create_filename(filename, PATH_MAX, bdaddr, "config");
1101 
1102 	create_file(filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
1103 
1104 	return textfile_put(filename, "pairable", mode ? "yes" : "no");
1105 }
1106 
read_device_pairable(bdaddr_t * bdaddr,gboolean * mode)1107 int read_device_pairable(bdaddr_t *bdaddr, gboolean *mode)
1108 {
1109 	char filename[PATH_MAX + 1], *str;
1110 
1111 	create_filename(filename, PATH_MAX, bdaddr, "config");
1112 
1113 	create_file(filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
1114 
1115 	str = textfile_get(filename, "pairable");
1116 	if (!str)
1117 		return -ENOENT;
1118 
1119 	*mode = strcmp(str, "yes") == 0 ? TRUE : FALSE;
1120 
1121 	free(str);
1122 
1123 	return 0;
1124 }
1125 
read_blocked(const bdaddr_t * local,const bdaddr_t * remote)1126 gboolean read_blocked(const bdaddr_t *local, const bdaddr_t *remote)
1127 {
1128 	char filename[PATH_MAX + 1], *str, addr[18];
1129 
1130 	create_filename(filename, PATH_MAX, local, "blocked");
1131 
1132 	ba2str(remote, addr);
1133 
1134 	str = textfile_caseget(filename, addr);
1135 	if (!str)
1136 		return FALSE;
1137 
1138 	free(str);
1139 
1140 	return TRUE;
1141 }
1142 
write_blocked(const bdaddr_t * local,const bdaddr_t * remote,gboolean blocked)1143 int write_blocked(const bdaddr_t *local, const bdaddr_t *remote,
1144 							gboolean blocked)
1145 {
1146 	char filename[PATH_MAX + 1], addr[18];
1147 
1148 	create_filename(filename, PATH_MAX, local, "blocked");
1149 
1150 	create_file(filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
1151 
1152 	ba2str(remote, addr);
1153 
1154 	if (blocked == FALSE)
1155 		return textfile_casedel(filename, addr);
1156 
1157 	return textfile_caseput(filename, addr, "");
1158 }
1159 
write_device_services(const bdaddr_t * sba,const bdaddr_t * dba,const char * services)1160 int write_device_services(const bdaddr_t *sba, const bdaddr_t *dba,
1161 							const char *services)
1162 {
1163 	char filename[PATH_MAX + 1], addr[18];
1164 
1165 	create_filename(filename, PATH_MAX, sba, "primary");
1166 
1167 	create_file(filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
1168 
1169 	ba2str(dba, addr);
1170 
1171 	return textfile_put(filename, addr, services);
1172 }
1173 
filter_keys(char * key,char * value,void * data)1174 static void filter_keys(char *key, char *value, void *data)
1175 {
1176 	struct match *match = data;
1177 	const char *address = match->pattern;
1178 
1179 	/* Each key contains: MAC#handle*/
1180 	if (strncasecmp(key, address, 17) == 0)
1181 		match->keys = g_slist_append(match->keys, g_strdup(key));
1182 }
1183 
delete_device_service(const bdaddr_t * sba,const bdaddr_t * dba)1184 int delete_device_service(const bdaddr_t *sba, const bdaddr_t *dba)
1185 {
1186 	GSList *l;
1187 	struct match match;
1188 	char filename[PATH_MAX + 1], address[18];
1189 	int err;
1190 
1191 	create_filename(filename, PATH_MAX, sba, "primary");
1192 
1193 	memset(address, 0, sizeof(address));
1194 	ba2str(dba, address);
1195 
1196 	err = textfile_del(filename, address);
1197 	if (err < 0)
1198 		return err;
1199 
1200 	/* Deleting all characteristics of a given address */
1201 	memset(&match, 0, sizeof(match));
1202 	match.pattern = address;
1203 
1204 	create_filename(filename, PATH_MAX, sba, "characteristic");
1205 	err = textfile_foreach(filename, filter_keys, &match);
1206 	if (err < 0)
1207 		return err;
1208 
1209 	for (l = match.keys; l; l = l->next) {
1210 		const char *key = l->data;
1211 		textfile_del(filename, key);
1212 	}
1213 
1214 	g_slist_foreach(match.keys, (GFunc) g_free, NULL);
1215 	g_slist_free(match.keys);
1216 
1217 	/* Deleting all attributes values of a given address */
1218 	memset(&match, 0, sizeof(match));
1219 	match.pattern = address;
1220 
1221 	create_filename(filename, PATH_MAX, sba, "attributes");
1222 	err = textfile_foreach(filename, filter_keys, &match);
1223 	if (err < 0)
1224 		return err;
1225 
1226 	for (l = match.keys; l; l = l->next) {
1227 		const char *key = l->data;
1228 		textfile_del(filename, key);
1229 	}
1230 
1231 	g_slist_foreach(match.keys, (GFunc) g_free, NULL);
1232 	g_slist_free(match.keys);
1233 
1234 	return 0;
1235 }
1236 
read_device_services(const bdaddr_t * sba,const bdaddr_t * dba)1237 char *read_device_services(const bdaddr_t *sba, const bdaddr_t *dba)
1238 {
1239 	char filename[PATH_MAX + 1], addr[18];
1240 
1241 	create_filename(filename, PATH_MAX, sba, "primary");
1242 
1243 	create_file(filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
1244 
1245 	ba2str(dba, addr);
1246 
1247 	return textfile_caseget(filename, addr);
1248 }
1249 
write_device_characteristics(const bdaddr_t * sba,const bdaddr_t * dba,uint16_t handle,const char * chars)1250 int write_device_characteristics(const bdaddr_t *sba, const bdaddr_t *dba,
1251 					uint16_t handle, const char *chars)
1252 {
1253 	char filename[PATH_MAX + 1], addr[18], key[23];
1254 
1255 	create_filename(filename, PATH_MAX, sba, "characteristic");
1256 
1257 	create_file(filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
1258 
1259 	ba2str(dba, addr);
1260 
1261 	snprintf(key, sizeof(key), "%17s#%04X", addr, handle);
1262 
1263 	return textfile_put(filename, key, chars);
1264 }
1265 
read_device_characteristics(const bdaddr_t * sba,const bdaddr_t * dba,uint16_t handle)1266 char *read_device_characteristics(const bdaddr_t *sba, const bdaddr_t *dba,
1267 							uint16_t handle)
1268 {
1269 	char filename[PATH_MAX + 1], addr[18], key[23];
1270 
1271 	create_filename(filename, PATH_MAX, sba, "characteristic");
1272 
1273 	create_file(filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
1274 
1275 	ba2str(dba, addr);
1276 
1277 	snprintf(key, sizeof(key), "%17s#%04X", addr, handle);
1278 
1279 	return textfile_caseget(filename, key);
1280 }
1281 
write_device_attribute(const bdaddr_t * sba,const bdaddr_t * dba,uint16_t handle,const char * chars)1282 int write_device_attribute(const bdaddr_t *sba, const bdaddr_t *dba,
1283 					uint16_t handle, const char *chars)
1284 {
1285 	char filename[PATH_MAX + 1], addr[18], key[23];
1286 
1287 	create_filename(filename, PATH_MAX, sba, "attributes");
1288 
1289 	create_file(filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
1290 
1291 	ba2str(dba, addr);
1292 
1293 	snprintf(key, sizeof(key), "%17s#%04X", addr, handle);
1294 
1295 	return textfile_put(filename, key, chars);
1296 }
1297 
read_device_attributes(const bdaddr_t * sba,textfile_cb func,void * data)1298 int read_device_attributes(const bdaddr_t *sba, textfile_cb func, void *data)
1299 {
1300 	char filename[PATH_MAX + 1];
1301 
1302 	create_filename(filename, PATH_MAX, sba, "attributes");
1303 
1304 	create_file(filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
1305 
1306 	return textfile_foreach(filename, func, data);
1307 }
1308 
write_device_type(const bdaddr_t * sba,const bdaddr_t * dba,device_type_t type)1309 int write_device_type(const bdaddr_t *sba, const bdaddr_t *dba,
1310 						device_type_t type)
1311 {
1312 	char filename[PATH_MAX + 1], addr[18], chars[3];
1313 
1314 	create_filename(filename, PATH_MAX, sba, "types");
1315 
1316 	create_file(filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
1317 
1318 	ba2str(dba, addr);
1319 
1320 	snprintf(chars, sizeof(chars), "%2.2X", type);
1321 
1322 	return textfile_put(filename, addr, chars);
1323 }
1324 
read_device_type(const bdaddr_t * sba,const bdaddr_t * dba)1325 device_type_t read_device_type(const bdaddr_t *sba, const bdaddr_t *dba)
1326 {
1327 	char filename[PATH_MAX + 1], addr[18], *chars;
1328 	device_type_t type;
1329 
1330 	create_filename(filename, PATH_MAX, sba, "types");
1331 
1332 	create_file(filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
1333 
1334 	ba2str(dba, addr);
1335 
1336 	chars = textfile_caseget(filename, addr);
1337 	if (chars == NULL)
1338 		return DEVICE_TYPE_UNKNOWN;
1339 
1340 	type = strtol(chars, NULL, 16);
1341 
1342 	free(chars);
1343 
1344 	return type;
1345 }
1346