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