@@ -516,6 +516,18 @@ static bool msg_recvd(uint16_t src, uint16_t idx, uint8_t *data,
break;
+ case OP_CONFIG_KEY_REFRESH_PHASE_STATUS:
+ if (len != 4)
+ break;
+
+ bt_shell_printf("Node %4.4x Key Refresh Phase status %s\n", src,
+ mesh_status_str(data[0]));
+ net_idx = get_le16(data + 1) & 0xfff;
+
+ bt_shell_printf("\tNetKey %3.3x\n", net_idx);
+ bt_shell_printf("\tKR Phase %2.2x\n", data[3]);
+ break;
+
case OP_MODEL_APP_STATUS:
if (len != 7 && len != 9)
break;
@@ -950,6 +962,74 @@ static void cmd_netkey_del(int argc, char *argv[])
return bt_shell_noninteractive_quit(EXIT_SUCCESS);
}
+static void cmd_kr_phase_get(int argc, char *argv[])
+{
+ uint16_t n;
+ uint8_t msg[32];
+
+ if (IS_UNASSIGNED(target)) {
+ bt_shell_printf("Destination not set\n");
+ return bt_shell_noninteractive_quit(EXIT_FAILURE);
+ }
+
+ n = mesh_opcode_set(OP_CONFIG_KEY_REFRESH_PHASE_GET, msg);
+
+ if (read_input_parameters(argc, argv) != 1)
+ return bt_shell_noninteractive_quit(EXIT_FAILURE);
+
+ put_le16(parms[0], msg + n);
+ n += 2;
+
+ if (!config_send(msg, n, OP_CONFIG_KEY_REFRESH_PHASE_GET))
+ return bt_shell_noninteractive_quit(EXIT_FAILURE);
+
+ return bt_shell_noninteractive_quit(EXIT_SUCCESS);
+}
+
+static void cmd_kr_phase_set(int argc, char *argv[])
+{
+ uint16_t n;
+ uint8_t msg[32];
+ uint8_t phase;
+
+ if (IS_UNASSIGNED(target)) {
+ bt_shell_printf("Destination not set\n");
+ return bt_shell_noninteractive_quit(EXIT_FAILURE);
+ }
+
+ n = mesh_opcode_set(OP_CONFIG_KEY_REFRESH_PHASE_SET, msg);
+
+ if (read_input_parameters(argc, argv) != 2)
+ return bt_shell_noninteractive_quit(EXIT_FAILURE);
+
+ if (parms[1] != KEY_REFRESH_PHASE_TWO &&
+ parms[1] != KEY_REFRESH_PHASE_THREE) {
+ bt_shell_printf("Invalid KR transition value %u\n", parms[1]);
+ bt_shell_printf("Allowed values: 2 or 3\n");
+ return bt_shell_noninteractive_quit(EXIT_FAILURE);
+ }
+
+ if (!keys_get_net_key_phase((uint16_t) parms[0], &phase)) {
+ bt_shell_printf("Subnet KR state not found\n");
+ return bt_shell_noninteractive_quit(EXIT_FAILURE);
+ }
+
+ if (phase != (parms[1] % KEY_REFRESH_PHASE_THREE)) {
+ bt_shell_printf("Subnet's phase must be updated first!\n");
+ return bt_shell_noninteractive_quit(EXIT_FAILURE);
+ }
+
+ put_le16(parms[0], msg + n);
+ n += 2;
+
+ msg[n++] = parms[1];
+
+ if (!config_send(msg, n, OP_CONFIG_KEY_REFRESH_PHASE_SET))
+ return bt_shell_noninteractive_quit(EXIT_FAILURE);
+
+ return bt_shell_noninteractive_quit(EXIT_SUCCESS);
+}
+
static void cmd_appkey_del(int argc, char *argv[])
{
uint16_t n;
@@ -1788,6 +1868,10 @@ static const struct bt_shell_menu cfg_menu = {
"Delete NetKey"},
{"netkey-get", NULL, cmd_netkey_get,
"List NetKeys known to the node"},
+ {"kr-phase-get", "<net_idx>", cmd_kr_phase_get,
+ "Get Key Refresh phase of a NetKey"},
+ {"kr-phase-set", "<net_idx> <phase>", cmd_kr_phase_set,
+ "Set Key Refresh phase transition of a NetKey"},
{"appkey-add", "<app_idx>", cmd_appkey_add,
"Add AppKey"},
{"appkey-update", "<app_idx>", cmd_appkey_update,
@@ -116,6 +116,21 @@ void keys_set_net_key_phase(uint16_t net_idx, uint8_t phase)
bt_shell_printf("Failed to save updated KR phase\n");
}
+bool keys_get_net_key_phase(uint16_t net_idx, uint8_t *phase)
+{
+ struct net_key *key;
+
+ if (!phase || !net_keys)
+ return false;
+
+ key = l_queue_find(net_keys, net_idx_match, L_UINT_TO_PTR(net_idx));
+ if (!key)
+ return false;
+
+ *phase = key->phase;
+ return true;
+}
+
void keys_add_app_key(uint16_t net_idx, uint16_t app_idx)
{
struct net_key *key;
@@ -21,6 +21,7 @@
void keys_add_net_key(uint16_t net_idx);
void keys_del_net_key(uint16_t net_idx);
void keys_set_net_key_phase(uint16_t net_idx, uint8_t phase);
+bool keys_get_net_key_phase(uint16_t net_idx, uint8_t *phase);
void keys_add_app_key(uint16_t net_idx, uint16_t app_idx);
void keys_del_app_key(uint16_t app_idx);
uint16_t keys_get_bound_key(uint16_t app_idx);