/src/wireshark/epan/dissectors/packet-sccpmg.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* packet-sccpmg.c |
2 | | * Routines for Signalling Connection Control Part (SCCP) Management dissection |
3 | | * |
4 | | * It is hopefully compliant to: |
5 | | * ANSI T1.112.3-1996 |
6 | | * ITU-T Q.713 7/1996 |
7 | | * YDN 038-1997 (Chinese ITU variant) |
8 | | * JT-Q714 and NTT-Q714 (Japan) |
9 | | * |
10 | | * Note that NTT Annex E (SCCP Management Procedure (Global Title Status |
11 | | * Management)) is not implemented (yet) |
12 | | * |
13 | | * Copyright 2002, Jeff Morriss <jeff.morriss.ws [AT] gmail.com> |
14 | | * |
15 | | * Wireshark - Network traffic analyzer |
16 | | * By Gerald Combs <gerald@wireshark.org> |
17 | | * Copyright 1998 Gerald Combs |
18 | | * |
19 | | * SPDX-License-Identifier: GPL-2.0-or-later |
20 | | */ |
21 | | |
22 | | #include "config.h" |
23 | | |
24 | | #include <epan/packet.h> |
25 | | #include <epan/expert.h> |
26 | | #include "packet-mtp3.h" |
27 | | |
28 | 14 | #define SCCPMG_SSN 1 |
29 | | |
30 | 0 | #define SCCPMG_MESSAGE_TYPE_SSA 0x01 |
31 | 0 | #define SCCPMG_MESSAGE_TYPE_SSP 0x02 |
32 | 0 | #define SCCPMG_MESSAGE_TYPE_SST 0x03 |
33 | 0 | #define SCCPMG_MESSAGE_TYPE_SOR 0x04 |
34 | 0 | #define SCCPMG_MESSAGE_TYPE_SOG 0x05 |
35 | | /* SSC is ITU only */ |
36 | 0 | #define SCCPMG_MESSAGE_TYPE_SSC 0x06 |
37 | | /* Below are ANSI only */ |
38 | 0 | #define SCCPMG_MESSAGE_TYPE_SBR 0xfd |
39 | 0 | #define SCCPMG_MESSAGE_TYPE_SNR 0xfe |
40 | 0 | #define SCCPMG_MESSAGE_TYPE_SRT 0xff |
41 | | |
42 | | void proto_register_sccpmg(void); |
43 | | void proto_reg_handoff_sccpmg(void); |
44 | | |
45 | | static dissector_handle_t sccpmg_handle; |
46 | | |
47 | | /* Same as below but with names typed out */ |
48 | | static const value_string sccpmg_message_type_values[] = { |
49 | | { SCCPMG_MESSAGE_TYPE_SSA, "SubSystem Allowed" }, |
50 | | { SCCPMG_MESSAGE_TYPE_SSP, "SubSystem Prohibited" }, |
51 | | { SCCPMG_MESSAGE_TYPE_SST, "Subsystem Status Test" }, |
52 | | { SCCPMG_MESSAGE_TYPE_SOR, "Subsystem Out of service Request" }, |
53 | | { SCCPMG_MESSAGE_TYPE_SOG, "Subsystem Out of service Grant" }, |
54 | | { SCCPMG_MESSAGE_TYPE_SSC, "SubSystem Congested (ITU)" }, |
55 | | { SCCPMG_MESSAGE_TYPE_SBR, "Subsystem Backup Routing (ANSI)" }, |
56 | | { SCCPMG_MESSAGE_TYPE_SNR, "Subsystem Normal Routing (ANSI)" }, |
57 | | { SCCPMG_MESSAGE_TYPE_SRT, "Subsystem Routing status Test (ANSI)" }, |
58 | | { 0, NULL } }; |
59 | | |
60 | | /* Same as above but in acronym for (for the Info column) */ |
61 | | static const value_string sccpmg_message_type_acro_values[] = { |
62 | | { SCCPMG_MESSAGE_TYPE_SSA, "SSA" }, |
63 | | { SCCPMG_MESSAGE_TYPE_SSP, "SSP" }, |
64 | | { SCCPMG_MESSAGE_TYPE_SST, "SST" }, |
65 | | { SCCPMG_MESSAGE_TYPE_SOR, "SOR" }, |
66 | | { SCCPMG_MESSAGE_TYPE_SOG, "SOG" }, |
67 | | { SCCPMG_MESSAGE_TYPE_SSC, "SSC" }, |
68 | | { SCCPMG_MESSAGE_TYPE_SBR, "SBR" }, |
69 | | { SCCPMG_MESSAGE_TYPE_SNR, "SNR" }, |
70 | | { SCCPMG_MESSAGE_TYPE_SRT, "SRT" }, |
71 | | { 0, NULL } }; |
72 | | |
73 | | |
74 | 2 | #define SCCPMG_MESSAGE_TYPE_OFFSET 0 |
75 | 1 | #define SCCPMG_MESSAGE_TYPE_LENGTH 1 |
76 | | |
77 | 0 | #define SCCPMG_AFFECTED_SSN_OFFSET SCCPMG_MESSAGE_TYPE_LENGTH |
78 | 0 | #define SCCPMG_AFFECTED_SSN_LENGTH 1 |
79 | | |
80 | 0 | #define SCCPMG_AFFECTED_PC_OFFSET (SCCPMG_AFFECTED_SSN_OFFSET + SCCPMG_AFFECTED_SSN_LENGTH) |
81 | 0 | #define ITU_SCCPMG_AFFECTED_PC_LENGTH 2 |
82 | 0 | #define ANSI_SCCPMG_AFFECTED_PC_LENGTH 3 |
83 | | |
84 | 0 | #define ITU_SCCPMG_SMI_OFFSET (SCCPMG_AFFECTED_PC_OFFSET + ITU_SCCPMG_AFFECTED_PC_LENGTH) |
85 | 0 | #define ANSI_SCCPMG_SMI_OFFSET (SCCPMG_AFFECTED_PC_OFFSET + ANSI_SCCPMG_AFFECTED_PC_LENGTH) |
86 | 0 | #define SCCPMG_SMI_LENGTH 1 |
87 | 14 | #define SCCPMG_SMI_MASK 0x3 |
88 | | |
89 | 0 | #define ITU_SCCPMG_CONGESTION_OFFSET (ITU_SCCPMG_SMI_OFFSET + SCCPMG_SMI_LENGTH) |
90 | 0 | #define ITU_SCCPMG_CONGESTION_LENGTH 1 |
91 | 14 | #define ITU_SCCPMG_CONGESTION_MASK 0x0f |
92 | 0 | #define CHINESE_ITU_SCCPMG_CONGESTION_OFFSET (ANSI_SCCPMG_SMI_OFFSET + SCCPMG_SMI_LENGTH) |
93 | | |
94 | 0 | #define SCCPMG_SSN_LENGTH 1 |
95 | | |
96 | | /* Initialize the protocol and registered fields */ |
97 | | static int proto_sccpmg; |
98 | | static int hf_sccpmg_message_type; |
99 | | static int hf_sccpmg_affected_ssn; |
100 | | static int hf_sccpmg_affected_itu_pc; |
101 | | static int hf_sccpmg_affected_japan_pc; |
102 | | static int hf_sccpmg_affected_ansi_pc; |
103 | | static int hf_sccpmg_affected_chinese_pc; |
104 | | static int hf_sccpmg_affected_pc_member; |
105 | | static int hf_sccpmg_affected_pc_cluster; |
106 | | static int hf_sccpmg_affected_pc_network; |
107 | | static int hf_sccpmg_smi; |
108 | | static int hf_sccpmg_congestion_level; |
109 | | |
110 | | /* Initialize the subtree pointers */ |
111 | | static int ett_sccpmg; |
112 | | static int ett_sccpmg_affected_pc; |
113 | | |
114 | | static expert_field ei_sccpmg_unknown_msg; |
115 | | |
116 | | static void |
117 | | dissect_sccpmg_affected_ssn(tvbuff_t *tvb, proto_tree *sccpmg_tree) |
118 | 0 | { |
119 | 0 | proto_tree_add_item(sccpmg_tree, hf_sccpmg_affected_ssn, tvb, |
120 | 0 | SCCPMG_AFFECTED_SSN_OFFSET, SCCPMG_SSN_LENGTH, |
121 | 0 | ENC_BIG_ENDIAN); |
122 | 0 | } |
123 | | |
124 | | static void |
125 | | dissect_sccpmg_affected_pc(tvbuff_t *tvb, proto_tree *sccpmg_tree) |
126 | 0 | { |
127 | 0 | int offset = SCCPMG_AFFECTED_PC_OFFSET; |
128 | |
|
129 | 0 | if (mtp3_standard == ITU_STANDARD) { |
130 | 0 | proto_tree_add_item(sccpmg_tree, hf_sccpmg_affected_itu_pc, tvb, |
131 | 0 | offset, ITU_PC_LENGTH, ENC_LITTLE_ENDIAN); |
132 | 0 | } else if (mtp3_standard == JAPAN_STANDARD) { |
133 | 0 | proto_tree_add_item(sccpmg_tree, hf_sccpmg_affected_japan_pc, |
134 | 0 | tvb, offset, JAPAN_PC_LENGTH, ENC_LITTLE_ENDIAN); |
135 | 0 | } else /* ANSI_STANDARD and CHINESE_ITU_STANDARD */ { |
136 | 0 | int *hf_affected_pc; |
137 | |
|
138 | 0 | if (mtp3_standard == ANSI_STANDARD) |
139 | 0 | { |
140 | 0 | hf_affected_pc = &hf_sccpmg_affected_ansi_pc; |
141 | 0 | } else /* CHINESE_ITU_STANDARD */ { |
142 | 0 | hf_affected_pc = &hf_sccpmg_affected_chinese_pc; |
143 | 0 | } |
144 | | |
145 | | /* create and fill the PC tree */ |
146 | 0 | dissect_mtp3_3byte_pc(tvb, offset, sccpmg_tree, |
147 | 0 | ett_sccpmg_affected_pc, *hf_affected_pc, |
148 | 0 | hf_sccpmg_affected_pc_network, |
149 | 0 | hf_sccpmg_affected_pc_cluster, |
150 | 0 | hf_sccpmg_affected_pc_member, 0, 0); |
151 | |
|
152 | 0 | } |
153 | 0 | } |
154 | | |
155 | | static void |
156 | | dissect_sccpmg_smi(tvbuff_t *tvb, proto_tree *sccpmg_tree) |
157 | 0 | { |
158 | 0 | int offset = 0; |
159 | |
|
160 | 0 | if (mtp3_standard == ITU_STANDARD || mtp3_standard == JAPAN_STANDARD) |
161 | 0 | offset = ITU_SCCPMG_SMI_OFFSET; |
162 | 0 | else /* ANSI_STANDARD and CHINESE_ITU_STANDARD */ |
163 | 0 | offset = ANSI_SCCPMG_SMI_OFFSET; |
164 | |
|
165 | 0 | proto_tree_add_item(sccpmg_tree, hf_sccpmg_smi, tvb, offset, |
166 | 0 | SCCPMG_SMI_LENGTH, ENC_BIG_ENDIAN); |
167 | 0 | } |
168 | | |
169 | | static void |
170 | | dissect_sccpmg_congestion_level(tvbuff_t *tvb, proto_tree *sccpmg_tree) |
171 | 0 | { |
172 | 0 | int offset = 0; |
173 | |
|
174 | 0 | if (mtp3_standard == CHINESE_ITU_STANDARD) |
175 | 0 | offset = CHINESE_ITU_SCCPMG_CONGESTION_OFFSET; |
176 | 0 | else /* ITU_STANDARD or JAPAN_STANDARD */ |
177 | 0 | offset = ITU_SCCPMG_CONGESTION_OFFSET; |
178 | |
|
179 | 0 | proto_tree_add_item(sccpmg_tree, hf_sccpmg_congestion_level, tvb, |
180 | 0 | offset, ITU_SCCPMG_CONGESTION_LENGTH, ENC_BIG_ENDIAN); |
181 | 0 | } |
182 | | |
183 | | static void |
184 | | dissect_sccpmg_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *sccpmg_tree) |
185 | 1 | { |
186 | 1 | uint8_t message_type; |
187 | | |
188 | | /* Extract the message type; all other processing is based on this */ |
189 | 1 | message_type = tvb_get_uint8(tvb, SCCPMG_MESSAGE_TYPE_OFFSET); |
190 | | |
191 | 1 | col_add_fstr(pinfo->cinfo, COL_INFO, "%s ", val_to_str_const(message_type, sccpmg_message_type_acro_values, "Unknown")); |
192 | | |
193 | 1 | if (sccpmg_tree) { |
194 | | /* add the message type to the protocol tree */ |
195 | 1 | proto_tree_add_uint(sccpmg_tree, hf_sccpmg_message_type, tvb, |
196 | 1 | SCCPMG_MESSAGE_TYPE_OFFSET, |
197 | 1 | SCCPMG_MESSAGE_TYPE_LENGTH, message_type); |
198 | 1 | } |
199 | | |
200 | 1 | switch(message_type) { |
201 | 0 | case SCCPMG_MESSAGE_TYPE_SBR: |
202 | 0 | case SCCPMG_MESSAGE_TYPE_SNR: |
203 | 0 | case SCCPMG_MESSAGE_TYPE_SRT: |
204 | 0 | if (mtp3_standard != ANSI_STANDARD) |
205 | 0 | { |
206 | 0 | proto_tree_add_expert(sccpmg_tree, pinfo, &ei_sccpmg_unknown_msg, tvb, 0, -1); |
207 | 0 | break; |
208 | 0 | } |
209 | | /* else fallthrough */ |
210 | 0 | case SCCPMG_MESSAGE_TYPE_SSA: |
211 | 0 | case SCCPMG_MESSAGE_TYPE_SSP: |
212 | 0 | case SCCPMG_MESSAGE_TYPE_SST: |
213 | 0 | case SCCPMG_MESSAGE_TYPE_SOR: |
214 | 0 | case SCCPMG_MESSAGE_TYPE_SOG: |
215 | 0 | dissect_sccpmg_affected_ssn(tvb, sccpmg_tree); |
216 | 0 | dissect_sccpmg_affected_pc(tvb, sccpmg_tree); |
217 | 0 | dissect_sccpmg_smi(tvb, sccpmg_tree); |
218 | |
|
219 | 0 | break; |
220 | 0 | case SCCPMG_MESSAGE_TYPE_SSC: |
221 | 0 | if (mtp3_standard != ANSI_STANDARD) |
222 | 0 | { |
223 | 0 | dissect_sccpmg_affected_ssn(tvb, sccpmg_tree); |
224 | 0 | dissect_sccpmg_affected_pc(tvb, sccpmg_tree); |
225 | 0 | dissect_sccpmg_smi(tvb, sccpmg_tree); |
226 | 0 | dissect_sccpmg_congestion_level(tvb, sccpmg_tree); |
227 | 0 | } |
228 | | /* else fallthrough */ |
229 | |
|
230 | 1 | default: |
231 | 1 | proto_tree_add_expert(sccpmg_tree, pinfo, &ei_sccpmg_unknown_msg, tvb, 0, -1); |
232 | 1 | } |
233 | 1 | } |
234 | | |
235 | | static int |
236 | | dissect_sccpmg(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) |
237 | 1 | { |
238 | 1 | proto_item *sccpmg_item; |
239 | 1 | proto_tree *sccpmg_tree = NULL; |
240 | | |
241 | | /* Make entry in the Protocol column on summary display */ |
242 | 1 | switch(mtp3_standard) { |
243 | 1 | case ITU_STANDARD: |
244 | 1 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "SCCPMG (Int. ITU)"); |
245 | 1 | break; |
246 | 0 | case ANSI_STANDARD: |
247 | 0 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "SCCPMG (ANSI)"); |
248 | 0 | break; |
249 | 0 | case CHINESE_ITU_STANDARD: |
250 | 0 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "SCCPMG (Chin. ITU)"); |
251 | 0 | break; |
252 | 1 | }; |
253 | | |
254 | | /* In the interest of speed, if "tree" is NULL, don't do any work not |
255 | | necessary to generate protocol tree items. */ |
256 | 1 | if (tree) { |
257 | | /* create the sccpmg protocol tree */ |
258 | 1 | sccpmg_item = proto_tree_add_item(tree, proto_sccpmg, tvb, 0, |
259 | 1 | -1, ENC_NA); |
260 | 1 | sccpmg_tree = proto_item_add_subtree(sccpmg_item, ett_sccpmg); |
261 | 1 | } |
262 | | |
263 | | /* dissect the message */ |
264 | 1 | dissect_sccpmg_message(tvb, pinfo, sccpmg_tree); |
265 | 1 | return tvb_captured_length(tvb); |
266 | 1 | } |
267 | | |
268 | | /* Register the protocol with Wireshark */ |
269 | | void |
270 | | proto_register_sccpmg(void) |
271 | 14 | { |
272 | | /* Setup list of header fields */ |
273 | 14 | static hf_register_info hf[] = { |
274 | 14 | { &hf_sccpmg_message_type, |
275 | 14 | { "Message Type", "sccpmg.message_type", |
276 | 14 | FT_UINT8, BASE_HEX, VALS(sccpmg_message_type_values), 0x0, |
277 | 14 | NULL, HFILL}}, |
278 | 14 | { &hf_sccpmg_affected_ssn, |
279 | 14 | { "Affected SubSystem Number", "sccpmg.ssn", |
280 | 14 | FT_UINT8, BASE_DEC, NULL, 0x0, |
281 | 14 | NULL, HFILL}}, |
282 | 14 | { &hf_sccpmg_affected_itu_pc, |
283 | 14 | { "Affected Point Code", "sccpmg.pc", |
284 | 14 | FT_UINT16, BASE_DEC, NULL, ITU_PC_MASK, |
285 | 14 | NULL, HFILL}}, |
286 | 14 | { &hf_sccpmg_affected_japan_pc, |
287 | 14 | { "Affected Point Code", "sccpmg.pc", |
288 | 14 | FT_UINT16, BASE_DEC, NULL, 0x0, |
289 | 14 | NULL, HFILL}}, |
290 | 14 | { &hf_sccpmg_affected_ansi_pc, |
291 | 14 | { "Affected Point Code", "sccpmg.ansi_pc", |
292 | 14 | FT_STRING, BASE_NONE, NULL, 0x0, |
293 | 14 | NULL, HFILL}}, |
294 | 14 | { &hf_sccpmg_affected_chinese_pc, |
295 | 14 | { "Affected Point Code", "sccpmg.chinese_pc", |
296 | 14 | FT_STRING, BASE_NONE, NULL, 0x0, |
297 | 14 | NULL, HFILL}}, |
298 | 14 | { &hf_sccpmg_affected_pc_network, |
299 | 14 | { "Affected PC Network", "sccpmg.network", |
300 | 14 | FT_UINT24, BASE_DEC, NULL, ANSI_NETWORK_MASK, |
301 | 14 | NULL, HFILL}}, |
302 | 14 | { &hf_sccpmg_affected_pc_cluster, |
303 | 14 | { "Affected PC Cluster", "sccpmg.cluster", |
304 | 14 | FT_UINT24, BASE_DEC, NULL, ANSI_CLUSTER_MASK, |
305 | 14 | NULL, HFILL}}, |
306 | 14 | { &hf_sccpmg_affected_pc_member, |
307 | 14 | { "Affected PC Member", "sccpmg.member", |
308 | 14 | FT_UINT24, BASE_DEC, NULL, ANSI_MEMBER_MASK, |
309 | 14 | NULL, HFILL}}, |
310 | 14 | { &hf_sccpmg_smi, |
311 | 14 | { "Subsystem Multiplicity Indicator", "sccpmg.smi", |
312 | 14 | FT_UINT8, BASE_DEC, NULL, SCCPMG_SMI_MASK, |
313 | 14 | NULL, HFILL}}, |
314 | 14 | { &hf_sccpmg_congestion_level, |
315 | 14 | { "SCCP Congestion Level (ITU)", "sccpmg.congestion", |
316 | 14 | FT_UINT8, BASE_DEC, NULL, ITU_SCCPMG_CONGESTION_MASK, |
317 | 14 | NULL, HFILL}} |
318 | 14 | }; |
319 | | |
320 | | /* Setup protocol subtree array */ |
321 | 14 | static int *ett[] = { |
322 | 14 | &ett_sccpmg, |
323 | 14 | &ett_sccpmg_affected_pc |
324 | 14 | }; |
325 | | |
326 | 14 | static ei_register_info ei[] = { |
327 | 14 | { &ei_sccpmg_unknown_msg, { "sccpmg.unknown_msg", PI_UNDECODED, PI_WARN, "Unknown message", EXPFILL }}, |
328 | 14 | }; |
329 | | |
330 | 14 | expert_module_t* expert_sccpmg; |
331 | | |
332 | | /* Register the protocol name and description */ |
333 | 14 | proto_sccpmg = proto_register_protocol("Signalling Connection Control Part Management", |
334 | 14 | "SCCPMG", "sccpmg"); |
335 | | |
336 | | /* Required function calls to register the header fields and subtrees |
337 | | used */ |
338 | 14 | proto_register_field_array(proto_sccpmg, hf, array_length(hf)); |
339 | 14 | proto_register_subtree_array(ett, array_length(ett)); |
340 | 14 | expert_sccpmg = expert_register_protocol(proto_sccpmg); |
341 | 14 | expert_register_field_array(expert_sccpmg, ei, array_length(ei)); |
342 | | |
343 | | /* Register the dissector handle */ |
344 | 14 | sccpmg_handle = register_dissector("sccpmg", dissect_sccpmg, proto_sccpmg); |
345 | 14 | } |
346 | | |
347 | | void |
348 | | proto_reg_handoff_sccpmg(void) |
349 | 14 | { |
350 | | /* Register for SCCP SSN=1 messages */ |
351 | 14 | dissector_add_uint("sccp.ssn", SCCPMG_SSN, sccpmg_handle); |
352 | 14 | } |
353 | | |
354 | | /* |
355 | | * Editor modelines - https://www.wireshark.org/tools/modelines.html |
356 | | * |
357 | | * Local variables: |
358 | | * c-basic-offset: 8 |
359 | | * tab-width: 8 |
360 | | * indent-tabs-mode: t |
361 | | * End: |
362 | | * |
363 | | * vi: set shiftwidth=8 tabstop=8 noexpandtab: |
364 | | * :indentSize=8:tabSize=8:noTabs=false: |
365 | | */ |