xref: /btstack/platform/posix/btstack_link_key_db_fs.c (revision d5bacf302a965e1fda77ec7e9b7d953ea264c3e0)
1caed94dfSMatthias Ringwald /*
2caed94dfSMatthias Ringwald  * Copyright (C) 2014 BlueKitchen GmbH
3caed94dfSMatthias Ringwald  *
4caed94dfSMatthias Ringwald  * Redistribution and use in source and binary forms, with or without
5caed94dfSMatthias Ringwald  * modification, are permitted provided that the following conditions
6caed94dfSMatthias Ringwald  * are met:
7caed94dfSMatthias Ringwald  *
8caed94dfSMatthias Ringwald  * 1. Redistributions of source code must retain the above copyright
9caed94dfSMatthias Ringwald  *    notice, this list of conditions and the following disclaimer.
10caed94dfSMatthias Ringwald  * 2. Redistributions in binary form must reproduce the above copyright
11caed94dfSMatthias Ringwald  *    notice, this list of conditions and the following disclaimer in the
12caed94dfSMatthias Ringwald  *    documentation and/or other materials provided with the distribution.
13caed94dfSMatthias Ringwald  * 3. Neither the name of the copyright holders nor the names of
14caed94dfSMatthias Ringwald  *    contributors may be used to endorse or promote products derived
15caed94dfSMatthias Ringwald  *    from this software without specific prior written permission.
16caed94dfSMatthias Ringwald  * 4. Any redistribution, use, or modification is done solely for
17caed94dfSMatthias Ringwald  *    personal benefit and not for any commercial purpose or for
18caed94dfSMatthias Ringwald  *    monetary gain.
19caed94dfSMatthias Ringwald  *
20caed94dfSMatthias Ringwald  * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
21caed94dfSMatthias Ringwald  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22caed94dfSMatthias Ringwald  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
232fca4dadSMilanka Ringwald  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BLUEKITCHEN
242fca4dadSMilanka Ringwald  * GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25caed94dfSMatthias Ringwald  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26caed94dfSMatthias Ringwald  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
27caed94dfSMatthias Ringwald  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28caed94dfSMatthias Ringwald  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29caed94dfSMatthias Ringwald  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
30caed94dfSMatthias Ringwald  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31caed94dfSMatthias Ringwald  * SUCH DAMAGE.
32caed94dfSMatthias Ringwald  *
33caed94dfSMatthias Ringwald  * Please inquire about commercial licensing options at
34caed94dfSMatthias Ringwald  * [email protected]
35caed94dfSMatthias Ringwald  *
36caed94dfSMatthias Ringwald  */
37caed94dfSMatthias Ringwald 
38e501bae0SMatthias Ringwald #define BTSTACK_FILE__ "btstack_link_key_db_fs.c"
39ab2c6ae4SMatthias Ringwald 
40caed94dfSMatthias Ringwald #include <string.h>
41caed94dfSMatthias Ringwald #include <stdlib.h>
42caed94dfSMatthias Ringwald #include <stdio.h>
43caed94dfSMatthias Ringwald #include <unistd.h>
44caed94dfSMatthias Ringwald 
45d08566fbSMatthias Ringwald #include "tinydir.h"
46d08566fbSMatthias Ringwald 
47fd19b115SMatthias Ringwald #include "btstack_config.h"
48caed94dfSMatthias Ringwald #include "btstack_link_key_db_fs.h"
49caed94dfSMatthias Ringwald #include "btstack_debug.h"
50caed94dfSMatthias Ringwald #include "btstack_util.h"
51caed94dfSMatthias Ringwald 
52fd19b115SMatthias Ringwald // allow to pre-set LINK_KEY_PATH from btstack_config.h
53fd19b115SMatthias Ringwald #ifndef LINK_KEY_PATH
549419a14fSMatthias Ringwald #ifdef _WIN32
559419a14fSMatthias Ringwald #define LINK_KEY_PATH ""
569419a14fSMatthias Ringwald #else
57caed94dfSMatthias Ringwald #define LINK_KEY_PATH "/tmp/"
589419a14fSMatthias Ringwald #endif
59fd19b115SMatthias Ringwald #endif
60fd19b115SMatthias Ringwald 
611624665aSMatthias Ringwald #define LINK_KEY_PREFIX "btstack_at_"
621624665aSMatthias Ringwald #define LINK_KEY_FOR "_link_key_for_"
631624665aSMatthias Ringwald #define LINK_KEY_SUFFIX ".txt"
641624665aSMatthias Ringwald #define LINK_KEY_STRING_LEN 17
65caed94dfSMatthias Ringwald 
661624665aSMatthias Ringwald static bd_addr_t local_addr;
67d08566fbSMatthias Ringwald // note: sizeof for string literals works at compile time while strlen only works with some optimizations turned on. sizeof includes the  \0
6818906008SMatthias Ringwald 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];
69caed94dfSMatthias Ringwald 
bd_addr_to_dash_str(bd_addr_t addr)70caed94dfSMatthias Ringwald static char * bd_addr_to_dash_str(bd_addr_t addr){
71924bf9b8SMatthias Ringwald     return bd_addr_to_str_with_delimiter(addr, '-');
72caed94dfSMatthias Ringwald }
73caed94dfSMatthias Ringwald 
741624665aSMatthias Ringwald static char link_key_to_str_buffer[LINK_KEY_STR_LEN+1];  // 11223344556677889900112233445566\0
link_key_to_str(link_key_t link_key)7558044c39SMatthias Ringwald static char *link_key_to_str(link_key_t link_key){
761624665aSMatthias Ringwald     char * p = link_key_to_str_buffer;
771624665aSMatthias Ringwald     int i;
781624665aSMatthias Ringwald     for (i = 0; i < LINK_KEY_LEN ; i++) {
791624665aSMatthias Ringwald         *p++ = char_for_nibble((link_key[i] >> 4) & 0x0F);
801624665aSMatthias Ringwald         *p++ = char_for_nibble((link_key[i] >> 0) & 0x0F);
811624665aSMatthias Ringwald     }
821624665aSMatthias Ringwald     *p = 0;
831624665aSMatthias Ringwald     return (char *) link_key_to_str_buffer;
841624665aSMatthias Ringwald }
851624665aSMatthias Ringwald 
861624665aSMatthias Ringwald static char link_key_type_to_str_buffer[2];
link_key_type_to_str(link_key_type_t link_key)8758044c39SMatthias Ringwald static char *link_key_type_to_str(link_key_type_t link_key){
88*d5bacf30SMatthias Ringwald     btstack_snprintf_assert_complete(link_key_type_to_str_buffer, sizeof(link_key_type_to_str_buffer), "%d", link_key);
891624665aSMatthias Ringwald     return (char *) link_key_type_to_str_buffer;
901624665aSMatthias Ringwald }
911624665aSMatthias Ringwald 
sscanf_link_key(char * addr_string,link_key_t link_key)9258044c39SMatthias Ringwald static int sscanf_link_key(char * addr_string, link_key_t link_key){
931624665aSMatthias Ringwald     unsigned int buffer[LINK_KEY_LEN];
941624665aSMatthias Ringwald 
951624665aSMatthias Ringwald     // reset result buffer
961624665aSMatthias Ringwald     memset(&buffer, 0, sizeof(buffer));
971624665aSMatthias Ringwald 
981624665aSMatthias Ringwald     // parse
991624665aSMatthias Ringwald     int result = sscanf( (char *) addr_string, "%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x",
1001624665aSMatthias Ringwald                                     &buffer[0], &buffer[1], &buffer[2], &buffer[3],
1011624665aSMatthias Ringwald                                     &buffer[4], &buffer[5], &buffer[6], &buffer[7],
1021624665aSMatthias Ringwald                                     &buffer[8], &buffer[9], &buffer[10], &buffer[11],
1031624665aSMatthias Ringwald                                     &buffer[12], &buffer[13], &buffer[14], &buffer[15] );
1041624665aSMatthias Ringwald 
1051624665aSMatthias Ringwald     if (result != LINK_KEY_LEN) return 0;
1061624665aSMatthias Ringwald 
1071624665aSMatthias Ringwald     // store
1081624665aSMatthias Ringwald     int i;
1091624665aSMatthias Ringwald     uint8_t *p = (uint8_t *) link_key;
1101624665aSMatthias Ringwald     for (i=0; i<LINK_KEY_LEN; i++ ) {
1111624665aSMatthias Ringwald         *p++ = (uint8_t) buffer[i];
1121624665aSMatthias Ringwald     }
1131624665aSMatthias Ringwald     return 1;
1141624665aSMatthias Ringwald }
1151624665aSMatthias Ringwald 
set_path(bd_addr_t bd_addr)116caed94dfSMatthias Ringwald static void set_path(bd_addr_t bd_addr){
117caed94dfSMatthias Ringwald     strcpy(keypath, LINK_KEY_PATH);
118caed94dfSMatthias Ringwald     strcat(keypath, LINK_KEY_PREFIX);
1191624665aSMatthias Ringwald     strcat(keypath, bd_addr_to_dash_str(local_addr));
1201624665aSMatthias Ringwald     strcat(keypath, LINK_KEY_FOR);
121caed94dfSMatthias Ringwald     strcat(keypath, bd_addr_to_dash_str(bd_addr));
1221624665aSMatthias Ringwald     strcat(keypath, LINK_KEY_SUFFIX);
123caed94dfSMatthias Ringwald }
124caed94dfSMatthias Ringwald 
125caed94dfSMatthias Ringwald // Device info
db_open(void)126caed94dfSMatthias Ringwald static void db_open(void){
127caed94dfSMatthias Ringwald }
128caed94dfSMatthias Ringwald 
db_set_local_bd_addr(bd_addr_t bd_addr)1291624665aSMatthias Ringwald static void db_set_local_bd_addr(bd_addr_t bd_addr){
1301624665aSMatthias Ringwald     memcpy(local_addr, bd_addr, 6);
1311624665aSMatthias Ringwald }
1321624665aSMatthias Ringwald 
db_close(void)133caed94dfSMatthias Ringwald static void db_close(void){
134caed94dfSMatthias Ringwald }
135caed94dfSMatthias Ringwald 
put_link_key(bd_addr_t bd_addr,link_key_t link_key,link_key_type_t link_key_type)136caed94dfSMatthias Ringwald static void put_link_key(bd_addr_t bd_addr, link_key_t link_key, link_key_type_t link_key_type){
137caed94dfSMatthias Ringwald     set_path(bd_addr);
138caed94dfSMatthias Ringwald     char * link_key_str = link_key_to_str(link_key);
139caed94dfSMatthias Ringwald     char * link_key_type_str = link_key_type_to_str(link_key_type);
140caed94dfSMatthias Ringwald 
141caed94dfSMatthias Ringwald     FILE * wFile = fopen(keypath,"w+");
1428300a979SBjoern Hartmann     if (wFile == NULL){
1438300a979SBjoern Hartmann         log_error("failed to create file");
1448300a979SBjoern Hartmann         return;
1458300a979SBjoern Hartmann     }
146caed94dfSMatthias Ringwald     fwrite(link_key_str, strlen(link_key_str), 1, wFile);
147caed94dfSMatthias Ringwald     fwrite(link_key_type_str, strlen(link_key_type_str), 1, wFile);
148caed94dfSMatthias Ringwald     fclose(wFile);
149caed94dfSMatthias Ringwald }
150caed94dfSMatthias Ringwald 
read_link_key(const char * path,link_key_t link_key,link_key_type_t * link_key_type)151d08566fbSMatthias Ringwald static int read_link_key(const char * path, link_key_t link_key, link_key_type_t * link_key_type){
152d08566fbSMatthias Ringwald     if (access(path, R_OK)) return 0;
153caed94dfSMatthias Ringwald 
154caed94dfSMatthias Ringwald     char link_key_str[LINK_KEY_STR_LEN + 1];
155caed94dfSMatthias Ringwald     char link_key_type_str[2];
156caed94dfSMatthias Ringwald 
157d08566fbSMatthias Ringwald     FILE * rFile = fopen(path,"r+");
1588300a979SBjoern Hartmann     if (rFile == NULL) return 0;
159caed94dfSMatthias Ringwald     size_t objects_read = fread(link_key_str, LINK_KEY_STR_LEN, 1, rFile );
160caed94dfSMatthias Ringwald     if (objects_read == 1){
161caed94dfSMatthias Ringwald         link_key_str[LINK_KEY_STR_LEN] = 0;
162caed94dfSMatthias Ringwald         log_info("Found link key %s\n", link_key_str);
163caed94dfSMatthias Ringwald         objects_read = fread(link_key_type_str, 1, 1, rFile );
164caed94dfSMatthias Ringwald     }
165caed94dfSMatthias Ringwald     fclose(rFile);
166caed94dfSMatthias Ringwald 
167caed94dfSMatthias Ringwald     if (objects_read != 1) return 0;
168caed94dfSMatthias Ringwald     link_key_type_str[1] = 0;
169caed94dfSMatthias Ringwald     log_info("Found link key type %s\n", link_key_type_str);
170caed94dfSMatthias Ringwald 
171caed94dfSMatthias Ringwald     int scan_result = sscanf_link_key(link_key_str, link_key);
172caed94dfSMatthias Ringwald     if (scan_result == 0 ) return 0;
173caed94dfSMatthias Ringwald 
174caed94dfSMatthias Ringwald     int link_key_type_buffer;
175caed94dfSMatthias Ringwald     scan_result = sscanf( (char *) link_key_type_str, "%d", &link_key_type_buffer);
176caed94dfSMatthias Ringwald     if (scan_result == 0 ) return 0;
177caed94dfSMatthias Ringwald     *link_key_type = (link_key_type_t) link_key_type_buffer;
178caed94dfSMatthias Ringwald     return 1;
179caed94dfSMatthias Ringwald }
180caed94dfSMatthias Ringwald 
get_link_key(bd_addr_t bd_addr,link_key_t link_key,link_key_type_t * link_key_type)181d08566fbSMatthias Ringwald static int get_link_key(bd_addr_t bd_addr, link_key_t link_key, link_key_type_t * link_key_type) {
182d08566fbSMatthias Ringwald     set_path(bd_addr);
183d08566fbSMatthias Ringwald     return read_link_key(keypath, link_key, link_key_type);
184d08566fbSMatthias Ringwald }
185d08566fbSMatthias Ringwald 
delete_link_key(bd_addr_t bd_addr)186caed94dfSMatthias Ringwald static void delete_link_key(bd_addr_t bd_addr){
187caed94dfSMatthias Ringwald     set_path(bd_addr);
188caed94dfSMatthias Ringwald     if (access(keypath, R_OK)) return;
189caed94dfSMatthias Ringwald     if(remove(keypath) != 0){
190caed94dfSMatthias Ringwald         log_error("File %s could not be deleted.\n", keypath);
191caed94dfSMatthias Ringwald     }
192caed94dfSMatthias Ringwald }
193caed94dfSMatthias Ringwald 
iterator_init(btstack_link_key_iterator_t * it)194d08566fbSMatthias Ringwald static int iterator_init(btstack_link_key_iterator_t * it){
195d622dcd0SMatthias Ringwald     tinydir_dir * dir = (tinydir_dir *) malloc(sizeof(tinydir_dir));
196d08566fbSMatthias Ringwald     if (!dir) return 0;
197d08566fbSMatthias Ringwald     it->context = dir;
198d08566fbSMatthias Ringwald     tinydir_open(dir, LINK_KEY_PATH);
199d08566fbSMatthias Ringwald     return 1;
200d08566fbSMatthias Ringwald }
201d08566fbSMatthias Ringwald 
iterator_get_next(btstack_link_key_iterator_t * it,bd_addr_t bd_addr,link_key_t link_key,link_key_type_t * type)202d08566fbSMatthias Ringwald 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){
203d08566fbSMatthias Ringwald     (void)bd_addr;
204d08566fbSMatthias Ringwald     (void)link_key;
205d08566fbSMatthias Ringwald     UNUSED(type);
206d08566fbSMatthias Ringwald     tinydir_dir * dir = (tinydir_dir*) it->context;
207d08566fbSMatthias Ringwald 
208d08566fbSMatthias Ringwald     // construct prefix
209d08566fbSMatthias Ringwald     strcpy(keypath, LINK_KEY_PREFIX);
210d08566fbSMatthias Ringwald     strcat(keypath, bd_addr_to_dash_str(local_addr));
211d08566fbSMatthias Ringwald     strcat(keypath, LINK_KEY_FOR);
212d08566fbSMatthias Ringwald 
213d08566fbSMatthias Ringwald     while (dir->has_next) {
214d08566fbSMatthias Ringwald         tinydir_file file;
215d08566fbSMatthias Ringwald         tinydir_readfile(dir, &file);
216d08566fbSMatthias Ringwald         tinydir_next(dir);
217d08566fbSMatthias Ringwald         // compare
218d08566fbSMatthias Ringwald         if (strncmp(keypath, file.name, strlen(keypath)) == 0){
219d08566fbSMatthias Ringwald             // parse bd_addr
220d08566fbSMatthias Ringwald             const int addr_offset = sizeof(LINK_KEY_PREFIX) + LINK_KEY_STRING_LEN + sizeof(LINK_KEY_FOR) - 2;   // -1 for each sizeof
221d08566fbSMatthias Ringwald             sscanf_bd_addr(&file.name[addr_offset], bd_addr);
222d08566fbSMatthias Ringwald             // path found, read file
223d08566fbSMatthias Ringwald             strcpy(keypath, LINK_KEY_PATH);
224d08566fbSMatthias Ringwald             strcat(keypath, file.name);
225d08566fbSMatthias Ringwald             read_link_key(keypath, link_key, type);
226d08566fbSMatthias Ringwald             return 1;
227d08566fbSMatthias Ringwald         }
228d08566fbSMatthias Ringwald     }
229d08566fbSMatthias Ringwald     return 0;
230d08566fbSMatthias Ringwald }
231d08566fbSMatthias Ringwald 
iterator_done(btstack_link_key_iterator_t * it)232d08566fbSMatthias Ringwald static void iterator_done(btstack_link_key_iterator_t * it){
233d08566fbSMatthias Ringwald     tinydir_close((tinydir_dir*)it->context);
234d08566fbSMatthias Ringwald     free(it->context);
235d08566fbSMatthias Ringwald     it->context = NULL;
236d08566fbSMatthias Ringwald }
237d08566fbSMatthias Ringwald 
23858044c39SMatthias Ringwald static const btstack_link_key_db_t btstack_link_key_db_fs = {
2391624665aSMatthias Ringwald     &db_open,
2401624665aSMatthias Ringwald     &db_set_local_bd_addr,
2411624665aSMatthias Ringwald     &db_close,
2421624665aSMatthias Ringwald     &get_link_key,
2431624665aSMatthias Ringwald     &put_link_key,
2441624665aSMatthias Ringwald     &delete_link_key,
245d08566fbSMatthias Ringwald     &iterator_init,
246d08566fbSMatthias Ringwald     &iterator_get_next,
247d08566fbSMatthias Ringwald     &iterator_done,
248caed94dfSMatthias Ringwald };
249caed94dfSMatthias Ringwald 
btstack_link_key_db_fs_instance(void)250caed94dfSMatthias Ringwald const btstack_link_key_db_t * btstack_link_key_db_fs_instance(void){
251caed94dfSMatthias Ringwald     return &btstack_link_key_db_fs;
252caed94dfSMatthias Ringwald }
253caed94dfSMatthias Ringwald 
254caed94dfSMatthias Ringwald 
255