diff options
-rw-r--r-- | hcid/hcid.h | 1 | ||||
-rw-r--r-- | hcid/security.c | 4 | ||||
-rw-r--r-- | hcid/storage.c | 178 |
3 files changed, 180 insertions, 3 deletions
diff --git a/hcid/hcid.h b/hcid/hcid.h index 845e3889..bcc43e4a 100644 --- a/hcid/hcid.h +++ b/hcid/hcid.h @@ -111,3 +111,4 @@ gboolean hcid_dbus_init(void); #endif int write_device_name(const bdaddr_t *local, const bdaddr_t *peer, const char *name); +int write_link_key(const bdaddr_t *local, const bdaddr_t *peer, const unsigned char *key, const int type); diff --git a/hcid/security.c b/hcid/security.c index f0bf12bd..92353373 100644 --- a/hcid/security.c +++ b/hcid/security.c @@ -193,6 +193,8 @@ static void link_key_notify(int dev, bdaddr_t *sba, void *ptr) key.time = time(0); save_link_key(&key); + + write_link_key(sba, dba, evt->link_key, evt->key_type); } /* PIN code handling */ @@ -386,7 +388,7 @@ static void remote_name_information(int dev, bdaddr_t *sba, void *ptr) evt_remote_name_req_complete *evt = ptr; bdaddr_t *dba = &evt->bdaddr; - if (!evt->status) + if (evt->status) return; write_device_name(sba, dba, evt->name); diff --git a/hcid/storage.c b/hcid/storage.c index cd04b254..a025e674 100644 --- a/hcid/storage.c +++ b/hcid/storage.c @@ -34,15 +34,189 @@ #include <stdio.h> #include <errno.h> +#include <fcntl.h> +#include <unistd.h> +#include <malloc.h> +#include <syslog.h> +#include <sys/file.h> +#include <sys/stat.h> #include <sys/socket.h> #include <bluetooth/bluetooth.h> #include "hcid.h" -#define DEVPATH "/etc/bluetooth/devices" +#define DEVPATH "/var/cache/bluetooth/" + +struct name_list { + bdaddr_t bdaddr; + char name[249]; + struct name_list *next; +}; + +static struct name_list *name_add(struct name_list *list, const bdaddr_t *bdaddr, const char *name) +{ + struct name_list *temp = list, *last = list; + + if (!bacmp(bdaddr, BDADDR_ANY)) + return list; + + while (temp) { + if (!bacmp(&temp->bdaddr, bdaddr)) { + memcpy(temp->name, name, sizeof(temp->name)); + return list; + } + temp = temp->next; + } + + temp = malloc(sizeof(*temp)); + if (!temp) + return list; + + memset(temp, 0, sizeof(*temp)); + + bacpy(&temp->bdaddr, bdaddr); + memcpy(temp->name, name, sizeof(temp->name)); + temp->next = NULL; + + if (!list) + return temp; + + while (last->next) + last = last->next; + + last->next = temp; + + return list; +} + +static struct name_list *name_free(struct name_list *list) +{ + struct name_list *temp = list; + + if (!list) + return NULL; + + while (list->next) { + temp = list; + list = list->next; + free(temp); + } + + return NULL; +} + +#define name_foreach(list, entry) \ + for (entry = list; entry; entry = entry->next) + +static int create_dirs(const char *filename, mode_t mode) +{ + struct stat st; + char dir[PATH_MAX + 1], *prev, *next; + int err; + + err = stat(filename, &st); + if (!err && S_ISREG(st.st_mode)) + return 0; + + memset(dir, 0, PATH_MAX + 1); + strcat(dir, "/"); + + prev = strchr(filename, '/'); + + while (prev) { + next = strchr(prev + 1, '/'); + if (!next) + break; + + if (next - prev == 1) { + prev = next; + continue; + } + + strncat(dir, prev + 1, next - prev); + mkdir(dir, mode); + + prev = next; + } + + return 0; +} int write_device_name(const bdaddr_t *local, const bdaddr_t *peer, const char *name) { - return -EIO; + struct name_list *temp, *list = NULL; + mode_t mode = S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH; + mode_t mask = S_IWGRP | S_IWOTH; + char filename[PATH_MAX + 1]; + char addr[18], str[249], *buf, *ptr; + bdaddr_t bdaddr; + struct stat st; + int fd, pos, err = 0; + + ba2str(local, addr); + snprintf(filename, PATH_MAX, "%s/%s/names", DEVPATH, addr); + + umask(mask); + create_dirs(filename, mode); + + fd = open(filename, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); + if (fd < 0) + return -errno; + + if (flock(fd, LOCK_EX) < 0) { + err = -errno; + goto close; + } + + if (fstat(fd, &st) < 0) { + err = -errno; + goto unlock; + } + + buf = malloc(st.st_size + 200); + if (!buf) { + err = -ENOMEM; + goto unlock; + } + + if (st.st_size > 0) { + read(fd, buf, st.st_size); + + ptr = buf; + + while (sscanf(ptr, "%17s %[^\n]\n%n", addr, str, &pos) != EOF) { + str2ba(addr, &bdaddr); + list = name_add(list, &bdaddr, str); + ptr += pos; + }; + + lseek(fd, 0, SEEK_SET); + ftruncate(fd, 0); + } + + list = name_add(list, peer, name); + if (!list) { + err = -EIO; + goto unlock; + } + + name_foreach(list, temp) { + ba2str(&temp->bdaddr, addr); + snprintf(buf, 200, "%s %s\n", addr, temp->name); + write(fd, buf, strlen(buf)); + } + +unlock: + flock(fd, LOCK_UN); + +close: + close(fd); + name_free(list); + return err; +} + +int write_link_key(const bdaddr_t *local, const bdaddr_t *peer, const unsigned char *key, const int type) +{ + return 0; } |