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