Re: [PATCH BlueZ 7/7] monitor: Add option to show only mesh advertisements

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Marcel,

On Tue, Jul 18, 2017 at 10:10 PM, Marcel Holtmann <marcel@xxxxxxxxxxxx> wrote:
> Hi Luiz,
>
>> 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);
>
> you also need to support hex input here as well.
>
>> +                             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;
>
> fall through comment is missing and also mesh_nid > 0 is wrong. Then using uint8_t mesh_nid would be fine. Which is actually what I think we should be doing anyway in the first place. This a cryptographic hash. Chances are super slim that we get 0x00 here.
>
>> +     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 },
>
> I really do not like this. Lets not add another function to these tables. Figure something else out. And frankly, I rather have a btmon --mesh command that focus purely on mesh advertising bearer. If not, then just leave all packets unfiltered.

I thought about that too, but there could be other related packets,
for example GATT proxy.

> Also we could just figure out on how to use BPF on the monitoring socket. Doing this outside the kernel seems pointless.

I will look into that, didn't know BPF could be used with any packet
based socket, well if it does then I completely agree with you, if it
doesn't then we might want something that could work with older
kernels.

-- 
Luiz Augusto von Dentz
--
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




[Index of Archives]     [Bluez Devel]     [Linux Wireless Networking]     [Linux Wireless Personal Area Networking]     [Linux ATH6KL]     [Linux USB Devel]     [Linux Media Drivers]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux