uint8_t uuid[16];
};
+struct generic_request {
+ uint32_t arg1;
+ uint32_t arg2;
+ uint32_t arg3;
+ uint8_t *data1;
+ uint8_t *data2;
+ const char *str;
+};
+
static struct l_dbus *dbus;
static struct l_queue *node_proxies;
bool update;
};
+static void append_byte_array(struct l_dbus_message_builder *builder,
+ unsigned char *data, unsigned int len)
+{
+ unsigned int i;
+
+ l_dbus_message_builder_enter_array(builder, "y");
+
+ for (i = 0; i < len; i++)
+ l_dbus_message_builder_append_basic(builder, 'y', &(data[i]));
+
+ l_dbus_message_builder_leave_array(builder);
+}
+
static void send_msg_setup(struct l_dbus_message *msg, void *user_data)
{
struct send_data *req = user_data;
if (req->is_dev_key)
l_dbus_message_builder_append_basic(builder, 'b', &req->rmt);
l_dbus_message_builder_append_basic(builder, 'q', &req->idx);
- l_dbus_message_builder_enter_array(builder, "y");
-
- while (req->len) {
- l_dbus_message_builder_append_basic(builder, 'y', req->data);
- req->data++;
- req->len--;
- }
-
- l_dbus_message_builder_leave_array(builder);
+ append_byte_array(builder, req->data, req->len);
l_dbus_message_builder_finalize(builder);
l_dbus_message_builder_destroy(builder);
}
}
static void attach_node_reply(struct l_dbus_proxy *proxy,
- struct l_dbus_message *msg,
- void *user_data)
+ struct l_dbus_message *msg, void *user_data)
{
struct meshcfg_node *node = user_data;
struct l_dbus_message_iter iter_cfg;
}
static void create_net_reply(struct l_dbus_proxy *proxy,
- struct l_dbus_message *msg,
- void *user_data)
+ struct l_dbus_message *msg, void *user_data)
{
char *str;
uint64_t tmp;
static void create_net_setup(struct l_dbus_message *msg, void *user_data)
{
- uint i;
struct l_dbus_message_builder *builder;
/* Generate random UUID */
builder = l_dbus_message_builder_new(msg);
l_dbus_message_builder_append_basic(builder, 'o', app.path);
- l_dbus_message_builder_enter_array(builder, "y");
-
- for (i = 0; i < L_ARRAY_SIZE(app.uuid); i++)
- l_dbus_message_builder_append_basic(builder, 'y',
- &(app.uuid[i]));
-
- l_dbus_message_builder_leave_array(builder);
-
+ append_byte_array(builder, app.uuid, 16);
l_dbus_message_builder_finalize(builder);
l_dbus_message_builder_destroy(builder);
}
remote_print_all();
}
+static void free_generic_request(void *data)
+{
+ struct generic_request *req = data;
+
+ l_free(req->data1);
+ l_free(req->data2);
+ l_free(req);
+}
+
+static void delete_node_setup(struct l_dbus_message *msg, void *user_data)
+{
+ struct generic_request *req = user_data;
+ uint16_t primary;
+ uint8_t ele_cnt;
+
+ primary = (uint16_t) req->arg1;
+ ele_cnt = (uint8_t) req->arg2;
+
+ l_dbus_message_set_arguments(msg, "qy", primary, ele_cnt);
+}
+
+static void cmd_delete_node(int argc, char *argv[])
+{
+ struct generic_request *req;
+
+ if (!local || !local->proxy || !local->mgmt_proxy) {
+ bt_shell_printf("Node is not attached\n");
+ return;
+ }
+
+ if (argc < 3) {
+ bt_shell_printf("Unicast and element count are required\n");
+ return;
+ }
+
+ req = l_new(struct generic_request, 1);
+
+ if (sscanf(argv[1], "%04x", &req->arg1) != 1)
+ goto fail;
+
+ if (sscanf(argv[2], "%u", &req->arg2) != 1)
+ goto fail;
+
+ l_dbus_proxy_method_call(local->mgmt_proxy, "DeleteRemoteNode",
+ delete_node_setup, NULL, req, l_free);
+
+ /* TODO:: Delete node from configuration */
+ return;
+
+fail:
+ l_free(req);
+}
+
+static void import_node_reply(struct l_dbus_proxy *proxy,
+ struct l_dbus_message *msg, void *user_data)
+{
+ struct generic_request *req = user_data;
+ uint16_t primary, net_idx;
+ uint8_t ele_cnt;
+
+ if (l_dbus_message_is_error(msg)) {
+ const char *name;
+
+ l_dbus_message_get_error(msg, &name, NULL);
+ l_error("Failed to import remote node: %s", name);
+ return;
+ }
+
+ net_idx = (uint16_t) req->arg1;
+ primary = (uint16_t) req->arg2;
+ ele_cnt = (uint8_t) req->arg3;
+
+ remote_add_node(req->data1, primary, ele_cnt, net_idx);
+}
+
+static void import_node_setup(struct l_dbus_message *msg, void *user_data)
+{
+ struct generic_request *req = user_data;
+ uint16_t primary;
+ uint8_t ele_cnt;
+ struct l_dbus_message_builder *builder;
+
+ primary = (uint16_t) req->arg2;
+ ele_cnt = (uint8_t) req->arg3;
+
+ builder = l_dbus_message_builder_new(msg);
+ l_dbus_message_builder_append_basic(builder, 'q', &primary);
+ l_dbus_message_builder_append_basic(builder, 'y', &ele_cnt);
+ append_byte_array(builder, req->data2, 16);
+ l_dbus_message_builder_finalize(builder);
+ l_dbus_message_builder_destroy(builder);
+}
+
+static void cmd_import_node(int argc, char *argv[])
+{
+ struct generic_request *req;
+ size_t sz;
+
+ if (!local || !local->proxy || !local->mgmt_proxy) {
+ bt_shell_printf("Node is not attached\n");
+ return;
+ }
+
+ if (argc < 6) {
+ bt_shell_printf("UUID, element count and device key");
+ bt_shell_printf("Unicast, element count and device key");
+ bt_shell_printf("are required\n");
+ return;
+ }
+
+ req = l_new(struct generic_request, 1);
+
+ /* Device UUID */
+ req->data1 = l_util_from_hexstring(argv[1], &sz);
+ if (!req->data1 || sz != 16) {
+ l_error("Failed to generate UUID array from %s", argv[1]);
+ goto fail;
+ }
+
+ /* NetKey Index*/
+ if (sscanf(argv[2], "%04x", &req->arg1) != 1)
+ goto fail;
+
+ /* Unicast of the primary element */
+ if (sscanf(argv[3], "%04x", &req->arg2) != 1)
+ goto fail;
+
+ /* Number of elements */
+ if (sscanf(argv[4], "%u", &req->arg3) != 1)
+ return;
+
+ /* DevKey */
+ req->data2 = l_util_from_hexstring(argv[5], &sz);
+ if (!req->data2 || sz != 16) {
+ l_error("Failed to generate DevKey array from %s", argv[5]);
+ goto fail;
+ }
+
+ l_dbus_proxy_method_call(local->mgmt_proxy, "ImportRemoteNode",
+ import_node_setup, import_node_reply,
+ req, free_generic_request);
+
+ return;
+
+fail:
+ free_generic_request(req);
+}
+
+static void subnet_set_phase_reply(struct l_dbus_proxy *proxy,
+ struct l_dbus_message *msg, void *user_data)
+{
+ if (l_dbus_message_is_error(msg)) {
+ const char *name;
+
+ l_dbus_message_get_error(msg, &name, NULL);
+ l_error("Failed to set subnet phase: %s", name);
+ }
+
+ /* TODO: Set key phase in configuration */
+}
+
+static void subnet_set_phase_setup(struct l_dbus_message *msg, void *user_data)
+{
+ struct generic_request *req = user_data;
+ uint16_t net_idx;
+ uint8_t phase;
+
+ net_idx = (uint16_t) req->arg1;
+ phase = (uint8_t) req->arg2;
+
+ l_dbus_message_set_arguments(msg, "qy", net_idx, phase);
+}
+
+static void cmd_subnet_set_phase(int argc, char *argv[])
+{
+ struct generic_request *req;
+
+ if (!local || !local->proxy || !local->mgmt_proxy) {
+ bt_shell_printf("Node is not attached\n");
+ return;
+ }
+
+ if (argc < 3) {
+ bt_shell_printf("NetKey index and phase are required\n");
+ return;
+ }
+
+ req = l_new(struct generic_request, 1);
+
+ if (sscanf(argv[1], "%04x", &req->arg1) != 1)
+ goto fail;
+
+ if (sscanf(argv[2], "%d", &req->arg2) != 1)
+ goto fail;
+
+ l_dbus_proxy_method_call(local->mgmt_proxy, "SetKeyPhase",
+ subnet_set_phase_setup,
+ subnet_set_phase_reply, req, l_free);
+
+ return;
+
+fail:
+ l_free(req);
+}
+
+static void mgr_key_reply(struct l_dbus_proxy *proxy,
+ struct l_dbus_message *msg, void *user_data)
+{
+ struct generic_request *req = user_data;
+ uint16_t idx = (uint16_t) req->arg1;
+ const char *method = req->str;
+
+ if (l_dbus_message_is_error(msg)) {
+ const char *name;
+
+ l_dbus_message_get_error(msg, &name, NULL);
+ l_error("Method %s returned error: %s", method, name);
+ return;
+ }
+
+ if (!strcmp("CreateSubnet", method))
+ keys_add_net_key(idx);
+ else if (!strcmp("DeleteSubnet", method))
+ keys_del_net_key(idx);
+ else if (!strcmp("DeleteAppKey", method))
+ keys_del_app_key(idx);
+}
+
+static void mgr_key_setup(struct l_dbus_message *msg, void *user_data)
+{
+ struct generic_request *req = user_data;
+ uint16_t idx = (uint16_t) req->arg1;
+
+ l_dbus_message_set_arguments(msg, "q", idx);
+}
+
+static void mgr_key_cmd(int argc, char *argv[], const char *method_name)
+{
+ struct generic_request *req;
+
+ if (!local || !local->proxy || !local->mgmt_proxy) {
+ bt_shell_printf("Node is not attached\n");
+ return;
+ }
+
+ if (argc < 2) {
+ bt_shell_printf("Missing required arguments\n");
+ return;
+ }
+
+ req = l_new(struct generic_request, 1);
+
+ if (sscanf(argv[1], "%04x", &req->arg1) != 1) {
+ l_free(req);
+ return;
+ }
+
+ req->str = method_name;
+
+ l_dbus_proxy_method_call(local->mgmt_proxy, method_name,
+ mgr_key_setup, mgr_key_reply,
+ req, l_free);
+}
+
+static void cmd_delete_appkey(int argc, char *argv[])
+{
+ mgr_key_cmd(argc, argv, "DeleteAppKey");
+}
+
+static void cmd_update_appkey(int argc, char *argv[])
+{
+ mgr_key_cmd(argc, argv, "UpdateAppKey");
+}
+
+static void cmd_delete_subnet(int argc, char *argv[])
+{
+ mgr_key_cmd(argc, argv, "DeleteSubnet");
+}
+
+static void cmd_update_subnet(int argc, char *argv[])
+{
+ mgr_key_cmd(argc, argv, "UpdateSubnet");
+}
+
+static void cmd_create_subnet(int argc, char *argv[])
+{
+ mgr_key_cmd(argc, argv, "CreateSubnet");
+}
+
+static void add_key_reply(struct l_dbus_proxy *proxy,
+ struct l_dbus_message *msg, void *user_data)
+{
+ struct generic_request *req = user_data;
+ uint16_t net_idx, app_idx;
+ const char *method = req->str;
+
+ if (l_dbus_message_is_error(msg)) {
+ const char *name;
+
+ l_dbus_message_get_error(msg, &name, NULL);
+ l_error("%s failed: %s", method, name);
+ return;
+ }
+
+ net_idx = (uint16_t) req->arg1;
+
+ if (!strcmp(method, "ImportSubnet")) {
+ keys_add_net_key(net_idx);
+ return;
+ }
+
+ app_idx = (uint16_t) req->arg2;
+ keys_add_app_key(net_idx, app_idx);
+}
+
+static void import_appkey_setup(struct l_dbus_message *msg, void *user_data)
+{
+ struct generic_request *req = user_data;
+ uint16_t net_idx, app_idx;
+ struct l_dbus_message_builder *builder;
+
+ net_idx = (uint16_t) req->arg1;
+ app_idx = (uint16_t) req->arg2;
+
+ builder = l_dbus_message_builder_new(msg);
+ l_dbus_message_builder_append_basic(builder, 'q', &net_idx);
+ l_dbus_message_builder_append_basic(builder, 'q', &app_idx);
+ append_byte_array(builder, req->data1, 16);
+ l_dbus_message_builder_finalize(builder);
+ l_dbus_message_builder_destroy(builder);
+}
+
+static void cmd_import_appkey(int argc, char *argv[])
+{
+ struct generic_request *req;
+ size_t sz;
+
+ if (!local || !local->proxy || !local->mgmt_proxy) {
+ bt_shell_printf("Node is not attached\n");
+ return;
+ }
+
+ if (argc < 4) {
+ bt_shell_printf("Netkey and AppKey indices and");
+ bt_shell_printf("key value are required\n");
+ return;
+ }
+
+ req = l_new(struct generic_request, 1);
+
+ if (sscanf(argv[1], "%04x", &req->arg1) != 1)
+ goto fail;
+
+ if (sscanf(argv[2], "%04x", &req->arg2) != 1)
+ goto fail;
+
+ req->data1 = l_util_from_hexstring(argv[3], &sz);
+ if (!req->data1 || sz != 16) {
+ l_error("Failed to generate key array from %s", argv[3]);
+ goto fail;
+ }
+
+ req->str = "ImportAppKey";
+
+ l_dbus_proxy_method_call(local->mgmt_proxy, "ImportAppKey",
+ import_appkey_setup, add_key_reply,
+ req, free_generic_request);
+
+ return;
+
+fail:
+ free_generic_request(req);
+}
+
+static void import_subnet_setup(struct l_dbus_message *msg, void *user_data)
+{
+ struct generic_request *req = user_data;
+ uint16_t net_idx;
+ struct l_dbus_message_builder *builder;
+
+ net_idx = (uint16_t) req->arg1;
+
+ builder = l_dbus_message_builder_new(msg);
+ l_dbus_message_builder_append_basic(builder, 'q', &net_idx);
+ append_byte_array(builder, req->data1, 16);
+ l_dbus_message_builder_finalize(builder);
+ l_dbus_message_builder_destroy(builder);
+}
+
+static void cmd_import_subnet(int argc, char *argv[])
+{
+ struct generic_request *req;
+ size_t sz;
+
+ if (!local || !local->proxy || !local->mgmt_proxy) {
+ bt_shell_printf("Node is not attached\n");
+ return;
+ }
+
+ if (argc < 3) {
+ bt_shell_printf("NetKey index and value are required\n");
+ return;
+ }
+
+ req = l_new(struct generic_request, 1);
+
+ if (sscanf(argv[1], "%04x", &req->arg1) != 1)
+ goto fail;
+
+ req->data1 = l_util_from_hexstring(argv[2], &sz);
+ if (!req->data1 || sz != 16) {
+ l_error("Failed to generate key array from %s", argv[2]);
+ goto fail;
+ }
+
+ req->str = "ImportSubnet";
+
+ l_dbus_proxy_method_call(local->mgmt_proxy, "ImportSubnet",
+ import_subnet_setup, add_key_reply,
+ req, free_generic_request);
+ return;
+
+fail:
+ free_generic_request(req);
+}
+
+static void create_appkey_setup(struct l_dbus_message *msg, void *user_data)
+{
+ struct generic_request *req = user_data;
+ uint16_t net_idx, app_idx;
+
+ net_idx = (uint16_t) req->arg1;
+ app_idx = (uint16_t) req->arg2;
+
+ l_dbus_message_set_arguments(msg, "qq", net_idx, app_idx);
+}
+
+static void cmd_create_appkey(int argc, char *argv[])
+{
+ struct generic_request *req;
+
+ if (!local || !local->proxy || !local->mgmt_proxy) {
+ bt_shell_printf("Node is not attached\n");
+ return;
+ }
+
+ if (argc < 3) {
+ bt_shell_printf("AppKey index is required\n");
+ return;
+ }
+
+ req = l_new(struct generic_request, 1);
+
+ if (sscanf(argv[1], "%04x", &req->arg1) != 1)
+ goto fail;
+
+ if (sscanf(argv[2], "%04x", &req->arg2) != 1)
+ goto fail;
+
+ req->str = "CreateAppKey";
+
+ l_dbus_proxy_method_call(local->mgmt_proxy, "CreateAppKey",
+ create_appkey_setup, add_key_reply,
+ req, l_free);
+ return;
+
+fail:
+ l_free(req);
+}
+
static void add_node_reply(struct l_dbus_proxy *proxy,
struct l_dbus_message *msg, void *user_data)
{
static void add_node_setup(struct l_dbus_message *msg, void *user_data)
{
- int i;
char *str = user_data;
size_t sz;
unsigned char *uuid;
}
builder = l_dbus_message_builder_new(msg);
-
- l_dbus_message_builder_enter_array(builder, "y");
-
- for (i = 0; i < (int)sz; i++)
- l_dbus_message_builder_append_basic(builder, 'y', &(uuid[i]));
-
- l_dbus_message_builder_leave_array(builder);
-
+ append_byte_array(builder, uuid, 16);
l_dbus_message_builder_finalize(builder);
l_dbus_message_builder_destroy(builder);
"Create new mesh network with one initial node" },
{ "discover-unprovisioned", "<on/off> [seconds]", cmd_scan_unprov,
"Look for devices to provision" },
+ { "appkey-create", "<net_idx> <app_idx>", cmd_create_appkey,
+ "Create a new local AppKey" },
+ { "appkey-import", "<net_idx> <app_idx> <key>", cmd_import_appkey,
+ "Import a new local AppKey" },
+ { "appkey-update", "<app_idx>", cmd_update_appkey,
+ "Update local AppKey" },
+ { "appkey-delete", "<app_idx>", cmd_delete_appkey,
+ "Delete local AppKey" },
+ { "subnet-create", "<net_idx>", cmd_create_subnet,
+ "Create a new local subnet (NetKey)" },
+ { "subnet-import", "<net_idx> <key>", cmd_import_subnet,
+ "Import a new local subnet (NetKey)" },
+ { "subnet-update", "<net_idx>", cmd_update_subnet,
+ "Update local subnet (NetKey)" },
+ { "subnet-delete", "<net_idx>", cmd_delete_subnet,
+ "Delete local subnet (NetKey)" },
+ { "subnet-set-phase", "<net_idx> <phase>", cmd_subnet_set_phase,
+ "Set subnet (NetKey) phase" },
{ "list-unprovisioned", NULL, cmd_list_unprov,
"List unprovisioned devices" },
{ "provision", "<uuid>", cmd_start_prov,
"Initiate provisioning"},
+ { "node-import", "<uuid> <net_idx> <primary> <ele_count> <dev_key>",
+ cmd_import_node,
+ "Import an externally provisioned remote node"},
+ { "node-delete", "<primary> <ele_count>", cmd_delete_node,
+ "Delete a remote node"},
{ "list-nodes", NULL, cmd_list_nodes,
"List remote mesh nodes"},
{ } },