Hi,
This patch set implements the commands in RFC v3 of the Network Management
API proposal for the btmgmt tool.
Please review,
Patrik
Patrik Flykt (3):
btmgmt: Implement Get Networks Management API command
btmgmt: Implement Add Network Management API command
btmgmt: Implement Remove Network Management API command
lib/mgmt.h | 45 ++++++++++
tools/btmgmt.c | 256 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 301 insertions(+)
--
2.1.4
Send MGMT_OP_REMOVE_NETWORK Management API command to disconnect a
connection to a remote 6LowPAN device. Wait for the command to
complete before printing out a result.
Also listen for MGMT_EV_NETWORK_REMOVED events that indicate
disconnection of other connections not requested by us.
---
lib/mgmt.h | 16 ++++++++++
tools/btmgmt.c | 96 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 112 insertions(+)
diff --git a/lib/mgmt.h b/lib/mgmt.h
index 8a9178e..43475e7 100644
--- a/lib/mgmt.h
+++ b/lib/mgmt.h
@@ -550,6 +550,15 @@ struct mgmt_rp_add_network {
int ifindex;
} __packed;
+#define MGMT_OP_REMOVE_NETWORK 0x0044
+#define MGMT_REMOVE_NETWORK_SIZE 7
+struct mgmt_cp_remove_network {
+ struct mgmt_addr_info dst;
+} __packed;
+struct mgmt_rp_remove_network {
+ struct mgmt_addr_info dst;
+} __packed;
+
#define MGMT_EV_CMD_COMPLETE 0x0001
struct mgmt_ev_cmd_complete {
uint16_t opcode;
@@ -768,6 +777,11 @@ struct mgmt_ev_network_added {
int ifindex;
} __packed;
+#define MGMT_EV_NETWORK_REMOVED 0x0026
+struct mgmt_ev_network_removed {
+ struct mgmt_addr_info dst;
+} __packed;
+
static const char *mgmt_op[] = {
"<0x0000>",
"Read Version",
@@ -837,6 +851,7 @@ static const char *mgmt_op[] = {
"Start Limited Discovery",
"Get Networks",
"Add Network",
+ "Remove Network",
};
static const char *mgmt_ev[] = {
@@ -878,6 +893,7 @@ static const char *mgmt_ev[] = {
"Advertising Added",
"Advertising Removed",
"Network Added",
+ "Network Removed",
};
static const char *mgmt_status[] = {
diff --git a/tools/btmgmt.c b/tools/btmgmt.c
index 7bd0943..4b842fb 100644
--- a/tools/btmgmt.c
+++ b/tools/btmgmt.c
@@ -1126,6 +1126,22 @@ static void network_added(uint16_t index, uint16_t len,
addr, typestr(ev->dst.type), index, ev->ifindex);
}
+static void network_removed(uint16_t index, uint16_t len,
+ const void *param, void *user_data)
+{
+ const struct mgmt_ev_network_removed *ev = param;
+ char addr[18];
+
+ if (len < sizeof(*ev)) {
+ error("Too few parameters returned (%u bytes)", len);
+ return;
+ }
+
+ ba2str(&ev->dst.bdaddr, addr);
+ print("Network Removed %s (%s) hci%d", addr, typestr(ev->dst.type),
+ index);
+}
+
static void version_rsp(uint8_t status, uint16_t len, const void *param,
void *user_data)
{
@@ -4446,6 +4462,82 @@ static void cmd_add_network(struct mgmt *mgmt, uint16_t index,
}
}
+static void remove_network_rsp(uint8_t status, uint16_t len, const void *param,
+ void *user_data)
+{
+ const struct mgmt_rp_remove_network *rp = param;
+ char addr[18];
+
+ if (len == 0 && status != 0) {
+ error("Remove Network failed, status 0x%02x (%s)",
+ status, mgmt_errstr(status));
+ return noninteractive_quit(EXIT_FAILURE);
+ }
+
+ if (len < sizeof(*rp)) {
+ error("Unexpected Remove Network len %u", len);
+ return noninteractive_quit(EXIT_FAILURE);
+ }
+
+ ba2str(&rp->dst.bdaddr, addr);
+
+ if (status)
+ error("Remove Network %s (%s) failed with status 0x%02x (%s)",
+ addr, typestr(rp->dst.type),
+ status, mgmt_errstr(status));
+ else
+ print("Remove Network %s (%s)", addr,
+ typestr(rp->dst.type));
+
+ noninteractive_quit(EXIT_SUCCESS);
+}
+
+static void cmd_remove_network(struct mgmt *mgmt, uint16_t index,
+ int argc, char **argv)
+{
+ struct mgmt_cp_remove_network cp;
+ uint8_t type = BDADDR_LE_PUBLIC;
+ int opt;
+
+ optind = 0;
+ while ((opt = getopt_long(argc, argv, "+t:h", network_info_options,
+ NULL)) != -1) {
+ switch (opt) {
+ case 't':
+ type = strtol(optarg, NULL, 0);
+ break;
+ case 'h':
+ network_usage(argv[0]);
+ return noninteractive_quit(EXIT_SUCCESS);
+ default:
+ network_usage(argv[0]);
+ return noninteractive_quit(EXIT_FAILURE);
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+ optind = 0;
+
+ if (argc < 1) {
+ network_usage(argv[0]);
+ return noninteractive_quit(EXIT_FAILURE);
+ }
+
+ if (index == MGMT_INDEX_NONE)
+ index = 0;
+
+ memset(&cp, 0, sizeof(cp));
+ str2ba(argv[0], &cp.dst.bdaddr);
+ cp.dst.type = type;
+
+ if (mgmt_send(mgmt, MGMT_OP_REMOVE_NETWORK, index, sizeof(cp), &cp,
+ remove_network_rsp, NULL, NULL) == 0) {
+ error("Unable to send Remove Network cmd");
+ return noninteractive_quit(EXIT_FAILURE);
+ }
+}
+
struct cmd_info {
char *cmd;
void (*func)(struct mgmt *mgmt, uint16_t index, int argc, char **argv);
@@ -4516,6 +4608,8 @@ static struct cmd_info all_cmd[] = {
{ "clr-adv", cmd_clr_adv, "Clear advertising instances" },
{ "get-networks", cmd_get_networks, "Get 6LowPAN networks" },
{ "add-network", cmd_add_network, "Add a 6LowPAN network" },
+ { "remove-network", cmd_remove_network,
+ "Remove a 6LowPAN network" },
};
static void cmd_quit(struct mgmt *mgmt, uint16_t index,
@@ -4578,6 +4672,8 @@ static void register_mgmt_callbacks(struct mgmt *mgmt, uint16_t index)
advertising_removed, NULL, NULL);
mgmt_register(mgmt, MGMT_EV_NETWORK_ADDED, index, network_added,
NULL, NULL);
+ mgmt_register(mgmt, MGMT_EV_NETWORK_REMOVED, index, network_removed,
+ NULL, NULL);
}
static void cmd_select(struct mgmt *mgmt, uint16_t index,
--
2.1.4
Send MGMT_OP_ADD_NETWORK Management API command to create a connection
to a remote 6LowPAN device and wait for the command to complete before
printing out a result.
Also listen for MGMT_EV_NETWORK_ADDED events that indicate creation of
other connections not requested by us.
---
lib/mgmt.h | 18 ++++++++++
tools/btmgmt.c | 106 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 124 insertions(+)
diff --git a/lib/mgmt.h b/lib/mgmt.h
index 9db853c..8a9178e 100644
--- a/lib/mgmt.h
+++ b/lib/mgmt.h
@@ -540,6 +540,16 @@ struct mgmt_rp_network {
uint32_t ifindex;
} __packed;
+#define MGMT_OP_ADD_NETWORK 0x0043
+#define MGMT_ADD_NETWORK_SIZE 7
+struct mgmt_cp_add_network {
+ struct mgmt_addr_info dst;
+} __packed;
+struct mgmt_rp_add_network {
+ struct mgmt_addr_info dst;
+ int ifindex;
+} __packed;
+
#define MGMT_EV_CMD_COMPLETE 0x0001
struct mgmt_ev_cmd_complete {
uint16_t opcode;
@@ -752,6 +762,12 @@ struct mgmt_ev_advertising_removed {
uint8_t instance;
} __packed;
+#define MGMT_EV_NETWORK_ADDED 0x0025
+struct mgmt_ev_network_added {
+ struct mgmt_addr_info dst;
+ int ifindex;
+} __packed;
+
static const char *mgmt_op[] = {
"<0x0000>",
"Read Version",
@@ -820,6 +836,7 @@ static const char *mgmt_op[] = {
"Get Advertising Size Information", /* 0x0040 */
"Start Limited Discovery",
"Get Networks",
+ "Add Network",
};
static const char *mgmt_ev[] = {
@@ -860,6 +877,7 @@ static const char *mgmt_ev[] = {
"Local Out Of Band Extended Data Updated",
"Advertising Added",
"Advertising Removed",
+ "Network Added",
};
static const char *mgmt_status[] = {
diff --git a/tools/btmgmt.c b/tools/btmgmt.c
index fb6eec3..7bd0943 100644
--- a/tools/btmgmt.c
+++ b/tools/btmgmt.c
@@ -1110,6 +1110,22 @@ static void advertising_removed(uint16_t index, uint16_t len,
print("hci%u advertising_removed: instance %u", index, ev->instance);
}
+static void network_added(uint16_t index, uint16_t len,
+ const void *param, void *user_data)
+{
+ const struct mgmt_ev_network_added *ev = param;
+ char addr[18];
+
+ if (len < sizeof(*ev)) {
+ error("Too few parameters returned (%u bytes)", len);
+ return;
+ }
+
+ ba2str(&ev->dst.bdaddr, addr);
+ print("Network Added %s (%s) hci%d interface %d",
+ addr, typestr(ev->dst.type), index, ev->ifindex);
+}
+
static void version_rsp(uint8_t status, uint16_t len, const void *param,
void *user_data)
{
@@ -4343,6 +4359,93 @@ static void cmd_get_networks(struct mgmt *mgmt, uint16_t index,
}
}
+static void network_usage(const char *command)
+{
+ print("Usage: %s [-t type] <remote address>", command);
+}
+
+static struct option network_info_options[] = {
+ { "help", 0, 0, 'h' },
+ { "type", 1, 0, 't' },
+ { 0, 0, 0, 0 }
+};
+
+static void add_network_rsp(uint8_t status, uint16_t len, const void *param,
+ void *user_data)
+{
+ const struct mgmt_rp_add_network *rp = param;
+ char addr[18];
+
+ if (len == 0 && status != 0) {
+ error("Add Network failed, status 0x%02x (%s)",
+ status, mgmt_errstr(status));
+ return noninteractive_quit(EXIT_FAILURE);
+ }
+
+ if (len < sizeof(*rp)) {
+ error("Unexpected Add Network len %u", len);
+ return noninteractive_quit(EXIT_FAILURE);
+ }
+
+ ba2str(&rp->dst.bdaddr, addr);
+
+ if (status)
+ error("Add Network %s (%s) failed with status 0x%02x (%s)",
+ addr, typestr(rp->dst.type),
+ status, mgmt_errstr(status));
+ else
+ print("Add Network %s (%s) interface %d", addr,
+ typestr(rp->dst.type), rp->ifindex);
+
+ noninteractive_quit(EXIT_SUCCESS);
+}
+
+static void cmd_add_network(struct mgmt *mgmt, uint16_t index,
+ int argc, char **argv)
+{
+ struct mgmt_cp_add_network cp;
+ uint8_t type = BDADDR_LE_PUBLIC;
+ int opt;
+
+ optind = 0;
+ while ((opt = getopt_long(argc, argv, "+t:h", network_info_options,
+ NULL)) != -1) {
+ switch (opt) {
+ case 't':
+ type = strtol(optarg, NULL, 0);
+ break;
+ case 'h':
+ network_usage("add-network");
+ return noninteractive_quit(EXIT_SUCCESS);
+ default:
+ network_usage("add-network");
+ return noninteractive_quit(EXIT_FAILURE);
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+ optind = 0;
+
+ if (argc < 1) {
+ network_usage("add-network");
+ return noninteractive_quit(EXIT_FAILURE);
+ }
+
+ if (index == MGMT_INDEX_NONE)
+ index = 0;
+
+ memset(&cp, 0, sizeof(cp));
+ str2ba(argv[0], &cp.dst.bdaddr);
+ cp.dst.type = type;
+
+ if (mgmt_send(mgmt, MGMT_OP_ADD_NETWORK, index, sizeof(cp), &cp,
+ add_network_rsp, NULL, NULL) == 0) {
+ error("Unable to send Add Network cmd");
+ return noninteractive_quit(EXIT_FAILURE);
+ }
+}
+
struct cmd_info {
char *cmd;
void (*func)(struct mgmt *mgmt, uint16_t index, int argc, char **argv);
@@ -4412,6 +4515,7 @@ static struct cmd_info all_cmd[] = {
{ "rm-adv", cmd_rm_adv, "Remove advertising instance" },
{ "clr-adv", cmd_clr_adv, "Clear advertising instances" },
{ "get-networks", cmd_get_networks, "Get 6LowPAN networks" },
+ { "add-network", cmd_add_network, "Add a 6LowPAN network" },
};
static void cmd_quit(struct mgmt *mgmt, uint16_t index,
@@ -4472,6 +4576,8 @@ static void register_mgmt_callbacks(struct mgmt *mgmt, uint16_t index)
advertising_added, NULL, NULL);
mgmt_register(mgmt, MGMT_EV_ADVERTISING_REMOVED, index,
advertising_removed, NULL, NULL);
+ mgmt_register(mgmt, MGMT_EV_NETWORK_ADDED, index, network_added,
+ NULL, NULL);
}
static void cmd_select(struct mgmt *mgmt, uint16_t index,
--
2.1.4
Send MGMT_OP_GET_NETWORKS Management API command and print out the
connected networks, if any.
---
lib/mgmt.h | 11 +++++++++++
tools/btmgmt.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 65 insertions(+)
diff --git a/lib/mgmt.h b/lib/mgmt.h
index f6a976a..9db853c 100644
--- a/lib/mgmt.h
+++ b/lib/mgmt.h
@@ -530,6 +530,16 @@ struct mgmt_rp_get_adv_size_info {
#define MGMT_OP_START_LIMITED_DISCOVERY 0x0041
+#define MGMT_OP_GET_NETWORKS 0x0042
+#define MGMT_GET_NETWORKS_SIZE 0
+struct mgmt_rp_get_networks {
+ uint16_t count;
+} __packed; /* followed by zero or more struct mgmt_rp_network */
+struct mgmt_rp_network {
+ struct mgmt_addr_info dst;
+ uint32_t ifindex;
+} __packed;
+
#define MGMT_EV_CMD_COMPLETE 0x0001
struct mgmt_ev_cmd_complete {
uint16_t opcode;
@@ -809,6 +819,7 @@ static const char *mgmt_op[] = {
"Remove Advertising",
"Get Advertising Size Information", /* 0x0040 */
"Start Limited Discovery",
+ "Get Networks",
};
static const char *mgmt_ev[] = {
diff --git a/tools/btmgmt.c b/tools/btmgmt.c
index 4c86dcb..fb6eec3 100644
--- a/tools/btmgmt.c
+++ b/tools/btmgmt.c
@@ -4290,6 +4290,59 @@ static void cmd_clr_adv(struct mgmt *mgmt, uint16_t index, int argc, char **argv
cmd_rm_adv(mgmt, index, 2, rm_argv);
}
+static void get_networks_rsp(uint8_t status, uint16_t len,
+ const void *param, void *user_data)
+{
+ const struct mgmt_rp_get_networks *rp = param;
+ struct mgmt_rp_network *nw;
+ char addr[18];
+ int i;
+
+ if (len == 0 && status != 0) {
+ error("Get Networks failed, status 0x%02x (%s)",
+ status, mgmt_errstr(status));
+ return noninteractive_quit(EXIT_FAILURE);
+ }
+
+ if (len < sizeof(*rp) || len != sizeof(*rp) +
+ rp->count * sizeof(*nw)) {
+ error("Unexpected Get Networks len %u", len);
+ return noninteractive_quit(EXIT_FAILURE);
+ }
+
+ if (status) {
+ error("Get Networks failed with status 0x%02x (%s)",
+ status, mgmt_errstr(status));
+ } else {
+ print("Get Networks %d items", rp->count);
+
+ nw = (struct mgmt_rp_network *)(rp + 1);
+ for (i = 0; i < rp->count; i++) {
+ ba2str(&nw->dst.bdaddr, addr);
+ print("%s (%s) interface %d", addr,
+ typestr(nw->dst.type), nw->ifindex);
+ nw++;
+ }
+ }
+
+ noninteractive_quit(EXIT_SUCCESS);
+}
+
+static void cmd_get_networks(struct mgmt *mgmt, uint16_t index,
+ int argc, char **argv)
+{
+ if (argc > 1) {
+ print("Usage: %s", argv[0]);
+ return noninteractive_quit(EXIT_FAILURE);
+ }
+
+ if (mgmt_send(mgmt, MGMT_OP_GET_NETWORKS, index, 0, NULL,
+ get_networks_rsp, NULL, NULL) == 0) {
+ error("Unable to send Get Networks cmd");
+ return noninteractive_quit(EXIT_FAILURE);
+ }
+}
+
struct cmd_info {
char *cmd;
void (*func)(struct mgmt *mgmt, uint16_t index, int argc, char **argv);
@@ -4358,6 +4411,7 @@ static struct cmd_info all_cmd[] = {
{ "add-adv", cmd_add_adv, "Add advertising instance" },
{ "rm-adv", cmd_rm_adv, "Remove advertising instance" },
{ "clr-adv", cmd_clr_adv, "Clear advertising instances" },
+ { "get-networks", cmd_get_networks, "Get 6LowPAN networks" },
};
static void cmd_quit(struct mgmt *mgmt, uint16_t index,
--
2.1.4