1 /* packet-btbnep.c
2  * Routines for Bluetooth BNEP dissection
3  *
4  * Copyright 2012, Michal Labedzki for Tieto Corporation
5  *
6  * Wireshark - Network traffic analyzer
7  * By Gerald Combs <gerald@wireshark.org>
8  * Copyright 1998 Gerald Combs
9  *
10  * SPDX-License-Identifier: GPL-2.0-or-later
11  */
12 
13 #include "config.h"
14 
15 #include <epan/packet.h>
16 #include <epan/prefs.h>
17 #include <epan/etypes.h>
18 #include <epan/expert.h>
19 
20 #include "packet-bluetooth.h"
21 #include "packet-btl2cap.h"
22 #include "packet-btsdp.h"
23 
24 #define BNEP_TYPE_GENERAL_ETHERNET                                          0x00
25 #define BNEP_TYPE_CONTROL                                                   0x01
26 #define BNEP_TYPE_COMPRESSED_ETHERNET                                       0x02
27 #define BNEP_TYPE_COMPRESSED_ETHERNET_SOURCE_ONLY                           0x03
28 #define BNEP_TYPE_COMPRESSED_ETHERNET_DESTINATION_ONLY                      0x04
29 #define RESERVED_802                                                        0x7F
30 
31 static int proto_btbnep                                                    = -1;
32 static int hf_btbnep_bnep_type                                             = -1;
33 static int hf_btbnep_extension_flag                                        = -1;
34 static int hf_btbnep_extension_type                                        = -1;
35 static int hf_btbnep_extension_length                                      = -1;
36 static int hf_btbnep_dst                                                   = -1;
37 static int hf_btbnep_src                                                   = -1;
38 static int hf_btbnep_len                                                   = -1;
39 static int hf_btbnep_invalid_lentype                                       = -1;
40 static int hf_btbnep_type                                                  = -1;
41 static int hf_btbnep_addr                                                  = -1;
42 static int hf_btbnep_lg                                                    = -1;
43 static int hf_btbnep_ig                                                    = -1;
44 static int hf_btbnep_control_type                                          = -1;
45 static int hf_btbnep_unknown_control_type                                  = -1;
46 static int hf_btbnep_uuid_size                                             = -1;
47 static int hf_btbnep_destination_service_uuid                              = -1;
48 static int hf_btbnep_source_service_uuid                                   = -1;
49 static int hf_btbnep_setup_connection_response_message                     = -1;
50 static int hf_btbnep_filter_net_type_response_message                      = -1;
51 static int hf_btbnep_filter_multi_addr_response_message                    = -1;
52 static int hf_btbnep_list_length                                           = -1;
53 static int hf_btbnep_network_type_start                                    = -1;
54 static int hf_btbnep_network_type_end                                      = -1;
55 static int hf_btbnep_multicast_address_start                               = -1;
56 static int hf_btbnep_multicast_address_end                                 = -1;
57 
58 static gint ett_btbnep                                                     = -1;
59 static gint ett_addr                                                       = -1;
60 
61 static expert_field ei_btbnep_src_not_group_address = EI_INIT;
62 static expert_field ei_btbnep_invalid_lentype       = EI_INIT;
63 static expert_field ei_btbnep_len_past_end          = EI_INIT;
64 
65 static dissector_handle_t btbnep_handle;
66 
67 static gboolean top_dissect                                              = TRUE;
68 
69 static dissector_handle_t llc_handle;
70 static dissector_handle_t ipx_handle;
71 static dissector_handle_t ethertype_handle;
72 
73 static const true_false_string ig_tfs = {
74     "Group address (multicast/broadcast)",
75     "Individual address (unicast)"
76 };
77 
78 static const true_false_string lg_tfs = {
79     "Locally administered address (this is NOT the factory default)",
80     "Globally unique address (factory default)"
81 };
82 
83 static const value_string bnep_type_vals[] = {
84     { 0x00,   "General Ethernet" },
85     { 0x01,   "Control" },
86     { 0x02,   "Compressed Ethernet" },
87     { 0x03,   "Compressed Ethernet Source Only" },
88     { 0x04,   "Compressed Ethernet Destination Only" },
89     { 0x7F,   "Reserved for 802.2 LLC Packets for IEEE 802.15.1 WG" },
90     { 0, NULL }
91 };
92 
93 static const value_string control_type_vals[] = {
94     { 0x00,   "Command Not Understood" },
95     { 0x01,   "Setup Connection Request" },
96     { 0x02,   "Setup Connection Response" },
97     { 0x03,   "Filter Net Type Set" },
98     { 0x04,   "Filter Net Type Response" },
99     { 0x05,   "Filter Multi Addr Set" },
100     { 0x06,   "Filter Multi Addr Response" },
101     { 0, NULL }
102 };
103 
104 static const value_string extension_type_vals[] = {
105     { 0x00,   "Extension Control" },
106     { 0, NULL }
107 };
108 
109 static const value_string setup_connection_response_message_vals[] = {
110     { 0x0000,   "Operation Successful" },
111     { 0x0001,   "Operation FAIL: Invalid Destination Service UUID" },
112     { 0x0002,   "Operation FAIL: Invalid Source Service UUID" },
113     { 0x0003,   "Operation FAIL: Invalid Service UUID Size" },
114     { 0x0004,   "Operation FAIL: Connection Not Allowed" },
115     { 0, NULL }
116 };
117 
118 static const value_string filter_net_type_response_message_vals[] = {
119     { 0x0000,   "Operation Successful" },
120     { 0x0001,   "Unsupported Request" },
121     { 0x0002,   "Operation FAIL: Invalid Networking Protocol Type Range" },
122     { 0x0003,   "Operation FAIL: Too many filters" },
123     { 0x0004,   "Operation FAIL: Unable to fulfill request due to security reasons" },
124     { 0, NULL }
125 };
126 
127 static const value_string filter_multi_addr_response_message_vals[] = {
128     { 0x0000,   "Operation Successful" },
129     { 0x0001,   "Unsupported Request" },
130     { 0x0002,   "Operation FAIL: Invalid Multicast Address" },
131     { 0x0003,   "Operation FAIL: Too many filters" },
132     { 0x0004,   "Operation FAIL: Unable to fulfill request due to security reasons" },
133     { 0, NULL }
134 };
135 
136 void proto_register_btbnep(void);
137 void proto_reg_handoff_btbnep(void);
138 
139 static int
dissect_control(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,int offset)140 dissect_control(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
141 {
142     proto_item  *pitem = NULL;
143     guint        control_type;
144     guint8       unknown_control_type;
145     guint8       uuid_size;
146     guint16      uuid_dst;
147     guint16      uuid_src;
148     guint16      response_message;
149     guint16      list_length;
150     guint        i_item;
151 
152     proto_tree_add_item(tree, hf_btbnep_control_type, tvb, offset, 1, ENC_BIG_ENDIAN);
153     control_type = tvb_get_guint8(tvb, offset);
154     offset += 1;
155 
156     col_append_fstr(pinfo->cinfo, COL_INFO, " - %s", val_to_str_const(control_type, control_type_vals,  "Unknown type"));
157 
158     switch(control_type) {
159         case 0x00: /* Command Not Understood */
160             proto_tree_add_item(tree, hf_btbnep_unknown_control_type, tvb, offset, 1, ENC_BIG_ENDIAN);
161             unknown_control_type = tvb_get_guint8(tvb, offset);
162             offset += 1;
163 
164             col_append_fstr(pinfo->cinfo, COL_INFO, " - Unknown(%s)", val_to_str_const(unknown_control_type, control_type_vals,  "Unknown type"));
165 
166             break;
167         case 0x01: /* Setup Connection Request */
168             proto_tree_add_item(tree, hf_btbnep_uuid_size, tvb, offset, 1, ENC_BIG_ENDIAN);
169             uuid_size = tvb_get_guint8(tvb, offset);
170             offset += 1;
171 
172             pitem = proto_tree_add_item(tree, hf_btbnep_destination_service_uuid, tvb, offset, uuid_size, ENC_NA);
173             uuid_dst = tvb_get_ntohs(tvb, offset);
174             proto_item_append_text(pitem, " (%s)", val_to_str_ext(uuid_dst, &bluetooth_uuid_vals_ext,  "Unknown uuid"));
175             offset += uuid_size;
176 
177             pitem = proto_tree_add_item(tree, hf_btbnep_source_service_uuid, tvb, offset, uuid_size, ENC_NA);
178             uuid_src = tvb_get_ntohs(tvb, offset);
179             proto_item_append_text(pitem, " (%s)", val_to_str_ext(uuid_src, &bluetooth_uuid_vals_ext,  "Unknown uuid"));
180             offset += uuid_size;
181 
182             col_append_fstr(pinfo->cinfo, COL_INFO, " - dst: <%s>, src: <%s>",
183                     val_to_str_ext(uuid_dst, &bluetooth_uuid_vals_ext,  "Unknown uuid"),
184                     val_to_str_ext(uuid_src, &bluetooth_uuid_vals_ext,  "Unknown uuid"));
185             break;
186         case 0x02: /* Setup Connection Response */
187             proto_tree_add_item(tree, hf_btbnep_setup_connection_response_message, tvb, offset, 2, ENC_BIG_ENDIAN);
188             response_message = tvb_get_ntohs(tvb, offset);
189             offset += 2;
190             col_append_fstr(pinfo->cinfo, COL_INFO, " - %s",
191                     val_to_str_const(response_message, setup_connection_response_message_vals,  "Unknown response message"));
192             break;
193         case 0x03: /* Filter Net Type Set */
194             proto_tree_add_item(tree, hf_btbnep_list_length, tvb, offset, 2, ENC_BIG_ENDIAN);
195             list_length = tvb_get_ntohs(tvb, offset);
196             offset += 2;
197 
198             for (i_item = 0; i_item + 4 > i_item && i_item < list_length; i_item += 4) {
199                 proto_tree_add_item(tree, hf_btbnep_network_type_start, tvb, offset, 2, ENC_BIG_ENDIAN);
200                 offset += 2;
201 
202                 proto_tree_add_item(tree, hf_btbnep_network_type_end, tvb, offset, 2, ENC_BIG_ENDIAN);
203                 offset += 2;
204             }
205             break;
206         case 0x04: /* Filter Net Type Response */
207             proto_tree_add_item(tree, hf_btbnep_filter_net_type_response_message, tvb, offset, 2, ENC_BIG_ENDIAN);
208             response_message = tvb_get_ntohs(tvb, offset);
209             offset += 2;
210             col_append_fstr(pinfo->cinfo, COL_INFO, " - %s",
211                     val_to_str_const(response_message, filter_net_type_response_message_vals,  "Unknown response message"));
212             break;
213         case 0x05: /*Filter Multi Addr Set*/
214             proto_tree_add_item(tree, hf_btbnep_list_length, tvb, offset, 2, ENC_BIG_ENDIAN);
215             list_length = tvb_get_ntohs(tvb, offset);
216             offset += 2;
217 
218             for (i_item = 0; i_item + 12 > i_item && i_item < list_length; i_item += 12) {
219                 proto_tree_add_item(tree, hf_btbnep_multicast_address_start, tvb, offset, FT_ETHER_LEN, ENC_NA);
220                 offset += FT_ETHER_LEN;
221 
222                 proto_tree_add_item(tree, hf_btbnep_multicast_address_end, tvb, offset, FT_ETHER_LEN, ENC_NA);
223                 offset += FT_ETHER_LEN;
224             }
225             break;
226         case 0x06: /* Filter Multi Addr Response */
227             proto_tree_add_item(tree, hf_btbnep_filter_multi_addr_response_message, tvb, offset, 2, ENC_BIG_ENDIAN);
228             response_message = tvb_get_ntohs(tvb, offset);
229             offset += 2;
230             col_append_fstr(pinfo->cinfo, COL_INFO, " - %s",
231                     val_to_str_const(response_message, filter_multi_addr_response_message_vals,  "Unknown response message"));
232             break;
233 
234     };
235 
236     return offset;
237 }
238 
239 static int
dissect_extension(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,int offset)240 dissect_extension(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
241 {
242     guint8  extension_flag;
243     guint8  extension_type;
244     guint16 extension_length;
245     guint8  type;
246 
247     proto_tree_add_item(tree, hf_btbnep_extension_type, tvb, offset, 1, ENC_BIG_ENDIAN);
248     proto_tree_add_item(tree, hf_btbnep_extension_flag, tvb, offset, 1, ENC_BIG_ENDIAN);
249     type = tvb_get_guint8(tvb, offset);
250     extension_flag = type & 0x01;
251     extension_type = type >> 1;
252     offset += 1;
253 
254     proto_tree_add_item(tree, hf_btbnep_extension_length, tvb, offset, 1, ENC_BIG_ENDIAN);
255     extension_length = tvb_get_ntohs(tvb, offset);
256     offset += 2;
257 
258     if (extension_type == 0x00) {
259         /* Extension Control */
260         offset = dissect_control(tvb, pinfo, tree, offset);
261     } else {
262         offset += extension_length;
263     }
264 
265     if (extension_flag) offset = dissect_extension(tvb, pinfo, tree, offset);
266 
267     return offset;
268 }
269 
270 static gint
dissect_btbnep(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)271 dissect_btbnep(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
272 {
273     proto_item   *pi;
274     proto_tree   *btbnep_tree;
275     gint          offset = 0;
276     guint         bnep_type;
277     guint         extension_flag;
278     guint         len_type = 0;
279     proto_item   *addr_item;
280     proto_tree   *addr_tree = NULL;
281     proto_item   *length_ti = NULL;
282 
283     pi = proto_tree_add_item(tree, proto_btbnep, tvb, offset, -1, ENC_NA);
284     btbnep_tree = proto_item_add_subtree(pi, ett_btbnep);
285 
286     col_set_str(pinfo->cinfo, COL_PROTOCOL, "BNEP");
287     col_clear(pinfo->cinfo, COL_INFO);
288 
289     switch (pinfo->p2p_dir) {
290         case P2P_DIR_SENT:
291             col_set_str(pinfo->cinfo, COL_INFO, "Sent ");
292             break;
293         case P2P_DIR_RECV:
294             col_set_str(pinfo->cinfo, COL_INFO, "Rcvd ");
295             break;
296         default:
297             col_set_str(pinfo->cinfo, COL_INFO, "UnknownDirection ");
298             break;
299     }
300 
301     proto_tree_add_item(btbnep_tree, hf_btbnep_extension_flag, tvb, offset, 1, ENC_BIG_ENDIAN);
302     proto_tree_add_item(btbnep_tree, hf_btbnep_bnep_type, tvb, offset, 1, ENC_BIG_ENDIAN);
303     bnep_type = tvb_get_guint8(tvb, offset);
304     extension_flag = bnep_type & 0x80;
305     bnep_type = bnep_type & 0x7F;
306     offset += 1;
307 
308     col_append_str(pinfo->cinfo, COL_INFO, val_to_str_const(bnep_type, bnep_type_vals,  "Unknown type"));
309     if (extension_flag) col_append_str(pinfo->cinfo, COL_INFO, "+E");
310 
311     if (bnep_type == BNEP_TYPE_GENERAL_ETHERNET || bnep_type == BNEP_TYPE_COMPRESSED_ETHERNET_DESTINATION_ONLY) {
312         set_address_tvb(&pinfo->dl_dst, AT_ETHER, 6, tvb, offset);
313         copy_address_shallow(&pinfo->dst, &pinfo->dl_dst);
314 
315         addr_item = proto_tree_add_item(btbnep_tree, hf_btbnep_dst, tvb, offset, FT_ETHER_LEN, ENC_NA);
316         addr_tree = proto_item_add_subtree(addr_item, ett_addr);
317         proto_tree_add_item(addr_tree, hf_btbnep_addr, tvb, offset, FT_ETHER_LEN, ENC_NA);
318         proto_tree_add_item(addr_tree, hf_btbnep_lg, tvb, offset, 3, ENC_BIG_ENDIAN);
319         proto_tree_add_item(addr_tree, hf_btbnep_ig, tvb, offset, 3, ENC_BIG_ENDIAN);
320         offset += FT_ETHER_LEN;
321     }
322 
323     if (bnep_type == BNEP_TYPE_GENERAL_ETHERNET || bnep_type == BNEP_TYPE_COMPRESSED_ETHERNET_SOURCE_ONLY) {
324         set_address_tvb(&pinfo->dl_src, AT_ETHER, 6, tvb, offset);
325         copy_address_shallow(&pinfo->src, &pinfo->dl_src);
326 
327         addr_item = proto_tree_add_item(btbnep_tree, hf_btbnep_src, tvb, offset, FT_ETHER_LEN, ENC_NA);
328         addr_tree = proto_item_add_subtree(addr_item, ett_addr);
329         if (tvb_get_guint8(tvb, offset) & 0x01) {
330             expert_add_info(pinfo, addr_item, &ei_btbnep_src_not_group_address);
331         }
332 
333         proto_tree_add_item(addr_tree, hf_btbnep_addr, tvb, offset, FT_ETHER_LEN, ENC_NA);
334         proto_tree_add_item(addr_tree, hf_btbnep_lg, tvb, offset, 3, ENC_BIG_ENDIAN);
335         proto_tree_add_item(addr_tree, hf_btbnep_ig, tvb, offset, 3, ENC_BIG_ENDIAN);
336         offset += FT_ETHER_LEN;
337     }
338 
339     if (bnep_type != BNEP_TYPE_CONTROL) {
340         len_type = tvb_get_ntohs(tvb, offset);
341         if (len_type <= IEEE_802_3_MAX_LEN) {
342             /*
343              * The BNEP Version 1.0 spec says, for BNEP_GENERAL_ETHERNET
344              * packets, "Note: Networking Protocol Types as used in this
345              * specification SHALL be taken to include values in the range
346              * 0x0000-0x05dc, used to represent the IEEE802.3 length
347              * interpretation of the IEEE802.3 length/type field.",
348              * although it says that it's not mandatory to process
349              * those packets.
350              */
351             length_ti = proto_tree_add_item(btbnep_tree, hf_btbnep_len, tvb, offset, 2, ENC_BIG_ENDIAN);
352         } else if (len_type < ETHERNET_II_MIN_LEN) {
353             /*
354              * Not a valid Ethernet length, not a valid Ethernet type.
355              */
356             proto_item *ti;
357 
358             ti = proto_tree_add_item(btbnep_tree, hf_btbnep_invalid_lentype, tvb, offset, 2, ENC_BIG_ENDIAN);
359             expert_add_info_format(pinfo, ti, &ei_btbnep_invalid_lentype,
360                                    "Invalid length/type: 0x%04x (%u)",
361                                    len_type, len_type);
362         } else {
363             /*
364              * Ethernet type.
365              */
366             if (!top_dissect)
367                 proto_tree_add_item(btbnep_tree, hf_btbnep_type, tvb, offset, 2, ENC_BIG_ENDIAN);
368             col_append_fstr(pinfo->cinfo, COL_INFO, " - Type: %s", val_to_str_const(len_type, etype_vals, "unknown"));
369         }
370         offset += 2;
371     } else {
372         offset = dissect_control(tvb, pinfo, btbnep_tree, offset);
373     }
374 
375     if (extension_flag) {
376         offset = dissect_extension(tvb, pinfo, btbnep_tree, offset);
377     }
378 
379     if (bnep_type != BNEP_TYPE_CONTROL) {
380         /* dissect normal network */
381         if (top_dissect) {
382             if (len_type <= IEEE_802_3_MAX_LEN) {
383                 gboolean is_802_2;
384                 gint reported_length;
385                 tvbuff_t  *next_tvb;
386 
387                 /*
388                  * The BNEP Version 1.0 spec says, for BNEP_GENERAL_ETHERNET
389                  * packets, "Note: Networking Protocol Types as used in this
390                  * specification SHALL be taken to include values in the range
391                  * 0x0000-0x05dc, used to represent the IEEE802.3 length
392                  * interpretation of the IEEE802.3 length/type field.",
393                  * although it says that it's not mandatory to process
394                  * those packets.
395                  */
396 
397                 /*
398                  * Is there an 802.2 layer? I can tell by looking at the
399                  * first 2 bytes of the payload. If they are 0xffff, then
400                  * the payload is IPX.
401                  *
402                  * (Probably won't happen, but we might as well do this
403                  * anyway.)
404                  */
405                 is_802_2 = TRUE;
406 
407                 /* Don't throw an exception for this check (even a BoundsError) */
408                 if (tvb_bytes_exist(tvb, offset, 2)) {
409                     if (tvb_get_ntohs(tvb, offset) == 0xffff) {
410                         is_802_2 = FALSE;
411                     }
412                 }
413 
414                 reported_length = tvb_reported_length_remaining(tvb, offset);
415 
416                 /*
417                  * Make sure the length doesn't go past the end of the
418                  * payload.
419                  */
420                 if (reported_length >= 0 && len_type > (guint)reported_length) {
421                     len_type = reported_length;
422                     expert_add_info(pinfo, length_ti, &ei_btbnep_len_past_end);
423                 }
424 
425                 /* Give the next dissector only 'len_type' number of bytes. */
426                 next_tvb = tvb_new_subset_length(tvb, offset, len_type);
427                 if (is_802_2) {
428                     call_dissector(llc_handle, next_tvb, pinfo, tree);
429                 } else {
430                     call_dissector(ipx_handle, next_tvb, pinfo, tree);
431                 }
432             } else if (len_type < ETHERNET_II_MIN_LEN) {
433                 /*
434                  * Not a valid packet.
435                  */
436                 tvbuff_t  *next_tvb;
437 
438                 next_tvb = tvb_new_subset_remaining(tvb, offset);
439                 call_data_dissector(next_tvb, pinfo, tree);
440             } else {
441                 /*
442                  * Valid Ethertype.
443                  */
444                 ethertype_data_t ethertype_data;
445 
446                 proto_tree_add_uint(btbnep_tree, hf_btbnep_type, tvb,
447                                     offset - 2, 2, len_type);
448 
449                 ethertype_data.etype = len_type;
450                 ethertype_data.payload_offset = offset;
451                 ethertype_data.fh_tree = btbnep_tree;
452                 ethertype_data.trailer_id = 0;
453                 ethertype_data.fcs_len = 0;
454 
455                 call_dissector_with_data(ethertype_handle, tvb, pinfo, tree, &ethertype_data);
456             }
457         } else {
458             tvbuff_t  *next_tvb;
459 
460             next_tvb = tvb_new_subset_remaining(tvb, offset);
461             call_data_dissector(next_tvb, pinfo, tree);
462         }
463     }
464 
465     return offset;
466 }
467 
468 void
proto_register_btbnep(void)469 proto_register_btbnep(void)
470 {
471     module_t *module;
472     expert_module_t* expert_btbnep;
473 
474     static hf_register_info hf[] = {
475         { &hf_btbnep_bnep_type,
476             { "BNEP Type",                         "btbnep.bnep_type",
477             FT_UINT8, BASE_HEX, VALS(bnep_type_vals), 0x7F,
478             NULL, HFILL }
479         },
480         { &hf_btbnep_extension_flag,
481             { "Extension Flag",                    "btbnep.extension_flag",
482             FT_BOOLEAN, 8, NULL, 0x80,
483             NULL, HFILL }
484         },
485         { &hf_btbnep_control_type,
486             { "Control Type",                      "btbnep.control_type",
487             FT_UINT8, BASE_HEX, VALS(control_type_vals), 0x00,
488             NULL, HFILL }
489         },
490         { &hf_btbnep_extension_type,
491             { "Extension Type",                    "btbnep.extension_type",
492             FT_UINT8, BASE_HEX, VALS(extension_type_vals), 0x00,
493             NULL, HFILL }
494         },
495         { &hf_btbnep_extension_length,
496             { "Extension Length",                  "btbnep.extension_length",
497             FT_UINT16, BASE_DEC, NULL, 0x00,
498             NULL, HFILL }
499         },
500         { &hf_btbnep_unknown_control_type,
501             { "Unknown Control Type",              "btbnep.unknown_control_type",
502             FT_UINT8, BASE_HEX, VALS(control_type_vals), 0x00,
503             NULL, HFILL }
504         },
505         { &hf_btbnep_uuid_size,
506             { "UIDD Size",                         "btbnep.uuid_size",
507             FT_UINT8, BASE_DEC, NULL, 0x00,
508             NULL, HFILL }
509         },
510         { &hf_btbnep_destination_service_uuid,
511             { "Destination Service UUID",          "btbnep.destination_service_uuid",
512             FT_NONE, BASE_NONE, NULL, 0x00,
513             NULL, HFILL }
514         },
515         { &hf_btbnep_source_service_uuid,
516             { "Source Service UUID",               "btbnep.source_service_uuid",
517             FT_NONE, BASE_NONE, NULL, 0x00,
518             NULL, HFILL }
519         },
520         { &hf_btbnep_setup_connection_response_message,
521             { "Response Message",                  "btbnep.setup_connection_response_message",
522             FT_UINT16, BASE_HEX, VALS(setup_connection_response_message_vals), 0x00,
523             NULL, HFILL }
524         },
525         { &hf_btbnep_filter_net_type_response_message,
526             { "Response Message",                  "btbnep.filter_net_type_response_message",
527             FT_UINT16, BASE_HEX, VALS(filter_net_type_response_message_vals), 0x00,
528             NULL, HFILL }
529         },
530         { &hf_btbnep_filter_multi_addr_response_message,
531             { "Response Message",                  "btbnep.filter_multi_addr_response_message",
532             FT_UINT16, BASE_HEX, VALS(filter_multi_addr_response_message_vals), 0x00,
533             NULL, HFILL }
534         },
535         { &hf_btbnep_list_length,
536             { "List Length",                       "btbnep.list_length",
537             FT_UINT16, BASE_DEC, NULL, 0x00,
538             NULL, HFILL }
539         },
540         /* http://www.iana.org/assignments/ethernet-numbers */
541         { &hf_btbnep_network_type_start,
542             { "Network Protocol Type Range Start", "btbnep.network_type_start",
543             FT_UINT16, BASE_HEX, VALS(etype_vals), 0x00,
544             NULL, HFILL }
545         },
546         { &hf_btbnep_network_type_end,
547             { "Network Protocol Type Range End",   "btbnep.network_type_end",
548             FT_UINT16, BASE_HEX, VALS(etype_vals), 0x00,
549             NULL, HFILL }
550         },
551         { &hf_btbnep_multicast_address_start,
552             { "Multicast Address Start",           "btbnep.multicast_address_start",
553             FT_ETHER, BASE_NONE, NULL, 0x00,
554             NULL, HFILL }
555         },
556         { &hf_btbnep_multicast_address_end,
557             { "Multicast Address End",             "btbnep.multicast_address_end",
558             FT_ETHER, BASE_NONE, NULL, 0x00,
559             NULL, HFILL }
560         },
561         { &hf_btbnep_dst,
562             { "Destination",                       "btbnep.dst",
563             FT_ETHER, BASE_NONE, NULL, 0x0,
564             "Destination Hardware Address", HFILL }
565         },
566         { &hf_btbnep_src,
567             { "Source",                            "btbnep.src",
568             FT_ETHER, BASE_NONE, NULL, 0x0,
569             "Source Hardware Address", HFILL }
570         },
571         { &hf_btbnep_len,
572             { "Length",                            "btbnep.len",
573             FT_UINT16, BASE_DEC, NULL, 0x0,
574             NULL, HFILL }
575         },
576         { &hf_btbnep_invalid_lentype,
577             { "Invalid length/type",               "btbnep.invalid_lentype",
578             FT_UINT16, BASE_HEX_DEC, NULL, 0x0,
579             NULL, HFILL }
580         },
581         { &hf_btbnep_type,
582             { "Type",                              "btbnep.type",
583             FT_UINT16, BASE_HEX, VALS(etype_vals), 0x0,
584             NULL, HFILL }
585         },
586         { &hf_btbnep_addr,
587             { "Address",                           "btbnep.addr",
588             FT_ETHER, BASE_NONE, NULL, 0x0,
589             "Source or Destination Hardware Address", HFILL }
590         },
591         { &hf_btbnep_lg,
592             { "LG bit",                            "btbnep.lg",
593             FT_BOOLEAN, 24, TFS(&lg_tfs), 0x020000,
594             "Specifies if this is a locally administered or globally unique (IEEE assigned) address", HFILL }
595         },
596         { &hf_btbnep_ig,
597             { "IG bit",                            "btbnep.ig",
598             FT_BOOLEAN, 24, TFS(&ig_tfs), 0x010000,
599             "Specifies if this is an individual (unicast) or group (broadcast/multicast) address", HFILL }
600         }
601     };
602 
603     static gint *ett[] = {
604         &ett_btbnep,
605         &ett_addr
606     };
607 
608     static ei_register_info ei[] = {
609         { &ei_btbnep_src_not_group_address, { "btbnep.src.not_group_address", PI_PROTOCOL, PI_WARN, "Source MAC must not be a group address: IEEE 802.3-2002, Section 3.2.3(b)", EXPFILL }},
610         { &ei_btbnep_invalid_lentype, { "btbnep.invalid_lentype.expert", PI_PROTOCOL, PI_WARN, "Invalid length/type", EXPFILL }},
611         { &ei_btbnep_len_past_end, { "btbnep.len.past_end", PI_MALFORMED, PI_ERROR, "Length field value goes past the end of the payload", EXPFILL }},
612     };
613 
614     proto_btbnep = proto_register_protocol("Bluetooth BNEP Protocol", "BT BNEP", "btbnep");
615     btbnep_handle = register_dissector("btbnep", dissect_btbnep, proto_btbnep);
616 
617     proto_register_field_array(proto_btbnep, hf, array_length(hf));
618     proto_register_subtree_array(ett, array_length(ett));
619     expert_btbnep = expert_register_protocol(proto_btbnep);
620     expert_register_field_array(expert_btbnep, ei, array_length(ei));
621 
622     module = prefs_register_protocol_subtree("Bluetooth", proto_btbnep, NULL);
623     prefs_register_static_text_preference(module, "bnep.version",
624             "Bluetooth Protocol BNEP version: 1.0",
625             "Version of protocol supported by this dissector.");
626 
627     prefs_register_bool_preference(module, "bnep.top_dissect",
628             "Dissecting the top protocols", "Dissecting the top protocols",
629             &top_dissect);
630 }
631 
632 void
proto_reg_handoff_btbnep(void)633 proto_reg_handoff_btbnep(void)
634 {
635     ipx_handle    = find_dissector_add_dependency("ipx", proto_btbnep);
636     llc_handle    = find_dissector_add_dependency("llc", proto_btbnep);
637     ethertype_handle = find_dissector_add_dependency("ethertype", proto_btbnep);
638 
639     dissector_add_string("bluetooth.uuid", "1115", btbnep_handle);
640     dissector_add_string("bluetooth.uuid", "1116", btbnep_handle);
641     dissector_add_string("bluetooth.uuid", "1117", btbnep_handle);
642 
643     dissector_add_uint("btl2cap.psm", BTL2CAP_PSM_BNEP, btbnep_handle);
644     dissector_add_for_decode_as("btl2cap.cid", btbnep_handle);
645 }
646 
647 /*
648  * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
649  *
650  * Local variables:
651  * c-basic-offset: 4
652  * tab-width: 8
653  * indent-tabs-mode: nil
654  * End:
655  *
656  * vi: set shiftwidth=4 tabstop=8 expandtab:
657  * :indentSize=4:tabSize=8:noTabs=true:
658  */
659