2 * Routines for IrCOMM dissection
3 * Copyright 2003 Jan Kiszka <jan.kiszka@web.de>
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * Copyright 1998 Gerald Combs
9 * SPDX-License-Identifier: GPL-2.0-or-later
14 #include <epan/packet.h>
19 * https://web.archive.org/web/20040405053146/http://www.irda.org/standards/specifications.asp
23 * https://archive.org/search?query=creator%3A%22Infrared+Data+Association%22
25 * for various IrDA specifications, including the IrCOMM 1.0 specification
28 * https://web.archive.org/web/20040229015523/http://www.irda.org/standards/pubs/IrCOMM10.PDF
32 * https://archive.org/details/ir-comm-10
35 #include "irda-appl.h"
38 /* Parameters common to all service types */
39 #define IRCOMM_SERVICE_TYPE 0x00
40 #define IRCOMM_PORT_TYPE 0x01 /* Only used in LM-IAS */
41 #define IRCOMM_PORT_NAME 0x02 /* Only used in LM-IAS */
43 /* Parameters for both 3 wire and 9 wire */
44 #define IRCOMM_DATA_RATE 0x10
45 #define IRCOMM_DATA_FORMAT 0x11
46 #define IRCOMM_FLOW_CONTROL 0x12
47 #define IRCOMM_XON_XOFF 0x13
48 #define IRCOMM_ENQ_ACK 0x14
49 #define IRCOMM_LINE_STATUS 0x15
50 #define IRCOMM_BREAK 0x16
52 /* Parameters for 9 wire */
53 #define IRCOMM_DTE 0x20
54 #define IRCOMM_DCE 0x21
55 #define IRCOMM_POLL 0x22
57 /* Service type (details) */
58 #define IRCOMM_3_WIRE_RAW 0x01
59 #define IRCOMM_3_WIRE 0x02
60 #define IRCOMM_9_WIRE 0x04
61 #define IRCOMM_CENTRONICS 0x08
63 /* Port type (details) */
64 #define IRCOMM_SERIAL 0x01
65 #define IRCOMM_PARALLEL 0x02
67 /* Data format (details) */
68 #define IRCOMM_WSIZE_5 0x00
69 #define IRCOMM_WSIZE_6 0x01
70 #define IRCOMM_WSIZE_7 0x02
71 #define IRCOMM_WSIZE_8 0x03
73 #define IRCOMM_1_STOP_BIT 0x00
74 #define IRCOMM_2_STOP_BIT 0x04 /* 1.5 if char len 5 */
76 #define IRCOMM_PARITY_DISABLE 0x00
77 #define IRCOMM_PARITY_ENABLE 0x08
79 #define IRCOMM_PARITY_ODD 0x00
80 #define IRCOMM_PARITY_EVEN 0x10
81 #define IRCOMM_PARITY_MARK 0x20
82 #define IRCOMM_PARITY_SPACE 0x30
85 #define IRCOMM_XON_XOFF_IN 0x01
86 #define IRCOMM_XON_XOFF_OUT 0x02
87 #define IRCOMM_RTS_CTS_IN 0x04
88 #define IRCOMM_RTS_CTS_OUT 0x08
89 #define IRCOMM_DSR_DTR_IN 0x10
90 #define IRCOMM_DSR_DTR_OUT 0x20
91 #define IRCOMM_ENQ_ACK_IN 0x40
92 #define IRCOMM_ENQ_ACK_OUT 0x80
95 #define IRCOMM_OVERRUN_ERROR 0x02
96 #define IRCOMM_PARITY_ERROR 0x04
97 #define IRCOMM_FRAMING_ERROR 0x08
99 /* DTE (Data terminal equipment) line settings */
100 #define IRCOMM_DELTA_DTR 0x01
101 #define IRCOMM_DELTA_RTS 0x02
102 #define IRCOMM_DTR 0x04
103 #define IRCOMM_RTS 0x08
105 /* DCE (Data communications equipment) line settings */
106 #define IRCOMM_DELTA_CTS 0x01 /* Clear to send has changed */
107 #define IRCOMM_DELTA_DSR 0x02 /* Data set ready has changed */
108 #define IRCOMM_DELTA_RI 0x04 /* Ring indicator has changed */
109 #define IRCOMM_DELTA_CD 0x08 /* Carrier detect has changed */
110 #define IRCOMM_CTS 0x10 /* Clear to send is high */
111 #define IRCOMM_DSR 0x20 /* Data set ready is high */
112 #define IRCOMM_RI 0x40 /* Ring indicator is high */
113 #define IRCOMM_CD 0x80 /* Carrier detect is high */
114 #define IRCOMM_DCE_DELTA_ANY 0x0f
116 void proto_reg_handoff_ircomm(void);
118 /* Initialize the subtree pointers */
119 static int ett_ircomm
;
120 static int ett_ircomm_ctrl
;
122 #define MAX_PARAMETERS 32
123 static int ett_param
[MAX_IAP_ENTRIES
* MAX_PARAMETERS
];
125 static dissector_handle_t ircomm_raw_handle
;
126 static dissector_handle_t ircomm_cooked_handle
;
128 static int proto_ircomm
;
129 static int hf_ircomm_param
;
130 /* static int hf_param_pi; */
131 /* static int hf_param_pl; */
132 /* static int hf_param_pv; */
133 static int hf_control
;
134 static int hf_control_len
;
136 static bool dissect_ircomm_parameters(tvbuff_t
* tvb
, unsigned offset
, packet_info
* pinfo
,
137 proto_tree
* tree
, unsigned list_index
, uint8_t attr_type
, uint8_t circuit_id
);
138 static bool dissect_ircomm_ttp_lsap(tvbuff_t
* tvb
, unsigned offset
, packet_info
* pinfo
,
139 proto_tree
* tree
, unsigned list_index
, uint8_t attr_type
, uint8_t circuit_id
);
140 static bool dissect_ircomm_lmp_lsap(tvbuff_t
* tvb
, unsigned offset
, packet_info
* pinfo
,
141 proto_tree
* tree
, unsigned list_index
, uint8_t attr_type
, uint8_t circuit_id
);
143 ias_attr_dissector_t ircomm_attr_dissector
[] = {
144 /* IrDA:IrCOMM attribute dissectors */
145 { "Parameters", dissect_ircomm_parameters
},
146 { "IrDA:TinyTP:LsapSel", dissect_ircomm_ttp_lsap
},
150 ias_attr_dissector_t irlpt_attr_dissector
[] = {
151 /* IrLPT attribute dissectors */
152 { "IrDA:IrLMP:LsapSel", dissect_ircomm_lmp_lsap
},
153 { "IrDA:IrLMP:LSAPSel", dissect_ircomm_lmp_lsap
}, /* according to IrCOMM V1.0, p25 */
159 * Dissect the cooked IrCOMM protocol
161 static int dissect_cooked_ircomm(tvbuff_t
* tvb
, packet_info
* pinfo
, proto_tree
* tree
, void* data _U_
)
164 proto_tree
*ircomm_tree
, *ctrl_tree
;
167 int len
= tvb_reported_length(tvb
);
172 /* Make entries in Protocol column on summary display */
173 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "IrCOMM");
175 clen
= tvb_get_uint8(tvb
, offset
);
179 col_add_fstr(pinfo
->cinfo
, COL_INFO
, "Clen=%d, UserData: %d byte%s", clen
, len
, (len
> 1)? "s": "");
181 col_add_fstr(pinfo
->cinfo
, COL_INFO
, "Clen=%d", clen
);
183 /* create display subtree for the protocol */
184 ti
= proto_tree_add_item(tree
, proto_ircomm
, tvb
, 0, -1, ENC_NA
);
185 ircomm_tree
= proto_item_add_subtree(ti
, ett_ircomm
);
187 ti
= proto_tree_add_item(ircomm_tree
, hf_control
, tvb
, 0, clen
+ 1, ENC_NA
);
188 ctrl_tree
= proto_item_add_subtree(ti
, ett_ircomm_ctrl
);
189 proto_tree_add_item(ctrl_tree
, hf_control_len
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
192 call_data_dissector(tvb_new_subset_length(tvb
, offset
, clen
), pinfo
, ctrl_tree
);
195 call_data_dissector(tvb_new_subset_remaining(tvb
, offset
), pinfo
, ircomm_tree
);
202 * Dissect the raw IrCOMM/IrLPT protocol
204 static int dissect_raw_ircomm(tvbuff_t
* tvb
, packet_info
* pinfo
, proto_tree
* tree
, void* data _U_
)
206 unsigned len
= tvb_reported_length(tvb
);
208 proto_tree
* ircomm_tree
;
213 /* Make entries in Protocol column on summary display */
214 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "IrCOMM");
216 col_add_fstr(pinfo
->cinfo
, COL_INFO
, "User Data: %d byte%s", len
, (len
> 1)? "s": "");
218 /* create display subtree for the protocol */
219 ti
= proto_tree_add_item(tree
, proto_ircomm
, tvb
, 0, -1, ENC_NA
);
220 ircomm_tree
= proto_item_add_subtree(ti
, ett_ircomm
);
222 call_data_dissector(tvb
, pinfo
, ircomm_tree
);
229 * Dissect IrCOMM IAS "Parameters" attribute
231 static bool dissect_ircomm_parameters(tvbuff_t
* tvb
, unsigned offset
, packet_info
* pinfo _U_
,
232 proto_tree
* tree
, unsigned list_index
, uint8_t attr_type
, uint8_t circuit_id _U_
)
242 if (!check_iap_octet_result(tvb
, tree
, offset
, "Parameters", attr_type
))
247 len
= tvb_get_ntohs(tvb
, offset
) + offset
+ 2;
252 uint8_t p_len
= tvb_get_uint8(tvb
, offset
+ 1);
255 ti
= proto_tree_add_item(tree
, hf_ircomm_param
, tvb
, offset
, p_len
+ 2, ENC_NA
);
256 p_tree
= proto_item_add_subtree(ti
, ett_param
[list_index
* MAX_PARAMETERS
+ n
]);
260 switch (tvb_get_uint8(tvb
, offset
))
262 case IRCOMM_SERVICE_TYPE
:
263 proto_item_append_text(ti
, ": Service Type (");
265 pv
= tvb_get_uint8(tvb
, offset
+2);
266 if (pv
& IRCOMM_3_WIRE_RAW
)
267 (void) g_strlcat(buf
, ", 3-Wire raw", 256);
268 if (pv
& IRCOMM_3_WIRE
)
269 (void) g_strlcat(buf
, ", 3-Wire", 256);
270 if (pv
& IRCOMM_9_WIRE
)
271 (void) g_strlcat(buf
, ", 9-Wire", 256);
272 if (pv
& IRCOMM_CENTRONICS
)
273 (void) g_strlcat(buf
, ", Centronics", 256);
275 (void) g_strlcat(buf
, ")", 256);
278 proto_item_append_text(ti
, "%s", buf
+2);
280 proto_item_append_text(ti
, "unknown)");
284 case IRCOMM_PORT_TYPE
:
285 proto_item_append_text(ti
, ": Port Type (");
287 pv
= tvb_get_uint8(tvb
, offset
+2);
288 if (pv
& IRCOMM_SERIAL
)
289 (void) g_strlcat(buf
, ", serial", 256);
290 if (pv
& IRCOMM_PARALLEL
)
291 (void) g_strlcat(buf
, ", parallel", 256);
293 (void) g_strlcat(buf
, ")", 256);
296 proto_item_append_text(ti
, "%s", buf
+2);
298 proto_item_append_text(ti
, "unknown)");
302 case IRCOMM_PORT_NAME
:
303 /* XXX - the IrCOMM V1.0 spec says this "Normally
304 human readable text, but not required". */
305 proto_item_append_text(ti
, ": Port Name (\"%s\")",
306 tvb_format_text(pinfo
->pool
, tvb
, offset
+2, p_len
));
311 proto_item_append_text(ti
, ": unknown");
314 offset
= dissect_param_tuple(tvb
, p_tree
, offset
);
325 * Dissect IrCOMM IAS "IrDA:TinyTP:LsapSel" attribute
327 static bool dissect_ircomm_ttp_lsap(tvbuff_t
* tvb
, unsigned offset
, packet_info
* pinfo
,
328 proto_tree
* tree
, unsigned list_index _U_
, uint8_t attr_type
, uint8_t circuit_id
)
333 if ((dlsap
= check_iap_lsap_result(tvb
, tree
, offset
, "IrDA:TinyTP:LsapSel", attr_type
)) == 0)
336 add_lmp_conversation(pinfo
, dlsap
, true, ircomm_cooked_handle
, circuit_id
);
343 * Dissect IrCOMM/IrLPT IAS "IrDA:IrLMP:LsapSel" attribute
345 static bool dissect_ircomm_lmp_lsap(tvbuff_t
* tvb
, unsigned offset
, packet_info
* pinfo
,
346 proto_tree
* tree
, unsigned list_index _U_
, uint8_t attr_type
, uint8_t circuit_id
)
351 if ((dlsap
= check_iap_lsap_result(tvb
, tree
, offset
, "IrDA:IrLMP:LsapSel", attr_type
)) == 0)
354 add_lmp_conversation(pinfo
, dlsap
, false, ircomm_raw_handle
, circuit_id
);
361 * Register the IrCOMM protocol
363 void proto_register_ircomm(void)
367 /* Setup list of header fields */
368 static hf_register_info hf_ircomm
[] = {
370 { "IrCOMM Parameter", "ircomm.parameter",
371 FT_NONE
, BASE_NONE
, NULL
, 0,
375 { "Parameter Identifier", "ircomm.pi",
376 FT_UINT8
, BASE_HEX
, NULL
, 0,
379 { "Parameter Length", "ircomm.pl",
380 FT_UINT8
, BASE_HEX
, NULL
, 0,
383 { "Parameter Value", "ircomm.pv",
384 FT_BYTES
, BASE_NONE
, NULL
, 0,
388 { "Control Channel", "ircomm.control",
389 FT_NONE
, BASE_NONE
, NULL
, 0,
392 { "Clen", "ircomm.control.len",
393 FT_UINT8
, BASE_DEC
, NULL
, 0,
397 /* Setup protocol subtree arrays */
398 static int* ett
[] = {
403 int* ett_p
[MAX_IAP_ENTRIES
* MAX_PARAMETERS
];
406 /* Register protocol names and descriptions */
407 proto_ircomm
= proto_register_protocol("IrCOMM Protocol", "IrCOMM", "ircomm");
408 ircomm_raw_handle
= register_dissector("ircomm_raw", dissect_raw_ircomm
, proto_ircomm
);
409 ircomm_cooked_handle
= register_dissector("ircomm_cooked", dissect_cooked_ircomm
, proto_ircomm
);
411 /* Required function calls to register the header fields */
412 proto_register_field_array(proto_ircomm
, hf_ircomm
, array_length(hf_ircomm
));
414 /* Register subtrees */
415 proto_register_subtree_array(ett
, array_length(ett
));
416 for (i
= 0; i
< MAX_IAP_ENTRIES
* MAX_PARAMETERS
; i
++)
418 ett_p
[i
] = &ett_param
[i
];
420 proto_register_subtree_array(ett_p
, MAX_IAP_ENTRIES
* MAX_PARAMETERS
);
424 * Editor modelines - https://www.wireshark.org/tools/modelines.html
429 * indent-tabs-mode: nil
432 * vi: set shiftwidth=4 tabstop=8 expandtab:
433 * :indentSize=4:tabSize=8:noTabs=true: