2016-03-04 11:41:47

by Patrik Flykt

[permalink] [raw]
Subject: [PATCH 0/3] Implement btmgmt BTLE Network Management API

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



2016-03-04 11:41:50

by Patrik Flykt

[permalink] [raw]
Subject: [PATCH 3/3] btmgmt: Implement Remove Network Management API command

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


2016-03-04 11:41:49

by Patrik Flykt

[permalink] [raw]
Subject: [PATCH 2/3] btmgmt: Implement Add Network Management API command

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


2016-03-04 11:41:48

by Patrik Flykt

[permalink] [raw]
Subject: [PATCH 1/3] btmgmt: Implement Get Networks Management API command

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