tools/mesh-cfgclient: add list of blacklisted addresses
authorInga Stotland <inga.stotland@intel.com>
Fri, 19 Jun 2020 21:26:55 +0000 (14:26 -0700)
committerAbhay Agarwal <ay.agarwal@samsung.com>
Mon, 28 Dec 2020 06:20:04 +0000 (11:50 +0530)
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.

Change-Id: I672c71cd18d6fc987a8ee3f8d27514b752b925e0
Signed-off-by: anuj.bhumiya <anuj.bhumiya@samsung.com>
tools/mesh-cfgclient.c
tools/mesh/mesh-db.c
tools/mesh/mesh-db.h
tools/mesh/remote.c
tools/mesh/remote.h

index 28506de..88fa95c 100644 (file)
@@ -701,6 +701,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;
@@ -1825,6 +1826,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);
                }
        }
 }
index 93a896c..a10c846 100644 (file)
@@ -1257,6 +1257,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)
 {
@@ -1307,6 +1444,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())
@@ -1372,6 +1515,8 @@ bool mesh_db_load(const char *fname)
 
        load_remotes(jcfg);
 
+       load_blacklisted(jcfg);
+
        return true;
 fail:
        release_config();
index 83fcfbe..49af33e 100644 (file)
@@ -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);
index 344de79..2a8f747 100644 (file)
@@ -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);
 }
index 33398c8..482817c 100644 (file)
@@ -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);