• 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 "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 < 0 ? -EIO : 0;
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,const char * name)206 int write_local_name(bdaddr_t *bdaddr, const 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 * page1,unsigned char * page2)486 int write_features_info(bdaddr_t *local, bdaddr_t *peer,
487 				unsigned char *page1, unsigned char *page2)
488 {
489 	char filename[PATH_MAX + 1], addr[18];
490 	char str[] = "0000000000000000 0000000000000000";
491 	char *old_value;
492 	int i;
493 
494 	ba2str(peer, addr);
495 
496 	create_filename(filename, PATH_MAX, local, "features");
497 	create_file(filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
498 
499 	old_value = textfile_get(filename, addr);
500 
501 	if (page1)
502 		for (i = 0; i < 8; i++)
503 			sprintf(str + (i * 2), "%2.2X", page1[i]);
504 	else if (old_value && strlen(old_value) >= 16)
505 		strncpy(str, old_value, 16);
506 
507 	if (page2)
508 		for (i = 0; i < 8; i++)
509 			sprintf(str + 17 + (i * 2), "%2.2X", page2[i]);
510 	else if (old_value && strlen(old_value) >= 33)
511 		strncpy(str + 17, old_value + 17, 16);
512 
513 	free(old_value);
514 
515 	return textfile_put(filename, addr, str);
516 }
517 
decode_bytes(const char * str,unsigned char * bytes,size_t len)518 static int decode_bytes(const char *str, unsigned char *bytes, size_t len)
519 {
520 	unsigned int i;
521 
522 	for (i = 0; i < len; i++) {
523 		if (sscanf(str + (i * 2), "%02hhX", &bytes[i]) != 1)
524 			return -EINVAL;
525 	}
526 
527 	return 0;
528 }
529 
read_remote_features(bdaddr_t * local,bdaddr_t * peer,unsigned char * page1,unsigned char * page2)530 int read_remote_features(bdaddr_t *local, bdaddr_t *peer,
531 				unsigned char *page1, unsigned char *page2)
532 {
533 	char filename[PATH_MAX + 1], addr[18], *str;
534 	size_t len;
535 	int err;
536 
537 	if (page1 == NULL && page2 == NULL)
538 		return -EINVAL;
539 
540 	create_filename(filename, PATH_MAX, local, "features");
541 
542 	ba2str(peer, addr);
543 
544 	str = textfile_get(filename, addr);
545 	if (!str)
546 		return -ENOENT;
547 
548 	len = strlen(str);
549 
550 	err = -ENOENT;
551 
552 	if (page1 && len >= 16)
553 		err = decode_bytes(str, page1, 8);
554 
555 	if (page2 && len >= 33)
556 		err = decode_bytes(str + 17, page2, 8);
557 
558 	free(str);
559 
560 	return err;
561 }
562 
write_lastseen_info(bdaddr_t * local,bdaddr_t * peer,struct tm * tm)563 int write_lastseen_info(bdaddr_t *local, bdaddr_t *peer, struct tm *tm)
564 {
565 	char filename[PATH_MAX + 1], addr[18], str[24];
566 
567 	memset(str, 0, sizeof(str));
568 	strftime(str, sizeof(str), "%Y-%m-%d %H:%M:%S %Z", tm);
569 
570 	create_filename(filename, PATH_MAX, local, "lastseen");
571 
572 	create_file(filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
573 
574 	ba2str(peer, addr);
575 	return textfile_put(filename, addr, str);
576 }
577 
write_lastused_info(bdaddr_t * local,bdaddr_t * peer,struct tm * tm)578 int write_lastused_info(bdaddr_t *local, bdaddr_t *peer, struct tm *tm)
579 {
580 	char filename[PATH_MAX + 1], addr[18], str[24];
581 
582 	memset(str, 0, sizeof(str));
583 	strftime(str, sizeof(str), "%Y-%m-%d %H:%M:%S %Z", tm);
584 
585 	create_filename(filename, PATH_MAX, local, "lastused");
586 
587 	create_file(filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
588 
589 	ba2str(peer, addr);
590 	return textfile_put(filename, addr, str);
591 }
592 
write_link_key(bdaddr_t * local,bdaddr_t * peer,unsigned char * key,uint8_t type,int length)593 int write_link_key(bdaddr_t *local, bdaddr_t *peer, unsigned char *key, uint8_t type, int length)
594 {
595 	char filename[PATH_MAX + 1], addr[18], str[38];
596 	int i;
597 
598 	memset(str, 0, sizeof(str));
599 	for (i = 0; i < 16; i++)
600 		sprintf(str + (i * 2), "%2.2X", key[i]);
601 	sprintf(str + 32, " %d %d", type, length);
602 
603 	create_filename(filename, PATH_MAX, local, "linkkeys");
604 
605 	create_file(filename, S_IRUSR | S_IWUSR);
606 
607 	ba2str(peer, addr);
608 
609 	if (length < 0) {
610 		char *tmp = textfile_get(filename, addr);
611 		if (tmp) {
612 			if (strlen(tmp) > 34)
613 				memcpy(str + 34, tmp + 34, 3);
614 			free(tmp);
615 		}
616 	}
617 
618 	return textfile_put(filename, addr, str);
619 }
620 
read_link_key(bdaddr_t * local,bdaddr_t * peer,unsigned char * key,uint8_t * type)621 int read_link_key(bdaddr_t *local, bdaddr_t *peer, unsigned char *key, uint8_t *type)
622 {
623 	char filename[PATH_MAX + 1], addr[18], tmp[3], *str;
624 	int i;
625 
626 	create_filename(filename, PATH_MAX, local, "linkkeys");
627 
628 	ba2str(peer, addr);
629 	str = textfile_get(filename, addr);
630 	if (!str)
631 		return -ENOENT;
632 
633 	if (!key) {
634 		free(str);
635 		return 0;
636 	}
637 
638 	memset(tmp, 0, sizeof(tmp));
639 	for (i = 0; i < 16; i++) {
640 		memcpy(tmp, str + (i * 2), 2);
641 		key[i] = (uint8_t) strtol(tmp, NULL, 16);
642 	}
643 
644 	if (type) {
645 		memcpy(tmp, str + 33, 2);
646 		*type = (uint8_t) strtol(tmp, NULL, 10);
647 	}
648 
649 	free(str);
650 
651 	return 0;
652 }
653 
read_pin_length(bdaddr_t * local,bdaddr_t * peer)654 int read_pin_length(bdaddr_t *local, bdaddr_t *peer)
655 {
656 	char filename[PATH_MAX + 1], addr[18], *str;
657 	int len;
658 
659 	create_filename(filename, PATH_MAX, local, "linkkeys");
660 
661 	ba2str(peer, addr);
662 	str = textfile_get(filename, addr);
663 	if (!str)
664 		return -ENOENT;
665 
666 	if (strlen(str) < 36) {
667 		free(str);
668 		return -ENOENT;
669 	}
670 
671 	len = atoi(str + 35);
672 
673 	free(str);
674 
675 	return len;
676 }
677 
read_pin_code(bdaddr_t * local,bdaddr_t * peer,char * pin)678 int read_pin_code(bdaddr_t *local, bdaddr_t *peer, char *pin)
679 {
680 	char filename[PATH_MAX + 1], addr[18], *str;
681 	int len;
682 
683 	create_filename(filename, PATH_MAX, local, "pincodes");
684 
685 	ba2str(peer, addr);
686 	str = textfile_get(filename, addr);
687 	if (!str)
688 		return -ENOENT;
689 
690 	strncpy(pin, str, 16);
691 	len = strlen(pin);
692 
693 	free(str);
694 
695 	return len;
696 }
697 
service_string_to_list(char * services)698 static GSList *service_string_to_list(char *services)
699 {
700 	GSList *l = NULL;
701 	char *start = services;
702 	int i, finished = 0;
703 
704 	for (i = 0; !finished; i++) {
705 		if (services[i] == '\0')
706 			finished = 1;
707 
708 		if (services[i] == ' ' || services[i] == '\0') {
709 			services[i] = '\0';
710 			l = g_slist_append(l, start);
711 			start = services + i + 1;
712 		}
713 	}
714 
715 	return l;
716 }
717 
service_list_to_string(GSList * services)718 static char *service_list_to_string(GSList *services)
719 {
720 	char str[1024];
721 	int len = 0;
722 
723 	if (!services)
724 		return g_strdup("");
725 
726 	memset(str, 0, sizeof(str));
727 
728 	while (services) {
729 		int ret;
730 		char *ident = services->data;
731 
732 		ret = snprintf(str + len, sizeof(str) - len - 1, "%s%s",
733 				ident, services->next ? " " : "");
734 
735 		if (ret > 0)
736 			len += ret;
737 
738 		services = services->next;
739 	}
740 
741 	return g_strdup(str);
742 }
743 
write_trust(const char * src,const char * addr,const char * service,gboolean trust)744 int write_trust(const char *src, const char *addr, const char *service,
745 		gboolean trust)
746 {
747 	char filename[PATH_MAX + 1], *str;
748 	GSList *services = NULL, *match;
749 	gboolean trusted;
750 	int ret;
751 
752 	create_name(filename, PATH_MAX, STORAGEDIR, src, "trusts");
753 
754 	create_file(filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
755 
756 	str = textfile_caseget(filename, addr);
757 	if (str)
758 		services = service_string_to_list(str);
759 
760 	match = g_slist_find_custom(services, service, (GCompareFunc) strcmp);
761 	trusted = match ? TRUE : FALSE;
762 
763 	/* If the old setting is the same as the requested one, we're done */
764 	if (trusted == trust) {
765 		g_slist_free(services);
766 		free(str);
767 		return 0;
768 	}
769 
770 	if (trust)
771 		services = g_slist_append(services, (void *) service);
772 	else
773 		services = g_slist_remove(services, match->data);
774 
775 	/* Remove the entry if the last trusted service was removed */
776 	if (!trust && !services)
777 		ret = textfile_casedel(filename, addr);
778 	else {
779 		char *new_str = service_list_to_string(services);
780 		ret = textfile_caseput(filename, addr, new_str);
781 		free(new_str);
782 	}
783 
784 	g_slist_free(services);
785 
786 	free(str);
787 
788 	return ret;
789 }
790 
read_trust(const bdaddr_t * local,const char * addr,const char * service)791 gboolean read_trust(const bdaddr_t *local, const char *addr, const char *service)
792 {
793 	char filename[PATH_MAX + 1], *str;
794 	GSList *services;
795 	gboolean ret;
796 
797 	create_filename(filename, PATH_MAX, local, "trusts");
798 
799 	str = textfile_caseget(filename, addr);
800 	if (!str)
801 		return FALSE;
802 
803 	services = service_string_to_list(str);
804 
805 	if (g_slist_find_custom(services, service, (GCompareFunc) strcmp))
806 		ret = TRUE;
807 	else
808 		ret = FALSE;
809 
810 	g_slist_free(services);
811 	free(str);
812 
813 	return ret;
814 }
815 
816 struct trust_list {
817 	GSList *trusts;
818 	const char *service;
819 };
820 
append_trust(char * key,char * value,void * data)821 static void append_trust(char *key, char *value, void *data)
822 {
823 	struct trust_list *list = data;
824 
825 	if (strstr(value, list->service))
826 		list->trusts = g_slist_append(list->trusts, g_strdup(key));
827 }
828 
list_trusts(bdaddr_t * local,const char * service)829 GSList *list_trusts(bdaddr_t *local, const char *service)
830 {
831 	char filename[PATH_MAX + 1];
832 	struct trust_list list;
833 
834 	create_filename(filename, PATH_MAX, local, "trusts");
835 
836 	list.trusts = NULL;
837 	list.service = service;
838 
839 	if (textfile_foreach(filename, append_trust, &list) < 0)
840 		return NULL;
841 
842 	return list.trusts;
843 }
844 
write_device_profiles(bdaddr_t * src,bdaddr_t * dst,const char * profiles)845 int write_device_profiles(bdaddr_t *src, bdaddr_t *dst, const char *profiles)
846 {
847 	char filename[PATH_MAX + 1], addr[18];
848 
849 	if (!profiles)
850 		return -EINVAL;
851 
852 	create_filename(filename, PATH_MAX, src, "profiles");
853 
854 	create_file(filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
855 
856 	ba2str(dst, addr);
857 	return textfile_put(filename, addr, profiles);
858 }
859 
delete_entry(bdaddr_t * src,const char * storage,const char * key)860 int delete_entry(bdaddr_t *src, const char *storage, const char *key)
861 {
862 	char filename[PATH_MAX + 1];
863 
864 	create_filename(filename, PATH_MAX, src, storage);
865 
866 	return textfile_del(filename, key);
867 }
868 
store_record(const gchar * src,const gchar * dst,sdp_record_t * rec)869 int store_record(const gchar *src, const gchar *dst, sdp_record_t *rec)
870 {
871 	char filename[PATH_MAX + 1], key[28];
872 	sdp_buf_t buf;
873 	int err, size, i;
874 	char *str;
875 
876 	create_name(filename, PATH_MAX, STORAGEDIR, src, "sdp");
877 
878 	create_file(filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
879 
880 	snprintf(key, sizeof(key), "%17s#%08X", dst, rec->handle);
881 
882 	if (sdp_gen_record_pdu(rec, &buf) < 0)
883 		return -1;
884 
885 	size = buf.data_size;
886 
887 	str = g_malloc0(size*2+1);
888 
889 	for (i = 0; i < size; i++)
890 		sprintf(str + (i * 2), "%02X", buf.data[i]);
891 
892 	err = textfile_put(filename, key, str);
893 
894 	free(buf.data);
895 	free(str);
896 
897 	return err;
898 }
899 
record_from_string(const gchar * str)900 sdp_record_t *record_from_string(const gchar *str)
901 {
902 	sdp_record_t *rec;
903 	int size, i, len;
904 	uint8_t *pdata;
905 	char tmp[3];
906 
907 	size = strlen(str)/2;
908 	pdata = g_malloc0(size);
909 
910 	tmp[2] = 0;
911 	for (i = 0; i < size; i++) {
912 		memcpy(tmp, str + (i * 2), 2);
913 		pdata[i] = (uint8_t) strtol(tmp, NULL, 16);
914 	}
915 
916 	rec = sdp_extract_pdu(pdata, size, &len);
917 	free(pdata);
918 
919 	return rec;
920 }
921 
922 
fetch_record(const gchar * src,const gchar * dst,const uint32_t handle)923 sdp_record_t *fetch_record(const gchar *src, const gchar *dst,
924 						const uint32_t handle)
925 {
926 	char filename[PATH_MAX + 1], key[28], *str;
927 	sdp_record_t *rec;
928 
929 	create_name(filename, PATH_MAX, STORAGEDIR, src, "sdp");
930 
931 	snprintf(key, sizeof(key), "%17s#%08X", dst, handle);
932 
933 	str = textfile_get(filename, key);
934 	if (!str)
935 		return NULL;
936 
937 	rec = record_from_string(str);
938 	free(str);
939 
940 	return rec;
941 }
942 
delete_record(const gchar * src,const gchar * dst,const uint32_t handle)943 int delete_record(const gchar *src, const gchar *dst, const uint32_t handle)
944 {
945 	char filename[PATH_MAX + 1], key[28];
946 
947 	create_name(filename, PATH_MAX, STORAGEDIR, src, "sdp");
948 
949 	snprintf(key, sizeof(key), "%17s#%08X", dst, handle);
950 
951 	return textfile_del(filename, key);
952 }
953 
954 struct record_list {
955 	sdp_list_t *recs;
956 	const gchar *addr;
957 };
958 
create_stored_records_from_keys(char * key,char * value,void * user_data)959 static void create_stored_records_from_keys(char *key, char *value,
960 							void *user_data)
961 {
962 	struct record_list *rec_list = user_data;
963 	const gchar *addr = rec_list->addr;
964 	sdp_record_t *rec;
965 
966 	if (strncmp(key, addr, 17))
967 		return;
968 
969 	rec = record_from_string(value);
970 
971 	rec_list->recs = sdp_list_append(rec_list->recs, rec);
972 }
973 
delete_all_records(const bdaddr_t * src,const bdaddr_t * dst)974 void delete_all_records(const bdaddr_t *src, const bdaddr_t *dst)
975 {
976 	sdp_list_t *records, *seq;
977 	char srcaddr[18], dstaddr[18];
978 
979 	ba2str(src, srcaddr);
980 	ba2str(dst, dstaddr);
981 
982 	records = read_records(src, dst);
983 
984 	for (seq = records; seq; seq = seq->next) {
985 		sdp_record_t *rec = seq->data;
986 		delete_record(srcaddr, dstaddr, rec->handle);
987 	}
988 
989 	if (records)
990 		sdp_list_free(records, (sdp_free_func_t) sdp_record_free);
991 }
992 
read_records(const bdaddr_t * src,const bdaddr_t * dst)993 sdp_list_t *read_records(const bdaddr_t *src, const bdaddr_t *dst)
994 {
995 	char filename[PATH_MAX + 1];
996 	struct record_list rec_list;
997 	char srcaddr[18], dstaddr[18];
998 
999 	ba2str(src, srcaddr);
1000 	ba2str(dst, dstaddr);
1001 
1002 	rec_list.addr = dstaddr;
1003 	rec_list.recs = NULL;
1004 
1005 	create_name(filename, PATH_MAX, STORAGEDIR, srcaddr, "sdp");
1006 	textfile_foreach(filename, create_stored_records_from_keys, &rec_list);
1007 
1008 	return rec_list.recs;
1009 }
1010 
find_record_in_list(sdp_list_t * recs,const char * uuid)1011 sdp_record_t *find_record_in_list(sdp_list_t *recs, const char *uuid)
1012 {
1013 	sdp_list_t *seq;
1014 
1015 	for (seq = recs; seq; seq = seq->next) {
1016 		sdp_record_t *rec = (sdp_record_t *) seq->data;
1017 		sdp_list_t *svcclass = NULL;
1018 		char *uuid_str;
1019 
1020 		if (sdp_get_service_classes(rec, &svcclass) < 0)
1021 			continue;
1022 
1023 		/* Extract the uuid */
1024 		uuid_str = bt_uuid2string(svcclass->data);
1025 		if (!uuid_str)
1026 			continue;
1027 
1028 		if (!strcasecmp(uuid_str, uuid)) {
1029 			sdp_list_free(svcclass, free);
1030 			free(uuid_str);
1031 			return rec;
1032 		}
1033 
1034 		sdp_list_free(svcclass, free);
1035 		free(uuid_str);
1036 	}
1037 	return NULL;
1038 }
1039 
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)1040 int store_device_id(const gchar *src, const gchar *dst,
1041 				const uint16_t source, const uint16_t vendor,
1042 				const uint16_t product, const uint16_t version)
1043 {
1044 	char filename[PATH_MAX + 1], str[20];
1045 
1046 	create_name(filename, PATH_MAX, STORAGEDIR, src, "did");
1047 
1048 	create_file(filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
1049 
1050 	snprintf(str, sizeof(str), "%04X %04X %04X %04X", source,
1051 						vendor, product, version);
1052 
1053 	return textfile_put(filename, dst, str);
1054 }
1055 
read_device_id_from_did(const gchar * src,const gchar * dst,uint16_t * source,uint16_t * vendor,uint16_t * product,uint16_t * version)1056 static int read_device_id_from_did(const gchar *src, const gchar *dst,
1057 					uint16_t *source, uint16_t *vendor,
1058 					uint16_t *product, uint16_t *version)
1059 {
1060 	char filename[PATH_MAX + 1];
1061 	char *str, *vendor_str, *product_str, *version_str;
1062 
1063 	create_name(filename, PATH_MAX, STORAGEDIR, src, "did");
1064 
1065 	str = textfile_get(filename, dst);
1066 	if (!str)
1067 		return -ENOENT;
1068 
1069 	vendor_str = strchr(str, ' ');
1070 	if (!vendor_str) {
1071 		free(str);
1072 		return -ENOENT;
1073 	}
1074 	*(vendor_str++) = 0;
1075 
1076 	product_str = strchr(vendor_str, ' ');
1077 	if (!product_str) {
1078 		free(str);
1079 		return -ENOENT;
1080 	}
1081 	*(product_str++) = 0;
1082 
1083 	version_str = strchr(product_str, ' ');
1084 	if (!version_str) {
1085 		free(str);
1086 		return -ENOENT;
1087 	}
1088 	*(version_str++) = 0;
1089 
1090 	if (source)
1091 		*source = (uint16_t) strtol(str, NULL, 16);
1092 	if (vendor)
1093 		*vendor = (uint16_t) strtol(vendor_str, NULL, 16);
1094 	if (product)
1095 		*product = (uint16_t) strtol(product_str, NULL, 16);
1096 	if (version)
1097 		*version = (uint16_t) strtol(version_str, NULL, 16);
1098 
1099 	free(str);
1100 
1101 	return 0;
1102 }
1103 
read_device_id(const gchar * srcaddr,const gchar * dstaddr,uint16_t * source,uint16_t * vendor,uint16_t * product,uint16_t * version)1104 int read_device_id(const gchar *srcaddr, const gchar *dstaddr,
1105 					uint16_t *source, uint16_t *vendor,
1106 					uint16_t *product, uint16_t *version)
1107 {
1108 	uint16_t lsource, lvendor, lproduct, lversion;
1109 	sdp_list_t *recs;
1110 	sdp_record_t *rec;
1111 	bdaddr_t src, dst;
1112 	int err;
1113 
1114 	err = read_device_id_from_did(srcaddr, dstaddr, &lsource,
1115 						vendor, product, version);
1116 	if (!err) {
1117 		if (lsource == 0xffff)
1118 			err = -ENOENT;
1119 
1120 		return err;
1121 	}
1122 
1123 	str2ba(srcaddr, &src);
1124 	str2ba(dstaddr, &dst);
1125 
1126 	recs = read_records(&src, &dst);
1127 	rec = find_record_in_list(recs, PNP_UUID);
1128 
1129 	if (rec) {
1130 		sdp_data_t *pdlist;
1131 
1132 		pdlist = sdp_data_get(rec, SDP_ATTR_VENDOR_ID_SOURCE);
1133 		lsource = pdlist ? pdlist->val.uint16 : 0x0000;
1134 
1135 		pdlist = sdp_data_get(rec, SDP_ATTR_VENDOR_ID);
1136 		lvendor = pdlist ? pdlist->val.uint16 : 0x0000;
1137 
1138 		pdlist = sdp_data_get(rec, SDP_ATTR_PRODUCT_ID);
1139 		lproduct = pdlist ? pdlist->val.uint16 : 0x0000;
1140 
1141 		pdlist = sdp_data_get(rec, SDP_ATTR_VERSION);
1142 		lversion = pdlist ? pdlist->val.uint16 : 0x0000;
1143 
1144 		err = 0;
1145 	}
1146 
1147 	sdp_list_free(recs, (sdp_free_func_t)sdp_record_free);
1148 
1149 	if (err) {
1150 		/* FIXME: We should try EIR data if we have it, too */
1151 
1152 		/* If we don't have the data, we don't want to go through the
1153 		 * above search every time. */
1154 		lsource = 0xffff;
1155 		lvendor = 0x0000;
1156 		lproduct = 0x0000;
1157 		lversion = 0x0000;
1158 	}
1159 
1160 	store_device_id(srcaddr, dstaddr, lsource, lvendor, lproduct, lversion);
1161 
1162 	if (err)
1163 		return err;
1164 
1165 	if (source)
1166 		*source = lsource;
1167 	if (vendor)
1168 		*vendor = lvendor;
1169 	if (product)
1170 		*product = lproduct;
1171 	if (version)
1172 		*version = lversion;
1173 
1174 	return 0;
1175 }
1176 
write_device_pairable(bdaddr_t * bdaddr,gboolean mode)1177 int write_device_pairable(bdaddr_t *bdaddr, gboolean mode)
1178 {
1179 	char filename[PATH_MAX + 1];
1180 
1181 	create_filename(filename, PATH_MAX, bdaddr, "config");
1182 
1183 	create_file(filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
1184 
1185 	return textfile_put(filename, "pairable", mode ? "yes" : "no");
1186 }
1187 
read_device_pairable(bdaddr_t * bdaddr,gboolean * mode)1188 int read_device_pairable(bdaddr_t *bdaddr, gboolean *mode)
1189 {
1190 	char filename[PATH_MAX + 1], *str;
1191 
1192 	create_filename(filename, PATH_MAX, bdaddr, "config");
1193 
1194 	create_file(filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
1195 
1196 	str = textfile_get(filename, "pairable");
1197 	if (!str)
1198 		return -ENOENT;
1199 
1200 	*mode = strcmp(str, "yes") == 0 ? TRUE : FALSE;
1201 
1202 	free(str);
1203 
1204 	return 0;
1205 }
1206 
read_blocked(const bdaddr_t * local,const bdaddr_t * remote)1207 gboolean read_blocked(const bdaddr_t *local, const bdaddr_t *remote)
1208 {
1209 	char filename[PATH_MAX + 1], *str, addr[18];
1210 
1211 	create_filename(filename, PATH_MAX, local, "blocked");
1212 
1213 	ba2str(remote, addr);
1214 
1215 	str = textfile_caseget(filename, addr);
1216 	if (!str)
1217 		return FALSE;
1218 
1219 	free(str);
1220 
1221 	return TRUE;
1222 }
1223 
write_blocked(const bdaddr_t * local,const bdaddr_t * remote,gboolean blocked)1224 int write_blocked(const bdaddr_t *local, const bdaddr_t *remote,
1225 							gboolean blocked)
1226 {
1227 	char filename[PATH_MAX + 1], addr[18];
1228 
1229 	create_filename(filename, PATH_MAX, local, "blocked");
1230 
1231 	create_file(filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
1232 
1233 	ba2str(remote, addr);
1234 
1235 	if (blocked == FALSE)
1236 		return textfile_casedel(filename, addr);
1237 
1238 	return textfile_caseput(filename, addr, "");
1239 }
1240