From: Luiz Augusto von Dentz <luiz.von.dentz@xxxxxxxxx> This adds -M/--mesh [nid] option to show only mesh advertisements which is very convenient when monitoring noisy environments. --- monitor/main.c | 17 +++++++++++- monitor/packet.c | 80 ++++++++++++++++++++++++++++++++++++++++++++------------ monitor/packet.h | 2 ++ 3 files changed, 82 insertions(+), 17 deletions(-) diff --git a/monitor/main.c b/monitor/main.c index b4e9a6a..fb7d5f5 100644 --- a/monitor/main.c +++ b/monitor/main.c @@ -71,6 +71,7 @@ static void usage(void) "\t-S, --sco Dump SCO traffic\n" "\t-A, --a2dp Dump A2DP stream traffic\n" "\t-E, --ellisys [ip] Send Ellisys HCI Injection\n" + "\t-M, --mesh [nid] Dump Mesh traffic only\n" "\t-h, --help Show help options\n"); } @@ -88,6 +89,7 @@ static const struct option main_options[] = { { "sco", no_argument, NULL, 'S' }, { "a2dp", no_argument, NULL, 'A' }, { "ellisys", required_argument, NULL, 'E' }, + { "mesh", optional_argument, NULL, 'M' }, { "todo", no_argument, NULL, '#' }, { "version", no_argument, NULL, 'v' }, { "help", no_argument, NULL, 'h' }, @@ -104,6 +106,7 @@ int main(int argc, char *argv[]) const char *tty = NULL; unsigned int tty_speed = B115200; unsigned short ellisys_port = 0; + int mesh_nid = -1; const char *str; int exit_status; sigset_t mask; @@ -115,7 +118,7 @@ int main(int argc, char *argv[]) for (;;) { int opt; - opt = getopt_long(argc, argv, "d:r:w:a:s:p:i:tTSAE:vh", + opt = getopt_long(argc, argv, "d:r:w:a:s:p:i:tTSAE:M::vh", main_options, NULL); if (opt < 0) break; @@ -176,6 +179,18 @@ int main(int argc, char *argv[]) ellisys_server = optarg; ellisys_port = 24352; break; + case 'M': + if (optarg) { + mesh_nid = atoi(optarg); + if (mesh_nid < 0 || mesh_nid > 0x7f) { + fprintf(stderr, "Invalid NID: %s\n", + optarg); + return EXIT_FAILURE; + } + packet_set_mesh_nid(mesh_nid); + } + filter_mask |= PACKET_FILTER_MESH_ONLY; + break; case '#': packet_todo(); lmp_todo(); diff --git a/monitor/packet.c b/monitor/packet.c index 678d7a7..c2ba66f 100644 --- a/monitor/packet.c +++ b/monitor/packet.c @@ -111,6 +111,7 @@ static unsigned long filter_mask = 0; static bool index_filter = false; static uint16_t index_number = 0; static uint16_t index_current = 0; +static int mesh_nid = -1; #define UNKNOWN_MANUFACTURER 0xffff @@ -268,6 +269,11 @@ void packet_select_index(uint16_t index) index_number = index; } +void packet_set_mesh_nid(uint8_t nid) +{ + mesh_nid = nid; +} + #define print_space(x) printf("%*c", (x), ' '); #define MAX_INDEX 16 @@ -8850,6 +8856,25 @@ rssi: } } +static bool le_adv_report_filter(uint8_t index, const void *data, uint8_t size) +{ + const struct bt_hci_evt_le_adv_report *evt = data; + + if (!packet_has_filter(PACKET_FILTER_MESH_ONLY)) + return false; + + switch (evt->data[1]) { + case BT_EIR_MESH_DATA: + if (mesh_nid > 0 && ((evt->data[2] & 0xfe) != mesh_nid)) + return true; + case BT_EIR_MESH_PROV: + case BT_EIR_MESH_BEACON: + return false; + } + + return true; +} + static void le_conn_update_complete_evt(uint8_t index, const void *data, uint8_t size) { const struct bt_hci_evt_le_conn_update_complete *evt = data; @@ -8998,6 +9023,7 @@ struct subevent_data { void (*func) (uint8_t index, const void *data, uint8_t size); uint8_t size; bool fixed; + bool (*filter) (uint8_t index, const void *data, uint8_t size); }; static void print_subevent(const struct subevent_data *subevent_data, @@ -9039,7 +9065,8 @@ static const struct subevent_data le_meta_event_table[] = { { 0x01, "LE Connection Complete", le_conn_complete_evt, 18, true }, { 0x02, "LE Advertising Report", - le_adv_report_evt, 1, false }, + le_adv_report_evt, 1, false, + le_adv_report_filter }, { 0x03, "LE Connection Update Complete", le_conn_update_complete_evt, 9, true }, { 0x04, "LE Read Remote Used Features", @@ -9072,29 +9099,45 @@ static const struct subevent_data le_meta_event_table[] = { { } }; -static void le_meta_event_evt(uint8_t index, const void *data, uint8_t size) +static const struct subevent_data *le_meta_event_find(uint8_t subevent) { - uint8_t subevent = *((const uint8_t *) data); - struct subevent_data unknown; - const struct subevent_data *subevent_data = &unknown; int i; - unknown.subevent = subevent; - unknown.str = "Unknown"; - unknown.func = NULL; - unknown.size = 0; - unknown.fixed = true; - for (i = 0; le_meta_event_table[i].str; i++) { - if (le_meta_event_table[i].subevent == subevent) { - subevent_data = &le_meta_event_table[i]; - break; - } + if (le_meta_event_table[i].subevent == subevent) + return &le_meta_event_table[i]; + } + + return NULL; +} + +static void le_meta_event_evt(uint8_t index, const void *data, uint8_t size) +{ + uint8_t subevent = *((const uint8_t *) data); + const struct subevent_data *subevent_data; + + subevent_data = le_meta_event_find(subevent); + if (!subevent_data) { + print_indent(6, COLOR_HCI_EVENT_UNKNOWN, "", "", COLOR_OFF, + " (0x%2.2x)", subevent); + return; } print_subevent(subevent_data, index, data + 1, size - 1); } +static bool le_meta_event_filter(uint8_t index, const void *data, uint8_t size) +{ + uint8_t subevent = *((const uint8_t *) data); + const struct subevent_data *subevent_data; + + subevent_data = le_meta_event_find(subevent); + if (!subevent_data || !subevent_data->filter) + return false; + + return subevent_data->filter(index, data + 1, size - 1); +} + static void vendor_evt(uint8_t index, const void *data, uint8_t size) { uint8_t subevent = *((const uint8_t *) data); @@ -9135,6 +9178,7 @@ struct event_data { void (*func) (uint8_t index, const void *data, uint8_t size); uint8_t size; bool fixed; + bool (*filter) (uint8_t index, const void *data, uint8_t size); }; static const struct event_data event_table[] = { @@ -9241,7 +9285,8 @@ static const struct event_data event_table[] = { { 0x3d, "Remote Host Supported Features", remote_host_features_notify_evt, 14, true }, { 0x3e, "LE Meta Event", - le_meta_event_evt, 1, false }, + le_meta_event_evt, 1, false, + le_meta_event_filter }, { 0x40, "Physical Link Complete", phy_link_complete_evt, 2, true }, { 0x41, "Channel Selected", @@ -9559,6 +9604,9 @@ void packet_hci_event(struct timeval *tv, struct ucred *cred, uint16_t index, } if (event_data) { + if (event_data->filter && event_data->filter(index, data, size)) + return; + if (event_data->func) event_color = COLOR_HCI_EVENT; else diff --git a/monitor/packet.h b/monitor/packet.h index a4fdcc6..e2ed233 100644 --- a/monitor/packet.h +++ b/monitor/packet.h @@ -34,6 +34,7 @@ #define PACKET_FILTER_SHOW_ACL_DATA (1 << 4) #define PACKET_FILTER_SHOW_SCO_DATA (1 << 5) #define PACKET_FILTER_SHOW_A2DP_STREAM (1 << 6) +#define PACKET_FILTER_MESH_ONLY (1 << 7) bool packet_has_filter(unsigned long filter); void packet_set_filter(unsigned long filter); @@ -42,6 +43,7 @@ void packet_del_filter(unsigned long filter); void packet_set_priority(const char *priority); void packet_select_index(uint16_t index); +void packet_set_mesh_nid(uint8_t nid); void packet_hexdump(const unsigned char *buf, uint16_t len); void packet_print_error(const char *label, uint8_t error); -- 2.9.4 -- To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html