~ubuntu-branches/ubuntu/wily/bluez/wily

« back to all changes in this revision

Viewing changes to src/storage.c

  • Committer: Bazaar Package Importer
  • Author(s): Mario Limonciello
  • Date: 2008-10-07 12:10:29 UTC
  • Revision ID: james.westby@ubuntu.com-20081007121029-4gup4fmmh2vfo5nh
Tags: upstream-4.12
ImportĀ upstreamĀ versionĀ 4.12

Show diffs side-by-side

added added

removed removed

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