@@ -699,6 +699,7 @@ static void attach_node_reply(struct l_dbus_proxy *proxy,
ivi != iv_index) {
iv_index = ivi;
mesh_db_set_iv_index(ivi);
+ remote_clear_blacklisted_addresses(ivi);
}
return;
@@ -1823,6 +1824,7 @@ static void property_changed(struct l_dbus_proxy *proxy, const char *name,
iv_index = ivi;
mesh_db_set_iv_index(ivi);
+ remote_clear_blacklisted_addresses(ivi);
}
}
}
@@ -1255,6 +1255,143 @@ bool mesh_db_set_iv_index(uint32_t ivi)
return save_config();
}
+static int get_blacklisted_by_iv_index(json_object *jarray, uint32_t iv_index)
+{
+ int i, cnt;
+
+ cnt = json_object_array_length(jarray);
+
+ for (i = 0; i < cnt; i++) {
+ json_object *jentry;
+ int index;
+
+ jentry = json_object_array_get_idx(jarray, i);
+
+ if (!get_int(jentry, "ivIndex", &index))
+ continue;
+
+ if (iv_index == (uint32_t)index)
+ return i;
+ }
+
+ return -1;
+}
+
+static bool load_blacklisted(json_object *jobj)
+{
+ json_object *jarray;
+ int i, cnt;
+
+ json_object_object_get_ex(jobj, "blacklistedAddresses", &jarray);
+ if (!jarray || json_object_get_type(jarray) != json_type_array)
+ return true;
+
+ cnt = json_object_array_length(jarray);
+
+ for (i = 0; i < cnt; i++) {
+ json_object *jaddrs, *jentry, *jval;
+ int iv_index, addr_cnt, j;
+
+ jentry = json_object_array_get_idx(jarray, i);
+
+ if (!get_int(jentry, "ivIndex", &iv_index))
+ return false;
+
+ if (!json_object_object_get_ex(jentry, "addresses",
+ &jaddrs))
+ return false;
+
+ addr_cnt = json_object_array_length(jaddrs);
+
+ for (j = 0; j < addr_cnt; j++) {
+ const char *str;
+ uint16_t unicast;
+
+ jval = json_object_array_get_idx(jaddrs, j);
+ str = json_object_get_string(jval);
+
+ if (sscanf(str, "%04hx", &unicast) != 1)
+ return false;
+
+ remote_add_blacklisted_address(unicast, iv_index,
+ false);
+ }
+ }
+
+ return true;
+}
+
+bool mesh_db_add_blacklisted_addr(uint16_t unicast, uint32_t iv_index)
+{
+ json_object *jarray, *jobj, *jaddrs, *jstring;
+ int idx;
+ char buf[5];
+
+ if (!cfg || !cfg->jcfg)
+ return false;
+
+ json_object_object_get_ex(cfg->jcfg, "blacklistedAddresses", &jarray);
+ if (!jarray) {
+ jarray = json_object_new_array();
+ json_object_object_add(cfg->jcfg, "blacklistedAddresses",
+ jarray);
+ }
+
+ idx = get_blacklisted_by_iv_index(jarray, iv_index);
+
+ if (idx < 0) {
+ jobj = json_object_new_object();
+
+ if (!write_int(jobj, "ivIndex", iv_index))
+ goto fail;
+
+ jaddrs = json_object_new_array();
+ json_object_object_add(jobj, "addresses", jaddrs);
+
+ } else {
+ jobj = json_object_array_get_idx(jarray, idx);
+ }
+
+ json_object_object_get_ex(jobj, "addresses", &jaddrs);
+
+ snprintf(buf, 5, "%4.4x", unicast);
+ jstring = json_object_new_string(buf);
+ if (!jstring)
+ goto fail;
+
+ json_object_array_add(jaddrs, jstring);
+
+ if (idx < 0)
+ json_object_array_add(jarray, jobj);
+
+ return save_config();
+
+fail:
+ json_object_put(jobj);
+ return false;
+}
+
+bool mesh_db_clear_blacklisted(uint32_t iv_index)
+{
+ json_object *jarray;
+ int idx;
+
+ if (!cfg || !cfg->jcfg)
+ return false;
+
+ json_object_object_get_ex(cfg->jcfg, "blacklistedAddresses", &jarray);
+ if (!jarray || json_object_get_type(jarray) != json_type_array)
+ return false;
+
+ idx = get_blacklisted_by_iv_index(jarray, iv_index);
+ if (idx < 0)
+ return true;
+
+ json_object_array_del_idx(jarray, idx, 1);
+
+ return save_config();
+}
+
bool mesh_db_create(const char *fname, const uint8_t token[8],
const char *mesh_name)
{
@@ -1305,6 +1442,12 @@ bool mesh_db_create(const char *fname, const uint8_t token[8],
json_object_object_add(jcfg, "appKeys", jarray);
+ jarray = json_object_new_array();
+ if (!jarray)
+ goto fail;
+
+ json_object_object_add(jcfg, "blacklistedAddresses", jarray);
+
write_int(jcfg, "ivIndex", 0);
if (!save_config())
@@ -1370,6 +1513,8 @@ bool mesh_db_load(const char *fname)
load_remotes(jcfg);
+ load_blacklisted(jcfg);
+
return true;
fail:
release_config();
@@ -58,3 +58,5 @@ bool mesh_db_node_model_binding_del(uint16_t unicast, uint8_t ele, bool vendor,
uint32_t mod_id, uint16_t app_idx);
struct l_queue *mesh_db_load_groups(void);
bool mesh_db_add_group(struct mesh_group *grp);
+bool mesh_db_add_blacklisted_addr(uint16_t unicast, uint32_t iv_index);
+bool mesh_db_clear_blacklisted(uint32_t iv_index);
@@ -31,6 +31,8 @@
#include "tools/mesh/mesh-db.h"
#include "tools/mesh/remote.h"
+#define abs_diff(a, b) ((a) > (b) ? (a) - (b) : (b) - (a))
+
struct remote_node {
uint16_t unicast;
struct l_queue *net_keys;
@@ -40,8 +42,13 @@ struct remote_node {
uint8_t num_ele;
};
-static struct l_queue *nodes;
+struct blacklisted_addr {
+ uint32_t iv_index;
+ uint16_t unicast;
+};
+static struct l_queue *nodes;
+static struct l_queue *blacklisted;
static bool key_present(struct l_queue *keys, uint16_t app_idx)
{
@@ -115,6 +122,7 @@ uint8_t remote_del_node(uint16_t unicast)
{
struct remote_node *rmt;
uint8_t num_ele, i;
+ uint32_t iv_index = mesh_db_get_iv_index();
rmt = l_queue_remove_if(nodes, match_node_addr, L_UINT_TO_PTR(unicast));
if (!rmt)
@@ -122,9 +130,10 @@ uint8_t remote_del_node(uint16_t unicast)
num_ele = rmt->num_ele;
- for (i = 0; i < num_ele; ++i)
+ for (i = 0; i < num_ele; ++i) {
l_queue_destroy(rmt->els[i], NULL);
-
+ remote_add_blacklisted_address(unicast + i, iv_index, true);
+ }
l_free(rmt->els);
l_queue_destroy(rmt->net_keys, l_free);
@@ -331,6 +340,46 @@ static void print_node(void *rmt, void *user_data)
print_element(node->els[i], i);
}
+static bool match_black_addr(const void *a, const void *b)
+{
+ const struct blacklisted_addr *addr = a;
+ uint16_t unicast = L_PTR_TO_UINT(b);
+
+ return addr->unicast == unicast;
+}
+
+static uint16_t get_next_addr(uint16_t high, uint16_t addr,
+ uint8_t ele_cnt)
+{
+ while ((addr + ele_cnt - 1) <= high) {
+ int i = 0;
+
+ for (i = 0; i < ele_cnt; i++) {
+ struct blacklisted_addr *black;
+
+ black = l_queue_find(blacklisted, match_black_addr,
+ L_UINT_TO_PTR(addr + i));
+ if (!black)
+ break;
+ }
+
+ addr += i;
+
+ if ((i != ele_cnt) && (addr + ele_cnt - 1) <= high)
+ return addr;
+ }
+
+ return 0;
+}
+
+static bool check_iv_index(const void *a, const void *b)
+{
+ const struct blacklisted_addr *black_addr = a;
+ uint32_t iv_index = L_PTR_TO_UINT(b);
+
+ return (abs_diff(iv_index, black_addr->iv_index) > 2);
+}
+
void remote_print_node(uint16_t addr)
{
struct remote_node *rmt;
@@ -373,15 +422,56 @@ uint16_t remote_get_next_unicast(uint16_t low, uint16_t high, uint8_t ele_cnt)
for (; l; l = l->next) {
rmt = l->data;
- if (rmt->unicast >= (addr + ele_cnt))
- return addr;
+ if (rmt->unicast < low)
+ continue;
+
+ if (rmt->unicast >= (addr + ele_cnt)) {
+ uint16_t unicast;
- if ((rmt->unicast + rmt->num_ele) > addr)
- addr = rmt->unicast + rmt->num_ele;
+ unicast = get_next_addr(rmt->unicast - 1, addr,
+ ele_cnt);
+ if (unicast)
+ return unicast;
+ }
+
+ addr = rmt->unicast + rmt->num_ele;
}
- if ((addr + ele_cnt - 1) <= high)
- return addr;
+ addr = get_next_addr(high, addr, ele_cnt);
- return 0;
+ return addr;
+}
+
+void remote_add_blacklisted_address(uint16_t addr, uint32_t iv_index,
+ bool save)
+{
+ struct blacklisted_addr *black_addr;
+
+ if (!blacklisted)
+ blacklisted = l_queue_new();
+
+ black_addr = l_new(struct blacklisted_addr, 1);
+ black_addr->unicast = addr;
+ black_addr->iv_index = iv_index;
+
+ l_queue_push_tail(blacklisted, black_addr);
+
+ if (save)
+ mesh_db_add_blacklisted_addr(addr, iv_index);
+}
+
+void remote_clear_blacklisted_addresses(uint32_t iv_index)
+{
+ struct blacklisted_addr *black_addr;
+
+ black_addr = l_queue_remove_if(blacklisted, check_iv_index,
+ L_UINT_TO_PTR(iv_index));
+
+ while (black_addr) {
+ l_free(black_addr);
+ black_addr = l_queue_remove_if(blacklisted, check_iv_index,
+ L_UINT_TO_PTR(iv_index));
+ }
+
+ mesh_db_clear_blacklisted(iv_index);
}
@@ -22,6 +22,9 @@ bool remote_add_node(const uint8_t uuid[16], uint16_t unicast,
uint8_t remote_del_node(uint16_t unicast);
bool remote_set_model(uint16_t unicast, uint8_t ele_idx, uint32_t mod_id,
bool vendor);
+void remote_add_blacklisted_address(uint16_t addr, uint32_t iv_index,
+ bool save);
+void remote_clear_blacklisted_addresses(uint32_t iv_index);
uint16_t remote_get_next_unicast(uint16_t low, uint16_t high, uint8_t ele_cnt);
bool remote_add_net_key(uint16_t addr, uint16_t net_idx);
bool remote_del_net_key(uint16_t addr, uint16_t net_idx);