@@ -447,13 +447,12 @@ static bool msg_recvd(uint16_t src, uint16_t idx, uint8_t *data,
if (!cmd)
break;
- if (cmd->opcode == OP_APPKEY_ADD) {
- if (remote_add_app_key(src, app_idx))
- mesh_db_node_app_key_add(src, app_idx);
- } else if (cmd->opcode == OP_APPKEY_DELETE) {
- if (remote_del_app_key(src, app_idx))
- mesh_db_node_app_key_del(src, app_idx);
- }
+ if (cmd->opcode == OP_APPKEY_ADD)
+ remote_add_app_key(src, app_idx, true);
+ else if (cmd->opcode == OP_APPKEY_DELETE)
+ remote_del_app_key(src, app_idx);
+ else if (cmd->opcode == OP_APPKEY_UPDATE)
+ remote_update_app_key(src, app_idx, true, true);
break;
@@ -492,13 +491,12 @@ static bool msg_recvd(uint16_t src, uint16_t idx, uint8_t *data,
if (!cmd)
break;
- if (cmd->opcode == OP_NETKEY_ADD) {
- if (remote_add_net_key(src, net_idx))
- mesh_db_node_net_key_add(src, net_idx);
- } else if (cmd->opcode == OP_NETKEY_DELETE) {
- if (remote_del_net_key(src, net_idx))
- mesh_db_node_net_key_del(src, net_idx);
- }
+ if (cmd->opcode == OP_NETKEY_ADD)
+ remote_add_net_key(src, net_idx, true);
+ else if (cmd->opcode == OP_NETKEY_DELETE)
+ remote_del_net_key(src, net_idx);
+ else if (cmd->opcode == OP_NETKEY_UPDATE)
+ remote_update_net_key(src, net_idx, true, true);
break;
@@ -534,6 +532,13 @@ static bool msg_recvd(uint16_t src, uint16_t idx, uint8_t *data,
bt_shell_printf("\tNetKey %u (0x%3.3x)\n", net_idx, net_idx);
bt_shell_printf("\tKR Phase %2.2x\n", data[3]);
+
+ if (data[0] != MESH_STATUS_SUCCESS)
+ return true;
+
+ if (data[3] == KEY_REFRESH_PHASE_NONE)
+ remote_finish_key_refresh(src, net_idx);
+
break;
case OP_MODEL_APP_STATUS:
@@ -200,6 +200,38 @@ static bool write_int(json_object *jobj, const char *keyword, int val)
return true;
}
+static bool get_bool(json_object *jobj, const char *keyword, bool *value)
+{
+ json_object *jvalue;
+
+ if (!json_object_object_get_ex(jobj, keyword, &jvalue))
+ return false;
+
+ if (json_object_get_type(jvalue) != json_type_boolean) {
+ l_error("Error: %s should contain a boolean value\n",
+ keyword);
+ return false;
+ }
+
+ *value = json_object_get_boolean(jvalue);
+
+ return true;
+}
+
+static bool write_bool(json_object *jobj, const char *keyword, bool val)
+{
+ json_object *jval;
+
+ json_object_object_del(jobj, keyword);
+
+ jval = json_object_new_boolean(val);
+ if (!jval)
+ return false;
+
+ json_object_object_add(jobj, keyword, jval);
+ return true;
+}
+
static json_object *get_key_object(json_object *jarray, uint16_t idx)
{
int i, sz = json_object_array_length(jarray);
@@ -347,6 +379,20 @@ static uint16_t node_parse_key(json_object *jarray, int i)
return (uint16_t)idx;
}
+static bool node_check_key_updated(json_object *jarray, int i, bool *updated)
+{
+ json_object *jkey;
+
+ jkey = json_object_array_get_idx(jarray, i);
+ if (!jkey)
+ return false;
+
+ if (!get_bool(jkey, "updated", updated))
+ return false;
+
+ return true;
+}
+
static int compare_group_addr(const void *a, const void *b, void *user_data)
{
const struct mesh_group *grp0 = a;
@@ -483,10 +529,17 @@ static void load_remotes(json_object *jcfg)
remote_add_node((const uint8_t *)uuid, unicast, ele_cnt,
key_idx);
for (j = 1; j < key_cnt; j++) {
+ bool updated = false;
+
key_idx = node_parse_key(jarray, j);
- if (key_idx != KEY_IDX_INVALID)
- remote_add_net_key(unicast, key_idx);
+ if (key_idx == KEY_IDX_INVALID)
+ continue;
+
+ remote_add_net_key(unicast, key_idx, false);
+
+ node_check_key_updated(jarray, j, &updated);
+ remote_update_net_key(unicast, key_idx, updated, false);
}
json_object_object_get_ex(jnode, "appKeys", &jarray);
@@ -496,10 +549,17 @@ static void load_remotes(json_object *jcfg)
key_cnt = json_object_array_length(jarray);
for (j = 0; j < key_cnt; j++) {
+ bool updated = false;
+
key_idx = node_parse_key(jarray, j);
- if (key_idx != KEY_IDX_INVALID)
- remote_add_app_key(unicast, key_idx);
+ if (key_idx == KEY_IDX_INVALID)
+ continue;
+
+ remote_add_app_key(unicast, key_idx, false);
+
+ node_check_key_updated(jarray, j, &updated);
+ remote_update_app_key(unicast, key_idx, updated, false);
}
load_composition(jnode, unicast);
@@ -554,28 +614,19 @@ static bool add_node_key(json_object *jobj, const char *desc, uint16_t idx)
jkey = json_object_new_object();
- if (!write_int(jkey, "index", (int)idx)) {
- json_object_put(jkey);
- return false;
- }
+ if (!write_int(jkey, "index", (int)idx))
+ goto fail;
+
+ if (!write_bool(jkey, "updated", false))
+ goto fail;
json_object_array_add(jarray, jkey);
return save_config();
-}
-
-bool mesh_db_node_net_key_add(uint16_t unicast, uint16_t idx)
-{
- json_object *jnode;
-
- if (!cfg || !cfg->jcfg)
- return false;
- jnode = get_node_by_unicast(unicast);
- if (!jnode)
- return false;
-
- return add_node_key(jnode, "netKeys", idx);
+fail:
+ json_object_put(jkey);
+ return false;
}
bool mesh_db_node_ttl_set(uint16_t unicast, uint8_t ttl)
@@ -628,6 +679,20 @@ static bool delete_key(json_object *jobj, const char *desc, uint16_t idx)
return save_config();
}
+bool mesh_db_node_net_key_add(uint16_t unicast, uint16_t idx)
+{
+ json_object *jnode;
+
+ if (!cfg || !cfg->jcfg)
+ return false;
+
+ jnode = get_node_by_unicast(unicast);
+ if (!jnode)
+ return false;
+
+ return add_node_key(jnode, "netKeys", idx);
+}
+
bool mesh_db_node_net_key_del(uint16_t unicast, uint16_t net_idx)
{
json_object *jnode;
@@ -642,6 +707,45 @@ bool mesh_db_node_net_key_del(uint16_t unicast, uint16_t net_idx)
return delete_key(jnode, "netKeys", net_idx);
}
+static bool key_update(uint16_t unicast, int16_t idx, bool updated,
+ const char *desc)
+{
+ json_object *jnode, *jarray;
+ int i, sz;
+
+ if (!cfg || !cfg->jcfg)
+ return false;
+
+ jnode = get_node_by_unicast(unicast);
+ if (!jnode)
+ return false;
+
+ if (!json_object_object_get_ex(jnode, desc, &jarray))
+ return false;
+
+ sz = json_object_array_length(jarray);
+
+ for (i = 0; i < sz; ++i) {
+ json_object *jentry;
+ int val;
+
+ jentry = json_object_array_get_idx(jarray, i);
+
+ if (!get_int(jentry, "index", &val))
+ continue;
+
+ if ((val == idx) && write_bool(jentry, "updated", updated))
+ return save_config();
+ }
+
+ return false;
+}
+
+bool mesh_db_node_net_key_update(uint16_t unicast, uint16_t idx, bool updated)
+{
+ return key_update(unicast, idx, updated, "netKeys");
+}
+
bool mesh_db_node_app_key_add(uint16_t unicast, uint16_t idx)
{
json_object *jnode;
@@ -670,6 +774,11 @@ bool mesh_db_node_app_key_del(uint16_t unicast, uint16_t idx)
return delete_key(jnode, "appKeys", idx);
}
+bool mesh_db_node_app_key_update(uint16_t unicast, uint16_t idx, bool updated)
+{
+ return key_update(unicast, idx, updated, "appKeys");
+}
+
static bool load_keys(json_object *jobj)
{
json_object *jarray, *jentry;
@@ -38,8 +38,10 @@ bool mesh_db_node_set_net_transmit(uint16_t unicast, uint8_t cnt,
uint16_t interval);
bool mesh_db_node_net_key_add(uint16_t unicast, uint16_t idx);
bool mesh_db_node_net_key_del(uint16_t unicast, uint16_t idx);
+bool mesh_db_node_net_key_update(uint16_t unicast, uint16_t idx, bool updated);
bool mesh_db_node_app_key_add(uint16_t unicast, uint16_t idx);
bool mesh_db_node_app_key_del(uint16_t unicast, uint16_t idx);
+bool mesh_db_node_app_key_update(uint16_t unicast, uint16_t idx, bool updated);
bool mesh_db_node_ttl_set(uint16_t unicast, uint8_t ttl);
bool mesh_db_node_write_mode(uint16_t unicast, const char *keyword, int value);
bool mesh_db_node_model_binding_add(uint16_t unicast, uint8_t ele, bool vendor,
@@ -25,6 +25,11 @@
#define abs_diff(a, b) ((a) > (b) ? (a) - (b) : (b) - (a))
+struct remote_key {
+ uint16_t idx;
+ bool updated;
+};
+
struct remote_node {
uint16_t unicast;
struct l_queue *net_keys;
@@ -42,20 +47,6 @@ struct rejected_addr {
static struct l_queue *nodes;
static struct l_queue *reject_list;
-static bool key_present(struct l_queue *keys, uint16_t app_idx)
-{
- const struct l_queue_entry *l;
-
- for (l = l_queue_get_entries(keys); l; l = l->next) {
- uint16_t idx = L_PTR_TO_UINT(l->data);
-
- if (idx == app_idx)
- return true;
- }
-
- return false;
-}
-
static int compare_mod_id(const void *a, const void *b, void *user_data)
{
uint32_t id1 = L_PTR_TO_UINT(a);
@@ -102,12 +93,20 @@ static bool match_node_addr(const void *a, const void *b)
return false;
}
+static bool match_key(const void *a, const void *b)
+{
+ const struct remote_key *key = a;
+ uint16_t idx = L_PTR_TO_UINT(b);
+
+ return (key->idx == idx);
+}
+
static bool match_bound_key(const void *a, const void *b)
{
- uint16_t app_idx = L_PTR_TO_UINT(a);
+ const struct remote_key *app_key = a;
uint16_t net_idx = L_PTR_TO_UINT(b);
- return (net_idx == keys_get_bound_key(app_idx));
+ return (net_idx == keys_get_bound_key(app_key->idx));
}
uint8_t remote_del_node(uint16_t unicast)
@@ -142,6 +141,7 @@ bool remote_add_node(const uint8_t uuid[16], uint16_t unicast,
uint8_t ele_cnt, uint16_t net_idx)
{
struct remote_node *rmt;
+ struct remote_key *key;
rmt = l_queue_find(nodes, match_node_addr, L_UINT_TO_PTR(unicast));
if (rmt)
@@ -153,7 +153,10 @@ bool remote_add_node(const uint8_t uuid[16], uint16_t unicast,
rmt->num_ele = ele_cnt;
rmt->net_keys = l_queue_new();
- l_queue_push_tail(rmt->net_keys, L_UINT_TO_PTR(net_idx));
+ key = l_new(struct remote_key, 1);
+ key->idx = net_idx;
+
+ l_queue_push_tail(rmt->net_keys, key);
rmt->els = l_new(struct l_queue *, ele_cnt);
@@ -161,6 +164,7 @@ bool remote_add_node(const uint8_t uuid[16], uint16_t unicast,
nodes = l_queue_new();
l_queue_insert(nodes, rmt, compare_unicast, NULL);
+
return true;
}
@@ -188,49 +192,84 @@ bool remote_set_model(uint16_t unicast, uint8_t ele_idx, uint32_t mod_id,
return true;
}
-bool remote_add_net_key(uint16_t addr, uint16_t net_idx)
+bool remote_add_net_key(uint16_t addr, uint16_t net_idx, bool save)
{
struct remote_node *rmt;
+ struct remote_key *key;
rmt = l_queue_find(nodes, match_node_addr, L_UINT_TO_PTR(addr));
if (!rmt)
return false;
- if (key_present(rmt->net_keys, net_idx))
- return false;
+ if (l_queue_find(rmt->net_keys, match_key, L_UINT_TO_PTR(net_idx)))
+ return true;
- l_queue_push_tail(rmt->net_keys, L_UINT_TO_PTR(net_idx));
- return true;
+ key = l_new(struct remote_key, 1);
+ key->idx = net_idx;
+
+ l_queue_push_tail(rmt->net_keys, key);
+
+ if (save)
+ return mesh_db_node_net_key_add(addr, net_idx);
+ else
+ return true;
}
bool remote_del_net_key(uint16_t addr, uint16_t net_idx)
{
struct remote_node *rmt;
- void *data;
+ struct remote_key *key;
rmt = l_queue_find(nodes, match_node_addr, L_UINT_TO_PTR(addr));
if (!rmt)
return false;
- if (!l_queue_remove(rmt->net_keys, L_UINT_TO_PTR(net_idx)))
+ key = l_queue_remove_if(rmt->net_keys, match_key,
+ L_UINT_TO_PTR(net_idx));
+ if (!key)
return false;
- data = l_queue_remove_if(rmt->app_keys, match_bound_key,
+ mesh_db_node_net_key_del(addr, net_idx);
+
+ l_free(key);
+ key = l_queue_remove_if(rmt->app_keys, match_bound_key,
L_UINT_TO_PTR(net_idx));
- while (data) {
- uint16_t app_idx = (uint16_t) L_PTR_TO_UINT(data);
- mesh_db_node_app_key_del(rmt->unicast, app_idx);
- data = l_queue_remove_if(rmt->app_keys, match_bound_key,
+ while (key) {
+ mesh_db_node_app_key_del(rmt->unicast, key->idx);
+ l_free(key);
+
+ key = l_queue_remove_if(rmt->app_keys, match_bound_key,
L_UINT_TO_PTR(net_idx));
}
return true;
}
-bool remote_add_app_key(uint16_t addr, uint16_t app_idx)
+bool remote_update_net_key(uint16_t addr, uint16_t net_idx, bool update,
+ bool save)
+{
+ struct remote_node *rmt;
+ struct remote_key *key;
+
+ rmt = l_queue_find(nodes, match_node_addr, L_UINT_TO_PTR(addr));
+ if (!rmt)
+ return false;
+
+ key = l_queue_find(rmt->net_keys, match_key,
+ L_UINT_TO_PTR(net_idx));
+ key->updated = update;
+
+ if (save)
+ return mesh_db_node_net_key_update(addr, net_idx, update);
+ else
+ return true;
+}
+
+bool remote_add_app_key(uint16_t addr, uint16_t app_idx, bool save)
{
struct remote_node *rmt;
+ struct remote_key *key;
rmt = l_queue_find(nodes, match_node_addr, L_UINT_TO_PTR(addr));
if (!rmt)
@@ -239,44 +278,105 @@ bool remote_add_app_key(uint16_t addr, uint16_t app_idx)
if (!rmt->app_keys)
rmt->app_keys = l_queue_new();
- if (key_present(rmt->app_keys, app_idx))
- return false;
+ if (l_queue_find(rmt->app_keys, match_key, L_UINT_TO_PTR(app_idx)))
+ return true;
- l_queue_push_tail(rmt->app_keys, L_UINT_TO_PTR(app_idx));
- return true;
+ key = l_new(struct remote_key, 1);
+ key->idx = app_idx;
+
+ l_queue_push_tail(rmt->app_keys, key);
+
+ if (save)
+ return mesh_db_node_app_key_add(addr, app_idx);
+ else
+ return true;
}
bool remote_del_app_key(uint16_t addr, uint16_t app_idx)
{
struct remote_node *rmt;
+ struct remote_key *key;
+
+ rmt = l_queue_find(nodes, match_node_addr, L_UINT_TO_PTR(addr));
+ if (!rmt)
+ return false;
+
+ key = l_queue_remove_if(rmt->app_keys, match_key,
+ L_UINT_TO_PTR(app_idx));
+ l_free(key);
+
+ return mesh_db_node_app_key_del(addr, app_idx);
+}
+
+bool remote_update_app_key(uint16_t addr, uint16_t app_idx, bool update,
+ bool save)
+{
+ struct remote_node *rmt;
+ struct remote_key *key;
rmt = l_queue_find(nodes, match_node_addr, L_UINT_TO_PTR(addr));
if (!rmt)
return false;
- return l_queue_remove(rmt->app_keys, L_UINT_TO_PTR(app_idx));
+ key = l_queue_find(rmt->app_keys, match_key,
+ L_UINT_TO_PTR(app_idx));
+ key->updated = update;
+
+ if (save)
+ return mesh_db_node_app_key_update(addr, app_idx, update);
+ else
+ return true;
+}
+
+void remote_finish_key_refresh(uint16_t addr, uint16_t net_idx)
+{
+ struct remote_node *rmt;
+ struct remote_key *key;
+ const struct l_queue_entry *l;
+
+ rmt = l_queue_find(nodes, match_node_addr, L_UINT_TO_PTR(addr));
+ if (!rmt)
+ return;
+
+ if (!remote_update_net_key(addr, net_idx, false, true))
+ return;
+
+ l = l_queue_get_entries(rmt->app_keys);
+
+ for (; l; l = l->next) {
+ key = l->data;
+
+ if (net_idx != keys_get_bound_key(key->idx))
+ continue;
+
+ key->updated = false;
+
+ mesh_db_node_app_key_update(addr, key->idx, false);
+ }
+
}
uint16_t remote_get_subnet_idx(uint16_t addr)
{
struct remote_node *rmt;
- uint32_t net_idx;
+ struct remote_key *key;
rmt = l_queue_find(nodes, match_node_addr, L_UINT_TO_PTR(addr));
if (!rmt || l_queue_isempty(rmt->net_keys))
return NET_IDX_INVALID;
- net_idx = L_PTR_TO_UINT(l_queue_peek_head(rmt->net_keys));
+ key = l_queue_peek_head(rmt->net_keys);
- return (uint16_t) net_idx;
+ return key->idx;
}
-static void print_key(void *key, void *user_data)
+static void print_key(void *data, void *user_data)
{
- uint16_t idx = L_PTR_TO_UINT(key);
+ struct remote_key *key = data;
- bt_shell_printf("%u (0x%3.3x), ", idx, idx);
+ bt_shell_printf("%u (0x%3.3x) %s, ", key->idx, key->idx,
+ key->updated ? ", updated":"");
}
static void print_model(void *model, void *user_data)
@@ -16,10 +16,15 @@ bool remote_set_model(uint16_t unicast, uint8_t ele_idx, uint32_t mod_id,
void remote_add_rejected_address(uint16_t addr, uint32_t iv_index, bool save);
void remote_clear_rejected_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_add_net_key(uint16_t addr, uint16_t net_idx, bool save);
bool remote_del_net_key(uint16_t addr, uint16_t net_idx);
-bool remote_add_app_key(uint16_t addr, uint16_t app_idx);
+bool remote_update_net_key(uint16_t addr, uint16_t net_idx, bool update,
+ bool save);
+bool remote_add_app_key(uint16_t addr, uint16_t app_idx, bool save);
bool remote_del_app_key(uint16_t addr, uint16_t app_idx);
+bool remote_update_app_key(uint16_t addr, uint16_t app_idx, bool update,
+ bool save);
+void remote_finish_key_refresh(uint16_t addr, uint16_t net_idx);
uint16_t remote_get_subnet_idx(uint16_t addr);
void remote_print_node(uint16_t addr);
void remote_print_all(void);