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