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 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.

Frankly, if you care about GATT proxy as well, then accept that you get everything.

>> 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.

I rather accept that it only works on newer kernels than hacking btmon into some complicated code base. That happened to hcidump and I have no intention to repeat it.

Regards

Marcel

--
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