Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-btrfcomm.c
blob5728e7c98e8474de09056d3799e23c84e021b27c
1 /* packet-btrfcomm.c
2 * Routines for Bluetooth RFCOMM protocol dissection
3 * and RFCOMM based profile dissection:
4 * - Dial-Up Networking Profile (DUN)
5 * - Serial Port Profile (SPP)
6 * - Global Navigation Satellite System (GNSS)
8 * Copyright 2002, Wolfgang Hansmann <hansmann@cs.uni-bonn.de>
10 * Refactored for wireshark checkin
11 * Ronnie Sahlberg 2006
13 * Wireshark - Network traffic analyzer
14 * By Gerald Combs <gerald@wireshark.org>
15 * Copyright 1998 Gerald Combs
17 * SPDX-License-Identifier: GPL-2.0-or-later
20 #include "config.h"
22 #include <epan/packet.h>
23 #include <epan/prefs.h>
24 #include <epan/expert.h>
25 #include <epan/uat.h>
26 #include <epan/decode_as.h>
27 #include <epan/proto_data.h>
29 #include "packet-bluetooth.h"
30 #include "packet-btsdp.h"
31 #include "packet-btl2cap.h"
32 #include "packet-btrfcomm.h"
34 static int hf_pf;
35 static int hf_ea;
36 static int hf_len;
37 static int hf_frame_type;
38 static int hf_cr;
39 static int hf_dlci;
40 static int hf_channel;
41 static int hf_direction;
42 static int hf_priority;
43 static int hf_error_recovery_mode;
44 static int hf_max_frame_size;
45 static int hf_max_retrans;
46 static int hf_fc_credits;
48 static int hf_mcc_pn_parameters;
49 static int hf_pn_i14;
50 static int hf_pn_c14;
52 static int hf_mcc;
53 static int hf_mcc_types;
54 static int hf_mcc_len;
55 static int hf_mcc_ea;
56 static int hf_mcc_cr;
57 static int hf_mcc_cmd;
59 static int hf_msc_parameters;
60 static int hf_msc_fc;
61 static int hf_msc_rtc;
62 static int hf_msc_rtr;
63 static int hf_msc_ic;
64 static int hf_msc_dv;
65 static int hf_msc_l;
66 static int hf_msc_break_bits;
68 static int hf_fcs;
70 static int hf_dun_at_cmd;
71 static int hf_spp_data;
72 static int hf_gnss_data;
74 static int hf_mcc_dlci;
75 static int hf_mcc_channel;
76 static int hf_mcc_direction;
77 static int hf_mcc_const_1;
79 static int hf_mcc_pn_dlci;
80 static int hf_mcc_pn_channel;
81 static int hf_mcc_pn_direction;
82 static int hf_mcc_pn_zeros_padding;
84 static int hf_acknowledgement_timer_t1;
85 static int hf_address;
86 static int hf_control;
88 /* Initialize the protocol and registered fields */
89 int proto_btrfcomm;
90 static int proto_btdun;
91 static int proto_btspp;
92 static int proto_btgnss;
94 /* Initialize the subtree pointers */
95 static int ett_btrfcomm;
96 static int ett_btrfcomm_ctrl;
97 static int ett_addr;
98 static int ett_control;
99 static int ett_mcc;
100 static int ett_ctrl_pn_ci;
101 static int ett_ctrl_pn_v24;
102 static int ett_dlci;
103 static int ett_mcc_dlci;
105 static int ett_btdun;
106 static int ett_btspp;
107 static int ett_btgnss;
109 static expert_field ei_btrfcomm_mcc_length_bad;
111 static dissector_handle_t btrfcomm_handle;
112 static dissector_handle_t btdun_handle;
113 static dissector_handle_t btspp_handle;
114 static dissector_handle_t btgnss_handle;
116 static dissector_table_t rfcomm_dlci_dissector_table;
118 static wmem_tree_t *service_directions;
120 typedef struct {
121 uint32_t direction;
122 uint32_t end_in;
123 } service_direction_t;
125 typedef struct {
126 unsigned channel;
127 char* payload_proto_name;
128 dissector_handle_t payload_proto;
129 } uat_rfcomm_channels_t;
131 static bool rfcomm_channels_enabled;
132 static uat_t *uat_rfcomm_channels;
133 static uat_rfcomm_channels_t *rfcomm_channels;
134 static unsigned num_rfcomm_channels;
136 UAT_DEC_CB_DEF(rfcomm_channels, channel, uat_rfcomm_channels_t)
137 UAT_DISSECTOR_DEF(rfcomm_channels, payload_proto, payload_proto, payload_proto_name, uat_rfcomm_channels_t)
139 static uat_field_t uat_rfcomm_channels_fields[] = {
140 UAT_FLD_DEC(rfcomm_channels, channel, "RFCOMM Channel",
141 "Range: 0-32"),
142 UAT_FLD_DISSECTOR(rfcomm_channels, payload_proto, "Payload dissector",
143 "Dissector name used to decode RFCOMM channel"),
144 UAT_END_FIELDS
147 static dissector_handle_t ppp_handle;
149 static const value_string vs_ctl_pn_i[] = {
150 {0x0, "use UIH Frames"},
151 #if 0 /* specified by 07.10, but not used by RFCOMM */
152 {0x1, "use UI Frames"},
153 {0x2, "use I Frames"},
154 #endif
155 {0, NULL}
158 static const value_string vs_ctl_pn_cl[] = {
160 {0x0, "no credit based flow control scheme"},
161 {0xe, "support of credit based flow control scheme (resp)"},
162 {0xf, "support of credit based flow control scheme (req)"},
163 #if 0 /* specified by 07.10. Redefined by RFCOMM */
164 {0x0, "type 1 (unstructured octet stream)"},
165 {0x1, "type 2 (unstructured octet stream with flow control)"},
166 {0x2, "type 3 (uninterruptible framed data)"},
167 {0x3, "type 4 (interruptible framed data)"},
168 #endif
169 {0, NULL}
173 static const value_string vs_frame_type[] = {
174 /* masked 0xef */
175 {0x2f, "Set Asynchronous Balanced Mode (SABM)"},
176 {0x63, "Unnumbered Acknowledgement (UA)"},
177 {0x0f, "Disconnected Mode (DM)"},
178 {0x43, "Disconnect (DISC)"},
179 {0xef, "Unnumbered Information with Header check (UIH)"},
180 #if 0 /* specified by 07.10, but not used by RFCOMM */
181 {0x03, "Unnumbered Information (UI)"},
182 #endif
183 {0, NULL}
187 static const value_string vs_frame_type_short[] = {
188 /* masked 0xef */
189 {0x2f, "SABM"},
190 {0x63, "UA"},
191 {0x0f, "DM"},
192 {0x43, "DISC"},
193 {0xef, "UIH"},
194 #if 0 /* specified by 07.10, but not used by RFCOMM */
195 {0x03, "UI"},
196 #endif
197 {0, NULL}
200 #define FRAME_TYPE_SABM 0x2F
201 #define FRAME_TYPE_UIH 0xEF
203 static const value_string vs_ctl[] = {
204 /* masked 0xfc */
205 {0x20, "DLC Parameter Negotiation (PN)"},
206 {0x08, "Test Command (Test)"},
207 {0x28, "Flow Control On Command (FCon)"},
208 {0x18, "Flow Control Off Command (FCoff)"},
209 {0x38, "Modem Status Command (MSC)"},
210 {0x04, "Non Supported Command Response (NSC)"},
211 {0x24, "Remote Port Negotiation Command (RPN)"},
212 {0x14, "Remote Line Status Command (RLS)"},
213 #if 0 /* Specified by 07.10, but not used by RFCOMM */
214 {0x10, "Power Saving Control (PSC)"},
215 {0x30, "Multiplexer close down (CLD)"},
216 {0x34, "Service Negotiation Command (SNC)"},
217 #endif
218 #if 0 /* old */
219 {0x80, "DLC parameter negotiation (PN)"},
220 {0x20, "Test Command (Test)"},
221 {0xa0, "Flow Control On Command (FCon)"},
222 {0x60, "Flow Control Off Command (FCoff)"},
223 {0xe0, "Modem Status Command (MSC)"},
224 {0x10, "Non Supported Command Response (NSC)"},
225 {0x90, "Remote Port Negotiation Command (RPN)"},
226 {0x50, "Remote Line Status Command (RLS)"},
227 {0x40, "Power Saving Control (PSC)"},
228 {0xc0, "Multiplexer close down (CLD)"},
229 {0xd0, "Service Negotiation Command (SNC)"},
230 #endif
231 {0x0, NULL}
234 static const value_string vs_ea[] = {
235 {1, "Last field octet"},
236 {0, "More field octets following"},
237 {0, NULL}
240 void proto_register_btrfcomm(void);
241 void proto_reg_handoff_btrfcomm(void);
242 void proto_register_btdun(void);
243 void proto_reg_handoff_btdun(void);
244 void proto_register_btspp(void);
245 void proto_reg_handoff_btspp(void);
246 void proto_register_btgnss(void);
247 void proto_reg_handoff_btgnss(void);
249 #define PROTO_DATA_BTRFCOMM_DIRECTED_CHANNEL 0
251 static void btrfcomm_directed_channel_prompt(packet_info *pinfo, char* result)
253 uint8_t *value_data;
255 value_data = (uint8_t *) p_get_proto_data(pinfo->pool, pinfo, proto_btrfcomm, PROTO_DATA_BTRFCOMM_DIRECTED_CHANNEL);
256 if (value_data)
257 snprintf(result, MAX_DECODE_AS_PROMPT_LEN, "RFCOMM Channel %d (direction: %u) as", (unsigned) (*value_data) >> 1, (unsigned) (*value_data) & 1);
258 else
259 snprintf(result, MAX_DECODE_AS_PROMPT_LEN, "Unknown RFCOMM Channel");
262 static void *btrfcomm_directed_channel_value(packet_info *pinfo)
264 uint8_t *value_data;
266 value_data = (uint8_t *) p_get_proto_data(pinfo->pool, pinfo, proto_btrfcomm, PROTO_DATA_BTRFCOMM_DIRECTED_CHANNEL);
268 if (value_data)
269 return GUINT_TO_POINTER((unsigned long)*value_data);
271 return NULL;
274 static dissector_handle_t
275 find_proto_by_channel(unsigned channel) {
276 unsigned i_channel;
278 for (i_channel = 0; i_channel < num_rfcomm_channels; ++i_channel) {
279 if (rfcomm_channels[i_channel].channel == channel) {
280 return rfcomm_channels[i_channel].payload_proto;
283 return NULL;
286 static int
287 get_le_multi_byte_value(tvbuff_t *tvb, int offset, proto_tree *tree, uint32_t *val_ptr, int hf_index)
289 uint8_t byte, bc = 0;
290 uint32_t val = 0;
291 int start_offset = offset;
293 do {
294 byte = tvb_get_uint8(tvb, offset);
295 offset += 1;
296 val |= ((byte >> 1) & 0xff) << (bc++ * 7);
297 } while (((byte & 0x1) == 0) && (bc <= 4));
299 *val_ptr = val;
301 if (hf_index > 0) {
302 proto_tree_add_uint(tree, hf_index, tvb, start_offset, offset - start_offset, val);
305 return offset;
309 static int
310 dissect_ctrl_pn(proto_tree *t, tvbuff_t *tvb, int offset, uint8_t *mcc_channel)
312 proto_tree *st;
313 proto_item *ti;
314 proto_tree *dlci_tree;
315 proto_item *dlci_item;
316 proto_item *item;
317 int mcc_dlci;
318 uint8_t flags;
320 proto_tree_add_item(t, hf_mcc_pn_zeros_padding, tvb, offset, 1, ENC_LITTLE_ENDIAN);
322 /* mcc dlci */
323 mcc_dlci = tvb_get_uint8(tvb, offset) & 0x3f;
324 *mcc_channel = mcc_dlci >> 1;
326 dlci_item = proto_tree_add_item(t, hf_mcc_pn_dlci, tvb, offset, 1, ENC_LITTLE_ENDIAN);
327 proto_item_append_text(dlci_item, " (Direction: %d, Channel: %u)", mcc_dlci & 0x01, *mcc_channel);
329 dlci_tree = proto_item_add_subtree(dlci_item, ett_mcc_dlci);
330 proto_tree_add_item(dlci_tree, hf_mcc_pn_channel, tvb, offset, 1, ENC_LITTLE_ENDIAN);
331 proto_tree_add_item(dlci_tree, hf_mcc_pn_direction, tvb, offset, 1, ENC_LITTLE_ENDIAN);
332 offset += 1;
334 flags = tvb_get_uint8(tvb, offset);
336 ti = proto_tree_add_none_format(t, hf_mcc_pn_parameters, tvb, offset, 1, "I1-I4: 0x%x, C1-C4: 0x%x", flags & 0xf, (flags >> 4) & 0xf);
337 st = proto_item_add_subtree(ti, ett_ctrl_pn_ci);
339 proto_tree_add_item(st, hf_pn_c14, tvb, offset, 1, ENC_LITTLE_ENDIAN);
340 proto_tree_add_item(st, hf_pn_i14, tvb, offset, 1, ENC_LITTLE_ENDIAN);
341 offset += 1;
343 /* priority */
344 proto_tree_add_item(t, hf_priority, tvb, offset, 1, ENC_LITTLE_ENDIAN);
345 offset += 1;
347 /* Ack timer */
348 item = proto_tree_add_item(t, hf_acknowledgement_timer_t1, tvb, offset, 1, ENC_LITTLE_ENDIAN);
349 proto_item_append_text(item, "(%d ms)", (uint32_t)tvb_get_uint8(tvb, offset) * 100);
350 offset += 1;
352 /* max frame size */
353 proto_tree_add_item(t, hf_max_frame_size, tvb, offset, 2, ENC_LITTLE_ENDIAN);
354 offset += 2;
356 /* max retrans */
357 proto_tree_add_item(t, hf_max_retrans, tvb, offset, 1, ENC_LITTLE_ENDIAN);
358 offset += 1;
360 /* error recovery mode */
361 proto_tree_add_item(t, hf_error_recovery_mode, tvb, offset, 1, ENC_LITTLE_ENDIAN);
362 offset += 1;
364 return offset;
367 static int
368 dissect_ctrl_msc(proto_tree *t, tvbuff_t *tvb, int offset, int length, uint8_t *mcc_channel)
371 proto_tree *st;
372 proto_item *it;
373 proto_tree *dlci_tree;
374 proto_item *dlci_item;
375 uint8_t mcc_dlci;
376 uint8_t status;
377 int start_offset;
379 mcc_dlci = tvb_get_uint8(tvb, offset) >> 2;
380 *mcc_channel = mcc_dlci >> 1;
382 dlci_item = proto_tree_add_item(t, hf_mcc_dlci, tvb, offset, 1, ENC_LITTLE_ENDIAN);
383 proto_item_append_text(dlci_item, " (Direction: %d, Channel: %u)", mcc_dlci & 0x01, *mcc_channel);
385 dlci_tree = proto_item_add_subtree(dlci_item, ett_mcc_dlci);
386 proto_tree_add_item(dlci_tree, hf_mcc_channel, tvb, offset, 1, ENC_LITTLE_ENDIAN);
387 proto_tree_add_item(dlci_tree, hf_mcc_direction, tvb, offset, 1, ENC_LITTLE_ENDIAN);
389 proto_tree_add_item(t, hf_mcc_const_1, tvb, offset, 1, ENC_LITTLE_ENDIAN);
390 proto_tree_add_item(t, hf_mcc_ea, tvb, offset, 1, ENC_LITTLE_ENDIAN);
392 offset += 1;
394 start_offset = offset;
395 status = tvb_get_uint8(tvb, offset);
396 it = proto_tree_add_none_format(t, hf_msc_parameters, tvb, offset, 1, "V.24 Signals: FC = %d, RTC = %d, RTR = %d, IC = %d, DV = %d", (status >> 1) & 1,
397 (status >> 2) & 1, (status >> 3) & 1,
398 (status >> 6) & 1, (status >> 7) & 1);
399 st = proto_item_add_subtree(it, ett_ctrl_pn_v24);
401 proto_tree_add_item(st, hf_msc_fc, tvb, offset, 1, ENC_LITTLE_ENDIAN);
402 proto_tree_add_item(st, hf_msc_rtc, tvb, offset, 1, ENC_LITTLE_ENDIAN);
403 proto_tree_add_item(st, hf_msc_rtr, tvb, offset, 1, ENC_LITTLE_ENDIAN);
404 proto_tree_add_item(st, hf_msc_ic, tvb, offset, 1, ENC_LITTLE_ENDIAN);
405 proto_tree_add_item(st, hf_msc_dv, tvb, offset, 1, ENC_LITTLE_ENDIAN);
406 offset += 1;
408 if (length == 3) {
409 proto_tree_add_item(t, hf_msc_break_bits, tvb, offset, 1, ENC_LITTLE_ENDIAN);
410 proto_tree_add_item(t, hf_msc_l, tvb, offset, 1, ENC_LITTLE_ENDIAN);
411 offset += 1;
414 proto_item_set_len(it, offset - start_offset);
416 return offset;
419 static int
420 dissect_btrfcomm_address(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree *tree, uint8_t *ea_flagp, uint8_t *cr_flagp, uint8_t *dlcip)
422 proto_item *ti;
423 proto_tree *addr_tree;
424 proto_tree *dlci_tree = NULL;
425 proto_item *dlci_item = NULL;
426 uint8_t dlci, cr_flag, ea_flag, flags, channel;
428 flags = tvb_get_uint8(tvb, offset);
430 ea_flag = flags & 0x01;
431 if (ea_flagp) {
432 *ea_flagp = ea_flag;
435 cr_flag = (flags & 0x02) ? 1 : 0;
436 if (cr_flagp) {
437 *cr_flagp = cr_flag;
440 dlci = flags >> 2;
441 if (dlcip) {
442 *dlcip = dlci;
445 ti = proto_tree_add_none_format(tree, hf_address, tvb, offset, 1, "Address: E/A flag: %d, C/R flag: %d, Direction: %d, Channel: %u", ea_flag, cr_flag, dlci & 0x01, dlci >> 1);
446 addr_tree = proto_item_add_subtree(ti, ett_addr);
448 dlci_item = proto_tree_add_item(addr_tree, hf_dlci, tvb, offset, 1, ENC_LITTLE_ENDIAN);
449 channel = dlci >> 1;
450 proto_item_append_text(dlci_item, " (Direction: %d, Channel: %u)", dlci & 0x01, channel);
452 if (p_get_proto_data(pinfo->pool, pinfo, proto_btrfcomm, PROTO_DATA_BTRFCOMM_DIRECTED_CHANNEL) == NULL) {
453 uint8_t *value_data;
455 value_data = wmem_new(wmem_file_scope(), uint8_t);
456 *value_data = dlci;
458 p_add_proto_data(pinfo->pool, pinfo, proto_btrfcomm, PROTO_DATA_BTRFCOMM_DIRECTED_CHANNEL, value_data);
461 dlci_tree = proto_item_add_subtree(dlci_item, ett_dlci);
462 proto_tree_add_item(dlci_tree, hf_channel, tvb, offset, 1, ENC_LITTLE_ENDIAN);
463 proto_tree_add_item(dlci_tree, hf_direction, tvb, offset, 1, ENC_LITTLE_ENDIAN);
465 proto_tree_add_item(addr_tree, hf_cr, tvb, offset, 1, ENC_LITTLE_ENDIAN);
466 proto_tree_add_item(addr_tree, hf_ea, tvb, offset, 1, ENC_LITTLE_ENDIAN);
467 offset += 1;
469 return offset;
472 static int
473 dissect_btrfcomm_control(tvbuff_t *tvb, int offset, proto_tree *tree, uint8_t *pf_flagp, uint8_t *frame_typep)
475 proto_item *ti;
476 proto_tree *hctl_tree;
477 uint8_t frame_type, pf_flag, flags;
479 flags = tvb_get_uint8(tvb, offset);
481 pf_flag = (flags & 0x10) ? 1 : 0;
482 if (pf_flagp) {
483 *pf_flagp = pf_flag;
486 frame_type = flags & 0xef;
487 if (frame_typep) {
488 *frame_typep = frame_type;
491 ti = proto_tree_add_none_format(tree, hf_control, tvb, offset, 1, "Control: Frame type: %s (0x%x), P/F flag: %d",
492 val_to_str_const(frame_type, vs_frame_type, "Unknown"), frame_type, pf_flag);
493 hctl_tree = proto_item_add_subtree(ti, ett_control);
495 proto_tree_add_item(hctl_tree, hf_pf, tvb, offset, 1, ENC_LITTLE_ENDIAN);
496 proto_tree_add_item(hctl_tree, hf_frame_type, tvb, offset, 1, ENC_LITTLE_ENDIAN);
498 offset += 1;
499 return offset;
504 static int
505 dissect_btrfcomm_payload_length(tvbuff_t *tvb, int offset, proto_tree *tree, uint16_t *frame_lenp)
507 uint16_t frame_len;
508 int start_offset = offset;
510 frame_len = tvb_get_uint8(tvb, offset);
511 offset += 1;
513 if (frame_len & 0x01) {
514 frame_len >>= 1; /* 0 - 127 */
515 } else {
516 frame_len >>= 1; /* 128 - ... */
517 frame_len |= (tvb_get_uint8(tvb, offset)) << 7;
518 offset += 1;
521 proto_tree_add_uint(tree, hf_len, tvb, start_offset, offset - start_offset, frame_len);
523 if (frame_lenp) {
524 *frame_lenp = frame_len;
527 return offset;
530 static int
531 dissect_btrfcomm_MccType(tvbuff_t *tvb, int offset, proto_tree *tree, uint8_t *mcc_cr_flagp, uint8_t *mcc_ea_flagp, uint32_t *mcc_typep)
533 int start_offset = offset;
534 proto_item *ti;
535 proto_tree *mcc_tree;
536 uint8_t flags, mcc_cr_flag, mcc_ea_flag;
537 uint32_t mcc_type;
539 flags = tvb_get_uint8(tvb, offset);
541 mcc_cr_flag = (flags & 0x2) ? 1 : 0;
542 if (mcc_cr_flagp) {
543 *mcc_cr_flagp = mcc_cr_flag;
546 mcc_ea_flag = flags & 0x1;
547 if (mcc_ea_flagp) {
548 *mcc_ea_flagp = mcc_ea_flag;
551 offset = get_le_multi_byte_value(tvb, offset, tree, &mcc_type, -1);
552 mcc_type = (mcc_type >> 1) & 0x3f; /* shift c/r flag off */
553 if (mcc_typep) {
554 *mcc_typep = mcc_type;
557 ti = proto_tree_add_none_format(tree, hf_mcc_types, tvb, start_offset, offset - start_offset,
558 "Type: %s (0x%x), C/R flag = %d, E/A flag = %d",
559 val_to_str_const(mcc_type, vs_ctl, "Unknown"),
560 mcc_type, mcc_cr_flag, mcc_ea_flag);
561 mcc_tree = proto_item_add_subtree(ti, ett_mcc);
563 proto_tree_add_item(mcc_tree, hf_mcc_cmd, tvb, start_offset, offset - start_offset, ENC_LITTLE_ENDIAN);
564 proto_tree_add_item(mcc_tree, hf_mcc_cr, tvb, start_offset, 1, ENC_LITTLE_ENDIAN);
565 proto_tree_add_item(mcc_tree, hf_mcc_ea, tvb, start_offset, 1, ENC_LITTLE_ENDIAN);
567 return offset;
570 static int
571 dissect_btrfcomm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
573 proto_item *ti;
574 proto_tree *rfcomm_tree;
575 int offset = 0;
576 int fcs_offset;
577 uint8_t dlci, cr_flag, ea_flag;
578 uint8_t frame_type, pf_flag;
579 uint16_t frame_len;
580 btl2cap_data_t *l2cap_data;
581 service_info_t *service_info = NULL;
583 /* Reject the packet if data is NULL */
584 if (data == NULL)
585 return 0;
586 l2cap_data = (btl2cap_data_t *) data;
588 ti = proto_tree_add_item(tree, proto_btrfcomm, tvb, offset, tvb_captured_length(tvb), ENC_NA);
589 rfcomm_tree = proto_item_add_subtree(ti, ett_btrfcomm);
591 col_set_str(pinfo->cinfo, COL_PROTOCOL, "RFCOMM");
593 switch (pinfo->p2p_dir) {
594 case P2P_DIR_SENT:
595 col_set_str(pinfo->cinfo, COL_INFO, "Sent ");
596 break;
597 case P2P_DIR_RECV:
598 col_set_str(pinfo->cinfo, COL_INFO, "Rcvd ");
599 break;
600 default:
601 col_set_str(pinfo->cinfo, COL_INFO, "UnknownDirection ");
602 break;
605 /* flags and dlci */
606 offset = dissect_btrfcomm_address(tvb, pinfo, offset, rfcomm_tree, &ea_flag, &cr_flag, &dlci);
607 /* pf and frame type */
608 offset = dissect_btrfcomm_control(tvb, offset, rfcomm_tree, &pf_flag, &frame_type);
609 /* payload length */
610 offset = dissect_btrfcomm_payload_length(tvb, offset, rfcomm_tree, &frame_len);
612 if (dlci && (frame_len || (frame_type == FRAME_TYPE_UIH) || (frame_type == FRAME_TYPE_SABM))) {
613 wmem_tree_key_t key[10];
614 uint32_t k_interface_id;
615 uint32_t k_adapter_id;
616 uint32_t k_psm;
617 uint32_t k_direction;
618 uint32_t k_bd_addr_oui;
619 uint32_t k_bd_addr_id;
620 uint32_t k_service_type;
621 uint32_t k_frame_number;
622 uint32_t k_chandle;
623 uint32_t k_channel;
624 uint32_t k_dlci;
625 service_direction_t *service_direction;
626 wmem_tree_t *subtree;
628 k_interface_id = l2cap_data->interface_id;
629 k_adapter_id = l2cap_data->adapter_id;
630 k_chandle = l2cap_data->chandle;
631 k_psm = l2cap_data->psm;
632 k_channel = dlci >> 1;
633 k_frame_number = pinfo->num;
634 k_dlci = dlci;
636 key[0].length = 1;
637 key[0].key = &k_interface_id;
638 key[1].length = 1;
639 key[1].key = &k_adapter_id;
640 key[2].length = 1;
641 key[2].key = &k_chandle;
642 key[3].length = 1;
643 key[3].key = &k_psm;
644 key[4].length = 1;
645 key[4].key = &k_dlci;
647 if (!pinfo->fd->visited && frame_type == FRAME_TYPE_SABM) {
648 key[5].length = 0;
649 key[5].key = NULL;
651 subtree = (wmem_tree_t *) wmem_tree_lookup32_array(service_directions, key);
652 service_direction = (subtree) ? (service_direction_t *) wmem_tree_lookup32_le(subtree, k_frame_number) : NULL;
653 if (service_direction && service_direction->end_in == bluetooth_max_disconnect_in_frame) {
654 service_direction->end_in = k_frame_number;
657 key[5].length = 1;
658 key[5].key = &k_frame_number;
659 key[6].length = 0;
660 key[6].key = NULL;
662 service_direction = wmem_new(wmem_file_scope(), service_direction_t);
663 service_direction->direction = (pinfo->p2p_dir == P2P_DIR_RECV) ? P2P_DIR_SENT : P2P_DIR_RECV;
664 service_direction->end_in = bluetooth_max_disconnect_in_frame;
666 wmem_tree_insert32_array(service_directions, key, service_direction);
668 key[4].key = &k_channel;
669 key[5].length = 0;
670 key[5].key = NULL;
672 subtree = (wmem_tree_t *) wmem_tree_lookup32_array(service_directions, key);
673 service_direction = (subtree) ? (service_direction_t *) wmem_tree_lookup32_le(subtree, k_frame_number) : NULL;
674 if (service_direction && service_direction->end_in > k_frame_number) {
675 k_direction = service_direction->direction;
676 } else {
677 if (dlci & 0x01)
678 k_direction = (l2cap_data->is_local_psm) ? P2P_DIR_RECV : P2P_DIR_SENT;
679 else
680 k_direction = (l2cap_data->is_local_psm) ? P2P_DIR_SENT : P2P_DIR_RECV;
683 k_psm = SDP_PSM_DEFAULT;
684 if (k_direction == P2P_DIR_RECV) {
685 k_bd_addr_oui = l2cap_data->remote_bd_addr_oui;
686 k_bd_addr_id = l2cap_data->remote_bd_addr_id;
687 } else {
688 k_bd_addr_oui = 0;
689 k_bd_addr_id = 0;
691 k_service_type = BTSDP_RFCOMM_PROTOCOL_UUID;
693 key[2].length = 1;
694 key[2].key = &k_psm;
695 key[3].length = 1;
696 key[3].key = &k_direction;
697 key[4].length = 1;
698 key[4].key = &k_bd_addr_oui;
699 key[5].length = 1;
700 key[5].key = &k_bd_addr_id;
701 key[6].length = 1;
702 key[6].key = &k_service_type;
703 key[7].length = 1;
704 key[7].key = &k_channel;
705 key[8].length = 1;
706 key[8].key = &k_frame_number;
707 key[9].length = 0;
708 key[9].key = NULL;
710 service_info = btsdp_get_service_info(key);
712 if (service_info && service_info->interface_id == l2cap_data->interface_id &&
713 service_info->adapter_id == l2cap_data->adapter_id &&
714 service_info->sdp_psm == SDP_PSM_DEFAULT &&
715 ((service_info->direction == P2P_DIR_RECV &&
716 service_info->bd_addr_oui == l2cap_data->remote_bd_addr_oui &&
717 service_info->bd_addr_id == l2cap_data->remote_bd_addr_id) ||
718 (service_info->direction != P2P_DIR_RECV &&
719 service_info->bd_addr_oui == 0 &&
720 service_info->bd_addr_id == 0)) &&
721 service_info->type == BTSDP_RFCOMM_PROTOCOL_UUID &&
722 service_info->channel == (dlci >> 1)) {
724 } else {
725 service_info = wmem_new0(pinfo->pool, service_info_t);
729 col_append_fstr(pinfo->cinfo, COL_INFO, "%s Channel=%u ",
730 val_to_str_const(frame_type, vs_frame_type_short, "Unknown"), dlci >> 1);
731 if (dlci && (frame_type == FRAME_TYPE_SABM) && service_info) {
732 if (service_info->uuid.size==16)
733 col_append_fstr(pinfo->cinfo, COL_INFO, "(UUID128: %s) ", print_bluetooth_uuid(pinfo->pool, &service_info->uuid));
734 else
735 col_append_fstr(pinfo->cinfo, COL_INFO, "(%s) ",
736 val_to_str_ext_const(service_info->uuid.bt_uuid, &bluetooth_uuid_vals_ext, "Unknown"));
739 /* UID frame */
740 if ((frame_type == FRAME_TYPE_UIH) && dlci && pf_flag) {
741 col_append_str(pinfo->cinfo, COL_INFO, "UID ");
743 /* add credit based flow control byte */
744 proto_tree_add_item(rfcomm_tree, hf_fc_credits, tvb, offset, 1, ENC_LITTLE_ENDIAN);
745 offset += 1;
749 fcs_offset = offset + frame_len;
751 /* multiplexer control command */
752 if (!dlci && frame_len) {
753 proto_item *mcc_ti;
754 proto_tree *ctrl_tree;
755 proto_tree *dlci_tree;
756 proto_item *dlci_item;
757 uint32_t mcc_type, length;
758 uint8_t mcc_cr_flag, mcc_ea_flag;
759 uint8_t mcc_channel;
760 uint8_t mcc_dlci;
761 int start_offset = offset;
763 mcc_ti = proto_tree_add_item(rfcomm_tree, hf_mcc, tvb, offset, 1, ENC_NA);
764 ctrl_tree = proto_item_add_subtree(mcc_ti, ett_btrfcomm_ctrl);
766 /* mcc type */
767 offset = dissect_btrfcomm_MccType(tvb, offset, ctrl_tree, &mcc_cr_flag, &mcc_ea_flag, &mcc_type);
769 /* len */
770 offset = get_le_multi_byte_value(tvb, offset, ctrl_tree, &length, hf_mcc_len);
772 if (length > (uint32_t) tvb_reported_length_remaining(tvb, offset)) {
773 expert_add_info_format(pinfo, ctrl_tree, &ei_btrfcomm_mcc_length_bad, "Huge MCC length: %u", length);
774 return offset;
777 switch(mcc_type) {
778 case 0x20: /* DLC Parameter Negotiation */
779 dissect_ctrl_pn(ctrl_tree, tvb, offset, &mcc_channel);
780 break;
781 case 0x24: /* Remote Port Negotiation */
782 mcc_dlci = tvb_get_uint8(tvb, offset) >> 2;
783 mcc_channel = mcc_dlci >> 1;
785 dlci_item = proto_tree_add_item(ctrl_tree, hf_mcc_dlci, tvb, offset, 1, ENC_LITTLE_ENDIAN);
786 proto_item_append_text(dlci_item, " (Direction: %d, Channel: %u)", mcc_dlci & 0x01, mcc_channel);
788 dlci_tree = proto_item_add_subtree(dlci_item, ett_mcc_dlci);
789 proto_tree_add_item(dlci_tree, hf_mcc_channel, tvb, offset, 1, ENC_LITTLE_ENDIAN);
790 proto_tree_add_item(dlci_tree, hf_mcc_direction, tvb, offset, 1, ENC_LITTLE_ENDIAN);
792 proto_tree_add_item(ctrl_tree, hf_mcc_const_1, tvb, offset, 1, ENC_LITTLE_ENDIAN);
793 proto_tree_add_item(ctrl_tree, hf_mcc_ea, tvb, offset, 1, ENC_LITTLE_ENDIAN);
795 break;
796 case 0x38: /* Modem Status Command */
797 dissect_ctrl_msc(ctrl_tree, tvb, offset, length, &mcc_channel);
798 break;
799 default:
800 mcc_channel = -1;
803 if (mcc_channel > 0) {
804 col_append_fstr(pinfo->cinfo, COL_INFO, "-> %d ", mcc_channel);
807 col_append_str(pinfo->cinfo, COL_INFO, "MPX_CTRL ");
809 if(mcc_type){
810 col_append_fstr(pinfo->cinfo, COL_INFO, "%s ", val_to_str_const(mcc_type, vs_ctl, "Unknown"));
813 offset += length;
815 proto_item_set_len(mcc_ti, offset - start_offset);
818 /* try to find a higher layer dissector that has registered to handle data
819 * for this kind of service, if none is found dissect it as raw "data"
821 if (dlci && frame_len) {
822 dissector_handle_t decode_by_dissector;
823 tvbuff_t *next_tvb;
824 btrfcomm_data_t *rfcomm_data;
826 next_tvb = tvb_new_subset_length(tvb, offset, frame_len);
828 rfcomm_data = (btrfcomm_data_t *) wmem_new(pinfo->pool, btrfcomm_data_t);
829 rfcomm_data->interface_id = l2cap_data->interface_id;
830 rfcomm_data->adapter_id = l2cap_data->adapter_id;
831 rfcomm_data->chandle = l2cap_data->chandle;
832 rfcomm_data->cid = l2cap_data->cid;
833 rfcomm_data->is_local_psm = l2cap_data->is_local_psm;
834 rfcomm_data->dlci = dlci;
835 rfcomm_data->remote_bd_addr_oui = l2cap_data->remote_bd_addr_oui;
836 rfcomm_data->remote_bd_addr_id = l2cap_data->remote_bd_addr_id;
838 if (service_info && service_info->uuid.size != 0 &&
839 p_get_proto_data(pinfo->pool, pinfo, proto_bluetooth, PROTO_DATA_BLUETOOTH_SERVICE_UUID) == NULL) {
840 uint8_t *value_data;
842 value_data = wmem_strdup(wmem_file_scope(), print_numeric_bluetooth_uuid(pinfo->pool, &service_info->uuid));
844 p_add_proto_data(pinfo->pool, pinfo, proto_bluetooth, PROTO_DATA_BLUETOOTH_SERVICE_UUID, value_data);
847 if (!dissector_try_uint_with_data(rfcomm_dlci_dissector_table, (uint32_t) dlci,
848 next_tvb, pinfo, tree, true, rfcomm_data)) {
849 if (service_info && (service_info->uuid.size == 0 ||
850 !dissector_try_string_with_data(bluetooth_uuid_table, print_numeric_bluetooth_uuid(pinfo->pool, &service_info->uuid),
851 next_tvb, pinfo, tree, true, rfcomm_data))) {
852 decode_by_dissector = find_proto_by_channel(dlci >> 1);
853 if (rfcomm_channels_enabled && decode_by_dissector) {
854 call_dissector_with_data(decode_by_dissector, next_tvb, pinfo, tree, rfcomm_data);
855 } else {
856 /* unknown service, let the data dissector handle it */
857 call_data_dissector(next_tvb, pinfo, tree);
863 proto_tree_add_item(rfcomm_tree, hf_fcs, tvb, fcs_offset, 1, ENC_LITTLE_ENDIAN);
864 offset += 1;
866 return offset;
869 static void*
870 uat_rfcomm_channels_copy_cb(void *dest, const void *source, size_t len _U_)
872 const uat_rfcomm_channels_t* o = (const uat_rfcomm_channels_t*)source;
873 uat_rfcomm_channels_t* d = (uat_rfcomm_channels_t*)dest;
875 d->channel = o->channel;
876 d->payload_proto = o->payload_proto;
877 d->payload_proto_name = g_strdup(o->payload_proto_name);
879 return dest;
882 static void
883 uat_rfcomm_channels_free_cb(void *r)
885 uat_rfcomm_channels_t *rec = (uat_rfcomm_channels_t *)r;
886 g_free(rec->payload_proto_name);
889 void
890 proto_register_btrfcomm(void)
892 module_t *module;
893 expert_module_t *expert_btrfcomm;
895 static hf_register_info hf[] = {
896 { &hf_dlci,
897 { "DLCI", "btrfcomm.dlci",
898 FT_UINT8, BASE_HEX, NULL, 0xFC,
899 "RFCOMM Data Link Connection Identifier", HFILL}
901 { &hf_channel,
902 { "Channel", "btrfcomm.channel",
903 FT_UINT8, BASE_DEC, NULL, 0xF8,
904 "RFCOMM Channel", HFILL}
906 { &hf_direction,
907 {"Direction", "btrfcomm.direction",
908 FT_UINT8, BASE_HEX, NULL, 0x04,
909 NULL, HFILL}
911 { &hf_priority,
912 { "Priority", "btrfcomm.priority",
913 FT_UINT8, BASE_DEC, NULL, 0x3f,
914 NULL, HFILL}
916 { &hf_max_frame_size,
917 { "Max Frame Size", "btrfcomm.max_frame_size",
918 FT_UINT16, BASE_DEC, NULL, 0,
919 "Maximum Frame Size", HFILL}
921 { &hf_max_retrans,
922 { "Maximum number of retransmissions", "btrfcomm.max_retrans",
923 FT_UINT8, BASE_DEC, NULL, 0,
924 NULL, HFILL}
926 { &hf_error_recovery_mode,
927 { "Error Recovery Mode", "btrfcomm.error_recovery_mode",
928 FT_UINT8, BASE_DEC, NULL, 0x07,
929 NULL, HFILL}
931 { &hf_ea,
932 { "EA Flag", "btrfcomm.ea",
933 FT_UINT8, BASE_HEX, VALS(vs_ea), 0x01,
934 "EA flag (should be always 1)", HFILL}
936 { &hf_cr,
937 { "C/R Flag", "btrfcomm.cr",
938 FT_BOOLEAN, 8, TFS(&tfs_command_response), 0x02,
939 "Command/Response flag", HFILL}
941 { &hf_mcc,
942 { "Multiplexer Control Command", "btrfcomm.mcc",
943 FT_NONE, BASE_NONE, NULL, 0x00,
944 NULL, HFILL}
946 { &hf_mcc_pn_parameters,
947 { "Parameters", "btrfcomm.mcc.pn_parameters",
948 FT_NONE, BASE_NONE, NULL, 0x00,
949 NULL, HFILL}
951 { &hf_mcc_types,
952 { "Types", "btrfcomm.mcc.types",
953 FT_NONE, BASE_NONE, NULL, 0x00,
954 NULL, HFILL}
956 { &hf_mcc_ea,
957 { "EA Flag", "btrfcomm.mcc.ea",
958 FT_UINT8, BASE_HEX, VALS(vs_ea), 0x01,
959 "RFCOMM MCC EA flag", HFILL}
961 { &hf_mcc_cr,
962 { "C/R Flag", "btrfcomm.mcc.cr",
963 FT_BOOLEAN, 8, TFS(&tfs_command_response), 0x02,
964 "Command/Response flag", HFILL}
966 { &hf_mcc_const_1,
967 { "Ones padding", "btrfcomm.mcc.padding",
968 FT_UINT8, BASE_HEX, NULL, 0x02,
969 NULL, HFILL}
971 { &hf_mcc_dlci,
972 { "MCC DLCI", "btrfcomm.mcc.dlci",
973 FT_UINT8, BASE_HEX, NULL, 0xFC,
974 "RFCOMM MCC Data Link Connection Identifier", HFILL}
976 { &hf_mcc_channel,
977 { "MCC Channel", "btrfcomm.mcc.channel",
978 FT_UINT8, BASE_DEC, NULL, 0xF8,
979 "RFCOMM MCC Channel", HFILL}
981 { &hf_mcc_direction,
982 { "MCC Direction", "btrfcomm.mcc.direction",
983 FT_UINT8, BASE_HEX, NULL, 0x04,
984 "RFCOMM MCC Direction", HFILL}
986 { &hf_mcc_pn_dlci,
987 { "MCC DLCI", "btrfcomm.mcc.dlci",
988 FT_UINT8, BASE_HEX, NULL, 0x3F,
989 "RFCOMM MCC Data Link Connection Identifier", HFILL}
991 { &hf_mcc_pn_channel,
992 { "MCC Channel", "btrfcomm.mcc.channel",
993 FT_UINT8, BASE_DEC, NULL, 0x3E,
994 "RFCOMM MCC Channel", HFILL}
996 { &hf_mcc_pn_direction,
997 { "MCC Direction", "btrfcomm.mcc.direction",
998 FT_UINT8, BASE_HEX, NULL, 0x01,
999 "RFCOMM MCC Direction", HFILL}
1001 { &hf_mcc_pn_zeros_padding,
1002 { "Zeros padding", "btrfcomm.mcc.padding",
1003 FT_UINT8, BASE_HEX, NULL, 0xC0,
1004 "RFCOMM MSC Zeros padding", HFILL}
1006 { &hf_mcc_cmd,
1007 { "MCC Command Type", "btrfcomm.mcc.cmd",
1008 FT_UINT8, BASE_HEX, VALS(vs_ctl), 0xFC,
1009 NULL, HFILL}
1011 { &hf_frame_type,
1012 { "Frame type", "btrfcomm.frame_type",
1013 FT_UINT8, BASE_HEX, VALS(vs_frame_type), 0xEF,
1014 NULL, HFILL}
1016 { &hf_acknowledgement_timer_t1,
1017 { "Acknowledgement Timer T1", "btrfcomm.acknowledgement_timer_t1",
1018 FT_UINT8, BASE_DEC, NULL, 0x00,
1019 NULL, HFILL}
1021 { &hf_pf,
1022 { "P/F flag", "btrfcomm.pf",
1023 FT_UINT8, BASE_HEX, NULL, 0x10,
1024 "Poll/Final bit", HFILL}
1026 { &hf_pn_i14,
1027 { "Type of frame", "btrfcomm.pn.i",
1028 FT_UINT8, BASE_HEX, VALS(vs_ctl_pn_i), 0x0F,
1029 "Type of information frames used for that particular DLCI",
1030 HFILL}
1032 { &hf_pn_c14,
1033 { "Convergence layer", "btrfcomm.pn.cl",
1034 FT_UINT8, BASE_HEX, VALS(vs_ctl_pn_cl), 0xF0,
1035 "Convergence layer used for that particular DLCI", HFILL}
1037 { &hf_len,
1038 { "Payload length", "btrfcomm.len",
1039 FT_UINT16, BASE_DEC, NULL, 0,
1040 "Frame length", HFILL}
1042 { &hf_mcc_len,
1043 { "MCC Length", "btrfcomm.mcc.len",
1044 FT_UINT16, BASE_DEC, NULL, 0,
1045 "Length of MCC data", HFILL}
1047 { &hf_fcs,
1048 { "Frame Check Sequence", "btrfcomm.fcs",
1049 FT_UINT8, BASE_HEX, NULL, 0,
1050 "Checksum over frame", HFILL}
1052 { &hf_msc_parameters,
1053 { "Parameters", "btrfcomm.mcc.msc_parameters",
1054 FT_NONE, BASE_NONE, NULL, 0x00,
1055 NULL, HFILL}
1057 { &hf_msc_fc,
1058 { "Flow Control (FC)", "btrfcomm.msc.fc",
1059 FT_UINT8, BASE_HEX, NULL, 0x02,
1060 NULL, HFILL}
1062 { &hf_msc_rtc,
1063 { "Ready To Communicate (RTC)", "btrfcomm.msc.rtc",
1064 FT_UINT8, BASE_HEX, NULL, 0x04,
1065 NULL, HFILL}
1067 { &hf_msc_rtr,
1068 { "Ready To Receive (RTR)", "btrfcomm.msc.rtr",
1069 FT_UINT8, BASE_HEX, NULL, 0x08,
1070 NULL, HFILL}
1072 { &hf_msc_ic,
1073 { "Incoming Call Indicator (IC)", "btrfcomm.msc.ic",
1074 FT_UINT8, BASE_HEX, NULL, 0x40,
1075 NULL, HFILL}
1077 { &hf_msc_dv,
1078 { "Data Valid (DV)", "btrfcomm.msc.dv",
1079 FT_UINT8, BASE_HEX, NULL, 0x80,
1080 NULL, HFILL}
1082 { &hf_msc_l,
1083 { "Length of break in units of 200ms", "btrfcomm.msc.bl",
1084 FT_UINT8, BASE_DEC, NULL, 0xF0,
1085 NULL, HFILL}
1087 { &hf_msc_break_bits,
1088 { "Break Bits", "btrfcomm.msc.break_bits",
1089 FT_UINT8, BASE_DEC, NULL, 0xE0,
1090 NULL, HFILL}
1092 { &hf_address,
1093 { "Address", "btrfcomm.address",
1094 FT_NONE, BASE_NONE, NULL, 0x00,
1095 NULL, HFILL}
1097 { &hf_control,
1098 { "Control", "btrfcomm.control",
1099 FT_NONE, BASE_NONE, NULL, 0x00,
1100 NULL, HFILL}
1102 { &hf_fc_credits,
1103 { "Credits", "btrfcomm.credits",
1104 FT_UINT8, BASE_DEC, NULL, 0,
1105 "Flow control: number of UIH frames allowed to send", HFILL}
1110 /* Setup protocol subtree array */
1111 static int *ett[] = {
1112 &ett_btrfcomm,
1113 &ett_btrfcomm_ctrl,
1114 &ett_addr,
1115 &ett_control,
1116 &ett_mcc,
1117 &ett_ctrl_pn_ci,
1118 &ett_ctrl_pn_v24,
1119 &ett_dlci,
1120 &ett_mcc_dlci
1123 static ei_register_info ei[] = {
1124 { &ei_btrfcomm_mcc_length_bad, { "btrfcomm.mcc_length_bad", PI_MALFORMED, PI_ERROR, "Huge MCC length", EXPFILL }},
1127 /* Decode As handling */
1128 static build_valid_func btrfcomm_directed_channel_da_build_value[1] = {btrfcomm_directed_channel_value};
1129 static decode_as_value_t btrfcomm_directed_channel_da_values = {btrfcomm_directed_channel_prompt, 1, btrfcomm_directed_channel_da_build_value};
1130 static decode_as_t btrfcomm_directed_channel_da = {"btrfcomm", "btrfcomm.dlci", 1, 0, &btrfcomm_directed_channel_da_values, NULL, NULL,
1131 decode_as_default_populate_list, decode_as_default_reset, decode_as_default_change, NULL};
1133 /* Register the protocol name and description */
1134 proto_btrfcomm = proto_register_protocol("Bluetooth RFCOMM Protocol", "BT RFCOMM", "btrfcomm");
1135 btrfcomm_handle = register_dissector("btrfcomm", dissect_btrfcomm, proto_btrfcomm);
1137 /* Required function calls to register the header fields and subtrees used */
1138 proto_register_field_array(proto_btrfcomm, hf, array_length(hf));
1139 proto_register_subtree_array(ett, array_length(ett));
1140 expert_btrfcomm = expert_register_protocol(proto_btrfcomm);
1141 expert_register_field_array(expert_btrfcomm, ei, array_length(ei));
1143 service_directions = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
1145 rfcomm_dlci_dissector_table = register_dissector_table("btrfcomm.dlci", "BT RFCOMM Directed Channel", proto_btrfcomm, FT_UINT16, BASE_DEC);
1147 module = prefs_register_protocol_subtree("Bluetooth", proto_btrfcomm, NULL);
1148 prefs_register_static_text_preference(module, "rfcomm.version",
1149 "Bluetooth Protocol RFCOMM version: 1.1", "Version of protocol supported by this dissector.");
1151 prefs_register_bool_preference(module, "rfcomm.decode_by.enabled",
1152 "Enable Force Decode by Channel",
1153 "Turn on/off decode by next rules",
1154 &rfcomm_channels_enabled);
1156 uat_rfcomm_channels = uat_new("Force Decode by Channel",
1157 sizeof(uat_rfcomm_channels_t),
1158 "rfcomm_channels",
1159 true,
1160 &rfcomm_channels,
1161 &num_rfcomm_channels,
1162 UAT_AFFECTS_DISSECTION,
1163 NULL,
1164 uat_rfcomm_channels_copy_cb,
1165 NULL,
1166 uat_rfcomm_channels_free_cb,
1167 NULL,
1168 NULL,
1169 uat_rfcomm_channels_fields);
1171 prefs_register_uat_preference(module, "rfcomm.channels",
1172 "Force Decode by channel",
1173 "Decode by channel",
1174 uat_rfcomm_channels);
1176 register_decode_as(&btrfcomm_directed_channel_da);
1179 void
1180 proto_reg_handoff_btrfcomm(void)
1182 dissector_add_uint("btl2cap.psm", BTL2CAP_PSM_RFCOMM, btrfcomm_handle);
1183 dissector_add_for_decode_as("btl2cap.cid", btrfcomm_handle);
1186 /* Bluetooth Dial-Up Networking (DUN) profile dissection */
1187 static int
1188 dissect_btdun(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
1190 proto_item *ti;
1191 proto_tree *st;
1192 bool is_at_cmd;
1193 unsigned i, length;
1195 length = tvb_captured_length(tvb);
1197 col_set_str(pinfo->cinfo, COL_PROTOCOL, "DUN");
1199 ti = proto_tree_add_item(tree, proto_btdun, tvb, 0, tvb_captured_length(tvb), ENC_NA);
1200 st = proto_item_add_subtree(ti, ett_btdun);
1202 is_at_cmd = true;
1203 for(i = 0; i < length && is_at_cmd; i++) {
1204 is_at_cmd = tvb_get_uint8(tvb, i) < 0x7d;
1207 if (is_at_cmd) {
1208 /* presumably an AT command */
1209 col_add_fstr(pinfo->cinfo, COL_INFO, "%s \"%s\"",
1210 (pinfo->p2p_dir == P2P_DIR_SENT) ? "Sent" : "Rcvd",
1211 tvb_format_text(pinfo->pool, tvb, 0, length));
1213 proto_tree_add_item(st, hf_dun_at_cmd, tvb, 0, tvb_reported_length(tvb), ENC_ASCII|ENC_NA);
1215 else {
1216 /* ... or raw PPP */
1217 if (ppp_handle)
1218 call_dissector(ppp_handle, tvb, pinfo, tree);
1219 else {
1220 /* TODO: remove the above 'if' and this 'else-body' when "ppp_raw_hdlc" is available, requires that it is
1221 made non-anonymous in ppp dissector to use */
1222 col_set_str(pinfo->cinfo, COL_PROTOCOL, "PPP");
1223 col_add_fstr(pinfo->cinfo, COL_INFO, "%s <PPP frame>", (pinfo->p2p_dir == P2P_DIR_SENT) ? "Sent" : "Rcvd");
1225 call_data_dissector(tvb, pinfo, tree);
1229 return tvb_reported_length(tvb);
1232 void
1233 proto_register_btdun(void)
1235 static hf_register_info hf[] = {
1236 { &hf_dun_at_cmd,
1237 { "AT Cmd", "btdun.atcmd",
1238 FT_STRING, BASE_NONE, NULL, 0,
1239 "AT Command", HFILL}
1243 /* Setup protocol subtree array */
1244 static int *ett[] = {
1245 &ett_btdun
1248 proto_btdun = proto_register_protocol("Bluetooth DUN Packet", "BT DUN", "btdun");
1249 btdun_handle = register_dissector("btdun", dissect_btdun, proto_btdun);
1251 /* Required function calls to register the header fields and subtrees used */
1252 proto_register_field_array(proto_btdun, hf, array_length(hf));
1253 proto_register_subtree_array(ett, array_length(ett));
1256 void
1257 proto_reg_handoff_btdun(void)
1259 dissector_add_string("bluetooth.uuid", "1103", btdun_handle);
1261 dissector_add_for_decode_as("btrfcomm.dlci", btdun_handle);
1263 ppp_handle = find_dissector_add_dependency("ppp_raw_hdlc", proto_btdun);
1266 /* Bluetooth Serial Port profile (SPP) dissection */
1267 static int
1268 dissect_btspp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
1270 proto_item *ti;
1271 proto_tree *st;
1272 bool ascii_only;
1273 unsigned i;
1274 unsigned length = tvb_captured_length(tvb);
1276 col_set_str(pinfo->cinfo, COL_PROTOCOL, "SPP");
1278 ti = proto_tree_add_item(tree, proto_btspp, tvb, 0, tvb_captured_length(tvb), ENC_NA);
1279 st = proto_item_add_subtree(ti, ett_btspp);
1281 length = MIN(length, 60);
1282 ascii_only = true;
1283 for(i = 0; i < length && ascii_only; i++) {
1284 ascii_only = tvb_get_uint8(tvb, i) < 0x80;
1287 if (ascii_only) {
1288 col_add_fstr(pinfo->cinfo, COL_INFO, "%s \"%s%s\"",
1289 (pinfo->p2p_dir == P2P_DIR_SENT) ? "Sent" : "Rcvd",
1290 tvb_format_text(pinfo->pool, tvb, 0, length),
1291 (tvb_captured_length(tvb) > length) ? "..." : "");
1294 proto_tree_add_item(st, hf_spp_data, tvb, 0, tvb_reported_length(tvb), ENC_NA);
1296 return tvb_reported_length(tvb);
1299 void
1300 proto_register_btspp(void)
1302 static hf_register_info hf[] = {
1303 { &hf_spp_data,
1304 { "Data", "btspp.data",
1305 FT_BYTES, BASE_NONE, NULL, 0,
1306 NULL, HFILL }
1310 /* Setup protocol subtree array */
1311 static int *ett[] = {
1312 &ett_btspp
1315 proto_btspp = proto_register_protocol("Bluetooth SPP Packet", "BT SPP", "btspp");
1316 btspp_handle = register_dissector("btspp", dissect_btspp, proto_btspp);
1318 /* Required function calls to register the header fields and subtrees used */
1319 proto_register_field_array(proto_btspp, hf, array_length(hf));
1320 proto_register_subtree_array(ett, array_length(ett));
1323 void
1324 proto_reg_handoff_btspp(void)
1326 dissector_add_string("bluetooth.uuid", "1101", btspp_handle);
1328 dissector_add_for_decode_as("btrfcomm.dlci", btspp_handle);
1332 /* Bluetooth Global Navigation Satellite System profile (GNSS) dissection */
1333 static int
1334 dissect_btgnss(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
1336 proto_item *main_item;
1337 proto_tree *main_tree;
1339 col_set_str(pinfo->cinfo, COL_PROTOCOL, "GNSS");
1341 main_item = proto_tree_add_item(tree, proto_btgnss, tvb, 0, tvb_captured_length(tvb), ENC_NA);
1342 main_tree = proto_item_add_subtree(main_item, ett_btgnss);
1344 col_add_fstr(pinfo->cinfo, COL_INFO, "%s %s",
1345 (pinfo->p2p_dir == P2P_DIR_SENT) ? "Sent" : "Rcvd",
1346 tvb_format_text(pinfo->pool, tvb, 0, tvb_captured_length(tvb)));
1348 /* GNSS using NMEA-0183 protocol, but it is not available */
1349 proto_tree_add_item(main_tree, hf_gnss_data, tvb, 0, tvb_reported_length(tvb), ENC_NA | ENC_ASCII);
1351 return tvb_reported_length(tvb);
1354 void
1355 proto_register_btgnss(void)
1357 static hf_register_info hf[] = {
1358 { &hf_gnss_data,
1359 { "Data", "btgnss.data",
1360 FT_STRING, BASE_NONE, NULL, 0,
1361 NULL, HFILL }
1365 static int *ett[] = {
1366 &ett_btgnss
1369 proto_btgnss = proto_register_protocol("Bluetooth GNSS Profile", "BT GNSS", "btgnss");
1370 btgnss_handle = register_dissector("btgnss", dissect_btgnss, proto_btgnss);
1372 proto_register_field_array(proto_btgnss, hf, array_length(hf));
1373 proto_register_subtree_array(ett, array_length(ett));
1376 void
1377 proto_reg_handoff_btgnss(void)
1379 dissector_add_string("bluetooth.uuid", "1135", btgnss_handle);
1380 dissector_add_string("bluetooth.uuid", "1136", btgnss_handle);
1382 dissector_add_for_decode_as("btrfcomm.dlci", btgnss_handle);
1386 * Editor modelines - https://www.wireshark.org/tools/modelines.html
1388 * Local variables:
1389 * c-basic-offset: 4
1390 * tab-width: 8
1391 * indent-tabs-mode: nil
1392 * End:
1394 * vi: set shiftwidth=4 tabstop=8 expandtab:
1395 * :indentSize=4:tabSize=8:noTabs=true: