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