2020-06-20 04:45:44

by Stotland, Inga

[permalink] [raw]
Subject: [PATCH BlueZ 0/3] Blacklist addresses of deleted nodes

This patch set adds a notion of blacklisted addresses for nodes that
have been removed from mesh network.
The addresses of nodes that have been removed should not be added
back into available unicast addresses pool (for assigning to newly
provisioned nodes) until mesh-wide IV Index is changed at least twice

Inga Stotland (3):
mesh: Emit PropertiesChanged when IV Index changes
tools/mesh-cfgclient: get/set IV index
tools/mesh-cfgclient: add list of blacklisted addresses

mesh/net.c | 2 +
mesh/node.c | 9 +++
mesh/node.h | 1 +
tools/mesh-cfgclient.c | 41 +++++++++-
tools/mesh/mesh-db.c | 170 +++++++++++++++++++++++++++++++++++++++++
tools/mesh/mesh-db.h | 5 +-
tools/mesh/remote.c | 110 +++++++++++++++++++++++---
tools/mesh/remote.h | 3 +
8 files changed, 329 insertions(+), 12 deletions(-)

--
2.26.2


2020-06-20 04:45:45

by Stotland, Inga

[permalink] [raw]
Subject: [PATCH BlueZ 3/3] tools/mesh-cfgclient: add list of blacklisted addresses

This adds a concept of "blacklisted" addresses. that a provisioner is
not allowed to assign to newly added mesh nodes.
An address may be "blacklisted" is a node has been removed from the network
(e.g., after node reset procedure). This ensures that the addresses are not
reused for provisioning new nodes to prevent a potential communication
problem due to saved RPL entries associated with these addresses in the
rest of the mesh network. The address is "cleared", when IV index updates
at least twice.
---
tools/mesh-cfgclient.c | 2 +
tools/mesh/mesh-db.c | 145 +++++++++++++++++++++++++++++++++++++++++
tools/mesh/mesh-db.h | 2 +
tools/mesh/remote.c | 110 ++++++++++++++++++++++++++++---
tools/mesh/remote.h | 3 +
5 files changed, 252 insertions(+), 10 deletions(-)

diff --git a/tools/mesh-cfgclient.c b/tools/mesh-cfgclient.c
index da9f83c29..0dd02fad8 100644
--- a/tools/mesh-cfgclient.c
+++ b/tools/mesh-cfgclient.c
@@ -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);
}
}
}
diff --git a/tools/mesh/mesh-db.c b/tools/mesh/mesh-db.c
index dbeed0214..7f2d5b358 100644
--- a/tools/mesh/mesh-db.c
+++ b/tools/mesh/mesh-db.c
@@ -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();
diff --git a/tools/mesh/mesh-db.h b/tools/mesh/mesh-db.h
index 83fcfbee7..49af33e87 100644
--- a/tools/mesh/mesh-db.h
+++ b/tools/mesh/mesh-db.h
@@ -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);
diff --git a/tools/mesh/remote.c b/tools/mesh/remote.c
index 344de798b..2a8f747d6 100644
--- a/tools/mesh/remote.c
+++ b/tools/mesh/remote.c
@@ -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);
}
diff --git a/tools/mesh/remote.h b/tools/mesh/remote.h
index 33398c8bd..482817c5a 100644
--- a/tools/mesh/remote.h
+++ b/tools/mesh/remote.h
@@ -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);
--
2.26.2

2020-06-20 04:46:09

by Stotland, Inga

[permalink] [raw]
Subject: [PATCH BlueZ 2/3] tools/mesh-cfgclient: get/set IV index

This adds keeping track of IV index changes.
The updates are detected by observing PropertiesChanged signal
on local node's object path and reading "IvIndex" property
---
tools/mesh-cfgclient.c | 39 ++++++++++++++++++++++++++++++++++++++-
tools/mesh/mesh-db.c | 25 +++++++++++++++++++++++++
tools/mesh/mesh-db.h | 3 ++-
3 files changed, 65 insertions(+), 2 deletions(-)

diff --git a/tools/mesh-cfgclient.c b/tools/mesh-cfgclient.c
index fe82a8bbe..da9f83c29 100644
--- a/tools/mesh-cfgclient.c
+++ b/tools/mesh-cfgclient.c
@@ -144,6 +144,7 @@ static const char *range_opt;
static const char *net_idx_opt;
static const char *config_opt;

+static uint32_t iv_index;
static uint16_t low_addr;
static uint16_t high_addr;
static uint16_t prov_net_idx;
@@ -664,6 +665,7 @@ static void attach_node_reply(struct l_dbus_proxy *proxy,
{
struct meshcfg_node *node = user_data;
struct l_dbus_message_iter iter_cfg;
+ uint32_t ivi;

if (l_dbus_message_is_error(msg)) {
const char *name;
@@ -693,6 +695,12 @@ static void attach_node_reply(struct l_dbus_proxy *proxy,
/* Inititalize config client model */
client_init();

+ if (l_dbus_proxy_get_property(local->proxy, "IvIndex", "u", &ivi) &&
+ ivi != iv_index) {
+ iv_index = ivi;
+ mesh_db_set_iv_index(ivi);
+ }
+
return;

fail:
@@ -1792,6 +1800,33 @@ static struct l_dbus_message *join_complete(struct l_dbus *dbus,
return l_dbus_message_new_method_return(message);
}

+static void property_changed(struct l_dbus_proxy *proxy, const char *name,
+ struct l_dbus_message *msg, void *user_data)
+{
+ const char *interface = l_dbus_proxy_get_interface(proxy);
+ const char *path = l_dbus_proxy_get_path(proxy);
+
+ if (strcmp(path, local->path))
+ return;
+
+ bt_shell_printf("Property changed: %s %s %s\n", name, path, interface);
+
+ if (!strcmp(interface, "org.bluez.mesh.Node1")) {
+
+ if (!strcmp(name, "IvIndex")) {
+ uint32_t ivi;
+
+ if (!l_dbus_message_get_arguments(msg, "u", &ivi))
+ return;
+
+ bt_shell_printf("New IV Index: %u\n", ivi);
+
+ iv_index = ivi;
+ mesh_db_set_iv_index(ivi);
+ }
+ }
+}
+
static void setup_app_iface(struct l_dbus_interface *iface)
{
l_dbus_interface_property(iface, "CompanyID", 0, "q", cid_getter,
@@ -1974,6 +2009,8 @@ static bool read_mesh_config(void)
high_addr = range_h;
}

+ iv_index = mesh_db_get_iv_index();
+
return true;
}

@@ -2040,7 +2077,7 @@ int main(int argc, char *argv[])
l_dbus_client_set_disconnect_handler(client, client_disconnected, NULL,
NULL);
l_dbus_client_set_proxy_handlers(client, proxy_added, proxy_removed,
- NULL, NULL, NULL);
+ property_changed, NULL, NULL);
l_dbus_client_set_ready_handler(client, client_ready, NULL, NULL);

node_proxies = l_queue_new();
diff --git a/tools/mesh/mesh-db.c b/tools/mesh/mesh-db.c
index b789c3933..dbeed0214 100644
--- a/tools/mesh/mesh-db.c
+++ b/tools/mesh/mesh-db.c
@@ -1232,6 +1232,29 @@ bool mesh_db_set_addr_range(uint16_t low, uint16_t high)
return save_config();
}

+uint32_t mesh_db_get_iv_index(void)
+{
+ int ivi;
+
+ if (!cfg || !cfg->jcfg)
+ return 0;
+
+ if (!get_int(cfg->jcfg, "ivIndex", &ivi))
+ return 0;
+
+ return (uint32_t) ivi;
+}
+
+bool mesh_db_set_iv_index(uint32_t ivi)
+{
+ if (!cfg || !cfg->jcfg)
+ return false;
+
+ write_int(cfg->jcfg, "ivIndex", ivi);
+
+ return save_config();
+}
+
bool mesh_db_create(const char *fname, const uint8_t token[8],
const char *mesh_name)
{
@@ -1282,6 +1305,8 @@ bool mesh_db_create(const char *fname, const uint8_t token[8],

json_object_object_add(jcfg, "appKeys", jarray);

+ write_int(jcfg, "ivIndex", 0);
+
if (!save_config())
goto fail;

diff --git a/tools/mesh/mesh-db.h b/tools/mesh/mesh-db.h
index 89c644400..83fcfbee7 100644
--- a/tools/mesh/mesh-db.h
+++ b/tools/mesh/mesh-db.h
@@ -26,7 +26,8 @@ bool mesh_db_create(const char *fname, const uint8_t token[8],
bool mesh_db_load(const char *fname);

bool mesh_db_get_token(uint8_t token[8]);
-
+bool mesh_db_set_iv_index(uint32_t ivi);
+uint32_t mesh_db_get_iv_index(void);
bool mesh_db_net_key_add(uint16_t idx);
bool mesh_db_net_key_del(uint16_t idx);
bool mesh_db_net_key_phase_set(uint16_t net_idx, uint8_t phase);
--
2.26.2

2020-06-20 04:47:59

by Stotland, Inga

[permalink] [raw]
Subject: [PATCH BlueZ 1/3] mesh: Emit PropertiesChanged when IV Index changes

This adds emitting of PropertiesChanged signal whenever the
mesh IV index is updated to indicate that the vlaues of "IvIndex"
property has been modified.
---
mesh/net.c | 2 ++
mesh/node.c | 9 +++++++++
mesh/node.h | 1 +
3 files changed, 12 insertions(+)

diff --git a/mesh/net.c b/mesh/net.c
index 3ab948be5..b54c647cb 100644
--- a/mesh/net.c
+++ b/mesh/net.c
@@ -2566,6 +2566,8 @@ static void update_iv_ivu_state(struct mesh_net *net, uint32_t iv_index,
rpl_init(net->node, iv_index);
}

+ node_property_changed(net->node, "IVIndex");
+
net->iv_index = iv_index;
net->iv_update = ivu;
}
diff --git a/mesh/node.c b/mesh/node.c
index cf4d93aec..ee6d1833f 100644
--- a/mesh/node.c
+++ b/mesh/node.c
@@ -2280,6 +2280,15 @@ static void setup_node_interface(struct l_dbus_interface *iface)
NULL);
}

+void node_property_changed(struct mesh_node *node, const char *property)
+{
+ struct l_dbus *bus = dbus_get_bus();
+
+ if (bus)
+ l_dbus_property_changed(dbus_get_bus(), node->obj_path,
+ MESH_NODE_INTERFACE, property);
+}
+
bool node_dbus_init(struct l_dbus *bus)
{
if (!l_dbus_register_interface(bus, MESH_NODE_INTERFACE,
diff --git a/mesh/node.h b/mesh/node.h
index b8b2b1b49..6c4542a78 100644
--- a/mesh/node.h
+++ b/mesh/node.h
@@ -99,3 +99,4 @@ struct mesh_agent *node_get_agent(struct mesh_node *node);
const char *node_get_storage_dir(struct mesh_node *node);
bool node_load_from_storage(const char *storage_dir);
void node_finalize_new_node(struct mesh_node *node, struct mesh_io *io);
+void node_property_changed(struct mesh_node *node, const char *property);
--
2.26.2

2020-06-22 21:40:22

by Gix, Brian

[permalink] [raw]
Subject: Re: [PATCH BlueZ 0/3] Blacklist addresses of deleted nodes

Patchset Applied
On Fri, 2020-06-19 at 14:26 -0700, Inga Stotland wrote:
> This patch set adds a notion of blacklisted addresses for nodes that
> have been removed from mesh network.
> The addresses of nodes that have been removed should not be added
> back into available unicast addresses pool (for assigning to newly
> provisioned nodes) until mesh-wide IV Index is changed at least twice
>
> Inga Stotland (3):
> mesh: Emit PropertiesChanged when IV Index changes
> tools/mesh-cfgclient: get/set IV index
> tools/mesh-cfgclient: add list of blacklisted addresses
>
> mesh/net.c | 2 +
> mesh/node.c | 9 +++
> mesh/node.h | 1 +
> tools/mesh-cfgclient.c | 41 +++++++++-
> tools/mesh/mesh-db.c | 170 +++++++++++++++++++++++++++++++++++++++++
> tools/mesh/mesh-db.h | 5 +-
> tools/mesh/remote.c | 110 +++++++++++++++++++++++---
> tools/mesh/remote.h | 3 +
> 8 files changed, 329 insertions(+), 12 deletions(-)
>