btstack_link_key_db_fs.c 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  1. /*
  2. * Copyright (C) 2014 BlueKitchen GmbH
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions
  6. * are met:
  7. *
  8. * 1. Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * 2. Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in the
  12. * documentation and/or other materials provided with the distribution.
  13. * 3. Neither the name of the copyright holders nor the names of
  14. * contributors may be used to endorse or promote products derived
  15. * from this software without specific prior written permission.
  16. * 4. Any redistribution, use, or modification is done solely for
  17. * personal benefit and not for any commercial purpose or for
  18. * monetary gain.
  19. *
  20. * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
  21. * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  22. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  23. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
  24. * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  25. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  26. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  27. * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  28. * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  29. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
  30. * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31. * SUCH DAMAGE.
  32. *
  33. * Please inquire about commercial licensing options at
  34. * contact@bluekitchen-gmbh.com
  35. *
  36. */
  37. #define BTSTACK_FILE__ "btstack_link_key_db_fs.c"
  38. #include <string.h>
  39. #include <stdlib.h>
  40. #include <stdio.h>
  41. #include <unistd.h>
  42. #include "tinydir.h"
  43. #include "btstack_config.h"
  44. #include "btstack_link_key_db_fs.h"
  45. #include "btstack_debug.h"
  46. #include "btstack_util.h"
  47. // allow to pre-set LINK_KEY_PATH from btstack_config.h
  48. #ifndef LINK_KEY_PATH
  49. #ifdef _WIN32
  50. #define LINK_KEY_PATH ""
  51. #else
  52. #define LINK_KEY_PATH "/tmp/"
  53. #endif
  54. #endif
  55. #define LINK_KEY_PREFIX "btstack_at_"
  56. #define LINK_KEY_FOR "_link_key_for_"
  57. #define LINK_KEY_SUFFIX ".txt"
  58. #define LINK_KEY_STRING_LEN 17
  59. static bd_addr_t local_addr;
  60. // note: sizeof for string literals works at compile time while strlen only works with some optimizations turned on. sizeof includes the  \0
  61. static char keypath[sizeof(LINK_KEY_PATH) + sizeof(LINK_KEY_PREFIX) + LINK_KEY_STRING_LEN + sizeof(LINK_KEY_FOR) + LINK_KEY_STRING_LEN + sizeof(LINK_KEY_SUFFIX) + 1];
  62. static char bd_addr_to_dash_str_buffer[6*3]; // 12-45-78-01-34-67\0
  63. static char * bd_addr_to_dash_str(bd_addr_t addr){
  64. char * p = bd_addr_to_dash_str_buffer;
  65. int i;
  66. for (i = 0; i < 6 ; i++) {
  67. *p++ = char_for_nibble((addr[i] >> 4) & 0x0F);
  68. *p++ = char_for_nibble((addr[i] >> 0) & 0x0F);
  69. *p++ = '-';
  70. }
  71. *--p = 0;
  72. return (char *) bd_addr_to_dash_str_buffer;
  73. }
  74. static char link_key_to_str_buffer[LINK_KEY_STR_LEN+1]; // 11223344556677889900112233445566\0
  75. static char *link_key_to_str(link_key_t link_key){
  76. char * p = link_key_to_str_buffer;
  77. int i;
  78. for (i = 0; i < LINK_KEY_LEN ; i++) {
  79. *p++ = char_for_nibble((link_key[i] >> 4) & 0x0F);
  80. *p++ = char_for_nibble((link_key[i] >> 0) & 0x0F);
  81. }
  82. *p = 0;
  83. return (char *) link_key_to_str_buffer;
  84. }
  85. static char link_key_type_to_str_buffer[2];
  86. static char *link_key_type_to_str(link_key_type_t link_key){
  87. snprintf(link_key_type_to_str_buffer, sizeof(link_key_type_to_str_buffer), "%d", link_key);
  88. return (char *) link_key_type_to_str_buffer;
  89. }
  90. static int sscanf_link_key(char * addr_string, link_key_t link_key){
  91. unsigned int buffer[LINK_KEY_LEN];
  92. // reset result buffer
  93. memset(&buffer, 0, sizeof(buffer));
  94. // parse
  95. int result = sscanf( (char *) addr_string, "%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x",
  96. &buffer[0], &buffer[1], &buffer[2], &buffer[3],
  97. &buffer[4], &buffer[5], &buffer[6], &buffer[7],
  98. &buffer[8], &buffer[9], &buffer[10], &buffer[11],
  99. &buffer[12], &buffer[13], &buffer[14], &buffer[15] );
  100. if (result != LINK_KEY_LEN) return 0;
  101. // store
  102. int i;
  103. uint8_t *p = (uint8_t *) link_key;
  104. for (i=0; i<LINK_KEY_LEN; i++ ) {
  105. *p++ = (uint8_t) buffer[i];
  106. }
  107. return 1;
  108. }
  109. static void set_path(bd_addr_t bd_addr){
  110. strcpy(keypath, LINK_KEY_PATH);
  111. strcat(keypath, LINK_KEY_PREFIX);
  112. strcat(keypath, bd_addr_to_dash_str(local_addr));
  113. strcat(keypath, LINK_KEY_FOR);
  114. strcat(keypath, bd_addr_to_dash_str(bd_addr));
  115. strcat(keypath, LINK_KEY_SUFFIX);
  116. }
  117. // Device info
  118. static void db_open(void){
  119. }
  120. static void db_set_local_bd_addr(bd_addr_t bd_addr){
  121. memcpy(local_addr, bd_addr, 6);
  122. }
  123. static void db_close(void){
  124. }
  125. static void put_link_key(bd_addr_t bd_addr, link_key_t link_key, link_key_type_t link_key_type){
  126. set_path(bd_addr);
  127. char * link_key_str = link_key_to_str(link_key);
  128. char * link_key_type_str = link_key_type_to_str(link_key_type);
  129. FILE * wFile = fopen(keypath,"w+");
  130. fwrite(link_key_str, strlen(link_key_str), 1, wFile);
  131. fwrite(link_key_type_str, strlen(link_key_type_str), 1, wFile);
  132. fclose(wFile);
  133. }
  134. static int read_link_key(const char * path, link_key_t link_key, link_key_type_t * link_key_type){
  135. if (access(path, R_OK)) return 0;
  136. char link_key_str[LINK_KEY_STR_LEN + 1];
  137. char link_key_type_str[2];
  138. FILE * rFile = fopen(path,"r+");
  139. size_t objects_read = fread(link_key_str, LINK_KEY_STR_LEN, 1, rFile );
  140. if (objects_read == 1){
  141. link_key_str[LINK_KEY_STR_LEN] = 0;
  142. log_info("Found link key %s\n", link_key_str);
  143. objects_read = fread(link_key_type_str, 1, 1, rFile );
  144. }
  145. fclose(rFile);
  146. if (objects_read != 1) return 0;
  147. link_key_type_str[1] = 0;
  148. log_info("Found link key type %s\n", link_key_type_str);
  149. int scan_result = sscanf_link_key(link_key_str, link_key);
  150. if (scan_result == 0 ) return 0;
  151. int link_key_type_buffer;
  152. scan_result = sscanf( (char *) link_key_type_str, "%d", &link_key_type_buffer);
  153. if (scan_result == 0 ) return 0;
  154. *link_key_type = (link_key_type_t) link_key_type_buffer;
  155. return 1;
  156. }
  157. static int get_link_key(bd_addr_t bd_addr, link_key_t link_key, link_key_type_t * link_key_type) {
  158. set_path(bd_addr);
  159. return read_link_key(keypath, link_key, link_key_type);
  160. }
  161. static void delete_link_key(bd_addr_t bd_addr){
  162. set_path(bd_addr);
  163. if (access(keypath, R_OK)) return;
  164. if(remove(keypath) != 0){
  165. log_error("File %s could not be deleted.\n", keypath);
  166. }
  167. }
  168. static int iterator_init(btstack_link_key_iterator_t * it){
  169. tinydir_dir * dir = (tinydir_dir *) malloc(sizeof(tinydir_dir));
  170. if (!dir) return 0;
  171. it->context = dir;
  172. tinydir_open(dir, LINK_KEY_PATH);
  173. return 1;
  174. }
  175. static int iterator_get_next(btstack_link_key_iterator_t * it, bd_addr_t bd_addr, link_key_t link_key, link_key_type_t * type){
  176. (void)bd_addr;
  177. (void)link_key;
  178. UNUSED(type);
  179. tinydir_dir * dir = (tinydir_dir*) it->context;
  180. // construct prefix
  181. strcpy(keypath, LINK_KEY_PREFIX);
  182. strcat(keypath, bd_addr_to_dash_str(local_addr));
  183. strcat(keypath, LINK_KEY_FOR);
  184. while (dir->has_next) {
  185. tinydir_file file;
  186. tinydir_readfile(dir, &file);
  187. tinydir_next(dir);
  188. // compare
  189. if (strncmp(keypath, file.name, strlen(keypath)) == 0){
  190. // parse bd_addr
  191. const int addr_offset = sizeof(LINK_KEY_PREFIX) + LINK_KEY_STRING_LEN + sizeof(LINK_KEY_FOR) - 2; // -1 for each sizeof
  192. sscanf_bd_addr(&file.name[addr_offset], bd_addr);
  193. // path found, read file
  194. strcpy(keypath, LINK_KEY_PATH);
  195. strcat(keypath, file.name);
  196. read_link_key(keypath, link_key, type);
  197. return 1;
  198. }
  199. }
  200. return 0;
  201. }
  202. static void iterator_done(btstack_link_key_iterator_t * it){
  203. tinydir_close((tinydir_dir*)it->context);
  204. free(it->context);
  205. it->context = NULL;
  206. }
  207. static const btstack_link_key_db_t btstack_link_key_db_fs = {
  208. &db_open,
  209. &db_set_local_bd_addr,
  210. &db_close,
  211. &get_link_key,
  212. &put_link_key,
  213. &delete_link_key,
  214. &iterator_init,
  215. &iterator_get_next,
  216. &iterator_done,
  217. };
  218. const btstack_link_key_db_t * btstack_link_key_db_fs_instance(void){
  219. return &btstack_link_key_db_fs;
  220. }