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