2 * Routines for X.75 frame disassembly
3 * Manawyrm <git@tbspace.de>
5 * based on lapb dissector by
6 * Olivier Abad <oabad@noos.fr>
8 * Wireshark - Network traffic analyzer
9 * By Gerald Combs <gerald@wireshark.org>
12 * SPDX-License-Identifier: GPL-2.0-or-later
17 #include <epan/decode_as.h>
18 #include <epan/packet.h>
20 #include <wsutil/array.h>
21 #include <epan/xdlc.h>
23 static dissector_table_t x75_subdissector_table
;
25 void proto_register_x75(void);
26 void proto_reg_handoff_x75(void);
28 #define X75_ADDRESS_SLP_STE_A 0x03
29 #define X75_ADDRESS_SLP_STE_B 0x01
30 #define X75_ADDRESS_MLP_STE_C 0x0F
31 #define X75_ADDRESS_MLP_STE_D 0x07
34 static int hf_x75_address
;
35 static int hf_x75_control
;
36 static int hf_x75_n_r
;
37 static int hf_x75_n_s
;
40 static int hf_x75_s_ftype
;
41 static int hf_x75_u_modifier_cmd
;
42 static int hf_x75_u_modifier_resp
;
43 static int hf_x75_ftype_i
;
44 static int hf_x75_ftype_s_u
;
47 static int ett_x75_control
;
49 static dissector_handle_t data_handle
;
50 static dissector_handle_t x75_handle
;
52 static const xdlc_cf_items x75_cf_items
= {
58 &hf_x75_u_modifier_cmd
,
59 &hf_x75_u_modifier_resp
,
65 dissect_x75(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data _U_
)
67 proto_tree
*x75_tree
, *ti
;
73 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "X.75");
74 col_set_str(pinfo
->cinfo
, COL_RES_NET_DST
, "Broadcast");
76 byte0
= tvb_get_uint8(tvb
, 0);
78 if (byte0
!= X75_ADDRESS_SLP_STE_A
&& byte0
!= X75_ADDRESS_SLP_STE_B
&&
79 byte0
!= X75_ADDRESS_MLP_STE_C
&& byte0
!= X75_ADDRESS_MLP_STE_D
) /* invalid X.75 frame */
81 col_set_str(pinfo
->cinfo
, COL_INFO
, "Invalid X.75 frame");
83 proto_tree_add_protocol_format(tree
, proto_x75
, tvb
, 0, -1,
84 "Invalid X.75 frame");
88 // Clear lower layer src/dst address types, so our custom names
89 // are shown in the Packet List pane
90 pinfo
->src
.type
= AT_NONE
;
91 pinfo
->dst
.type
= AT_NONE
;
93 switch (pinfo
->p2p_dir
) {
95 if (byte0
== X75_ADDRESS_SLP_STE_A
|| byte0
== X75_ADDRESS_SLP_STE_B
)
97 col_set_str(pinfo
->cinfo
, COL_RES_DL_SRC
, "STE A");
98 col_set_str(pinfo
->cinfo
, COL_RES_DL_DST
, "STE B");
102 col_set_str(pinfo
->cinfo
, COL_RES_DL_SRC
, "STE C");
103 col_set_str(pinfo
->cinfo
, COL_RES_DL_DST
, "STE D");
106 if (byte0
== X75_ADDRESS_SLP_STE_A
|| byte0
== X75_ADDRESS_MLP_STE_C
)
113 if (byte0
== X75_ADDRESS_SLP_STE_A
|| byte0
== X75_ADDRESS_SLP_STE_B
)
115 col_set_str(pinfo
->cinfo
, COL_RES_DL_SRC
, "STE B");
116 col_set_str(pinfo
->cinfo
, COL_RES_DL_DST
, "STE A");
120 col_set_str(pinfo
->cinfo
, COL_RES_DL_SRC
, "STE D");
121 col_set_str(pinfo
->cinfo
, COL_RES_DL_DST
, "STE C");
124 if (byte0
== X75_ADDRESS_SLP_STE_B
|| byte0
== X75_ADDRESS_MLP_STE_D
)
137 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "X.75 RSP");
141 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "X.75 CMD");
144 ti
= proto_tree_add_protocol_format(tree
, proto_x75
, tvb
, 0, 2,
146 x75_tree
= proto_item_add_subtree(ti
, ett_x75
);
147 proto_tree_add_uint(x75_tree
, hf_x75_address
, tvb
, 0, 1, byte0
);
149 control
= dissect_xdlc_control(tvb
, 1, pinfo
, x75_tree
, hf_x75_control
,
150 ett_x75_control
, &x75_cf_items
, NULL
, NULL
, NULL
,
151 is_response
, false, false);
153 /* information frame ==> data */
154 if (XDLC_IS_INFORMATION(control
)) {
155 next_tvb
= tvb_new_subset_remaining(tvb
, 2);
157 int len
= tvb_reported_length_remaining(next_tvb
, 0);
159 // limit number of bytes being shown in COL_INFO
163 col_append_fstr(pinfo
->cinfo
, COL_INFO
, ", %s", tvb_format_text(pinfo
->pool
, next_tvb
, 0, len
));
165 if (!dissector_try_payload_with_data(x75_subdissector_table
, next_tvb
, pinfo
, tree
, true, NULL
)) {
166 call_dissector(data_handle
, next_tvb
, pinfo
, tree
);
169 return tvb_captured_length(tvb
);
173 proto_register_x75(void)
175 static hf_register_info hf
[] = {
177 { "Address", "x75.address", FT_UINT8
, BASE_HEX
, NULL
, 0x0,
181 { "Control Field", "x75.control", FT_UINT8
, BASE_HEX
, NULL
, 0x0,
185 { "N(R)", "x75.control.n_r", FT_UINT8
, BASE_DEC
,
186 NULL
, XDLC_N_R_MASK
, NULL
, HFILL
}},
189 { "N(S)", "x75.control.n_s", FT_UINT8
, BASE_DEC
,
190 NULL
, XDLC_N_S_MASK
, NULL
, HFILL
}},
193 { "Poll", "x75.control.p", FT_BOOLEAN
, 8,
194 TFS(&tfs_set_notset
), XDLC_P_F
, NULL
, HFILL
}},
197 { "Final", "x75.control.f", FT_BOOLEAN
, 8,
198 TFS(&tfs_set_notset
), XDLC_P_F
, NULL
, HFILL
}},
201 { "Supervisory frame type", "x75.control.s_ftype", FT_UINT8
, BASE_HEX
,
202 VALS(stype_vals
), XDLC_S_FTYPE_MASK
, NULL
, HFILL
}},
204 { &hf_x75_u_modifier_cmd
,
205 { "Command", "x75.control.u_modifier_cmd", FT_UINT8
, BASE_HEX
,
206 VALS(modifier_vals_cmd
), XDLC_U_MODIFIER_MASK
, NULL
, HFILL
}},
208 { &hf_x75_u_modifier_resp
,
209 { "Response", "x75.control.u_modifier_resp", FT_UINT8
, BASE_HEX
,
210 VALS(modifier_vals_resp
), XDLC_U_MODIFIER_MASK
, NULL
, HFILL
}},
213 { "Frame type", "x75.control.ftype", FT_UINT8
, BASE_HEX
,
214 VALS(ftype_vals
), XDLC_I_MASK
, NULL
, HFILL
}},
217 { "Frame type", "x75.control.ftype", FT_UINT8
, BASE_HEX
,
218 VALS(ftype_vals
), XDLC_S_U_MASK
, NULL
, HFILL
}},
220 static int *ett
[] = {
225 proto_x75
= proto_register_protocol("Async data over ISDN (X.75)",
227 proto_register_field_array (proto_x75
, hf
, array_length(hf
));
228 proto_register_subtree_array(ett
, array_length(ett
));
230 x75_handle
= register_dissector("x75", dissect_x75
, proto_x75
);
232 x75_subdissector_table
=
233 register_decode_as_next_proto(proto_x75
,
234 "x75.subdissector", "X.75 payload subdissector", NULL
);
238 proto_reg_handoff_x75(void)
240 data_handle
= find_dissector("data");
244 * Editor modelines - https://www.wireshark.org/tools/modelines.html
249 * indent-tabs-mode: nil
252 * vi: set shiftwidth=4 tabstop=8 expandtab:
253 * :indentSize=4:tabSize=8:noTabs=true: