#include "mesh/mesh-config.h"
#include "mesh/model.h"
#include "mesh/appkey.h"
+#include "mesh/rpl.h"
#define abs_diff(a, b) ((a) > (b) ? (a) - (b) : (b) - (a))
bool processed;
};
-struct mesh_rpl {
- uint32_t iv_index;
- uint32_t seq;
- uint16_t src;
-};
-
#define FAST_CACHE_SIZE 8
static struct l_queue *fast_cache;
static struct l_queue *nets;
struct mesh_config *cfg = node_config_get(net->node);
mesh_config_write_iv_index(cfg, iv_index, ivu);
+
+ /* Cleanup Replay Protection List NVM */
+ rpl_init(net->node, iv_index);
}
net->iv_index = iv_index;
if (!net || !net->node)
return true;
- if (!net->replay_cache)
+ if (!net->replay_cache) {
net->replay_cache = l_queue_new();
+ rpl_init(net->node, net->iv_index);
+ rpl_get_list(net->node, net->replay_cache);
+ }
l_debug("Test Replay src: %4.4x seq: %6.6x iv: %8.8x",
src, seq, iv_index);
if (iv_index > rpe->iv_index) {
rpe->seq = seq;
rpe->iv_index = iv_index;
+ rpl_put_entry(net->node, src, iv_index, seq);
return false;
}
rpe->seq = seq;
+ rpl_put_entry(net->node, src, iv_index, seq);
+
return false;
}
return true;
}
+ if (!rpl_put_entry(net->node, src, iv_index, seq))
+ return true;
+
rpe = l_new(struct mesh_rpl, 1);
rpe->src = src;
rpe->seq = seq;
--- /dev/null
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2020 Intel Corporation. All rights reserved.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifndef TIZEN_FEATURE_BLUEZ_MODIFY
+#define _GNU_SOURCE
+#endif
+
+#include <fcntl.h>
+#include <limits.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <dirent.h>
+
+#include <sys/stat.h>
+
+#include <ell/ell.h>
+
+#include "mesh/mesh-defs.h"
+
+#include "mesh/node.h"
+#include "mesh/net.h"
+#include "mesh/util.h"
+#include "mesh/rpl.h"
+
+const char *rpl_dir = "/rpl";
+
+bool rpl_put_entry(struct mesh_node *node, uint16_t src, uint32_t iv_index,
+ uint32_t seq)
+{
+ const char *node_path;
+ char src_file[PATH_MAX];
+ char seq_txt[7];
+ bool result = false;
+ DIR *dir;
+ int fd;
+
+ if (!node || !IS_UNICAST(src))
+ return false;
+
+ node_path = node_get_storage_dir(node);
+
+ if (strlen(node_path) + strlen(rpl_dir) + 15 >= PATH_MAX)
+ return false;
+
+ snprintf(src_file, PATH_MAX, "%s%s/%8.8x", node_path, rpl_dir,
+ iv_index);
+ dir = opendir(src_file);
+
+ if (!dir)
+ mkdir(src_file, 0755);
+ else
+ closedir(dir);
+
+ snprintf(src_file, PATH_MAX, "%s%s/%8.8x/%4.4x", node_path, rpl_dir,
+ iv_index, src);
+
+ fd = open(src_file, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
+ if (fd >= 0) {
+ snprintf(seq_txt, 7, "%6.6x", seq);
+ if (write(fd, seq_txt, 6) == 6)
+ result = true;
+
+ close(fd);
+ }
+
+ if (!result)
+ return false;
+
+ /* Delete RPL entry from old iv_index (if it exists) */
+ iv_index--;
+ snprintf(src_file, PATH_MAX, "%s%s/%8.8x/%4.4x", node_path, rpl_dir,
+ iv_index, src);
+ remove(src_file);
+
+
+ return result;
+}
+
+void rpl_del_entry(struct mesh_node *node, uint16_t src)
+{
+ const char *node_path;
+ char rpl_path[PATH_MAX];
+ struct dirent *entry;
+ DIR *dir;
+
+ if (!node || !IS_UNICAST(src))
+ return;
+
+ node_path = node_get_storage_dir(node);
+
+ if (strlen(node_path) + strlen(rpl_dir) + 15 >= PATH_MAX)
+ return;
+
+ snprintf(rpl_path, PATH_MAX, "%s%s", node_path, rpl_dir);
+ dir = opendir(rpl_path);
+
+ if (!dir)
+ return;
+
+ /* Remove all instances of src address */
+ while ((entry = readdir(dir)) != NULL) {
+ if (entry->d_type == DT_DIR && entry->d_name[0] != '.') {
+ snprintf(rpl_path, PATH_MAX, "%s%s/%s/%4.4x",
+ node_path, rpl_dir, entry->d_name, src);
+ remove(rpl_path);
+ }
+ }
+
+ closedir(dir);
+}
+
+static bool match_src(const void *a, const void *b)
+{
+ const struct mesh_rpl *rpl = a;
+ uint16_t src = L_PTR_TO_UINT(b);
+
+ return rpl->src == src;
+}
+
+static void get_entries(const char *iv_path, struct l_queue *rpl_list)
+{
+ struct mesh_rpl *rpl;
+ struct dirent *entry;
+ DIR *dir;
+ int fd;
+ const char *iv_txt;
+ char src_path[PATH_MAX];
+ char seq_txt[7];
+ uint32_t iv_index, seq;
+ uint16_t src;
+
+ dir = opendir(iv_path);
+
+ if (!dir)
+ return;
+
+ iv_txt = basename(iv_path);
+ if (sscanf(iv_txt, "%08x", &iv_index) != 1)
+ return;
+
+ memset(seq_txt, 0, sizeof(seq_txt));
+
+ while ((entry = readdir(dir)) != NULL) {
+ /* RPL sequences are stored in src files under iv_index */
+ if (entry->d_type == DT_REG) {
+ if (sscanf(entry->d_name, "%04hx", &src) != 1)
+ continue;
+
+ snprintf(src_path, PATH_MAX, "%s/%4.4x", iv_path, src);
+ fd = open(src_path, O_RDONLY);
+
+ if (fd < 0)
+ continue;
+
+ if (read(fd, seq_txt, 6) == 6 &&
+ sscanf(seq_txt, "%06x", &seq) == 1) {
+
+ rpl = l_queue_find(rpl_list, match_src,
+ L_UINT_TO_PTR(src));
+
+ if (rpl) {
+ /* Replace older entries */
+ if (rpl->iv_index < iv_index) {
+ rpl->iv_index = iv_index;
+ rpl->seq = seq;
+ }
+ } else if (seq <= SEQ_MASK && IS_UNICAST(src)) {
+ rpl = l_new(struct mesh_rpl, 1);
+ rpl->src = src;
+ rpl->iv_index = iv_index;
+ rpl->seq = seq;
+
+ l_queue_push_head(rpl_list, rpl);
+ }
+ }
+ close(fd);
+ }
+ }
+
+ closedir(dir);
+}
+
+bool rpl_get_list(struct mesh_node *node, struct l_queue *rpl_list)
+{
+ const char *node_path;
+ struct dirent *entry;
+ char *rpl_path;
+ size_t len;
+ DIR *dir;
+
+ if (!node || !rpl_list)
+ return false;
+
+ node_path = node_get_storage_dir(node);
+
+ len = strlen(node_path) + strlen(rpl_dir) + 14;
+
+ if (len > PATH_MAX)
+ return false;
+
+ rpl_path = l_malloc(len);
+ snprintf(rpl_path, len, "%s%s", node_path, rpl_dir);
+
+ dir = opendir(rpl_path);
+
+ if (!dir) {
+ l_error("Failed to read RPL dir: %s", rpl_path);
+ l_free(rpl_path);
+ return false;
+ }
+
+ while ((entry = readdir(dir)) != NULL) {
+ /* RPL sequences are stored in files under iv_indexs */
+ if (entry->d_type == DT_DIR && entry->d_name[0] != '.') {
+ snprintf(rpl_path, len, "%s%s/%s",
+ node_path, rpl_dir, entry->d_name);
+ get_entries(rpl_path, rpl_list);
+ }
+ }
+
+ l_free(rpl_path);
+ closedir(dir);
+
+ return true;
+}
+
+void rpl_init(struct mesh_node *node, uint32_t cur)
+{
+ uint32_t old = cur - 1;
+ const char *node_path;
+ struct dirent *entry;
+ char path[PATH_MAX];
+ DIR *dir;
+
+ if (!node)
+ return;
+
+ node_path = node_get_storage_dir(node);
+
+ if (strlen(node_path) + strlen(rpl_dir) + 10 >= PATH_MAX)
+ return;
+
+ /* Make sure path exists */
+ snprintf(path, PATH_MAX, "%s%s", node_path, rpl_dir);
+ mkdir(path, 0755);
+
+ dir = opendir(path);
+ if (!dir)
+ return;
+
+ /* Cleanup any stale or malformed trees */
+ while ((entry = readdir(dir)) != NULL) {
+ if (entry->d_type == DT_DIR && entry->d_name[0] != '.') {
+ uint32_t val;
+ bool del = false;
+
+ if (strlen(entry->d_name) != 8)
+ del = true;
+ else if (sscanf(entry->d_name, "%08x", &val) != 1)
+ del = true;
+
+ /* Delete all invalid iv_index trees */
+ if (del || (val != cur && val != old)) {
+ snprintf(path, PATH_MAX, "%s%s/%s",
+ node_path, rpl_dir, entry->d_name);
+ del_path(path);
+ }
+ }
+ }
+
+ closedir(dir);
+}