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