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