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