/src/wireshark/epan/dissectors/packet-sccp.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* packet-sccp.c |
2 | | * Routines for Signalling Connection Control Part (SCCP) dissection |
3 | | * |
4 | | * It is hopefully compliant to: |
5 | | * ANSI T1.112.3-2001 |
6 | | * ITU-T Q.713 7/1996 |
7 | | * YDN 038-1997 (Chinese ITU variant) |
8 | | * JT-Q713 and NTT-Q713 (Japan) |
9 | | * |
10 | | * Note that Japan-specific GTT is incomplete; in particular, the specific |
11 | | * TTs that are defined in TTC and NTT are not decoded in detail. |
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 | | * Copied from packet-m2pa.c |
20 | | * |
21 | | * SPDX-License-Identifier: GPL-2.0-or-later |
22 | | */ |
23 | | |
24 | | |
25 | | #include "config.h" |
26 | | |
27 | | |
28 | | #include <epan/packet.h> |
29 | | #include <epan/prefs.h> |
30 | | #include <epan/reassemble.h> |
31 | | #include <epan/address_types.h> |
32 | | #include <epan/asn1.h> |
33 | | #include <epan/uat.h> |
34 | | #include <epan/expert.h> |
35 | | #include <epan/tap.h> |
36 | | #include <epan/to_str.h> |
37 | | #include <epan/decode_as.h> |
38 | | #include <epan/proto_data.h> |
39 | | #include <wiretap/wtap.h> |
40 | | #include <wsutil/str_util.h> |
41 | | #include "packet-mtp3.h" |
42 | | #include "packet-tcap.h" |
43 | | #include "packet-sccp.h" |
44 | | #include "packet-e164.h" |
45 | | #include "packet-e212.h" |
46 | | |
47 | | /* function prototypes */ |
48 | | void proto_register_sccp(void); |
49 | | void proto_reg_handoff_sccp(void); |
50 | | |
51 | | static Standard_Type decode_mtp3_standard; |
52 | | |
53 | 562 | #define SCCP_MSG_TYPE_OFFSET 0 |
54 | 562 | #define SCCP_MSG_TYPE_LENGTH 1 |
55 | 1.32k | #define POINTER_LENGTH 1 |
56 | 1.18k | #define POINTER_LENGTH_LONG 2 |
57 | | |
58 | | /* Same as below but with names typed out */ |
59 | | static const value_string sccp_message_type_values[] = { |
60 | | { SCCP_MSG_TYPE_CR, "Connection Request" }, |
61 | | { SCCP_MSG_TYPE_CC, "Connection Confirm" }, |
62 | | { SCCP_MSG_TYPE_CREF, "Connection Refused" }, |
63 | | { SCCP_MSG_TYPE_RLSD, "Released" }, |
64 | | { SCCP_MSG_TYPE_RLC, "Release Complete" }, |
65 | | { SCCP_MSG_TYPE_DT1, "Data Form 1" }, |
66 | | { SCCP_MSG_TYPE_DT2, "Data Form 2" }, |
67 | | { SCCP_MSG_TYPE_AK, "Data Acknowledgement" }, |
68 | | { SCCP_MSG_TYPE_UDT, "Unitdata" }, |
69 | | { SCCP_MSG_TYPE_UDTS, "Unitdata Service" }, |
70 | | { SCCP_MSG_TYPE_ED, "Expedited Data" }, |
71 | | { SCCP_MSG_TYPE_EA, "Expedited Data Acknowledgement" }, |
72 | | { SCCP_MSG_TYPE_RSR, "Reset Request" }, |
73 | | { SCCP_MSG_TYPE_RSC, "Reset Confirmation" }, |
74 | | { SCCP_MSG_TYPE_ERR, "Error" }, |
75 | | { SCCP_MSG_TYPE_IT, "Inactivity Timer" }, |
76 | | { SCCP_MSG_TYPE_XUDT, "Extended Unitdata" }, |
77 | | { SCCP_MSG_TYPE_XUDTS, "Extended Unitdata Service" }, |
78 | | { SCCP_MSG_TYPE_LUDT, "Long Unitdata" }, |
79 | | { SCCP_MSG_TYPE_LUDTS, "Long Unitdata Service" }, |
80 | | { 0, NULL } }; |
81 | | |
82 | | /* Same as above but in acronym form (for the Info column) */ |
83 | | const value_string sccp_message_type_acro_values[] = { |
84 | | { SCCP_MSG_TYPE_CR, "CR" }, |
85 | | { SCCP_MSG_TYPE_CC, "CC" }, |
86 | | { SCCP_MSG_TYPE_CREF, "CREF" }, |
87 | | { SCCP_MSG_TYPE_RLSD, "RLSD" }, |
88 | | { SCCP_MSG_TYPE_RLC, "RLC" }, |
89 | | { SCCP_MSG_TYPE_DT1, "DT1" }, |
90 | | { SCCP_MSG_TYPE_DT2, "DT2" }, |
91 | | { SCCP_MSG_TYPE_AK, "AK" }, |
92 | | { SCCP_MSG_TYPE_UDT, "UDT" }, |
93 | | { SCCP_MSG_TYPE_UDTS, "UDTS" }, |
94 | | { SCCP_MSG_TYPE_ED, "ED" }, |
95 | | { SCCP_MSG_TYPE_EA, "EA" }, |
96 | | { SCCP_MSG_TYPE_RSR, "RSR" }, |
97 | | { SCCP_MSG_TYPE_RSC, "RSC" }, |
98 | | { SCCP_MSG_TYPE_ERR, "ERR" }, |
99 | | { SCCP_MSG_TYPE_IT, "IT" }, |
100 | | { SCCP_MSG_TYPE_XUDT, "XUDT" }, |
101 | | { SCCP_MSG_TYPE_XUDTS, "XUDTS" }, |
102 | | { SCCP_MSG_TYPE_LUDT, "LUDT" }, |
103 | | { SCCP_MSG_TYPE_LUDTS, "LUDTS" }, |
104 | | { 0, NULL } }; |
105 | | |
106 | 2.32k | #define PARAMETER_LENGTH_LENGTH 1 |
107 | 3 | #define PARAMETER_LONG_DATA_LENGTH_LENGTH 2 |
108 | 2.02k | #define PARAMETER_TYPE_LENGTH 1 |
109 | | |
110 | 2.37k | #define PARAMETER_END_OF_OPTIONAL_PARAMETERS 0x00 |
111 | 1.98k | #define PARAMETER_DESTINATION_LOCAL_REFERENCE 0x01 |
112 | 1.43k | #define PARAMETER_SOURCE_LOCAL_REFERENCE 0x02 |
113 | 630 | #define PARAMETER_CALLED_PARTY_ADDRESS 0x03 |
114 | 764 | #define PARAMETER_CALLING_PARTY_ADDRESS 0x04 |
115 | 480 | #define PARAMETER_CLASS 0x05 |
116 | 77 | #define PARAMETER_SEGMENTING_REASSEMBLING 0x06 |
117 | 36 | #define PARAMETER_RECEIVE_SEQUENCE_NUMBER 0x07 |
118 | 66 | #define PARAMETER_SEQUENCING_SEGMENTING 0x08 |
119 | 55 | #define PARAMETER_CREDIT 0x09 |
120 | 1.49k | #define PARAMETER_RELEASE_CAUSE 0x0a |
121 | 1.72k | #define PARAMETER_RETURN_CAUSE 0x0b |
122 | 1.60k | #define PARAMETER_RESET_CAUSE 0x0c |
123 | 1.64k | #define PARAMETER_ERROR_CAUSE 0x0d |
124 | 1.74k | #define PARAMETER_REFUSAL_CAUSE 0x0e |
125 | 5.03k | #define PARAMETER_DATA 0x0f |
126 | 406 | #define PARAMETER_SEGMENTATION 0x10 |
127 | 144 | #define PARAMETER_HOP_COUNTER 0x11 |
128 | | /* Importance is ITU only */ |
129 | 68 | #define PARAMETER_IMPORTANCE 0x12 |
130 | 2.80k | #define PARAMETER_LONG_DATA 0x13 |
131 | | /* ISNI is ANSI only */ |
132 | 7 | #define PARAMETER_ISNI 0xfa |
133 | | |
134 | | static const value_string sccp_parameter_values[] = { |
135 | | { PARAMETER_END_OF_OPTIONAL_PARAMETERS, "End of Optional Parameters" }, |
136 | | { PARAMETER_DESTINATION_LOCAL_REFERENCE, "Destination Local Reference" }, |
137 | | { PARAMETER_SOURCE_LOCAL_REFERENCE, "Source Local Reference" }, |
138 | | { PARAMETER_CALLED_PARTY_ADDRESS, "Called Party Address" }, |
139 | | { PARAMETER_CALLING_PARTY_ADDRESS, "Calling Party Address" }, |
140 | | { PARAMETER_CLASS, "Protocol Class" }, |
141 | | { PARAMETER_SEGMENTING_REASSEMBLING, "Segmenting/Reassembling" }, |
142 | | { PARAMETER_RECEIVE_SEQUENCE_NUMBER, "Receive Sequence Number" }, |
143 | | { PARAMETER_SEQUENCING_SEGMENTING, "Sequencing/Segmenting" }, |
144 | | { PARAMETER_CREDIT, "Credit" }, |
145 | | { PARAMETER_RELEASE_CAUSE, "Release Cause" }, |
146 | | { PARAMETER_RETURN_CAUSE, "Return Cause" }, |
147 | | { PARAMETER_RESET_CAUSE, "Reset Cause" }, |
148 | | { PARAMETER_ERROR_CAUSE, "Error Cause" }, |
149 | | { PARAMETER_REFUSAL_CAUSE, "Refusal Cause" }, |
150 | | { PARAMETER_DATA, "Data" }, |
151 | | { PARAMETER_SEGMENTATION, "Segmentation" }, |
152 | | { PARAMETER_HOP_COUNTER, "Hop Counter" }, |
153 | | { PARAMETER_IMPORTANCE, "Importance (ITU)" }, |
154 | | { PARAMETER_LONG_DATA, "Long Data" }, |
155 | | { PARAMETER_ISNI, "Intermediate Signaling Network Identification (ANSI)" }, |
156 | | { 0, NULL } }; |
157 | | |
158 | | |
159 | 206 | #define END_OF_OPTIONAL_PARAMETERS_LENGTH 1 |
160 | 89 | #define DESTINATION_LOCAL_REFERENCE_LENGTH 3 |
161 | 171 | #define SOURCE_LOCAL_REFERENCE_LENGTH 3 |
162 | 209 | #define PROTOCOL_CLASS_LENGTH 1 |
163 | | #define RECEIVE_SEQUENCE_NUMBER_LENGTH 1 |
164 | | #define CREDIT_LENGTH 1 |
165 | | #define RELEASE_CAUSE_LENGTH 1 |
166 | | #define RETURN_CAUSE_LENGTH 1 |
167 | | #define RESET_CAUSE_LENGTH 1 |
168 | | #define ERROR_CAUSE_LENGTH 1 |
169 | | #define REFUSAL_CAUSE_LENGTH 1 |
170 | | #define HOP_COUNTER_LENGTH 1 |
171 | | #define IMPORTANCE_LENGTH 1 |
172 | | |
173 | | |
174 | | /* Parts of the Called and Calling Address parameters */ |
175 | | /* Address Indicator */ |
176 | 3.15k | #define ADDRESS_INDICATOR_LENGTH 1 |
177 | 481 | #define ITU_RESERVED_MASK 0x80 |
178 | 28 | #define ANSI_NATIONAL_MASK 0x80 |
179 | 481 | #define ROUTING_INDICATOR_MASK 0x40 |
180 | 509 | #define GTI_MASK 0x3C |
181 | 379 | #define GTI_SHIFT 2 |
182 | 478 | #define ITU_SSN_INDICATOR_MASK 0x02 |
183 | 478 | #define ITU_PC_INDICATOR_MASK 0x01 |
184 | 28 | #define ANSI_PC_INDICATOR_MASK 0x02 |
185 | 28 | #define ANSI_SSN_INDICATOR_MASK 0x01 |
186 | | |
187 | | static const value_string sccp_ansi_national_indicator_values[] = { |
188 | | { 0x0, "Address coded to International standard" }, |
189 | | { 0x1, "Address coded to National standard" }, |
190 | | { 0, NULL } }; |
191 | | |
192 | 0 | #define ROUTE_ON_GT 0x0 |
193 | 666 | #define ROUTE_ON_SSN 0x1 |
194 | 453 | #define ROUTING_INDICATOR_SHIFT 6 |
195 | | static const value_string sccp_routing_indicator_values[] = { |
196 | | { ROUTE_ON_GT, "Route on GT" }, |
197 | | { ROUTE_ON_SSN, "Route on SSN" }, |
198 | | { 0, NULL } }; |
199 | | |
200 | 436 | #define AI_GTI_NO_GT 0x0 |
201 | 551 | #define ITU_AI_GTI_NAI 0x1 |
202 | 758 | #define AI_GTI_TT 0x2 |
203 | 742 | #define ITU_AI_GTI_TT_NP_ES 0x3 |
204 | 866 | #define ITU_AI_GTI_TT_NP_ES_NAI 0x4 |
205 | | static const value_string sccp_itu_global_title_indicator_values[] = { |
206 | | { AI_GTI_NO_GT, "No Global Title" }, |
207 | | { ITU_AI_GTI_NAI, "Nature of Address Indicator only" }, |
208 | | { AI_GTI_TT, "Translation Type only" }, |
209 | | { ITU_AI_GTI_TT_NP_ES, "Translation Type, Numbering Plan, and Encoding Scheme included" }, |
210 | | { ITU_AI_GTI_TT_NP_ES_NAI, "Translation Type, Numbering Plan, Encoding Scheme, and Nature of Address Indicator included" }, |
211 | | { 0, NULL } }; |
212 | | |
213 | | /* #define AI_GTI_NO_GT 0x0 */ |
214 | 0 | #define ANSI_AI_GTI_TT_NP_ES 0x1 |
215 | | /* #define AI_GTI_TT 0x2 */ |
216 | | static const value_string sccp_ansi_global_title_indicator_values[] = { |
217 | | { AI_GTI_NO_GT, "No Global Title" }, |
218 | | { ANSI_AI_GTI_TT_NP_ES, "Translation Type, Numbering Plan, and Encoding Scheme included" }, |
219 | | { AI_GTI_TT, "Translation Type only" }, |
220 | | { 0, NULL } }; |
221 | | |
222 | | static const value_string sccp_ai_pci_values[] = { |
223 | | { 0x1, "Point Code present" }, |
224 | | { 0x0, "Point Code not present" }, |
225 | | { 0, NULL } }; |
226 | | |
227 | | static const value_string sccp_ai_ssni_values[] = { |
228 | | { 0x1, "SSN present" }, |
229 | | { 0x0, "SSN not present" }, |
230 | | { 0, NULL } }; |
231 | | |
232 | 733 | #define ADDRESS_SSN_LENGTH 1 |
233 | 1.35k | #define INVALID_SSN 0xff |
234 | | /* Some values from 3GPP TS 23.003 */ |
235 | | /* Japan TTC and NTT define a lot of SSNs, some of which conflict with |
236 | | * these. They are not added for now. |
237 | | */ |
238 | | static const value_string sccp_ssn_values[] = { |
239 | | { 0x00, "SSN not known/not used" }, |
240 | | { 0x01, "SCCP management" }, |
241 | | { 0x02, "Reserved for ITU-T allocation" }, |
242 | | { 0x03, "ISDN User Part" }, |
243 | | { 0x04, "OMAP (Operation, Maintenance, and Administration Part)" }, |
244 | | { 0x05, "MAP (Mobile Application Part)" }, |
245 | | { 0x06, "HLR (Home Location Register)" }, |
246 | | { 0x07, "VLR (Visitor Location Register)" }, |
247 | | { 0x08, "MSC (Mobile Switching Center)" }, |
248 | | { 0x09, "EIC/EIR (Equipment Identifier Center/Equipment Identification Register)" }, |
249 | | { 0x0a, "AUC/AC (Authentication Center)" }, |
250 | | { 0x0b, "ISDN supplementary services (ITU only)" }, |
251 | | { 0x0c, "Reserved for international use (ITU only)" }, |
252 | | { 0x0d, "Broadband ISDN edge-to-edge applications (ITU only)" }, |
253 | | { 0x0e, "TC test responder (ITU only)" }, |
254 | | /* The following national network subsystem numbers have been allocated for use within and |
255 | | * between GSM/UMTS networks: |
256 | | */ |
257 | | { 0x8e, "RANAP" }, |
258 | | { 0x8f, "RNSAP" }, |
259 | | { 0x91, "GMLC(MAP)" }, |
260 | | { 0x92, "CAP" }, |
261 | | { 0x93, "gsmSCF (MAP) or IM-SSF (MAP) or Presence Network Agent" }, |
262 | | { 0x94, "SIWF (MAP)" }, |
263 | | { 0x95, "SGSN (MAP)" }, |
264 | | { 0x96, "GGSN (MAP)" }, |
265 | | /* The following national network subsystem numbers have been allocated for use within GSM/UMTS networks:*/ |
266 | | { 0xf8, "CSS (MAP)" }, |
267 | | { 0xf9, "PCAP" }, |
268 | | { 0xfa, "BSC (BSSAP-LE)" }, |
269 | | { 0xfb, "MSC (BSSAP-LE)" }, |
270 | | { 0xfc, "IOS or SMLC (BSSAP-LE)" }, |
271 | | { 0xfd, "BSS O&M (A interface)" }, |
272 | | { 0xfe, "BSSAP/BSAP" }, |
273 | | { 0, NULL } }; |
274 | | |
275 | | |
276 | | /* * * * * * * * * * * * * * * * * |
277 | | * Global Title: ITU GTI == 0001 * |
278 | | * * * * * * * * * * * * * * * * */ |
279 | 200 | #define GT_NAI_MASK 0x7F |
280 | 487 | #define GT_NAI_LENGTH 1 |
281 | | #define GT_NAI_UNKNOWN 0x00 |
282 | | #define GT_NAI_SUBSCRIBER_NUMBER 0x01 |
283 | | #define GT_NAI_RESERVED_NATIONAL 0x02 |
284 | | #define GT_NAI_NATIONAL_SIG_NUM 0x03 |
285 | 17 | #define GT_NAI_INTERNATIONAL_NUM 0x04 |
286 | | static const value_string sccp_nai_values[] = { |
287 | | { GT_NAI_UNKNOWN, "NAI unknown" }, |
288 | | { GT_NAI_SUBSCRIBER_NUMBER, "Subscriber Number" }, |
289 | | { GT_NAI_RESERVED_NATIONAL, "Reserved for national use" }, |
290 | | { GT_NAI_NATIONAL_SIG_NUM, "National significant number" }, |
291 | | { GT_NAI_INTERNATIONAL_NUM, "International number" }, |
292 | | { 0, NULL } }; |
293 | | |
294 | | |
295 | 171 | #define GT_OE_MASK 0x80 |
296 | 143 | #define GT_OE_EVEN 0 |
297 | | #define GT_OE_ODD 1 |
298 | | static const value_string sccp_oe_values[] = { |
299 | | { GT_OE_EVEN, "Even number of address signals" }, |
300 | | { GT_OE_ODD, "Odd number of address signals" }, |
301 | | { 0, NULL } }; |
302 | | |
303 | | const value_string sccp_address_signal_values[] = { |
304 | | { 0, "0" }, |
305 | | { 1, "1" }, |
306 | | { 2, "2" }, |
307 | | { 3, "3" }, |
308 | | { 4, "4" }, |
309 | | { 5, "5" }, |
310 | | { 6, "6" }, |
311 | | { 7, "7" }, |
312 | | { 8, "8" }, |
313 | | { 9, "9" }, |
314 | | { 10, "(spare)" }, |
315 | | { 11, "11" }, |
316 | | { 12, "12" }, |
317 | | { 13, "(spare)" }, |
318 | | { 14, "(spare)" }, |
319 | | { 15, "ST" }, |
320 | | { 0, NULL } }; |
321 | | |
322 | | |
323 | | /* * * * * * * * * * * * * * * * * * * * * |
324 | | * Global Title: ITU and ANSI GTI == 0010 * |
325 | | * * * * * * * * * * * * * * * * * * * * */ |
326 | 202 | #define GT_TT_LENGTH 1 |
327 | | |
328 | | |
329 | | /* * * * * * * * * * * * * * * * * * * * * * * * * * |
330 | | * Global Title: ITU GTI == 0011, ANSI GTI == 0001 * |
331 | | * * * * * * * * * * * * * * * * * * * * * * * * * */ |
332 | 113 | #define GT_NP_MASK 0xf0 |
333 | 376 | #define GT_NP_SHIFT 4 |
334 | 255 | #define GT_NP_ES_LENGTH 1 |
335 | | #define GT_NP_UNKNOWN 0x00 |
336 | 13 | #define GT_NP_ISDN 0x01 |
337 | | #define GT_NP_GENERIC_RESERVED 0x02 |
338 | | #define GT_NP_DATA 0x03 |
339 | | #define GT_NP_TELEX 0x04 |
340 | | #define GT_NP_MARITIME_MOBILE 0x05 |
341 | 4 | #define GT_NP_LAND_MOBILE 0x06 |
342 | 17 | #define GT_NP_ISDN_MOBILE 0x07 |
343 | | #define GT_NP_PRIVATE_NETWORK 0x0e |
344 | | #define GT_NP_RESERVED 0x0f |
345 | | static const value_string sccp_np_values[] = { |
346 | | { GT_NP_UNKNOWN, "Unknown" }, |
347 | | { GT_NP_ISDN, "ISDN/telephony" }, |
348 | | { GT_NP_GENERIC_RESERVED, "Generic (ITU)/Reserved (ANSI)" }, |
349 | | { GT_NP_DATA, "Data" }, |
350 | | { GT_NP_TELEX, "Telex" }, |
351 | | { GT_NP_MARITIME_MOBILE, "Maritime mobile" }, |
352 | | { GT_NP_LAND_MOBILE, "Land mobile" }, |
353 | | { GT_NP_ISDN_MOBILE, "ISDN/mobile" }, |
354 | | { GT_NP_PRIVATE_NETWORK, "Private network or network-specific" }, |
355 | | { GT_NP_RESERVED, "Reserved" }, |
356 | | { 0, NULL } }; |
357 | | |
358 | 113 | #define GT_ES_MASK 0x0f |
359 | | #define GT_ES_UNKNOWN 0x0 |
360 | | #define GT_ES_BCD_ODD 0x1 |
361 | 85 | #define GT_ES_BCD_EVEN 0x2 |
362 | | #define GT_ES_NATIONAL 0x3 |
363 | | #define GT_ES_RESERVED 0xf |
364 | | static const value_string sccp_es_values[] = { |
365 | | { GT_ES_UNKNOWN, "Unknown" }, |
366 | | { GT_ES_BCD_ODD, "BCD, odd number of digits" }, |
367 | | { GT_ES_BCD_EVEN, "BCD, even number of digits" }, |
368 | | { GT_ES_NATIONAL, "National specific" }, |
369 | | { GT_ES_RESERVED, "Reserved (ITU)/Spare (ANSI)" }, |
370 | | { 0, NULL } }; |
371 | | |
372 | | /* Address signals above */ |
373 | | |
374 | | |
375 | | /* * * * * * * * * * * * * * * * * |
376 | | * Global Title: ITU GTI == 0100 * |
377 | | * * * * * * * * * * * * * * * * */ |
378 | | /* NP above */ |
379 | | /* ES above */ |
380 | | /* NAI above */ |
381 | | /* Address signals above */ |
382 | | |
383 | | |
384 | 225 | #define CLASS_CLASS_MASK 0xf |
385 | 106 | #define CLASS_SPARE_HANDLING_MASK 0xf0 |
386 | 92 | #define CLASS_SPARE_HANDLING_SHIFT 4 |
387 | | static const value_string sccp_class_handling_values [] = { |
388 | | { 0x0, "No special options" }, |
389 | | { 0x8, "Return message on error" }, |
390 | | { 0, NULL } }; |
391 | | |
392 | | |
393 | 5 | #define SEGMENTING_REASSEMBLING_LENGTH 1 |
394 | 19 | #define SEGMENTING_REASSEMBLING_MASK 0x01 |
395 | | #define NO_MORE_DATA 0 |
396 | | #define MORE_DATA 1 |
397 | | /* This is also used by sequencing-segmenting parameter */ |
398 | | static const value_string sccp_segmenting_reassembling_values [] = { |
399 | | { NO_MORE_DATA, "No more data" }, |
400 | | { MORE_DATA, "More data" }, |
401 | | { 0, NULL } }; |
402 | | |
403 | | |
404 | 1 | #define RECEIVE_SEQUENCE_NUMBER_LENGTH 1 |
405 | 14 | #define RSN_MASK 0xfe |
406 | | |
407 | 8 | #define SEQUENCING_SEGMENTING_LENGTH 2 |
408 | 87 | #define SEQUENCING_SEGMENTING_SSN_LENGTH 1 |
409 | 58 | #define SEQUENCING_SEGMENTING_RSN_LENGTH 1 |
410 | 14 | #define SEND_SEQUENCE_NUMBER_MASK 0xfe |
411 | 14 | #define RECEIVE_SEQUENCE_NUMBER_MASK 0xfe |
412 | 14 | #define SEQUENCING_SEGMENTING_MORE_MASK 0x01 |
413 | | |
414 | | |
415 | 8 | #define CREDIT_LENGTH 1 |
416 | | |
417 | 8 | #define RELEASE_CAUSE_LENGTH 1 |
418 | | const value_string sccp_release_cause_values [] = { |
419 | | { 0x00, "End user originated" }, |
420 | | { 0x01, "End user congestion" }, |
421 | | { 0x02, "End user failure" }, |
422 | | { 0x03, "SCCP user originated" }, |
423 | | { 0x04, "Remote procedure error" }, |
424 | | { 0x05, "Inconsistent connection data" }, |
425 | | { 0x06, "Access failure" }, |
426 | | { 0x07, "Access congestion" }, |
427 | | { 0x08, "Subsystem failure" }, |
428 | | { 0x09, "Subsystem congestion" }, |
429 | | { 0x0a, "MTP failure" }, |
430 | | { 0x0b, "Network congestion" }, |
431 | | { 0x0c, "Expiration of reset timer" }, |
432 | | { 0x0d, "Expiration of receive inactivity timer" }, |
433 | | { 0x0e, "Reserved" }, |
434 | | { 0x0f, "Unqualified" }, |
435 | | { 0x10, "SCCP failure (ITU only)" }, |
436 | | { 0, NULL } }; |
437 | | |
438 | | |
439 | 34 | #define RETURN_CAUSE_LENGTH 1 |
440 | | const value_string sccp_return_cause_values [] = { |
441 | | { 0x00, "No translation for an address of such nature" }, |
442 | | { 0x01, "No translation for this specific address" }, |
443 | | { 0x02, "Subsystem congestion" }, |
444 | | { 0x03, "Subsystem failure" }, |
445 | | { 0x04, "Unequipped failure" }, |
446 | | { 0x05, "MTP failure" }, |
447 | | { 0x06, "Network congestion" }, |
448 | | { 0x07, "Unqualified" }, |
449 | | { 0x08, "Error in message transport" }, |
450 | | { 0x09, "Error in local processing" }, |
451 | | { 0x0a, "Destination cannot perform reassembly" }, |
452 | | { 0x0b, "SCCP failure" }, |
453 | | { 0x0c, "Hop counter violation" }, |
454 | | { 0x0d, "Segmentation not supported" }, |
455 | | { 0x0e, "Segmentation failure" }, |
456 | | { 0xf7, "Message change failure (ANSI only)" }, |
457 | | { 0xf8, "Invalid INS routing request (ANSI only)" }, |
458 | | { 0xf9, "Invalid ISNI routing request (ANSI only)"}, |
459 | | { 0xfa, "Unauthorized message (ANSI only)" }, |
460 | | { 0xfb, "Message incompatibility (ANSI only)" }, |
461 | | { 0xfc, "Cannot perform ISNI constrained routing (ANSI only)" }, |
462 | | { 0xfd, "Redundant ISNI constrained routing (ANSI only)" }, |
463 | | { 0xfe, "Unable to perform ISNI identification (ANSI only)" }, |
464 | | { 0, NULL } }; |
465 | | |
466 | | |
467 | 0 | #define RESET_CAUSE_LENGTH 1 |
468 | | const value_string sccp_reset_cause_values [] = { |
469 | | { 0x00, "End user originated" }, |
470 | | { 0x01, "SCCP user originated" }, |
471 | | { 0x02, "Message out of order - incorrect send sequence number" }, |
472 | | { 0x03, "Message out of order - incorrect receive sequence number" }, |
473 | | { 0x04, "Remote procedure error - message out of window" }, |
474 | | { 0x05, "Remote procedure error - incorrect send sequence number after (re)initialization" }, |
475 | | { 0x06, "Remote procedure error - general" }, |
476 | | { 0x07, "Remote end user operational" }, |
477 | | { 0x08, "Network operational" }, |
478 | | { 0x09, "Access operational" }, |
479 | | { 0x0a, "Network congestion" }, |
480 | | { 0x0b, "Reserved (ITU)/Not obtainable (ANSI)" }, |
481 | | { 0x0c, "Unqualified" }, |
482 | | { 0, NULL } }; |
483 | | |
484 | | |
485 | 2 | #define ERROR_CAUSE_LENGTH 1 |
486 | | const value_string sccp_error_cause_values [] = { |
487 | | { 0x00, "Local Reference Number (LRN) mismatch - unassigned destination LRN" }, |
488 | | { 0x01, "Local Reference Number (LRN) mismatch - inconsistent source LRN" }, |
489 | | { 0x02, "Point code mismatch" }, |
490 | | { 0x03, "Service class mismatch" }, |
491 | | { 0x04, "Unqualified" }, |
492 | | { 0, NULL } }; |
493 | | |
494 | | |
495 | 8 | #define REFUSAL_CAUSE_LENGTH 1 |
496 | | const value_string sccp_refusal_cause_values [] = { |
497 | | { 0x00, "End user originated" }, |
498 | | { 0x01, "End user congestion" }, |
499 | | { 0x02, "End user failure" }, |
500 | | { 0x03, "SCCP user originated" }, |
501 | | { 0x04, "Destination address unknown" }, |
502 | | { 0x05, "Destination inaccessible" }, |
503 | | { 0x06, "Network resource - QOS not available/non-transient" }, |
504 | | { 0x07, "Network resource - QOS not available/transient" }, |
505 | | { 0x08, "Access failure" }, |
506 | | { 0x09, "Access congestion" }, |
507 | | { 0x0a, "Subsystem failure" }, |
508 | | { 0x0b, "Subsystem congestion" }, |
509 | | { 0x0c, "Expiration of connection establishment timer" }, |
510 | | { 0x0d, "Incompatible user data" }, |
511 | | { 0x0e, "Reserved" }, |
512 | | { 0x0f, "Unqualified" }, |
513 | | { 0x10, "Hop counter violation" }, |
514 | | { 0x11, "SCCP failure (ITU only)" }, |
515 | | { 0x12, "No translation for an address of such nature" }, |
516 | | { 0x13, "Unequipped user" }, |
517 | | { 0, NULL } }; |
518 | | |
519 | | |
520 | | #define SEGMENTATION_LENGTH 4 |
521 | 14 | #define SEGMENTATION_FIRST_SEGMENT_MASK 0x80 |
522 | 14 | #define SEGMENTATION_CLASS_MASK 0x40 |
523 | | #define SEGMENTATION_SPARE_MASK 0x30 |
524 | 14 | #define SEGMENTATION_REMAINING_MASK 0x0f |
525 | | static const value_string sccp_segmentation_first_segment_values [] = { |
526 | | { 1, "First segment" }, |
527 | | { 0, "Not first segment" }, |
528 | | { 0, NULL } }; |
529 | | static const value_string sccp_segmentation_class_values [] = { |
530 | | { 0, "Class 0 selected" }, |
531 | | { 1, "Class 1 selected" }, |
532 | | { 0, NULL } }; |
533 | | |
534 | | |
535 | 70 | #define HOP_COUNTER_LENGTH 1 |
536 | | |
537 | | #define IMPORTANCE_LENGTH 1 |
538 | 14 | #define IMPORTANCE_IMPORTANCE_MASK 0x7 |
539 | | |
540 | | |
541 | 0 | #define ANSI_ISNI_ROUTING_CONTROL_LENGTH 1 |
542 | 14 | #define ANSI_ISNI_MI_MASK 0x01 |
543 | 14 | #define ANSI_ISNI_IRI_MASK 0x06 |
544 | | #define ANSI_ISNI_RES_MASK 0x08 |
545 | 14 | #define ANSI_ISNI_TI_MASK 0x10 |
546 | 0 | #define ANSI_ISNI_TI_SHIFT 4 |
547 | 14 | #define ANSI_ISNI_COUNTER_MASK 0xe0 |
548 | 14 | #define ANSI_ISNI_NETSPEC_MASK 0x03 |
549 | | |
550 | | static const value_string sccp_isni_mark_for_id_values [] = { |
551 | | { 0x0, "Do not identify networks" }, |
552 | | { 0x1, "Identify networks" }, |
553 | | { 0, NULL } }; |
554 | | |
555 | | static const value_string sccp_isni_iri_values [] = { |
556 | | { 0x0, "Neither constrained nor suggested ISNI routing" }, |
557 | | { 0x1, "Constrained ISNI routing" }, |
558 | | { 0x2, "Reserved for suggested ISNI routing" }, |
559 | | { 0x3, "Spare" }, |
560 | | { 0, NULL } }; |
561 | | |
562 | | #define ANSI_ISNI_TYPE_0 0x0 |
563 | 0 | #define ANSI_ISNI_TYPE_1 0x1 |
564 | | static const value_string sccp_isni_ti_values [] = { |
565 | | { ANSI_ISNI_TYPE_0, "Type zero ISNI parameter format" }, |
566 | | { ANSI_ISNI_TYPE_1, "Type one ISNI parameter format" }, |
567 | | { 0, NULL } }; |
568 | | |
569 | | /* Laded from e212 hf*/ |
570 | | static int hf_assoc_imsi; |
571 | | |
572 | | /* Initialize the protocol and registered fields */ |
573 | | static int proto_sccp; |
574 | | static int hf_sccp_message_type; |
575 | | static int hf_sccp_variable_pointer1; |
576 | | static int hf_sccp_variable_pointer2; |
577 | | static int hf_sccp_variable_pointer3; |
578 | | static int hf_sccp_optional_pointer; |
579 | | static int hf_sccp_param_length; |
580 | | static int hf_sccp_ssn; |
581 | | static int hf_sccp_gt_digits; |
582 | | |
583 | | /* Called Party address */ |
584 | | static int hf_sccp_called_ansi_national_indicator; |
585 | | static int hf_sccp_called_itu_natl_use_bit; |
586 | | static int hf_sccp_called_routing_indicator; |
587 | | static int hf_sccp_called_itu_global_title_indicator; |
588 | | static int hf_sccp_called_ansi_global_title_indicator; |
589 | | static int hf_sccp_called_itu_ssn_indicator; |
590 | | static int hf_sccp_called_itu_point_code_indicator; |
591 | | static int hf_sccp_called_ansi_ssn_indicator; |
592 | | static int hf_sccp_called_ansi_point_code_indicator; |
593 | | static int hf_sccp_called_ssn; |
594 | | static int hf_sccp_called_pc_member; |
595 | | static int hf_sccp_called_pc_cluster; |
596 | | static int hf_sccp_called_pc_network; |
597 | | static int hf_sccp_called_ansi_pc; |
598 | | static int hf_sccp_called_chinese_pc; |
599 | | static int hf_sccp_called_itu_pc; |
600 | | static int hf_sccp_called_japan_pc; |
601 | | static int hf_sccp_called_gt_nai; |
602 | | static int hf_sccp_called_gt_oe; |
603 | | static int hf_sccp_called_gt_tt; |
604 | | static int hf_sccp_called_gt_np; |
605 | | static int hf_sccp_called_gt_es; |
606 | | static int hf_sccp_called_gt_digits; |
607 | | static int hf_sccp_called_gt_digits_length; |
608 | | |
609 | | /* Calling party address */ |
610 | | static int hf_sccp_calling_ansi_national_indicator; |
611 | | static int hf_sccp_calling_itu_natl_use_bit; |
612 | | static int hf_sccp_calling_routing_indicator; |
613 | | static int hf_sccp_calling_itu_global_title_indicator; |
614 | | static int hf_sccp_calling_ansi_global_title_indicator; |
615 | | static int hf_sccp_calling_itu_ssn_indicator; |
616 | | static int hf_sccp_calling_itu_point_code_indicator; |
617 | | static int hf_sccp_calling_ansi_ssn_indicator; |
618 | | static int hf_sccp_calling_ansi_point_code_indicator; |
619 | | static int hf_sccp_calling_ssn; |
620 | | static int hf_sccp_calling_pc_member; |
621 | | static int hf_sccp_calling_pc_cluster; |
622 | | static int hf_sccp_calling_pc_network; |
623 | | static int hf_sccp_calling_ansi_pc; |
624 | | static int hf_sccp_calling_chinese_pc; |
625 | | static int hf_sccp_calling_itu_pc; |
626 | | static int hf_sccp_calling_japan_pc; |
627 | | static int hf_sccp_calling_gt_nai; |
628 | | static int hf_sccp_calling_gt_oe; |
629 | | static int hf_sccp_calling_gt_tt; |
630 | | static int hf_sccp_calling_gt_np; |
631 | | static int hf_sccp_calling_gt_es; |
632 | | static int hf_sccp_calling_gt_digits; |
633 | | static int hf_sccp_calling_gt_digits_length; |
634 | | |
635 | | /* Other parameter values */ |
636 | | static int hf_sccp_dlr; |
637 | | static int hf_sccp_slr; |
638 | | static int hf_sccp_lr; |
639 | | static int hf_sccp_class; |
640 | | static int hf_sccp_handling; |
641 | | static int hf_sccp_more; |
642 | | static int hf_sccp_rsn; |
643 | | static int hf_sccp_sequencing_segmenting_ssn; |
644 | | static int hf_sccp_sequencing_segmenting_rsn; |
645 | | static int hf_sccp_sequencing_segmenting_more; |
646 | | static int hf_sccp_credit; |
647 | | static int hf_sccp_release_cause; |
648 | | static int hf_sccp_return_cause; |
649 | | static int hf_sccp_reset_cause; |
650 | | static int hf_sccp_error_cause; |
651 | | static int hf_sccp_refusal_cause; |
652 | | static int hf_sccp_segmentation_first; |
653 | | static int hf_sccp_segmentation_class; |
654 | | static int hf_sccp_segmentation_remaining; |
655 | | static int hf_sccp_segmentation_slr; |
656 | | static int hf_sccp_hop_counter; |
657 | | static int hf_sccp_importance; |
658 | | static int hf_sccp_ansi_isni_mi; |
659 | | static int hf_sccp_ansi_isni_iri; |
660 | | static int hf_sccp_ansi_isni_ti; |
661 | | static int hf_sccp_ansi_isni_netspec; |
662 | | static int hf_sccp_ansi_isni_counter; |
663 | | static int hf_sccp_ansi_isni_network; |
664 | | static int hf_sccp_ansi_isni_cluster; |
665 | | static int hf_sccp_xudt_msg_fragments; |
666 | | static int hf_sccp_xudt_msg_fragment; |
667 | | static int hf_sccp_xudt_msg_fragment_overlap; |
668 | | static int hf_sccp_xudt_msg_fragment_overlap_conflicts; |
669 | | static int hf_sccp_xudt_msg_fragment_multiple_tails; |
670 | | static int hf_sccp_xudt_msg_fragment_too_long_fragment; |
671 | | static int hf_sccp_xudt_msg_fragment_error; |
672 | | static int hf_sccp_xudt_msg_fragment_count; |
673 | | static int hf_sccp_xudt_msg_reassembled_in; |
674 | | static int hf_sccp_xudt_msg_reassembled_length; |
675 | | static int hf_sccp_assoc_msg; |
676 | | static int hf_sccp_assoc_id; |
677 | | static int hf_sccp_segmented_data; |
678 | | static int hf_sccp_linked_dissector; |
679 | | static int hf_sccp_end_optional_param; |
680 | | static int hf_sccp_unknown_message; |
681 | | static int hf_sccp_unknown_parameter; |
682 | | |
683 | | /* Initialize the subtree pointers */ |
684 | | static int ett_sccp; |
685 | | static int ett_sccp_called; |
686 | | static int ett_sccp_called_ai; |
687 | | static int ett_sccp_called_pc; |
688 | | static int ett_sccp_called_gt; |
689 | | static int ett_sccp_called_gt_digits; |
690 | | static int ett_sccp_calling; |
691 | | static int ett_sccp_calling_ai; |
692 | | static int ett_sccp_calling_pc; |
693 | | static int ett_sccp_calling_gt; |
694 | | static int ett_sccp_calling_gt_digits; |
695 | | static int ett_sccp_sequencing_segmenting; |
696 | | static int ett_sccp_segmentation; |
697 | | static int ett_sccp_ansi_isni_routing_control; |
698 | | static int ett_sccp_xudt_msg_fragment; |
699 | | static int ett_sccp_xudt_msg_fragments; |
700 | | static int ett_sccp_assoc; |
701 | | |
702 | | static expert_field ei_sccp_wrong_length; |
703 | | static expert_field ei_sccp_international_standard_address; |
704 | | static expert_field ei_sccp_no_ssn_present; |
705 | | static expert_field ei_sccp_ssn_zero; |
706 | | static expert_field ei_sccp_class_unexpected; |
707 | | static expert_field ei_sccp_handling_invalid; |
708 | | static expert_field ei_sccp_gt_digits_missing; |
709 | | static expert_field ei_sccp_externally_reassembled; |
710 | | |
711 | | |
712 | | static bool sccp_reassemble = true; |
713 | | static bool show_key_params; |
714 | | static bool set_addresses; |
715 | | static bool dt1_ignore_length; |
716 | | |
717 | | static int ss7pc_address_type = -1; |
718 | | |
719 | | static int sccp_tap; |
720 | | |
721 | | |
722 | | static const fragment_items sccp_xudt_msg_frag_items = { |
723 | | /* Fragment subtrees */ |
724 | | &ett_sccp_xudt_msg_fragment, |
725 | | &ett_sccp_xudt_msg_fragments, |
726 | | /* Fragment fields */ |
727 | | &hf_sccp_xudt_msg_fragments, |
728 | | &hf_sccp_xudt_msg_fragment, |
729 | | &hf_sccp_xudt_msg_fragment_overlap, |
730 | | &hf_sccp_xudt_msg_fragment_overlap_conflicts, |
731 | | &hf_sccp_xudt_msg_fragment_multiple_tails, |
732 | | &hf_sccp_xudt_msg_fragment_too_long_fragment, |
733 | | &hf_sccp_xudt_msg_fragment_error, |
734 | | &hf_sccp_xudt_msg_fragment_count, |
735 | | /* Reassembled in field */ |
736 | | &hf_sccp_xudt_msg_reassembled_in, |
737 | | /* Reassembled length field */ |
738 | | &hf_sccp_xudt_msg_reassembled_length, |
739 | | /* Reassembled data field */ |
740 | | NULL, |
741 | | /* Tag */ |
742 | | "SCCP XUDT Message fragments" |
743 | | }; |
744 | | |
745 | | static reassembly_table sccp_xudt_msg_reassembly_table; |
746 | | |
747 | | |
748 | | #define SCCP_USER_DATA 0 |
749 | | #define SCCP_USER_TCAP 1 |
750 | | #define SCCP_USER_RANAP 2 |
751 | | #define SCCP_USER_BSSAP 3 |
752 | | #define SCCP_USER_GSMMAP 4 |
753 | | #define SCCP_USER_CAMEL 5 |
754 | | #define SCCP_USER_INAP 6 |
755 | | #define SCCP_USER_BSAP 7 |
756 | | #define SCCP_USER_BSSAP_LE 8 |
757 | | #define SCCP_USER_BSSAP_PLUS 9 |
758 | | |
759 | | typedef struct _sccp_user_t { |
760 | | unsigned ni; |
761 | | range_t *called_pc; |
762 | | range_t *called_ssn; |
763 | | unsigned user; |
764 | | bool uses_tcap; |
765 | | dissector_handle_t *handlep; |
766 | | } sccp_user_t; |
767 | | |
768 | | static sccp_user_t *sccp_users; |
769 | | static unsigned num_sccp_users; |
770 | | |
771 | | static dissector_handle_t sccp_handle; |
772 | | static dissector_handle_t data_handle; |
773 | | static dissector_handle_t tcap_handle; |
774 | | static dissector_handle_t ranap_handle; |
775 | | static dissector_handle_t bssap_handle; |
776 | | static dissector_handle_t gsmmap_handle; |
777 | | static dissector_handle_t camel_handle; |
778 | | static dissector_handle_t inap_handle; |
779 | | static dissector_handle_t bsap_handle; |
780 | | static dissector_handle_t bssap_le_handle; |
781 | | static dissector_handle_t bssap_plus_handle; |
782 | | static dissector_handle_t default_handle; |
783 | | |
784 | | static const char *default_payload; |
785 | | |
786 | | static const value_string sccp_users_vals[] = { |
787 | | { SCCP_USER_DATA, "Data"}, |
788 | | { SCCP_USER_TCAP, "TCAP"}, |
789 | | { SCCP_USER_RANAP, "RANAP"}, |
790 | | { SCCP_USER_BSSAP, "BSSAP"}, |
791 | | { SCCP_USER_GSMMAP, "GSM MAP"}, |
792 | | { SCCP_USER_CAMEL, "CAMEL"}, |
793 | | { SCCP_USER_INAP, "INAP"}, |
794 | | { SCCP_USER_BSAP, "BSAP"}, |
795 | | { SCCP_USER_BSSAP_LE, "BSSAP-LE"}, |
796 | | { SCCP_USER_BSSAP_PLUS, "BSSAP+"}, |
797 | | { 0, NULL } |
798 | | }; |
799 | | |
800 | | /* |
801 | | * Here are the global variables associated with |
802 | | * the various user definable characteristics of the dissection |
803 | | */ |
804 | | static uint32_t sccp_source_pc_global; |
805 | | static bool sccp_show_length; |
806 | | static bool trace_sccp; |
807 | | |
808 | | static heur_dissector_list_t heur_subdissector_list; |
809 | | |
810 | | static dissector_table_t sccp_ssn_dissector_table; |
811 | | |
812 | | static wmem_tree_t *assocs; |
813 | | static sccp_assoc_info_t no_assoc = { 0,0,0,INVALID_SSN,INVALID_SSN,false,false,NULL,NULL,SCCP_PLOAD_NONE,NULL,NULL,NULL, NULL, 0 }; |
814 | | static uint32_t next_assoc_id; |
815 | | |
816 | | static const value_string assoc_protos[] = { |
817 | | { SCCP_PLOAD_BSSAP, "BSSAP" }, |
818 | | { SCCP_PLOAD_RANAP, "RANAP" }, |
819 | | { 0, NULL } |
820 | | }; |
821 | | |
822 | | /* |
823 | | * Fragment reassembly helpers. |
824 | | * |
825 | | * SCCP data can span multiple messages. As the same local reference number is |
826 | | * used throughout a connection, this identifier is not sufficient for |
827 | | * identifying reassembled PDUs with multiple fragments in the same frame. For |
828 | | * that reason, create a new identifier for each group of fragments based on the |
829 | | * more-data indicator (M-bit) and use that in place of the local reference |
830 | | * number. |
831 | | * |
832 | | * As an optimization, if fragments do not need reassembly (a single message |
833 | | * with the M-bit set), then no surrogate ID is needed nor stored since |
834 | | * reassembly is skipped. |
835 | | */ |
836 | | static uint32_t sccp_reassembly_id_next; |
837 | | |
838 | | /* Maps a key to the current identifier as used in the reassembly API (first pass only). */ |
839 | | static wmem_tree_t *sccp_reassembly_ids; |
840 | | |
841 | | /* Maps (frame number, offset) to a reassembly API identifier. */ |
842 | | static wmem_map_t *sccp_reassembly_id_map; |
843 | | |
844 | | static uint32_t |
845 | | sccp_reassembly_get_id_pass1(uint32_t frame, uint32_t offset, uint32_t key, bool more_frags) |
846 | 13 | { |
847 | 13 | uint32_t id = GPOINTER_TO_UINT(wmem_tree_lookup32(sccp_reassembly_ids, key)); |
848 | 13 | if (!id) { |
849 | 13 | if (!more_frags) { |
850 | | /* This is the last and only fragment, no need to reassembly anything. */ |
851 | 9 | return 0; |
852 | 9 | } |
853 | | |
854 | | /* This is a new fragment and "local reference", so create a new one. */ |
855 | 4 | id = sccp_reassembly_id_next++; |
856 | 4 | wmem_tree_insert32(sccp_reassembly_ids, key, GUINT_TO_POINTER(id)); |
857 | 4 | } |
858 | | /* Save ID for second pass. */ |
859 | 4 | uint64_t *frame_offset = wmem_new(wmem_file_scope(), uint64_t); |
860 | 4 | *frame_offset = ((uint64_t)offset << 32) | frame; |
861 | 4 | wmem_map_insert(sccp_reassembly_id_map, frame_offset, GUINT_TO_POINTER(id)); |
862 | 4 | return id; |
863 | 13 | } |
864 | | |
865 | | static uint32_t |
866 | | sccp_reassembly_get_id_pass2(uint32_t frame, uint32_t offset) |
867 | 0 | { |
868 | 0 | uint64_t frame_offset = ((uint64_t)offset << 32) | frame; |
869 | 0 | return GPOINTER_TO_UINT(wmem_map_lookup(sccp_reassembly_id_map, &frame_offset)); |
870 | 0 | } |
871 | | |
872 | | /** |
873 | | * Returns the reassembly ID for the given frame at the given position or 0 if |
874 | | * reassembly is not necessary. |
875 | | */ |
876 | | static uint32_t |
877 | | sccp_reassembly_get_id(packet_info *pinfo, uint32_t offset, uint32_t key, bool more_frags) |
878 | 13 | { |
879 | 13 | if (!PINFO_FD_VISITED(pinfo)) { |
880 | 13 | return sccp_reassembly_get_id_pass1(pinfo->num, offset, key, more_frags); |
881 | 13 | } else { |
882 | 0 | return sccp_reassembly_get_id_pass2(pinfo->num, offset); |
883 | 0 | } |
884 | 13 | } |
885 | | |
886 | | static tvbuff_t * |
887 | | sccp_reassemble_fragments(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, |
888 | | uint16_t length_offset, uint32_t source_local_ref, bool more_frags, |
889 | | uint8_t pointer_length) |
890 | 13 | { |
891 | 13 | bool save_fragmented; |
892 | 13 | tvbuff_t *new_tvb; |
893 | 13 | fragment_head *frag_msg = NULL; |
894 | 13 | unsigned fragment_len; |
895 | 13 | uint32_t abs_offset, frags_id; |
896 | | |
897 | 13 | switch (pointer_length) { |
898 | 13 | case POINTER_LENGTH: |
899 | 13 | fragment_len = tvb_get_uint8(tvb, length_offset); |
900 | 13 | break; |
901 | 0 | case POINTER_LENGTH_LONG: |
902 | 0 | fragment_len = tvb_get_uint16(tvb, length_offset, ENC_LITTLE_ENDIAN); |
903 | 0 | break; |
904 | 0 | default: |
905 | 0 | ws_assert_not_reached(); |
906 | 13 | } |
907 | | /* Assume that the absolute offset within the tvb uniquely identifies the |
908 | | * message in this frame. */ |
909 | 13 | abs_offset = tvb_raw_offset(tvb) + length_offset; |
910 | 13 | frags_id = sccp_reassembly_get_id(pinfo, abs_offset, source_local_ref, more_frags); |
911 | 13 | if (frags_id) { |
912 | | /* |
913 | | * This fragment is part of multiple fragments, reassembly is required. |
914 | | */ |
915 | 4 | save_fragmented = pinfo->fragmented; |
916 | 4 | pinfo->fragmented = true; |
917 | 4 | frag_msg = fragment_add_seq_next(&sccp_xudt_msg_reassembly_table, |
918 | 4 | tvb, length_offset + pointer_length, |
919 | 4 | pinfo, |
920 | 4 | frags_id, /* ID for fragments belonging together */ |
921 | 4 | NULL, |
922 | 4 | fragment_len, /* fragment length - to the end */ |
923 | 4 | more_frags); /* More fragments? */ |
924 | | |
925 | 4 | if (!PINFO_FD_VISITED(pinfo) && frag_msg) { |
926 | | /* Reassembly has finished, ensure that the next fragment gets a new ID. */ |
927 | 0 | wmem_tree_remove32(sccp_reassembly_ids, source_local_ref); |
928 | 0 | } |
929 | | |
930 | 4 | new_tvb = process_reassembled_data(tvb, length_offset + pointer_length, pinfo, |
931 | 4 | "Reassembled SCCP", frag_msg, |
932 | 4 | &sccp_xudt_msg_frag_items, |
933 | 4 | NULL, tree); |
934 | 4 | if (frag_msg) { /* Reassembled */ |
935 | 0 | col_append_str(pinfo->cinfo, COL_INFO, "(Message reassembled) "); |
936 | 4 | } else { /* Not last packet of reassembled message */ |
937 | 4 | col_append_str(pinfo->cinfo, COL_INFO, "(Message fragment) "); |
938 | 4 | } |
939 | 4 | pinfo->fragmented = save_fragmented; |
940 | 9 | } else { |
941 | | /* |
942 | | * There is only a single fragment, reassembly is not required. |
943 | | */ |
944 | 9 | new_tvb = tvb_new_subset_length(tvb, length_offset + pointer_length, fragment_len); |
945 | 9 | } |
946 | 13 | return new_tvb; |
947 | 13 | } |
948 | | |
949 | | |
950 | | #define is_connectionless(m) \ |
951 | 1.18k | ( m == SCCP_MSG_TYPE_UDT || m == SCCP_MSG_TYPE_UDTS \ |
952 | 591 | || m == SCCP_MSG_TYPE_XUDT|| m == SCCP_MSG_TYPE_XUDTS \ |
953 | 591 | || m == SCCP_MSG_TYPE_LUDT|| m == SCCP_MSG_TYPE_LUDTS) |
954 | | |
955 | | #define RETURN_FALSE \ |
956 | 0 | do { \ |
957 | 0 | /*ws_warning("Frame %d not protocol %d @ line %d", frame_num, my_mtp3_standard, __LINE__);*/ \ |
958 | 0 | return false; \ |
959 | 0 | } while (0) |
960 | | |
961 | | |
962 | | static void sccp_prompt(packet_info *pinfo _U_, char* result) |
963 | 0 | { |
964 | 0 | snprintf(result, MAX_DECODE_AS_PROMPT_LEN, "Dissect SSN %d as", |
965 | 0 | GPOINTER_TO_UINT(p_get_proto_data(pinfo->pool, pinfo, proto_sccp, 0))); |
966 | 0 | } |
967 | | |
968 | | static void *sccp_value(packet_info *pinfo) |
969 | 0 | { |
970 | 0 | return p_get_proto_data(pinfo->pool, pinfo, proto_sccp, 0); |
971 | 0 | } |
972 | | |
973 | | static bool |
974 | | sccp_called_calling_looks_valid(uint32_t frame_num _U_, tvbuff_t *tvb, uint8_t my_mtp3_standard, bool is_co) |
975 | 0 | { |
976 | 0 | uint8_t ai, ri, gti, ssni, pci; |
977 | 0 | uint8_t len_needed = 1; /* need at least the Address Indicator */ |
978 | 0 | unsigned len = tvb_reported_length(tvb); |
979 | |
|
980 | 0 | ai = tvb_get_uint8(tvb, 0); |
981 | 0 | if ((my_mtp3_standard == ANSI_STANDARD) && ((ai & ANSI_NATIONAL_MASK) == 0)) |
982 | 0 | RETURN_FALSE; |
983 | | |
984 | 0 | gti = (ai & GTI_MASK) >> GTI_SHIFT; |
985 | 0 | if (my_mtp3_standard == ANSI_STANDARD) { |
986 | 0 | if (gti > 2) |
987 | 0 | RETURN_FALSE; |
988 | 0 | } else { |
989 | 0 | if (gti > 4) |
990 | 0 | RETURN_FALSE; |
991 | 0 | } |
992 | | |
993 | 0 | ri = (ai & ROUTING_INDICATOR_MASK) >> ROUTING_INDICATOR_SHIFT; |
994 | 0 | if (my_mtp3_standard == ANSI_STANDARD) { |
995 | 0 | pci = ai & ANSI_PC_INDICATOR_MASK; |
996 | 0 | ssni = ai & ANSI_SSN_INDICATOR_MASK; |
997 | 0 | } else { |
998 | 0 | ssni = ai & ITU_SSN_INDICATOR_MASK; |
999 | 0 | pci = ai & ITU_PC_INDICATOR_MASK; |
1000 | 0 | } |
1001 | | |
1002 | | /* Route on SSN with no SSN? */ |
1003 | 0 | if ((ri == ROUTE_ON_SSN) && (ssni == 0)) |
1004 | 0 | RETURN_FALSE; |
1005 | | |
1006 | | /* Route on GT with no GT? */ |
1007 | 0 | if ((ri == ROUTE_ON_GT) && (gti == AI_GTI_NO_GT)) |
1008 | 0 | RETURN_FALSE; |
1009 | | |
1010 | | /* GT routed and connection-oriented (Class-2)? |
1011 | | * Yes, that's theoretically possible, but it's not used. |
1012 | | */ |
1013 | 0 | if ((ri == ROUTE_ON_GT) && is_co) |
1014 | 0 | RETURN_FALSE; |
1015 | | |
1016 | 0 | if (ssni) |
1017 | 0 | len_needed += ADDRESS_SSN_LENGTH; |
1018 | 0 | if (pci) { |
1019 | 0 | if (my_mtp3_standard == ANSI_STANDARD || |
1020 | 0 | my_mtp3_standard == CHINESE_ITU_STANDARD) |
1021 | 0 | len_needed += ANSI_PC_LENGTH; |
1022 | 0 | else |
1023 | 0 | len_needed += ITU_PC_LENGTH; |
1024 | 0 | } |
1025 | 0 | if (gti) |
1026 | 0 | len_needed += 2; |
1027 | |
|
1028 | 0 | if (len_needed > len) |
1029 | 0 | RETURN_FALSE; |
1030 | | |
1031 | 0 | return true; |
1032 | 0 | } |
1033 | | |
1034 | | bool |
1035 | | looks_like_valid_sccp(uint32_t frame_num _U_, tvbuff_t *tvb, uint8_t my_mtp3_standard) |
1036 | 0 | { |
1037 | 0 | unsigned offset; |
1038 | 0 | uint8_t msgtype, msg_class, cause; |
1039 | 0 | unsigned called_ptr = 0; |
1040 | 0 | unsigned calling_ptr = 0; |
1041 | 0 | unsigned data_ptr = 0; |
1042 | 0 | unsigned opt_ptr = 0; |
1043 | 0 | uint8_t pointer_length = POINTER_LENGTH; |
1044 | 0 | unsigned len = tvb_captured_length(tvb); |
1045 | | |
1046 | | /* Ensure we can do some basic checks without throwing an exception. |
1047 | | * Accesses beyond this length need to check the length first because |
1048 | | * we don't want to throw an exception in here... |
1049 | | */ |
1050 | 0 | if (len < 5) |
1051 | 0 | RETURN_FALSE; |
1052 | | |
1053 | 0 | msgtype = tvb_get_uint8(tvb, SCCP_MSG_TYPE_OFFSET); |
1054 | 0 | if (!try_val_to_str(msgtype, sccp_message_type_acro_values)) { |
1055 | 0 | RETURN_FALSE; |
1056 | 0 | } |
1057 | 0 | offset = SCCP_MSG_TYPE_LENGTH; |
1058 | |
|
1059 | 0 | switch (msgtype) { |
1060 | 0 | case SCCP_MSG_TYPE_UDT: |
1061 | 0 | case SCCP_MSG_TYPE_XUDT: |
1062 | 0 | case SCCP_MSG_TYPE_LUDT: |
1063 | 0 | case SCCP_MSG_TYPE_UDTS: |
1064 | 0 | case SCCP_MSG_TYPE_XUDTS: |
1065 | 0 | case SCCP_MSG_TYPE_LUDTS: |
1066 | 0 | { |
1067 | 0 | if (msgtype == SCCP_MSG_TYPE_XUDT || msgtype == SCCP_MSG_TYPE_XUDTS) { |
1068 | 0 | if (SCCP_MSG_TYPE_LENGTH + |
1069 | 0 | PROTOCOL_CLASS_LENGTH + /* or Cause for XUDTS */ |
1070 | 0 | HOP_COUNTER_LENGTH + |
1071 | 0 | POINTER_LENGTH + |
1072 | 0 | POINTER_LENGTH + |
1073 | 0 | POINTER_LENGTH + |
1074 | 0 | POINTER_LENGTH > len) |
1075 | 0 | RETURN_FALSE; |
1076 | 0 | } |
1077 | | |
1078 | 0 | if (msgtype == SCCP_MSG_TYPE_LUDT || msgtype == SCCP_MSG_TYPE_LUDTS) { |
1079 | 0 | if (SCCP_MSG_TYPE_LENGTH + |
1080 | 0 | PROTOCOL_CLASS_LENGTH + /* or Cause for LUDTS */ |
1081 | 0 | HOP_COUNTER_LENGTH + |
1082 | 0 | POINTER_LENGTH_LONG + |
1083 | 0 | POINTER_LENGTH_LONG + |
1084 | 0 | POINTER_LENGTH_LONG + |
1085 | 0 | POINTER_LENGTH_LONG > len) |
1086 | 0 | RETURN_FALSE; |
1087 | | |
1088 | 0 | pointer_length = POINTER_LENGTH_LONG; |
1089 | 0 | } |
1090 | | |
1091 | 0 | if (msgtype == SCCP_MSG_TYPE_UDT || msgtype == SCCP_MSG_TYPE_XUDT || |
1092 | 0 | msgtype == SCCP_MSG_TYPE_LUDT) { |
1093 | |
|
1094 | 0 | msg_class = tvb_get_uint8(tvb, offset) & CLASS_CLASS_MASK; |
1095 | 0 | if (msg_class > 1) |
1096 | 0 | RETURN_FALSE; |
1097 | 0 | offset += PROTOCOL_CLASS_LENGTH; |
1098 | 0 | } |
1099 | | |
1100 | 0 | if (msgtype == SCCP_MSG_TYPE_XUDT || msgtype == SCCP_MSG_TYPE_LUDT) |
1101 | 0 | offset += HOP_COUNTER_LENGTH; |
1102 | |
|
1103 | 0 | if (msgtype == SCCP_MSG_TYPE_UDTS || |
1104 | 0 | msgtype == SCCP_MSG_TYPE_XUDTS || |
1105 | 0 | msgtype == SCCP_MSG_TYPE_LUDTS) { |
1106 | |
|
1107 | 0 | cause = tvb_get_uint8(tvb, offset); |
1108 | 0 | if (!try_val_to_str(cause, sccp_return_cause_values)) |
1109 | 0 | RETURN_FALSE; |
1110 | 0 | offset += RETURN_CAUSE_LENGTH; |
1111 | 0 | } |
1112 | | |
1113 | 0 | if (msgtype == SCCP_MSG_TYPE_XUDTS || msgtype == SCCP_MSG_TYPE_LUDTS) |
1114 | 0 | offset += HOP_COUNTER_LENGTH; |
1115 | |
|
1116 | 0 | if (msgtype == SCCP_MSG_TYPE_LUDT || msgtype == SCCP_MSG_TYPE_LUDTS) |
1117 | 0 | called_ptr = tvb_get_letohs(tvb, offset); |
1118 | 0 | else |
1119 | 0 | called_ptr = tvb_get_uint8(tvb, offset); |
1120 | 0 | if (called_ptr == 0) /* Mandatory variable parameters must be present */ |
1121 | 0 | RETURN_FALSE; |
1122 | 0 | called_ptr += offset; |
1123 | 0 | offset += pointer_length; |
1124 | |
|
1125 | 0 | if (msgtype == SCCP_MSG_TYPE_LUDT || msgtype == SCCP_MSG_TYPE_LUDTS) |
1126 | 0 | calling_ptr = tvb_get_letohs(tvb, offset); |
1127 | 0 | else |
1128 | 0 | calling_ptr = tvb_get_uint8(tvb, offset); |
1129 | 0 | if (calling_ptr == 0) /* Mandatory variable parameters must be present */ |
1130 | 0 | RETURN_FALSE; |
1131 | 0 | calling_ptr += offset; |
1132 | 0 | offset += pointer_length; |
1133 | |
|
1134 | 0 | if (msgtype == SCCP_MSG_TYPE_LUDT || msgtype == SCCP_MSG_TYPE_LUDTS) |
1135 | 0 | data_ptr = tvb_get_letohs(tvb, offset); |
1136 | 0 | else |
1137 | 0 | data_ptr = tvb_get_uint8(tvb, offset); |
1138 | 0 | if (data_ptr == 0) /* Mandatory variable parameters must be present */ |
1139 | 0 | RETURN_FALSE; |
1140 | 0 | data_ptr += offset; |
1141 | 0 | offset += pointer_length; |
1142 | |
|
1143 | 0 | if (msgtype == SCCP_MSG_TYPE_XUDT || msgtype == SCCP_MSG_TYPE_XUDTS) { |
1144 | 0 | opt_ptr = tvb_get_uint8(tvb, offset); |
1145 | 0 | offset += POINTER_LENGTH; |
1146 | 0 | } else if (msgtype == SCCP_MSG_TYPE_LUDT || msgtype == SCCP_MSG_TYPE_LUDTS) { |
1147 | 0 | opt_ptr = tvb_get_letohs(tvb, offset); |
1148 | 0 | offset += POINTER_LENGTH_LONG; |
1149 | 0 | } |
1150 | |
|
1151 | 0 | if (msgtype == SCCP_MSG_TYPE_LUDT || msgtype == SCCP_MSG_TYPE_LUDTS) { |
1152 | | /* Long pointers count from the 2nd (MSB) octet of the pointer */ |
1153 | 0 | called_ptr += 1; |
1154 | 0 | calling_ptr += 1; |
1155 | 0 | data_ptr += 1; |
1156 | 0 | if (opt_ptr) |
1157 | 0 | opt_ptr += 1; |
1158 | 0 | } |
1159 | | |
1160 | | /* Check that the variable pointers are within bounds */ |
1161 | 0 | if (called_ptr > len || calling_ptr > len || data_ptr > len) |
1162 | 0 | RETURN_FALSE; |
1163 | | |
1164 | | /* Check that the lengths of the variable parameters are within bounds */ |
1165 | 0 | if (tvb_get_uint8(tvb, called_ptr)+called_ptr > len || |
1166 | 0 | tvb_get_uint8(tvb, calling_ptr)+calling_ptr > len) |
1167 | 0 | RETURN_FALSE; |
1168 | 0 | if (msgtype == SCCP_MSG_TYPE_LUDT || msgtype == SCCP_MSG_TYPE_LUDTS) { |
1169 | 0 | if (tvb_get_letohs(tvb, data_ptr)+data_ptr > len) |
1170 | 0 | RETURN_FALSE; |
1171 | 0 | } else { |
1172 | 0 | if (tvb_get_uint8(tvb, data_ptr)+data_ptr > len) |
1173 | 0 | RETURN_FALSE; |
1174 | 0 | } |
1175 | 0 | } |
1176 | 0 | break; |
1177 | 0 | case SCCP_MSG_TYPE_CR: |
1178 | 0 | { |
1179 | 0 | if (len < SCCP_MSG_TYPE_LENGTH |
1180 | 0 | + DESTINATION_LOCAL_REFERENCE_LENGTH |
1181 | 0 | + PROTOCOL_CLASS_LENGTH |
1182 | 0 | + POINTER_LENGTH |
1183 | 0 | + POINTER_LENGTH) |
1184 | 0 | RETURN_FALSE; |
1185 | | |
1186 | 0 | offset += DESTINATION_LOCAL_REFERENCE_LENGTH; |
1187 | | |
1188 | | /* Class is only the lower 4 bits, but the upper 4 bits are spare |
1189 | | * in Class-2. Don't mask them off so the below comparison also |
1190 | | * fails if any of those spare bits are set. |
1191 | | */ |
1192 | 0 | msg_class = tvb_get_uint8(tvb, offset); |
1193 | 0 | if (msg_class != 2) |
1194 | 0 | RETURN_FALSE; |
1195 | | |
1196 | 0 | offset += PROTOCOL_CLASS_LENGTH; |
1197 | 0 | data_ptr = tvb_get_uint8(tvb, offset); |
1198 | 0 | if (data_ptr == 0) |
1199 | 0 | RETURN_FALSE; |
1200 | | |
1201 | 0 | offset += POINTER_LENGTH; |
1202 | 0 | opt_ptr = tvb_get_uint8(tvb, offset); |
1203 | 0 | if (opt_ptr == 0) |
1204 | 0 | RETURN_FALSE; |
1205 | | |
1206 | 0 | offset += POINTER_LENGTH; |
1207 | 0 | } |
1208 | 0 | break; |
1209 | 0 | case SCCP_MSG_TYPE_CC: |
1210 | 0 | { |
1211 | 0 | if (len < SCCP_MSG_TYPE_LENGTH |
1212 | 0 | + DESTINATION_LOCAL_REFERENCE_LENGTH |
1213 | 0 | + SOURCE_LOCAL_REFERENCE_LENGTH |
1214 | 0 | + PROTOCOL_CLASS_LENGTH |
1215 | 0 | + POINTER_LENGTH) |
1216 | 0 | RETURN_FALSE; |
1217 | | |
1218 | 0 | offset += DESTINATION_LOCAL_REFERENCE_LENGTH; |
1219 | 0 | offset += SOURCE_LOCAL_REFERENCE_LENGTH; |
1220 | | |
1221 | | /* Class is only the lower 4 bits, but the upper 4 bits are spare |
1222 | | * in Class-2. Don't mask them off so the below comparison also |
1223 | | * fails if any of those spare bits are set. |
1224 | | */ |
1225 | 0 | msg_class = tvb_get_uint8(tvb, offset); |
1226 | 0 | if (msg_class != 2) |
1227 | 0 | RETURN_FALSE; |
1228 | 0 | offset += PROTOCOL_CLASS_LENGTH; |
1229 | |
|
1230 | 0 | opt_ptr = tvb_get_uint8(tvb, offset); |
1231 | 0 | offset += POINTER_LENGTH; |
1232 | | |
1233 | | /* If the pointer isn't 0 (no optional parameters) or 1 (optional |
1234 | | * parameter starts immediately after the pointer) then what would |
1235 | | * be between the pointer and the parameter? |
1236 | | */ |
1237 | 0 | if (opt_ptr > 1) |
1238 | 0 | RETURN_FALSE; |
1239 | | |
1240 | | /* If there are no optional parameters, are we at the end of the |
1241 | | * message? |
1242 | | */ |
1243 | 0 | if ((opt_ptr == 0) && (offset != len)) |
1244 | 0 | RETURN_FALSE; |
1245 | 0 | } |
1246 | 0 | break; |
1247 | 0 | case SCCP_MSG_TYPE_CREF: |
1248 | 0 | { |
1249 | 0 | if (len < SCCP_MSG_TYPE_LENGTH |
1250 | 0 | + DESTINATION_LOCAL_REFERENCE_LENGTH |
1251 | 0 | + REFUSAL_CAUSE_LENGTH |
1252 | 0 | + POINTER_LENGTH) |
1253 | 0 | RETURN_FALSE; |
1254 | | |
1255 | 0 | offset += DESTINATION_LOCAL_REFERENCE_LENGTH; |
1256 | |
|
1257 | 0 | cause = tvb_get_uint8(tvb, offset); |
1258 | 0 | if (!try_val_to_str(cause, sccp_refusal_cause_values)) |
1259 | 0 | RETURN_FALSE; |
1260 | 0 | offset += REFUSAL_CAUSE_LENGTH; |
1261 | |
|
1262 | 0 | opt_ptr = tvb_get_uint8(tvb, offset); |
1263 | 0 | offset += POINTER_LENGTH; |
1264 | | |
1265 | | /* If the pointer isn't 0 (no optional parameters) or 1 (optional |
1266 | | * parameter starts immediately after the pointer) then what would |
1267 | | * be between the pointer and the parameter? |
1268 | | */ |
1269 | 0 | if (opt_ptr > 1) |
1270 | 0 | RETURN_FALSE; |
1271 | | |
1272 | | /* If there are no optional parameters, are we at the end of the |
1273 | | * message? |
1274 | | */ |
1275 | 0 | if ((opt_ptr == 0) && (offset != len)) |
1276 | 0 | RETURN_FALSE; |
1277 | 0 | } |
1278 | 0 | break; |
1279 | 0 | case SCCP_MSG_TYPE_RLSD: |
1280 | 0 | { |
1281 | 0 | if (len < SCCP_MSG_TYPE_LENGTH |
1282 | 0 | + DESTINATION_LOCAL_REFERENCE_LENGTH |
1283 | 0 | + SOURCE_LOCAL_REFERENCE_LENGTH |
1284 | 0 | + RELEASE_CAUSE_LENGTH |
1285 | 0 | + POINTER_LENGTH) |
1286 | 0 | RETURN_FALSE; |
1287 | | |
1288 | 0 | offset += DESTINATION_LOCAL_REFERENCE_LENGTH; |
1289 | 0 | offset += SOURCE_LOCAL_REFERENCE_LENGTH; |
1290 | |
|
1291 | 0 | cause = tvb_get_uint8(tvb, offset); |
1292 | 0 | if (!try_val_to_str(cause, sccp_release_cause_values)) |
1293 | 0 | RETURN_FALSE; |
1294 | 0 | offset += RELEASE_CAUSE_LENGTH; |
1295 | |
|
1296 | 0 | opt_ptr = tvb_get_uint8(tvb, offset); |
1297 | 0 | offset += POINTER_LENGTH; |
1298 | | |
1299 | | /* If the pointer isn't 0 (no optional parameters) or 1 (optional |
1300 | | * parameter starts immediately after the pointer) then what would |
1301 | | * be between the pointer and the parameter? |
1302 | | */ |
1303 | 0 | if (opt_ptr > 1) |
1304 | 0 | RETURN_FALSE; |
1305 | | |
1306 | | /* If there are no optional parameters, are we at the end of the |
1307 | | * message? |
1308 | | */ |
1309 | 0 | if ((opt_ptr == 0) && (offset != len)) |
1310 | 0 | RETURN_FALSE; |
1311 | 0 | } |
1312 | 0 | break; |
1313 | 0 | case SCCP_MSG_TYPE_RLC: |
1314 | 0 | { |
1315 | 0 | if (len != SCCP_MSG_TYPE_LENGTH |
1316 | 0 | + DESTINATION_LOCAL_REFERENCE_LENGTH |
1317 | 0 | + SOURCE_LOCAL_REFERENCE_LENGTH) |
1318 | 0 | RETURN_FALSE; |
1319 | 0 | } |
1320 | 0 | break; |
1321 | 0 | case SCCP_MSG_TYPE_ERR: |
1322 | 0 | { |
1323 | 0 | if (len != SCCP_MSG_TYPE_LENGTH |
1324 | 0 | + DESTINATION_LOCAL_REFERENCE_LENGTH |
1325 | 0 | + ERROR_CAUSE_LENGTH) |
1326 | 0 | RETURN_FALSE; |
1327 | | |
1328 | 0 | offset += DESTINATION_LOCAL_REFERENCE_LENGTH; |
1329 | |
|
1330 | 0 | cause = tvb_get_uint8(tvb, offset); |
1331 | 0 | if (!try_val_to_str(cause, sccp_error_cause_values)) |
1332 | 0 | RETURN_FALSE; |
1333 | 0 | } |
1334 | 0 | break; |
1335 | 0 | case SCCP_MSG_TYPE_DT1: |
1336 | 0 | { |
1337 | 0 | if (len < SCCP_MSG_TYPE_LENGTH |
1338 | 0 | + DESTINATION_LOCAL_REFERENCE_LENGTH |
1339 | 0 | + SEGMENTING_REASSEMBLING_LENGTH |
1340 | 0 | + POINTER_LENGTH |
1341 | 0 | + PARAMETER_LENGTH_LENGTH |
1342 | 0 | + 1) /* At least 1 byte of payload */ |
1343 | 0 | RETURN_FALSE; |
1344 | 0 | offset += DESTINATION_LOCAL_REFERENCE_LENGTH; |
1345 | | |
1346 | | /* Are any of the spare bits in set? */ |
1347 | 0 | if (tvb_get_uint8(tvb, offset) & ~SEGMENTING_REASSEMBLING_MASK) |
1348 | 0 | RETURN_FALSE; |
1349 | 0 | offset += SEGMENTING_REASSEMBLING_LENGTH; |
1350 | |
|
1351 | 0 | data_ptr = tvb_get_uint8(tvb, offset) + offset; |
1352 | | /* Verify the data pointer is within bounds */ |
1353 | 0 | if (data_ptr > len) |
1354 | 0 | RETURN_FALSE; |
1355 | 0 | offset += POINTER_LENGTH; |
1356 | | |
1357 | | /* Verify the data length uses the rest of the message */ |
1358 | 0 | if (tvb_get_uint8(tvb, data_ptr) + offset + 1U != len) |
1359 | 0 | RETURN_FALSE; |
1360 | 0 | } |
1361 | 0 | break; |
1362 | 0 | case SCCP_MSG_TYPE_IT: |
1363 | 0 | { |
1364 | 0 | if (len < SCCP_MSG_TYPE_LENGTH |
1365 | 0 | + DESTINATION_LOCAL_REFERENCE_LENGTH |
1366 | 0 | + SOURCE_LOCAL_REFERENCE_LENGTH |
1367 | 0 | + PROTOCOL_CLASS_LENGTH |
1368 | 0 | + SEQUENCING_SEGMENTING_LENGTH |
1369 | 0 | + CREDIT_LENGTH) |
1370 | 0 | RETURN_FALSE; |
1371 | | |
1372 | 0 | offset += DESTINATION_LOCAL_REFERENCE_LENGTH; |
1373 | 0 | offset += SOURCE_LOCAL_REFERENCE_LENGTH; |
1374 | | |
1375 | | /* Class is only the lower 4 bits, but the upper 4 bits are spare |
1376 | | * in Class-2. Don't mask them off so the below comparison also |
1377 | | * fails if any of those spare bits are set. |
1378 | | */ |
1379 | 0 | msg_class = tvb_get_uint8(tvb, offset); |
1380 | 0 | if (msg_class != 2) |
1381 | 0 | RETURN_FALSE; |
1382 | 0 | offset += PROTOCOL_CLASS_LENGTH; |
1383 | 0 | } |
1384 | 0 | break; |
1385 | 0 | case SCCP_MSG_TYPE_AK: |
1386 | 0 | case SCCP_MSG_TYPE_DT2: |
1387 | 0 | case SCCP_MSG_TYPE_EA: |
1388 | 0 | case SCCP_MSG_TYPE_ED: |
1389 | 0 | case SCCP_MSG_TYPE_RSC: |
1390 | 0 | case SCCP_MSG_TYPE_RSR: |
1391 | | /* Class-3 is never actually used in the real world */ |
1392 | 0 | RETURN_FALSE; |
1393 | 0 | break; |
1394 | | |
1395 | 0 | default: |
1396 | 0 | DISSECTOR_ASSERT_NOT_REACHED(); |
1397 | 0 | } |
1398 | | |
1399 | 0 | if (called_ptr) { |
1400 | 0 | uint8_t param_len = tvb_get_uint8(tvb, called_ptr); |
1401 | 0 | tvbuff_t *param_tvb; |
1402 | |
|
1403 | 0 | if (param_len == 0) |
1404 | 0 | RETURN_FALSE; |
1405 | 0 | param_tvb = tvb_new_subset_length(tvb, called_ptr+1, param_len); |
1406 | |
|
1407 | 0 | if (!sccp_called_calling_looks_valid(frame_num, param_tvb, my_mtp3_standard, !is_connectionless(msgtype))) |
1408 | 0 | RETURN_FALSE; |
1409 | 0 | } |
1410 | | |
1411 | 0 | if (calling_ptr) { |
1412 | 0 | uint8_t param_len = tvb_get_uint8(tvb, calling_ptr); |
1413 | 0 | tvbuff_t *param_tvb; |
1414 | |
|
1415 | 0 | if (param_len == 0) |
1416 | 0 | RETURN_FALSE; |
1417 | 0 | param_tvb = tvb_new_subset_length(tvb, calling_ptr+1, param_len); |
1418 | |
|
1419 | 0 | if (!sccp_called_calling_looks_valid(frame_num, param_tvb, my_mtp3_standard, !is_connectionless(msgtype))) |
1420 | 0 | RETURN_FALSE; |
1421 | 0 | } |
1422 | | |
1423 | 0 | if (opt_ptr) { |
1424 | 0 | uint8_t opt_param; |
1425 | |
|
1426 | 0 | opt_ptr += offset-pointer_length; /* (offset was already incremented) */ |
1427 | | |
1428 | | /* Check that the optional pointer is within bounds */ |
1429 | 0 | if (opt_ptr > len) |
1430 | 0 | RETURN_FALSE; |
1431 | | |
1432 | 0 | opt_param = tvb_get_uint8(tvb, opt_ptr); |
1433 | | /* Check if the (1st) optional parameter tag is valid */ |
1434 | 0 | if (!try_val_to_str(opt_param, sccp_parameter_values)) |
1435 | 0 | RETURN_FALSE; |
1436 | | |
1437 | | /* Check that the (1st) parameter length is within bounds */ |
1438 | 0 | if ((opt_param != PARAMETER_END_OF_OPTIONAL_PARAMETERS) && |
1439 | 0 | ((opt_ptr+1U) <= len) && |
1440 | 0 | ((tvb_get_uint8(tvb, opt_ptr+1U)+offset) > len)) |
1441 | 0 | RETURN_FALSE; |
1442 | | |
1443 | | /* If we're at the end of the parameters, are we also at the end of the |
1444 | | * message? |
1445 | | */ |
1446 | 0 | if ((opt_param == PARAMETER_END_OF_OPTIONAL_PARAMETERS) && ((opt_ptr+1U) != len)) |
1447 | 0 | RETURN_FALSE; |
1448 | 0 | } |
1449 | | |
1450 | 0 | return true; |
1451 | 0 | } |
1452 | | |
1453 | | static sccp_assoc_info_t * |
1454 | | new_assoc(uint32_t calling, uint32_t called) |
1455 | 57 | { |
1456 | 57 | sccp_assoc_info_t *a = wmem_new0(wmem_file_scope(), sccp_assoc_info_t); |
1457 | | |
1458 | 57 | a->id = next_assoc_id++; |
1459 | 57 | a->calling_dpc = calling; |
1460 | 57 | a->called_dpc = called; |
1461 | 57 | a->calling_ssn = INVALID_SSN; |
1462 | 57 | a->called_ssn = INVALID_SSN; |
1463 | 57 | a->msgs = NULL; |
1464 | 57 | a->curr_msg = NULL; |
1465 | 57 | a->payload = SCCP_PLOAD_NONE; |
1466 | 57 | a->calling_party = NULL; |
1467 | 57 | a->called_party = NULL; |
1468 | 57 | a->extra_info = NULL; |
1469 | 57 | a->imsi = NULL; |
1470 | | |
1471 | 57 | return a; |
1472 | 57 | } |
1473 | | |
1474 | | sccp_assoc_info_t * |
1475 | | get_sccp_assoc(packet_info *pinfo, unsigned offset, sccp_decode_context_t* value) |
1476 | 270 | { |
1477 | 270 | uint32_t opck, dpck; |
1478 | 270 | address *opc = &(pinfo->src); |
1479 | 270 | address *dpc = &(pinfo->dst); |
1480 | 270 | unsigned framenum = pinfo->num; |
1481 | | |
1482 | 270 | if (value->assoc) |
1483 | 0 | return value->assoc; |
1484 | | |
1485 | 270 | opck = opc->type == ss7pc_address_type ? mtp3_pc_hash((const mtp3_addr_pc_t *)opc->data) : g_str_hash(address_to_str(pinfo->pool, opc)); |
1486 | 270 | dpck = dpc->type == ss7pc_address_type ? mtp3_pc_hash((const mtp3_addr_pc_t *)dpc->data) : g_str_hash(address_to_str(pinfo->pool, dpc)); |
1487 | | |
1488 | | |
1489 | 270 | switch (value->message_type) { |
1490 | 100 | case SCCP_MSG_TYPE_CR: |
1491 | 100 | { |
1492 | | /* CR contains the opc,dpc,dlr key of backward messages swapped as dpc,opc,slr */ |
1493 | 100 | wmem_tree_key_t bw_key[4]; |
1494 | | |
1495 | 100 | bw_key[0].length = 1; |
1496 | 100 | bw_key[0].key = &dpck; |
1497 | | |
1498 | 100 | bw_key[1].length = 1; |
1499 | 100 | bw_key[1].key = &opck; |
1500 | | |
1501 | 100 | bw_key[2].length = 1; |
1502 | 100 | bw_key[2].key = &value->slr; |
1503 | | |
1504 | 100 | bw_key[3].length = 0; |
1505 | 100 | bw_key[3].key = NULL; |
1506 | | |
1507 | 100 | if (! (value->assoc = (sccp_assoc_info_t *)wmem_tree_lookup32_array(assocs, bw_key) ) && ! PINFO_FD_VISITED(pinfo) ) { |
1508 | 32 | value->assoc = new_assoc(opck, dpck); |
1509 | 32 | wmem_tree_insert32_array(assocs, bw_key, value->assoc); |
1510 | 32 | value->assoc->has_bw_key = true; |
1511 | 32 | } |
1512 | | |
1513 | 100 | pinfo->p2p_dir = P2P_DIR_SENT; |
1514 | | |
1515 | 100 | break; |
1516 | 0 | } |
1517 | 54 | case SCCP_MSG_TYPE_CC: |
1518 | 54 | { |
1519 | 54 | wmem_tree_key_t fw_key[4]; |
1520 | 54 | wmem_tree_key_t bw_key[4]; |
1521 | | |
1522 | 54 | fw_key[0].length = 1; |
1523 | 54 | fw_key[0].key = &dpck; |
1524 | | |
1525 | 54 | fw_key[1].length = 1; |
1526 | 54 | fw_key[1].key = &opck; |
1527 | | |
1528 | 54 | fw_key[2].length = 1; |
1529 | 54 | fw_key[2].key = &value->slr; |
1530 | | |
1531 | 54 | fw_key[3].length = 0; |
1532 | 54 | fw_key[3].key = NULL; |
1533 | | |
1534 | 54 | bw_key[0].length = 1; |
1535 | 54 | bw_key[0].key = &opck; |
1536 | | |
1537 | 54 | bw_key[1].length = 1; |
1538 | 54 | bw_key[1].key = &dpck; |
1539 | | |
1540 | 54 | bw_key[2].length = 1; |
1541 | 54 | bw_key[2].key = &value->dlr; |
1542 | | |
1543 | 54 | bw_key[3].length = 0; |
1544 | 54 | bw_key[3].key = NULL; |
1545 | | |
1546 | | |
1547 | 54 | if ( (value->assoc = (sccp_assoc_info_t *)wmem_tree_lookup32_array(assocs, bw_key) ) ) { |
1548 | 32 | goto got_assoc; |
1549 | 32 | } |
1550 | | |
1551 | 22 | if ( (value->assoc = (sccp_assoc_info_t *)wmem_tree_lookup32_array(assocs, fw_key) ) ) { |
1552 | 0 | goto got_assoc; |
1553 | 0 | } |
1554 | | |
1555 | 22 | value->assoc = new_assoc(dpck, opck); |
1556 | | |
1557 | 54 | got_assoc: |
1558 | | |
1559 | 54 | pinfo->p2p_dir = P2P_DIR_RECV; |
1560 | | |
1561 | 54 | if ( ! PINFO_FD_VISITED(pinfo) && ! value->assoc->has_bw_key ) { |
1562 | 22 | wmem_tree_insert32_array(assocs, bw_key, value->assoc); |
1563 | 22 | value->assoc->has_bw_key = true; |
1564 | 22 | } |
1565 | | |
1566 | 54 | if ( ! PINFO_FD_VISITED(pinfo) && ! value->assoc->has_fw_key ) { |
1567 | 22 | wmem_tree_insert32_array(assocs, fw_key, value->assoc); |
1568 | 22 | value->assoc->has_fw_key = true; |
1569 | 22 | } |
1570 | | |
1571 | 54 | break; |
1572 | 22 | } |
1573 | 6 | case SCCP_MSG_TYPE_IT: |
1574 | | /* fall-through */ |
1575 | 7 | case SCCP_MSG_TYPE_RLC: |
1576 | 7 | { |
1577 | 7 | wmem_tree_key_t fw_key[4]; |
1578 | 7 | wmem_tree_key_t bw_key[4]; |
1579 | | |
1580 | 7 | fw_key[0].length = 1; |
1581 | 7 | fw_key[0].key = &dpck; |
1582 | | |
1583 | 7 | fw_key[1].length = 1; |
1584 | 7 | fw_key[1].key = &opck; |
1585 | | |
1586 | 7 | fw_key[2].length = 1; |
1587 | 7 | fw_key[2].key = &value->slr; |
1588 | | |
1589 | 7 | fw_key[3].length = 0; |
1590 | 7 | fw_key[3].key = NULL; |
1591 | | |
1592 | 7 | bw_key[0].length = 1; |
1593 | 7 | bw_key[0].key = &opck; |
1594 | | |
1595 | 7 | bw_key[1].length = 1; |
1596 | 7 | bw_key[1].key = &dpck; |
1597 | | |
1598 | 7 | bw_key[2].length = 1; |
1599 | 7 | bw_key[2].key = &value->dlr; |
1600 | | |
1601 | 7 | bw_key[3].length = 0; |
1602 | 7 | bw_key[3].key = NULL; |
1603 | | |
1604 | 7 | if ( (value->assoc = (sccp_assoc_info_t *)wmem_tree_lookup32_array(assocs, bw_key) ) ) { |
1605 | 2 | goto got_assoc_rlc; |
1606 | 2 | } |
1607 | | |
1608 | 5 | if ( (value->assoc = (sccp_assoc_info_t *)wmem_tree_lookup32_array(assocs, fw_key) ) ) { |
1609 | 2 | goto got_assoc_rlc; |
1610 | 2 | } |
1611 | | |
1612 | 3 | value->assoc = new_assoc(dpck, opck); |
1613 | | |
1614 | 7 | got_assoc_rlc: |
1615 | | |
1616 | 7 | pinfo->p2p_dir = P2P_DIR_SENT; |
1617 | | |
1618 | 7 | if ( ! PINFO_FD_VISITED(pinfo) && ! value->assoc->has_bw_key ) { |
1619 | 3 | wmem_tree_insert32_array(assocs, bw_key, value->assoc); |
1620 | 3 | value->assoc->has_bw_key = true; |
1621 | 3 | } |
1622 | | |
1623 | 7 | if ( ! PINFO_FD_VISITED(pinfo) && ! value->assoc->has_fw_key ) { |
1624 | 3 | wmem_tree_insert32_array(assocs, fw_key, value->assoc); |
1625 | 3 | value->assoc->has_fw_key = true; |
1626 | 3 | } |
1627 | 7 | break; |
1628 | 3 | } |
1629 | 109 | default: |
1630 | 109 | { |
1631 | 109 | wmem_tree_key_t key[4]; |
1632 | | |
1633 | 109 | key[0].length = 1; |
1634 | 109 | key[0].key = &opck; |
1635 | | |
1636 | 109 | key[1].length = 1; |
1637 | 109 | key[1].key = &dpck; |
1638 | | |
1639 | 109 | key[2].length = 1; |
1640 | 109 | key[2].key = &value->dlr; |
1641 | | |
1642 | 109 | key[3].length = 0; |
1643 | 109 | key[3].key = NULL; |
1644 | | |
1645 | | |
1646 | 109 | value->assoc = (sccp_assoc_info_t *)wmem_tree_lookup32_array(assocs, key); |
1647 | | |
1648 | 109 | if (value->assoc) { |
1649 | 1 | if (value->assoc->calling_dpc == dpck) { |
1650 | 1 | pinfo->p2p_dir = P2P_DIR_RECV; |
1651 | 1 | } else { |
1652 | 0 | pinfo->p2p_dir = P2P_DIR_SENT; |
1653 | 0 | } |
1654 | 1 | } |
1655 | | |
1656 | 109 | break; |
1657 | 3 | } |
1658 | 270 | } |
1659 | | |
1660 | 270 | if (value->assoc && trace_sccp) { |
1661 | 0 | if ( ! PINFO_FD_VISITED(pinfo)) { |
1662 | 0 | sccp_msg_info_t *msg = wmem_new0(wmem_file_scope(), sccp_msg_info_t); |
1663 | 0 | msg->framenum = framenum; |
1664 | 0 | msg->offset = offset; |
1665 | 0 | msg->data.co.next = NULL; |
1666 | 0 | msg->data.co.assoc = value->assoc; |
1667 | 0 | msg->data.co.label = NULL; |
1668 | 0 | msg->data.co.comment = NULL; |
1669 | 0 | msg->data.co.imsi = NULL; |
1670 | 0 | msg->type = value->message_type; |
1671 | |
|
1672 | 0 | if (value->assoc->msgs) { |
1673 | 0 | sccp_msg_info_t *m; |
1674 | 0 | for (m = value->assoc->msgs; m->data.co.next; m = m->data.co.next) ; |
1675 | 0 | m->data.co.next = msg; |
1676 | 0 | } else { |
1677 | 0 | value->assoc->msgs = msg; |
1678 | 0 | } |
1679 | |
|
1680 | 0 | value->assoc->curr_msg = msg; |
1681 | |
|
1682 | 0 | } else { |
1683 | |
|
1684 | 0 | sccp_msg_info_t *m; |
1685 | |
|
1686 | 0 | for (m = value->assoc->msgs; m; m = m->data.co.next) { |
1687 | 0 | if (m->data.co.imsi != NULL && value->assoc->imsi == NULL) { |
1688 | 0 | value->assoc->imsi = wmem_strdup(wmem_epan_scope(), m->data.co.imsi); |
1689 | 0 | } |
1690 | 0 | if ((m->framenum == framenum) && (m->offset == offset)) { |
1691 | 0 | value->assoc->curr_msg = m; |
1692 | 0 | break; |
1693 | 0 | } |
1694 | 0 | } |
1695 | 0 | } |
1696 | 0 | } |
1697 | | |
1698 | 270 | return value->assoc ? value->assoc : &no_assoc; |
1699 | 270 | } |
1700 | | |
1701 | | |
1702 | | static void |
1703 | | dissect_sccp_unknown_message(tvbuff_t *message_tvb, proto_tree *sccp_tree) |
1704 | 10 | { |
1705 | 10 | uint32_t message_length; |
1706 | | |
1707 | 10 | message_length = tvb_captured_length(message_tvb); |
1708 | | |
1709 | 10 | proto_tree_add_bytes_format(sccp_tree, hf_sccp_unknown_message, message_tvb, 0, message_length, |
1710 | 10 | NULL, "Unknown message (%u byte%s)", |
1711 | 10 | message_length, plurality(message_length, "", "s")); |
1712 | 10 | } |
1713 | | |
1714 | | static void |
1715 | | dissect_sccp_unknown_param(tvbuff_t *tvb, proto_tree *tree, uint8_t type, unsigned length) |
1716 | 372 | { |
1717 | 372 | proto_tree_add_bytes_format(tree, hf_sccp_unknown_parameter, tvb, 0, length, NULL, |
1718 | 372 | "Unknown parameter 0x%x (%u byte%s)", type, length, plurality(length, "", "s")); |
1719 | 372 | } |
1720 | | |
1721 | | static void |
1722 | | dissect_sccp_dlr_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned length, sccp_decode_context_t* sccp_info) |
1723 | 476 | { |
1724 | 476 | proto_item *lr_item; |
1725 | | |
1726 | 476 | if (length != 3) { |
1727 | 383 | proto_tree_add_expert_format(tree, pinfo, &ei_sccp_wrong_length, tvb, 0, length, |
1728 | 383 | "Wrong length indicated. Expected 3, got %u", length); |
1729 | 383 | return; |
1730 | 383 | } |
1731 | | |
1732 | 93 | sccp_info->dlr = tvb_get_letoh24(tvb, 0); |
1733 | 93 | proto_tree_add_uint(tree, hf_sccp_dlr, tvb, 0, length, sccp_info->dlr); |
1734 | 93 | lr_item = proto_tree_add_uint(tree, hf_sccp_lr, tvb, 0, length, sccp_info->dlr); |
1735 | 93 | proto_item_set_generated(lr_item); |
1736 | | |
1737 | 93 | if (show_key_params) |
1738 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, "DLR=%d ", sccp_info->dlr); |
1739 | 93 | } |
1740 | | |
1741 | | static void |
1742 | | dissect_sccp_slr_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned length, sccp_decode_context_t* sccp_info) |
1743 | 320 | { |
1744 | 320 | proto_item *lr_item; |
1745 | | |
1746 | 320 | if (length != 3) { |
1747 | 146 | proto_tree_add_expert_format(tree, pinfo, &ei_sccp_wrong_length, tvb, 0, length, |
1748 | 146 | "Wrong length indicated. Expected 3, got %u", length); |
1749 | 146 | return; |
1750 | 146 | } |
1751 | | |
1752 | 174 | sccp_info->slr = tvb_get_letoh24(tvb, 0); |
1753 | 174 | proto_tree_add_uint(tree, hf_sccp_slr, tvb, 0, length, sccp_info->slr); |
1754 | 174 | lr_item = proto_tree_add_uint(tree, hf_sccp_lr, tvb, 0, length, sccp_info->slr); |
1755 | 174 | proto_item_set_generated(lr_item); |
1756 | | |
1757 | 174 | if (show_key_params) |
1758 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, "SLR=%d ", sccp_info->slr); |
1759 | 174 | } |
1760 | | |
1761 | | static proto_tree * |
1762 | | dissect_sccp_gt_address_information(tvbuff_t *tvb, packet_info *pinfo, |
1763 | | proto_tree *tree, unsigned length, |
1764 | | bool even_length, bool called, |
1765 | | sccp_decode_context_t* sccp_info) |
1766 | 375 | { |
1767 | 375 | unsigned offset = 0; |
1768 | 375 | uint8_t odd_signal, even_signal; |
1769 | 375 | proto_item *digits_item; |
1770 | 375 | proto_tree *digits_tree; |
1771 | 375 | char *gt_digits; |
1772 | | |
1773 | 375 | gt_digits = (char *)wmem_alloc0(pinfo->pool, GT_MAX_SIGNALS+1); |
1774 | | |
1775 | 19.1k | while (offset < length) { |
1776 | 18.7k | odd_signal = tvb_get_uint8(tvb, offset) & GT_ODD_SIGNAL_MASK; |
1777 | 18.7k | even_signal = tvb_get_uint8(tvb, offset) & GT_EVEN_SIGNAL_MASK; |
1778 | 18.7k | even_signal >>= GT_EVEN_SIGNAL_SHIFT; |
1779 | | |
1780 | 18.7k | (void) g_strlcat(gt_digits, val_to_str(odd_signal, sccp_address_signal_values, |
1781 | 18.7k | "Unknown: %d"), GT_MAX_SIGNALS+1); |
1782 | | |
1783 | | /* If the last signal is NOT filler */ |
1784 | 18.7k | if (offset != (length - 1) || even_length == true) |
1785 | 18.6k | (void) g_strlcat(gt_digits, val_to_str(even_signal, sccp_address_signal_values, |
1786 | 18.6k | "Unknown: %d"), GT_MAX_SIGNALS+1); |
1787 | | |
1788 | 18.7k | offset += GT_SIGNAL_LENGTH; |
1789 | 18.7k | } |
1790 | | |
1791 | 375 | if (is_connectionless(sccp_info->message_type) && sccp_info->sccp_msg) { |
1792 | 138 | uint8_t **gt_ptr = called ? &(sccp_info->sccp_msg->data.ud.called_gt) : &(sccp_info->sccp_msg->data.ud.calling_gt); |
1793 | | |
1794 | 138 | *gt_ptr = (uint8_t *)wmem_strdup(pinfo->pool, gt_digits); |
1795 | 138 | } |
1796 | | |
1797 | 375 | digits_item = proto_tree_add_string(tree, called ? hf_sccp_called_gt_digits |
1798 | 375 | : hf_sccp_calling_gt_digits, |
1799 | 375 | tvb, 0, length, gt_digits); |
1800 | 375 | digits_tree = proto_item_add_subtree(digits_item, called ? ett_sccp_called_gt_digits |
1801 | 375 | : ett_sccp_calling_gt_digits); |
1802 | | |
1803 | 375 | if (set_addresses) { |
1804 | 0 | if (called) { |
1805 | 0 | set_address(&pinfo->dst, AT_STRINGZ, 1+(int)strlen(gt_digits), gt_digits); |
1806 | 0 | } else { |
1807 | 0 | set_address(&pinfo->src, AT_STRINGZ, 1+(int)strlen(gt_digits), gt_digits); |
1808 | 0 | } |
1809 | 0 | } |
1810 | | |
1811 | 375 | proto_tree_add_string(digits_tree, hf_sccp_gt_digits, tvb, 0, length, gt_digits); |
1812 | 375 | proto_tree_add_uint(digits_tree, called ? hf_sccp_called_gt_digits_length |
1813 | 375 | : hf_sccp_calling_gt_digits_length, |
1814 | 375 | tvb, 0, length, (uint32_t)strlen(gt_digits)); |
1815 | | |
1816 | 375 | return digits_tree; |
1817 | 375 | } |
1818 | | |
1819 | | static void |
1820 | | dissect_sccp_global_title(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned length, |
1821 | | uint8_t gti, bool called, sccp_decode_context_t* sccp_info) |
1822 | 379 | { |
1823 | 379 | proto_item *gt_item; |
1824 | 379 | proto_tree *gt_tree; |
1825 | 379 | proto_tree *digits_tree; |
1826 | 379 | tvbuff_t *signals_tvb; |
1827 | 379 | unsigned offset = 0; |
1828 | 379 | uint8_t odd_even, nai = 0, np = 0, es; |
1829 | 379 | bool even = true; |
1830 | | |
1831 | | /* Shift GTI to where we can work with it */ |
1832 | 379 | gti >>= GTI_SHIFT; |
1833 | | |
1834 | 379 | gt_tree = proto_tree_add_subtree_format(tree, tvb, offset, length, |
1835 | 379 | called ? ett_sccp_called_gt : ett_sccp_calling_gt, >_item, |
1836 | 379 | "Global Title 0x%x (%u byte%s)", |
1837 | 379 | gti, length, plurality(length,"", "s")); |
1838 | | |
1839 | | /* Decode Transaction Type (if present) */ |
1840 | 379 | if ((gti == AI_GTI_TT) || |
1841 | 379 | ((decode_mtp3_standard != ANSI_STANDARD) && |
1842 | 363 | ((gti == ITU_AI_GTI_TT_NP_ES) || (gti == ITU_AI_GTI_TT_NP_ES_NAI))) || |
1843 | 379 | ((decode_mtp3_standard == ANSI_STANDARD) && (gti == ANSI_AI_GTI_TT_NP_ES))) { |
1844 | | |
1845 | 101 | proto_tree_add_item(gt_tree, called ? hf_sccp_called_gt_tt |
1846 | 101 | : hf_sccp_calling_gt_tt, |
1847 | 101 | tvb, offset, GT_TT_LENGTH, ENC_NA); |
1848 | 101 | offset += GT_TT_LENGTH; |
1849 | 101 | } |
1850 | | |
1851 | 379 | if (gti == AI_GTI_TT) { |
1852 | | /* Protocol doesn't tell us, so we ASSUME even... */ |
1853 | 16 | even = true; |
1854 | 16 | } |
1855 | | |
1856 | | /* Decode Numbering Plan and Encoding Scheme (if present) */ |
1857 | 379 | if (((decode_mtp3_standard != ANSI_STANDARD) && |
1858 | 379 | ((gti == ITU_AI_GTI_TT_NP_ES) || (gti == ITU_AI_GTI_TT_NP_ES_NAI))) || |
1859 | 379 | ((decode_mtp3_standard == ANSI_STANDARD) && (gti == ANSI_AI_GTI_TT_NP_ES))) { |
1860 | | |
1861 | 85 | np = tvb_get_uint8(tvb, offset) & GT_NP_MASK; |
1862 | 85 | proto_tree_add_uint(gt_tree, called ? hf_sccp_called_gt_np |
1863 | 85 | : hf_sccp_calling_gt_np, |
1864 | 85 | tvb, offset, GT_NP_ES_LENGTH, np); |
1865 | | |
1866 | 85 | es = tvb_get_uint8(tvb, offset) & GT_ES_MASK; |
1867 | 85 | proto_tree_add_uint(gt_tree, called ? hf_sccp_called_gt_es |
1868 | 85 | : hf_sccp_calling_gt_es, |
1869 | 85 | tvb, offset, GT_NP_ES_LENGTH, es); |
1870 | | |
1871 | 85 | even = (es == GT_ES_BCD_EVEN) ? true : false; |
1872 | | |
1873 | 85 | offset += GT_NP_ES_LENGTH; |
1874 | 85 | } |
1875 | | |
1876 | | /* Decode Nature of Address Indicator (if present) */ |
1877 | 379 | if ((decode_mtp3_standard != ANSI_STANDARD) && |
1878 | 379 | ((gti == ITU_AI_GTI_NAI) || (gti == ITU_AI_GTI_TT_NP_ES_NAI))) { |
1879 | | |
1880 | | /* Decode Odd/Even Indicator (if present) */ |
1881 | 172 | if (gti == ITU_AI_GTI_NAI) { |
1882 | 143 | odd_even = tvb_get_uint8(tvb, offset) & GT_OE_MASK; |
1883 | 143 | proto_tree_add_uint(gt_tree, called ? hf_sccp_called_gt_oe |
1884 | 143 | : hf_sccp_calling_gt_oe, |
1885 | 143 | tvb, offset, GT_NAI_LENGTH, odd_even); |
1886 | 143 | even = (odd_even == GT_OE_EVEN) ? true : false; |
1887 | 143 | } |
1888 | | |
1889 | 172 | nai = tvb_get_uint8(tvb, offset) & GT_NAI_MASK; |
1890 | 172 | proto_tree_add_uint(gt_tree, called ? hf_sccp_called_gt_nai |
1891 | 172 | : hf_sccp_calling_gt_nai, |
1892 | 172 | tvb, offset, GT_NAI_LENGTH, nai); |
1893 | | |
1894 | 172 | offset += GT_NAI_LENGTH; |
1895 | 172 | } |
1896 | | |
1897 | 379 | if(length == 0){ |
1898 | 3 | expert_add_info(pinfo, gt_item, &ei_sccp_gt_digits_missing); |
1899 | 3 | return; |
1900 | 3 | } |
1901 | | |
1902 | | /* Decode address signal(s) */ |
1903 | 376 | if (length < offset) |
1904 | 0 | return; |
1905 | | |
1906 | 376 | signals_tvb = tvb_new_subset_length(tvb, offset, (length - offset)); |
1907 | | |
1908 | 376 | digits_tree = dissect_sccp_gt_address_information(signals_tvb, pinfo, gt_tree, |
1909 | 376 | (length - offset), |
1910 | 376 | even, called, sccp_info); |
1911 | | |
1912 | | /* Display the country code (if we can) */ |
1913 | 376 | switch (np >> GT_NP_SHIFT) { |
1914 | 13 | case GT_NP_ISDN: |
1915 | 17 | case GT_NP_ISDN_MOBILE: |
1916 | 17 | if (nai == GT_NAI_INTERNATIONAL_NUM) { |
1917 | 0 | dissect_e164_cc(signals_tvb, pinfo, digits_tree, 0, E164_ENC_BCD); |
1918 | 0 | } |
1919 | 17 | break; |
1920 | 4 | case GT_NP_LAND_MOBILE: |
1921 | 4 | dissect_e212_mcc_mnc_in_address(signals_tvb, pinfo, digits_tree, 0); |
1922 | 4 | break; |
1923 | 327 | default: |
1924 | 327 | break; |
1925 | 376 | } |
1926 | 376 | } |
1927 | | |
1928 | | static int |
1929 | | dissect_sccp_3byte_pc(tvbuff_t *tvb, packet_info* pinfo, proto_tree *call_tree, unsigned offset, |
1930 | | bool called) |
1931 | 0 | { |
1932 | 0 | int hf_pc; |
1933 | |
|
1934 | 0 | if (decode_mtp3_standard == ANSI_STANDARD) |
1935 | 0 | { |
1936 | 0 | if (called) |
1937 | 0 | hf_pc = hf_sccp_called_ansi_pc; |
1938 | 0 | else |
1939 | 0 | hf_pc = hf_sccp_calling_ansi_pc; |
1940 | 0 | } else /* CHINESE_ITU_STANDARD */ { |
1941 | 0 | if (called) |
1942 | 0 | hf_pc = hf_sccp_called_chinese_pc; |
1943 | 0 | else |
1944 | 0 | hf_pc = hf_sccp_calling_chinese_pc; |
1945 | 0 | } |
1946 | | |
1947 | | /* create and fill the PC tree */ |
1948 | 0 | dissect_mtp3_3byte_pc(tvb, pinfo, offset, call_tree, |
1949 | 0 | called ? ett_sccp_called_pc : ett_sccp_calling_pc, |
1950 | 0 | hf_pc, |
1951 | 0 | called ? hf_sccp_called_pc_network : hf_sccp_calling_pc_network, |
1952 | 0 | called ? hf_sccp_called_pc_cluster : hf_sccp_calling_pc_cluster, |
1953 | 0 | called ? hf_sccp_called_pc_member : hf_sccp_calling_pc_member, |
1954 | 0 | 0, 0); |
1955 | |
|
1956 | 0 | return offset + ANSI_PC_LENGTH; |
1957 | 0 | } |
1958 | | |
1959 | | /* FUNCTION dissect_sccp_called_calling_param(): |
1960 | | * Dissect the Calling or Called Party Address parameters. |
1961 | | * |
1962 | | * The boolean 'called' describes whether this function is decoding a |
1963 | | * called (true) or calling (false) party address. There is simply too |
1964 | | * much code in this function to have 2 copies of it (one for called, one |
1965 | | * for calling). |
1966 | | * |
1967 | | * NOTE: this function is called even when (!tree) so that we can get |
1968 | | * the SSN and subsequently call subdissectors (if and when there's a data |
1969 | | * parameter). Realistically we should put if (!tree)'s around a lot of the |
1970 | | * code, but I think that would make it unreadable--and the expense of not |
1971 | | * doing so does not appear to be very high. |
1972 | | */ |
1973 | | static void |
1974 | | dissect_sccp_called_calling_param(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo, |
1975 | | unsigned length, bool called, sccp_decode_context_t* sccp_info) |
1976 | 453 | { |
1977 | 453 | proto_item *call_ai_item, *item, *hidden_item, *expert_item; |
1978 | 453 | proto_tree *call_tree, *call_ai_tree; |
1979 | 453 | unsigned offset; |
1980 | 453 | uint8_t national = 0xFFU, routing_ind, gti, pci, ssni, ssn; |
1981 | 453 | tvbuff_t *gt_tvb; |
1982 | 453 | dissector_handle_t ssn_dissector = NULL, tcap_ssn_dissector = NULL; |
1983 | 453 | const char *ssn_dissector_description = NULL; |
1984 | 453 | const char *tcap_ssn_dissector_description = NULL; |
1985 | | |
1986 | 453 | call_tree = proto_tree_add_subtree_format(tree, tvb, 0, length, |
1987 | 453 | called ? ett_sccp_called : ett_sccp_calling, NULL, |
1988 | 453 | "%s Party address (%u byte%s)", |
1989 | 453 | called ? "Called" : "Calling", length, |
1990 | 453 | plurality(length, "", "s")); |
1991 | | |
1992 | 453 | call_ai_tree = proto_tree_add_subtree(call_tree, tvb, 0, |
1993 | 453 | ADDRESS_INDICATOR_LENGTH, |
1994 | 453 | called ? ett_sccp_called_ai : ett_sccp_calling_ai, &call_ai_item, "Address Indicator"); |
1995 | | |
1996 | 453 | if (decode_mtp3_standard == ANSI_STANDARD) { |
1997 | 0 | national = tvb_get_uint8(tvb, 0) & ANSI_NATIONAL_MASK; |
1998 | 0 | expert_item = proto_tree_add_uint(call_ai_tree, called ? hf_sccp_called_ansi_national_indicator |
1999 | 0 | : hf_sccp_calling_ansi_national_indicator, |
2000 | 0 | tvb, 0, ADDRESS_INDICATOR_LENGTH, national); |
2001 | 0 | if (national == 0) |
2002 | 0 | expert_add_info(pinfo, expert_item, &ei_sccp_international_standard_address); |
2003 | 453 | } else { |
2004 | 453 | uint8_t natl_use_bit = tvb_get_uint8(tvb, 0) & ITU_RESERVED_MASK; |
2005 | | |
2006 | 453 | proto_tree_add_uint(call_ai_tree, called ? hf_sccp_called_itu_natl_use_bit |
2007 | 453 | : hf_sccp_calling_itu_natl_use_bit, |
2008 | 453 | tvb, 0, ADDRESS_INDICATOR_LENGTH, natl_use_bit); |
2009 | 453 | } |
2010 | | |
2011 | 453 | routing_ind = tvb_get_uint8(tvb, 0) & ROUTING_INDICATOR_MASK; |
2012 | 453 | proto_tree_add_uint(call_ai_tree, called ? hf_sccp_called_routing_indicator : hf_sccp_calling_routing_indicator, |
2013 | 453 | tvb, 0, ADDRESS_INDICATOR_LENGTH, routing_ind); |
2014 | | /* Only shift off the other bits after adding the item */ |
2015 | 453 | routing_ind >>= ROUTING_INDICATOR_SHIFT; |
2016 | | |
2017 | 453 | gti = tvb_get_uint8(tvb, 0) & GTI_MASK; |
2018 | | |
2019 | 453 | if (decode_mtp3_standard == ITU_STANDARD || |
2020 | 453 | decode_mtp3_standard == CHINESE_ITU_STANDARD || |
2021 | 453 | decode_mtp3_standard == JAPAN_STANDARD || |
2022 | 453 | national == 0) { |
2023 | | |
2024 | 450 | proto_tree_add_uint(call_ai_tree, |
2025 | 450 | called ? hf_sccp_called_itu_global_title_indicator : hf_sccp_calling_itu_global_title_indicator, |
2026 | 450 | tvb, 0, ADDRESS_INDICATOR_LENGTH, gti); |
2027 | | |
2028 | 450 | ssni = tvb_get_uint8(tvb, 0) & ITU_SSN_INDICATOR_MASK; |
2029 | 450 | expert_item = proto_tree_add_uint(call_ai_tree, |
2030 | 450 | called ? hf_sccp_called_itu_ssn_indicator : hf_sccp_calling_itu_ssn_indicator, |
2031 | 450 | tvb, 0, ADDRESS_INDICATOR_LENGTH, ssni); |
2032 | 450 | if ((routing_ind == ROUTE_ON_SSN) && (ssni == 0)) { |
2033 | 40 | expert_add_info(pinfo, expert_item, &ei_sccp_no_ssn_present); |
2034 | 40 | } |
2035 | | |
2036 | 450 | pci = tvb_get_uint8(tvb, 0) & ITU_PC_INDICATOR_MASK; |
2037 | 450 | proto_tree_add_uint(call_ai_tree, called ? hf_sccp_called_itu_point_code_indicator : hf_sccp_calling_itu_point_code_indicator, |
2038 | 450 | tvb, 0, ADDRESS_INDICATOR_LENGTH, pci); |
2039 | | |
2040 | 450 | offset = ADDRESS_INDICATOR_LENGTH; |
2041 | | |
2042 | | /* Dissect PC (if present) */ |
2043 | 450 | if (pci) { |
2044 | 191 | if (decode_mtp3_standard == ITU_STANDARD || national == 0) { |
2045 | 191 | if (length < offset + ITU_PC_LENGTH) { |
2046 | 14 | proto_tree_add_expert_format(call_tree, pinfo, &ei_sccp_wrong_length, tvb, 0, -1, |
2047 | 14 | "Wrong length indicated (%u) should be at least %u, PC is %u octets", |
2048 | 14 | length, offset + ITU_PC_LENGTH, ITU_PC_LENGTH); |
2049 | 14 | return; |
2050 | 14 | } |
2051 | 177 | proto_tree_add_item(call_tree, called ? hf_sccp_called_itu_pc : hf_sccp_calling_itu_pc, |
2052 | 177 | tvb, offset, ITU_PC_LENGTH, ENC_LITTLE_ENDIAN); |
2053 | 177 | offset += ITU_PC_LENGTH; |
2054 | | |
2055 | 177 | } else if (decode_mtp3_standard == JAPAN_STANDARD) { |
2056 | |
|
2057 | 0 | if (length < offset + JAPAN_PC_LENGTH) { |
2058 | 0 | proto_tree_add_expert_format(call_tree, pinfo, &ei_sccp_wrong_length, tvb, 0, -1, |
2059 | 0 | "Wrong length indicated (%u) should be at least %u, PC is %u octets", |
2060 | 0 | length, offset + JAPAN_PC_LENGTH, JAPAN_PC_LENGTH); |
2061 | 0 | return; |
2062 | 0 | } |
2063 | 0 | proto_tree_add_item(call_tree, called ? hf_sccp_called_japan_pc : hf_sccp_calling_japan_pc, |
2064 | 0 | tvb, offset, JAPAN_PC_LENGTH, ENC_LITTLE_ENDIAN); |
2065 | |
|
2066 | 0 | offset += JAPAN_PC_LENGTH; |
2067 | |
|
2068 | 0 | } else /* CHINESE_ITU_STANDARD */ { |
2069 | |
|
2070 | 0 | if (length < offset + ANSI_PC_LENGTH) { |
2071 | 0 | proto_tree_add_expert_format(call_tree, pinfo, &ei_sccp_wrong_length, tvb, 0, -1, |
2072 | 0 | "Wrong length indicated (%u) should be at least %u, PC is %u octets", |
2073 | 0 | length, offset + ANSI_PC_LENGTH, ANSI_PC_LENGTH); |
2074 | 0 | return; |
2075 | 0 | } |
2076 | 0 | offset = dissect_sccp_3byte_pc(tvb, pinfo, call_tree, offset, called); |
2077 | |
|
2078 | 0 | } |
2079 | 191 | } |
2080 | | |
2081 | | /* Dissect SSN (if present) */ |
2082 | 436 | if (ssni) { |
2083 | 216 | ssn = tvb_get_uint8(tvb, offset); |
2084 | | |
2085 | 216 | if ((routing_ind == ROUTE_ON_SSN) && (ssn == 0)) { |
2086 | 5 | expert_add_info(pinfo, expert_item, &ei_sccp_ssn_zero); |
2087 | 5 | } |
2088 | | |
2089 | 216 | if (called && sccp_info->assoc) |
2090 | 128 | sccp_info->assoc->called_ssn = ssn; |
2091 | 88 | else if (sccp_info->assoc) |
2092 | 87 | sccp_info->assoc->calling_ssn = ssn; |
2093 | | |
2094 | 216 | if (is_connectionless(sccp_info->message_type) && sccp_info->sccp_msg) { |
2095 | 103 | unsigned *ssn_ptr = called ? &(sccp_info->sccp_msg->data.ud.called_ssn) : &(sccp_info->sccp_msg->data.ud.calling_ssn); |
2096 | | |
2097 | 103 | *ssn_ptr = ssn; |
2098 | 103 | } |
2099 | | |
2100 | 216 | proto_tree_add_uint(call_tree, called ? hf_sccp_called_ssn |
2101 | 216 | : hf_sccp_calling_ssn, |
2102 | 216 | tvb, offset, ADDRESS_SSN_LENGTH, ssn); |
2103 | 216 | hidden_item = proto_tree_add_uint(call_tree, hf_sccp_ssn, tvb, offset, |
2104 | 216 | ADDRESS_SSN_LENGTH, ssn); |
2105 | 216 | proto_item_set_hidden(hidden_item); |
2106 | | |
2107 | 216 | offset += ADDRESS_SSN_LENGTH; |
2108 | | |
2109 | | /* Get the dissector handle of the dissector registered for this ssn |
2110 | | * And print its name. |
2111 | | */ |
2112 | 216 | ssn_dissector = dissector_get_uint_handle(sccp_ssn_dissector_table, ssn); |
2113 | | |
2114 | 216 | if (ssn_dissector) { |
2115 | 85 | ssn_dissector_description = dissector_handle_get_description(ssn_dissector); |
2116 | | |
2117 | 85 | if (ssn_dissector_description) { |
2118 | 85 | item = proto_tree_add_string_format(call_tree, hf_sccp_linked_dissector, tvb, offset - 1, ADDRESS_SSN_LENGTH, |
2119 | 85 | ssn_dissector_description, "Linked to %s", ssn_dissector_description); |
2120 | 85 | proto_item_set_generated(item); |
2121 | | |
2122 | 85 | if (g_ascii_strncasecmp("TCAP", ssn_dissector_description, 4)== 0) { |
2123 | 64 | tcap_ssn_dissector = get_itu_tcap_subdissector(ssn); |
2124 | | |
2125 | 64 | if (tcap_ssn_dissector) { |
2126 | 35 | tcap_ssn_dissector_description = dissector_handle_get_description(tcap_ssn_dissector); |
2127 | 35 | proto_item_append_text(item,", TCAP SSN linked to %s", tcap_ssn_dissector_description); |
2128 | 35 | } |
2129 | 64 | } |
2130 | 85 | } /* short name */ |
2131 | 85 | } /* ssn_dissector */ |
2132 | 216 | } /* ssni */ |
2133 | | |
2134 | | /* Dissect GT (if present) */ |
2135 | 436 | if (gti != AI_GTI_NO_GT) { |
2136 | 379 | if (length < offset) |
2137 | 0 | return; |
2138 | | |
2139 | 379 | gt_tvb = tvb_new_subset_length(tvb, offset, (length - offset)); |
2140 | 379 | dissect_sccp_global_title(gt_tvb, pinfo, call_tree, (length - offset), gti, |
2141 | 379 | called, sccp_info); |
2142 | 379 | } |
2143 | | |
2144 | 436 | } else if (decode_mtp3_standard == ANSI_STANDARD) { |
2145 | |
|
2146 | 0 | proto_tree_add_uint(call_ai_tree, called ? hf_sccp_called_ansi_global_title_indicator |
2147 | 0 | : hf_sccp_calling_ansi_global_title_indicator, |
2148 | 0 | tvb, 0, ADDRESS_INDICATOR_LENGTH, gti); |
2149 | |
|
2150 | 0 | pci = tvb_get_uint8(tvb, 0) & ANSI_PC_INDICATOR_MASK; |
2151 | 0 | proto_tree_add_uint(call_ai_tree, called ? hf_sccp_called_ansi_point_code_indicator |
2152 | 0 | : hf_sccp_calling_ansi_point_code_indicator, |
2153 | 0 | tvb, 0, ADDRESS_INDICATOR_LENGTH, pci); |
2154 | |
|
2155 | 0 | ssni = tvb_get_uint8(tvb, 0) & ANSI_SSN_INDICATOR_MASK; |
2156 | 0 | expert_item = proto_tree_add_uint(call_ai_tree, called ? hf_sccp_called_ansi_ssn_indicator |
2157 | 0 | : hf_sccp_calling_ansi_ssn_indicator, |
2158 | 0 | tvb, 0, ADDRESS_INDICATOR_LENGTH, ssni); |
2159 | 0 | if ((routing_ind == ROUTE_ON_SSN) && (ssni == 0)) { |
2160 | 0 | expert_add_info(pinfo, expert_item, &ei_sccp_no_ssn_present); |
2161 | 0 | } |
2162 | |
|
2163 | 0 | offset = ADDRESS_INDICATOR_LENGTH; |
2164 | | |
2165 | | /* Dissect SSN (if present) */ |
2166 | 0 | if (ssni) { |
2167 | 0 | ssn = tvb_get_uint8(tvb, offset); |
2168 | |
|
2169 | 0 | if ((routing_ind == ROUTE_ON_SSN) && (ssn == 0)) { |
2170 | 0 | expert_add_info(pinfo, expert_item, &ei_sccp_ssn_zero); |
2171 | 0 | } |
2172 | |
|
2173 | 0 | if (called && sccp_info->assoc) { |
2174 | 0 | sccp_info->assoc->called_ssn = ssn; |
2175 | 0 | } else if (sccp_info->assoc) { |
2176 | 0 | sccp_info->assoc->calling_ssn = ssn; |
2177 | 0 | } |
2178 | |
|
2179 | 0 | if (is_connectionless(sccp_info->message_type) && sccp_info->sccp_msg) { |
2180 | 0 | unsigned *ssn_ptr = called ? &(sccp_info->sccp_msg->data.ud.called_ssn) : &(sccp_info->sccp_msg->data.ud.calling_ssn); |
2181 | |
|
2182 | 0 | *ssn_ptr = ssn; |
2183 | 0 | } |
2184 | |
|
2185 | 0 | proto_tree_add_uint(call_tree, called ? hf_sccp_called_ssn |
2186 | 0 | : hf_sccp_calling_ssn, |
2187 | 0 | tvb, offset, ADDRESS_SSN_LENGTH, ssn); |
2188 | 0 | hidden_item = proto_tree_add_uint(call_tree, hf_sccp_ssn, tvb, offset, |
2189 | 0 | ADDRESS_SSN_LENGTH, ssn); |
2190 | 0 | proto_item_set_hidden(hidden_item); |
2191 | |
|
2192 | 0 | offset += ADDRESS_SSN_LENGTH; |
2193 | 0 | } |
2194 | | |
2195 | | /* Dissect PC (if present) */ |
2196 | 0 | if (pci) { |
2197 | 0 | offset = dissect_sccp_3byte_pc(tvb, pinfo, call_tree, offset, called); |
2198 | 0 | } |
2199 | | |
2200 | | /* Dissect GT (if present) */ |
2201 | 0 | if (gti != AI_GTI_NO_GT) { |
2202 | 0 | if (length < offset) |
2203 | 0 | return; |
2204 | 0 | gt_tvb = tvb_new_subset_length(tvb, offset, (length - offset)); |
2205 | 0 | dissect_sccp_global_title(gt_tvb, pinfo, call_tree, (length - offset), gti, |
2206 | 0 | called, sccp_info); |
2207 | 0 | } |
2208 | |
|
2209 | 0 | } |
2210 | | |
2211 | 453 | } |
2212 | | |
2213 | | static void |
2214 | | dissect_sccp_called_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned length, sccp_decode_context_t* sccp_info) |
2215 | 224 | { |
2216 | 224 | dissect_sccp_called_calling_param(tvb, tree, pinfo, length, true, sccp_info); |
2217 | 224 | } |
2218 | | |
2219 | | static void |
2220 | | dissect_sccp_calling_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned length, sccp_decode_context_t* sccp_info) |
2221 | 229 | { |
2222 | 229 | dissect_sccp_called_calling_param(tvb, tree, pinfo, length, false, sccp_info); |
2223 | 229 | } |
2224 | | |
2225 | | static void |
2226 | | dissect_sccp_class_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned length, sccp_decode_context_t* sccp_info) |
2227 | 271 | { |
2228 | 271 | uint8_t msg_class; |
2229 | 271 | proto_item *pi; |
2230 | 271 | bool invalid_class = false; |
2231 | | |
2232 | 271 | if (length != 1) { |
2233 | 60 | proto_tree_add_expert_format(tree, pinfo, &ei_sccp_wrong_length, tvb, 0, length, |
2234 | 60 | "Wrong length indicated. Expected 1, got %u", length); |
2235 | 60 | return; |
2236 | 60 | } |
2237 | | |
2238 | 211 | msg_class = tvb_get_uint8(tvb, 0) & CLASS_CLASS_MASK; |
2239 | 211 | pi = proto_tree_add_uint(tree, hf_sccp_class, tvb, 0, length, msg_class); |
2240 | | |
2241 | 211 | switch (sccp_info->message_type) { |
2242 | 0 | case SCCP_MSG_TYPE_DT1: |
2243 | 0 | if (msg_class != 2) |
2244 | 0 | invalid_class = true; |
2245 | 0 | break; |
2246 | 0 | case SCCP_MSG_TYPE_DT2: |
2247 | 0 | case SCCP_MSG_TYPE_AK: |
2248 | 0 | case SCCP_MSG_TYPE_ED: |
2249 | 0 | case SCCP_MSG_TYPE_EA: |
2250 | 0 | case SCCP_MSG_TYPE_RSR: |
2251 | 0 | case SCCP_MSG_TYPE_RSC: |
2252 | 0 | if (msg_class != 3) |
2253 | 0 | invalid_class = true; |
2254 | 0 | break; |
2255 | 102 | case SCCP_MSG_TYPE_CR: |
2256 | 156 | case SCCP_MSG_TYPE_CC: |
2257 | 156 | case SCCP_MSG_TYPE_CREF: |
2258 | 157 | case SCCP_MSG_TYPE_RLSD: |
2259 | 157 | case SCCP_MSG_TYPE_RLC: |
2260 | 157 | case SCCP_MSG_TYPE_ERR: |
2261 | 163 | case SCCP_MSG_TYPE_IT: |
2262 | 163 | if ((msg_class != 2) && (msg_class != 3)) |
2263 | 139 | invalid_class = true; |
2264 | 163 | break; |
2265 | 6 | case SCCP_MSG_TYPE_UDT: |
2266 | 6 | case SCCP_MSG_TYPE_UDTS: |
2267 | 47 | case SCCP_MSG_TYPE_XUDT: |
2268 | 47 | case SCCP_MSG_TYPE_XUDTS: |
2269 | 48 | case SCCP_MSG_TYPE_LUDT: |
2270 | 48 | case SCCP_MSG_TYPE_LUDTS: |
2271 | 48 | if ((msg_class != 0) && (msg_class != 1)) |
2272 | 9 | invalid_class = true; |
2273 | 48 | break; |
2274 | 211 | } |
2275 | | |
2276 | 211 | if (invalid_class) |
2277 | 148 | expert_add_info(pinfo, pi, &ei_sccp_class_unexpected); |
2278 | | |
2279 | 211 | if (msg_class == 0 || msg_class == 1) { |
2280 | 92 | uint8_t handling = tvb_get_uint8(tvb, 0) & CLASS_SPARE_HANDLING_MASK; |
2281 | | |
2282 | 92 | pi = proto_tree_add_item(tree, hf_sccp_handling, tvb, 0, length, ENC_NA); |
2283 | 92 | handling >>= CLASS_SPARE_HANDLING_SHIFT; |
2284 | | |
2285 | 92 | if (try_val_to_str(handling, sccp_class_handling_values) == NULL) { |
2286 | 50 | expert_add_info(pinfo, pi, &ei_sccp_handling_invalid); |
2287 | 50 | } |
2288 | 92 | } |
2289 | 211 | } |
2290 | | |
2291 | | static void |
2292 | | dissect_sccp_segmenting_reassembling_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned length) |
2293 | 72 | { |
2294 | 72 | if (length != 1) { |
2295 | 66 | proto_tree_add_expert_format(tree, pinfo, &ei_sccp_wrong_length, tvb, 0, length, |
2296 | 66 | "Wrong length indicated. Expected 1, got %u", length); |
2297 | 66 | return; |
2298 | 66 | } |
2299 | | |
2300 | 6 | proto_tree_add_item(tree, hf_sccp_more, tvb, 0, length, ENC_BIG_ENDIAN); |
2301 | 6 | } |
2302 | | |
2303 | | static void |
2304 | | dissect_sccp_receive_sequence_number_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned length) |
2305 | 35 | { |
2306 | 35 | if (length != 1) { |
2307 | 33 | proto_tree_add_expert_format(tree, pinfo, &ei_sccp_wrong_length, tvb, 0, length, |
2308 | 33 | "Wrong length indicated. Expected 1, got %u", length); |
2309 | 33 | return; |
2310 | 33 | } |
2311 | | |
2312 | 2 | proto_tree_add_item(tree, hf_sccp_rsn, tvb, 0, length, ENC_NA); |
2313 | 2 | } |
2314 | | |
2315 | | static void |
2316 | | dissect_sccp_sequencing_segmenting_param(tvbuff_t *tvb, proto_tree *tree, unsigned length) |
2317 | 29 | { |
2318 | 29 | proto_tree *param_tree; |
2319 | | |
2320 | 29 | param_tree = proto_tree_add_subtree(tree, tvb, 0, length, ett_sccp_sequencing_segmenting, NULL, |
2321 | 29 | val_to_str(PARAMETER_SEQUENCING_SEGMENTING, |
2322 | 29 | sccp_parameter_values, "Unknown: %d")); |
2323 | | |
2324 | 29 | proto_tree_add_item(param_tree, hf_sccp_sequencing_segmenting_ssn, tvb, 0, |
2325 | 29 | SEQUENCING_SEGMENTING_SSN_LENGTH, ENC_NA); |
2326 | 29 | proto_tree_add_item(param_tree, hf_sccp_sequencing_segmenting_rsn, tvb, |
2327 | 29 | SEQUENCING_SEGMENTING_SSN_LENGTH, |
2328 | 29 | SEQUENCING_SEGMENTING_RSN_LENGTH, ENC_NA); |
2329 | 29 | proto_tree_add_item(param_tree, hf_sccp_sequencing_segmenting_more, tvb, |
2330 | 29 | SEQUENCING_SEGMENTING_SSN_LENGTH, |
2331 | 29 | SEQUENCING_SEGMENTING_RSN_LENGTH, ENC_NA); |
2332 | 29 | } |
2333 | | |
2334 | | static void |
2335 | | dissect_sccp_credit_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned length) |
2336 | 47 | { |
2337 | 47 | if (length != 1) { |
2338 | 33 | proto_tree_add_expert_format(tree, pinfo, &ei_sccp_wrong_length, tvb, 0, length, |
2339 | 33 | "Wrong length indicated. Expected 1, got %u", length); |
2340 | 33 | return; |
2341 | 33 | } |
2342 | | |
2343 | 14 | proto_tree_add_item(tree, hf_sccp_credit, tvb, 0, length, ENC_NA); |
2344 | 14 | } |
2345 | | |
2346 | | static void |
2347 | | dissect_sccp_release_cause_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned length) |
2348 | 36 | { |
2349 | 36 | if (length != 1) { |
2350 | 27 | proto_tree_add_expert_format(tree, pinfo, &ei_sccp_wrong_length, tvb, 0, length, |
2351 | 27 | "Wrong length indicated. Expected 1, got %u", length); |
2352 | 27 | return; |
2353 | 27 | } |
2354 | | |
2355 | 9 | proto_tree_add_item(tree, hf_sccp_release_cause, tvb, 0, length, ENC_LITTLE_ENDIAN); |
2356 | | |
2357 | 9 | if (show_key_params) |
2358 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, "Cause=%d ", tvb_get_uint8(tvb, 0)); |
2359 | 9 | } |
2360 | | |
2361 | | static void |
2362 | | dissect_sccp_return_cause_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned length) |
2363 | 118 | { |
2364 | 118 | if (length != 1) { |
2365 | 81 | proto_tree_add_expert_format(tree, pinfo, &ei_sccp_wrong_length, tvb, 0, length, |
2366 | 81 | "Wrong length indicated. Expected 1, got %u", length); |
2367 | 81 | return; |
2368 | 81 | } |
2369 | | |
2370 | 37 | proto_tree_add_item(tree, hf_sccp_return_cause, tvb, 0, length, ENC_LITTLE_ENDIAN); |
2371 | | |
2372 | 37 | if (show_key_params) |
2373 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, "Cause=%d ", tvb_get_uint8(tvb, 0)); |
2374 | 37 | } |
2375 | | |
2376 | | static void |
2377 | | dissect_sccp_reset_cause_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned length) |
2378 | 15 | { |
2379 | 15 | if (length != 1) { |
2380 | 15 | proto_tree_add_expert_format(tree, pinfo, &ei_sccp_wrong_length, tvb, 0, length, |
2381 | 15 | "Wrong length indicated. Expected 1, got %u", length); |
2382 | 15 | return; |
2383 | 15 | } |
2384 | | |
2385 | 0 | proto_tree_add_item(tree, hf_sccp_reset_cause, tvb, 0, length, ENC_LITTLE_ENDIAN); |
2386 | |
|
2387 | 0 | if (show_key_params) |
2388 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, "Cause=%d ", tvb_get_uint8(tvb, 0)); |
2389 | 0 | } |
2390 | | |
2391 | | static void |
2392 | | dissect_sccp_error_cause_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned length) |
2393 | 29 | { |
2394 | 29 | if (length != 1) { |
2395 | 27 | proto_tree_add_expert_format(tree, pinfo, &ei_sccp_wrong_length, tvb, 0, length, |
2396 | 27 | "Wrong length indicated. Expected 1, got %u", length); |
2397 | 27 | return; |
2398 | 27 | } |
2399 | | |
2400 | 2 | proto_tree_add_item(tree, hf_sccp_error_cause, tvb, 0, length, ENC_LITTLE_ENDIAN); |
2401 | | |
2402 | 2 | if (show_key_params) |
2403 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, "Cause=%d ", tvb_get_uint8(tvb, 0)); |
2404 | 2 | } |
2405 | | |
2406 | | static void |
2407 | | dissect_sccp_refusal_cause_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned length) |
2408 | 61 | { |
2409 | 61 | if (length != 1) { |
2410 | 50 | proto_tree_add_expert_format(tree, pinfo, &ei_sccp_wrong_length, tvb, 0, length, |
2411 | 50 | "Wrong length indicated. Expected 1, got %u", length); |
2412 | 50 | return; |
2413 | 50 | } |
2414 | | |
2415 | 11 | proto_tree_add_item(tree, hf_sccp_refusal_cause, tvb, 0, length, ENC_LITTLE_ENDIAN); |
2416 | | |
2417 | 11 | if (show_key_params) |
2418 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, "Cause=%d ", tvb_get_uint8(tvb, 0)); |
2419 | 11 | } |
2420 | | |
2421 | | |
2422 | | /* This function is used for both data and long data (ITU only) parameters */ |
2423 | | static void |
2424 | | dissect_sccp_data_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, sccp_assoc_info_t *assoc) |
2425 | 177 | { |
2426 | 177 | uint8_t ssn = INVALID_SSN; |
2427 | 177 | uint8_t other_ssn = INVALID_SSN; |
2428 | 177 | const mtp3_addr_pc_t *dpc = NULL; |
2429 | 177 | const mtp3_addr_pc_t *opc = NULL; |
2430 | 177 | heur_dtbl_entry_t *hdtbl_entry; |
2431 | 177 | struct _sccp_msg_info_t* sccp_info = NULL; |
2432 | | |
2433 | 177 | if ((trace_sccp) && (assoc && assoc != &no_assoc)) { |
2434 | 0 | sccp_info = assoc->curr_msg; |
2435 | 0 | } |
2436 | | |
2437 | 177 | if (assoc) { |
2438 | 177 | switch (pinfo->p2p_dir) { |
2439 | 54 | case P2P_DIR_SENT: |
2440 | 54 | ssn = assoc->calling_ssn; |
2441 | 54 | other_ssn = assoc->called_ssn; |
2442 | 54 | dpc = (const mtp3_addr_pc_t*)pinfo->dst.data; |
2443 | 54 | opc = (const mtp3_addr_pc_t*)pinfo->src.data; |
2444 | 54 | break; |
2445 | 23 | case P2P_DIR_RECV: |
2446 | 23 | ssn = assoc->called_ssn; |
2447 | 23 | other_ssn = assoc->calling_ssn; |
2448 | 23 | dpc = (const mtp3_addr_pc_t*)pinfo->src.data; |
2449 | 23 | opc = (const mtp3_addr_pc_t*)pinfo->dst.data; |
2450 | 23 | break; |
2451 | 100 | default: |
2452 | 100 | ssn = assoc->called_ssn; |
2453 | 100 | other_ssn = assoc->calling_ssn; |
2454 | 100 | dpc = (const mtp3_addr_pc_t*)pinfo->dst.data; |
2455 | 100 | opc = (const mtp3_addr_pc_t*)pinfo->src.data; |
2456 | 100 | break; |
2457 | 177 | } |
2458 | 177 | } |
2459 | | |
2460 | | |
2461 | 177 | if ((num_sccp_users) && (pinfo->src.type == ss7pc_address_type)) { |
2462 | 0 | unsigned i; |
2463 | 0 | dissector_handle_t handle = NULL; |
2464 | 0 | bool uses_tcap = false; |
2465 | |
|
2466 | 0 | for (i=0; i < num_sccp_users; i++) { |
2467 | 0 | sccp_user_t *u = &(sccp_users[i]); |
2468 | |
|
2469 | 0 | if (!dpc || dpc->ni != u->ni) continue; |
2470 | | |
2471 | 0 | if (value_is_in_range(u->called_ssn, ssn) && value_is_in_range(u->called_pc, dpc->pc) ) { |
2472 | 0 | handle = *(u->handlep); |
2473 | 0 | uses_tcap = u->uses_tcap; |
2474 | 0 | break; |
2475 | 0 | } else if (value_is_in_range(u->called_ssn, other_ssn) && opc && value_is_in_range(u->called_pc, opc->pc) ) { |
2476 | 0 | handle = *(u->handlep); |
2477 | 0 | uses_tcap = u->uses_tcap; |
2478 | 0 | break; |
2479 | 0 | } |
2480 | 0 | } |
2481 | |
|
2482 | 0 | if (handle) { |
2483 | 0 | if (uses_tcap) { |
2484 | 0 | call_tcap_dissector(handle, tvb, pinfo, tree); |
2485 | 0 | } else { |
2486 | 0 | call_dissector_with_data(handle, tvb, pinfo, tree, sccp_info); |
2487 | 0 | } |
2488 | 0 | return; |
2489 | 0 | } |
2490 | |
|
2491 | 0 | } |
2492 | | |
2493 | | /* Save SSN for Decode As */ |
2494 | 177 | p_add_proto_data(pinfo->pool, pinfo, proto_sccp, 0, GUINT_TO_POINTER((unsigned)ssn)); |
2495 | | |
2496 | 177 | if ((ssn != INVALID_SSN) && dissector_try_uint_with_data(sccp_ssn_dissector_table, ssn, tvb, pinfo, tree, true, sccp_info)) { |
2497 | 27 | return; |
2498 | 27 | } |
2499 | | |
2500 | 150 | if ((other_ssn != INVALID_SSN) && dissector_try_uint_with_data(sccp_ssn_dissector_table, other_ssn, tvb, pinfo, tree, true, sccp_info)) { |
2501 | 34 | return; |
2502 | 34 | } |
2503 | | |
2504 | | /* try heuristic subdissector list to see if there are any takers */ |
2505 | 116 | if (dissector_try_heuristic(heur_subdissector_list, tvb, pinfo, tree, &hdtbl_entry, sccp_info)) { |
2506 | 0 | return; |
2507 | 0 | } |
2508 | | |
2509 | | /* try user default subdissector */ |
2510 | 116 | if (default_handle) { |
2511 | 0 | call_dissector_with_data(default_handle, tvb, pinfo, tree, sccp_info); |
2512 | 0 | return; |
2513 | 0 | } |
2514 | | |
2515 | | /* No sub-dissection occurred, treat it as raw data */ |
2516 | 116 | call_dissector(data_handle, tvb, pinfo, tree); |
2517 | | |
2518 | 116 | } |
2519 | | |
2520 | | static void |
2521 | | dissect_sccp_segmentation_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned length) |
2522 | 50 | { |
2523 | 50 | proto_tree *param_tree; |
2524 | | |
2525 | 50 | param_tree = proto_tree_add_subtree(tree, tvb, 0, length, ett_sccp_segmentation, NULL, |
2526 | 50 | val_to_str(PARAMETER_SEGMENTATION, |
2527 | 50 | sccp_parameter_values, "Unknown: %d")); |
2528 | | |
2529 | 50 | proto_tree_add_item(param_tree, hf_sccp_segmentation_first, tvb, 0, 1, ENC_NA); |
2530 | 50 | proto_tree_add_item(param_tree, hf_sccp_segmentation_class, tvb, 0, 1, ENC_NA); |
2531 | 50 | proto_tree_add_item(param_tree, hf_sccp_segmentation_remaining, tvb, 0, 1, ENC_NA); |
2532 | | |
2533 | 50 | if (length-1 != 3) { |
2534 | 48 | proto_tree_add_expert_format(tree, pinfo, &ei_sccp_wrong_length, tvb, 0, length-1, |
2535 | 48 | "Wrong length indicated. Expected 3, got %u", length-1); |
2536 | 48 | return; |
2537 | 48 | } |
2538 | | |
2539 | 2 | proto_tree_add_item(param_tree, hf_sccp_segmentation_slr, tvb, 1, length-1, ENC_LITTLE_ENDIAN); |
2540 | 2 | } |
2541 | | |
2542 | | static void |
2543 | | dissect_sccp_hop_counter_param(tvbuff_t *tvb, proto_tree *tree, unsigned length) |
2544 | 74 | { |
2545 | 74 | uint8_t hops; |
2546 | | |
2547 | 74 | hops = tvb_get_uint8(tvb, 0); |
2548 | 74 | proto_tree_add_uint(tree, hf_sccp_hop_counter, tvb, 0, length, hops); |
2549 | 74 | } |
2550 | | |
2551 | | static void |
2552 | | dissect_sccp_importance_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned length) |
2553 | 68 | { |
2554 | 68 | if (length != 1) { |
2555 | 68 | proto_tree_add_expert_format(tree, pinfo, &ei_sccp_wrong_length, tvb, 0, length, |
2556 | 68 | "Wrong length indicated. Expected 1, got %u", length); |
2557 | 68 | return; |
2558 | 68 | } |
2559 | | |
2560 | 0 | proto_tree_add_item(tree, hf_sccp_importance, tvb, 0, length, ENC_NA); |
2561 | 0 | } |
2562 | | |
2563 | | static void |
2564 | | dissect_sccp_isni_param(tvbuff_t *tvb, proto_tree *tree, unsigned length) |
2565 | 0 | { |
2566 | 0 | uint8_t ti; |
2567 | 0 | unsigned offset = 0; |
2568 | 0 | proto_tree *param_tree; |
2569 | | |
2570 | | /* Create a subtree for ISNI Routing Control */ |
2571 | 0 | param_tree = proto_tree_add_subtree(tree, tvb, offset, ANSI_ISNI_ROUTING_CONTROL_LENGTH, |
2572 | 0 | ett_sccp_ansi_isni_routing_control, NULL, "ISNI Routing Control"); |
2573 | |
|
2574 | 0 | proto_tree_add_item(param_tree, hf_sccp_ansi_isni_mi, tvb, offset, |
2575 | 0 | ANSI_ISNI_ROUTING_CONTROL_LENGTH, ENC_NA); |
2576 | |
|
2577 | 0 | proto_tree_add_item(param_tree, hf_sccp_ansi_isni_iri, tvb, offset, |
2578 | 0 | ANSI_ISNI_ROUTING_CONTROL_LENGTH, ENC_NA); |
2579 | |
|
2580 | 0 | ti = tvb_get_uint8(tvb, offset) & ANSI_ISNI_TI_MASK; |
2581 | 0 | proto_tree_add_uint(param_tree, hf_sccp_ansi_isni_ti, tvb, offset, |
2582 | 0 | ANSI_ISNI_ROUTING_CONTROL_LENGTH, ti); |
2583 | |
|
2584 | 0 | proto_tree_add_item(param_tree, hf_sccp_ansi_isni_counter, tvb, offset, |
2585 | 0 | ANSI_ISNI_ROUTING_CONTROL_LENGTH, ENC_NA); |
2586 | |
|
2587 | 0 | offset += ANSI_ISNI_ROUTING_CONTROL_LENGTH; |
2588 | |
|
2589 | 0 | if ((ti >> ANSI_ISNI_TI_SHIFT) == ANSI_ISNI_TYPE_1) { |
2590 | 0 | proto_tree_add_uint(param_tree, hf_sccp_ansi_isni_netspec, tvb, offset, |
2591 | 0 | ANSI_ISNI_ROUTING_CONTROL_LENGTH, ti); |
2592 | 0 | offset += ANSI_ISNI_ROUTING_CONTROL_LENGTH; |
2593 | 0 | } |
2594 | |
|
2595 | 0 | while (offset < length) { |
2596 | |
|
2597 | 0 | proto_tree_add_item(tree, hf_sccp_ansi_isni_network, tvb, offset, |
2598 | 0 | ANSI_NCM_LENGTH, ENC_NA); |
2599 | 0 | offset++; |
2600 | |
|
2601 | 0 | proto_tree_add_item(tree, hf_sccp_ansi_isni_cluster, tvb, offset, |
2602 | 0 | ANSI_NCM_LENGTH, ENC_NA); |
2603 | 0 | offset++; |
2604 | 0 | } |
2605 | |
|
2606 | 0 | } |
2607 | | |
2608 | | /* FUNCTION dissect_sccp_parameter(): |
2609 | | * Dissect a parameter given its type, offset into tvb, and length. |
2610 | | */ |
2611 | | static uint16_t |
2612 | | dissect_sccp_parameter(tvbuff_t *tvb, packet_info *pinfo, proto_tree *sccp_tree, |
2613 | | proto_tree *tree, uint8_t parameter_type, int offset, |
2614 | | uint16_t parameter_length, sccp_decode_context_t *sccp_info) |
2615 | 2.76k | { |
2616 | 2.76k | tvbuff_t *parameter_tvb; |
2617 | | |
2618 | 2.76k | switch (parameter_type) { |
2619 | 224 | case PARAMETER_CALLED_PARTY_ADDRESS: |
2620 | 453 | case PARAMETER_CALLING_PARTY_ADDRESS: |
2621 | 618 | case PARAMETER_DATA: |
2622 | 621 | case PARAMETER_LONG_DATA: |
2623 | 941 | case PARAMETER_SOURCE_LOCAL_REFERENCE: |
2624 | 1.41k | case PARAMETER_DESTINATION_LOCAL_REFERENCE: |
2625 | 1.45k | case PARAMETER_RELEASE_CAUSE: |
2626 | 1.57k | case PARAMETER_RETURN_CAUSE: |
2627 | 1.58k | case PARAMETER_RESET_CAUSE: |
2628 | 1.61k | case PARAMETER_ERROR_CAUSE: |
2629 | 1.67k | case PARAMETER_REFUSAL_CAUSE: |
2630 | | |
2631 | | /* These parameters must be dissected even if !sccp_tree (so that |
2632 | | * assoc information can be created). |
2633 | | */ |
2634 | 1.67k | break; |
2635 | | |
2636 | 1.09k | default: |
2637 | 1.09k | if (!sccp_tree) return parameter_length; |
2638 | | |
2639 | 2.76k | } |
2640 | | |
2641 | 2.76k | parameter_tvb = tvb_new_subset_length(tvb, offset, parameter_length); |
2642 | | |
2643 | 2.76k | switch (parameter_type) { |
2644 | | |
2645 | 72 | case PARAMETER_END_OF_OPTIONAL_PARAMETERS: |
2646 | 72 | proto_tree_add_item(sccp_tree, hf_sccp_end_optional_param, tvb, offset, parameter_length, ENC_NA); |
2647 | 72 | break; |
2648 | | |
2649 | 476 | case PARAMETER_DESTINATION_LOCAL_REFERENCE: |
2650 | 476 | dissect_sccp_dlr_param(parameter_tvb, pinfo, sccp_tree, parameter_length, sccp_info); |
2651 | 476 | break; |
2652 | | |
2653 | 320 | case PARAMETER_SOURCE_LOCAL_REFERENCE: |
2654 | 320 | dissect_sccp_slr_param(parameter_tvb, pinfo, sccp_tree, parameter_length, sccp_info); |
2655 | 320 | break; |
2656 | | |
2657 | 224 | case PARAMETER_CALLED_PARTY_ADDRESS: |
2658 | 224 | dissect_sccp_called_param(parameter_tvb, pinfo, sccp_tree, parameter_length, sccp_info); |
2659 | 224 | break; |
2660 | | |
2661 | 229 | case PARAMETER_CALLING_PARTY_ADDRESS: |
2662 | 229 | dissect_sccp_calling_param(parameter_tvb, pinfo, sccp_tree, parameter_length, sccp_info); |
2663 | 229 | break; |
2664 | | |
2665 | 271 | case PARAMETER_CLASS: |
2666 | 271 | dissect_sccp_class_param(parameter_tvb, pinfo, sccp_tree, parameter_length, sccp_info); |
2667 | 271 | break; |
2668 | | |
2669 | 72 | case PARAMETER_SEGMENTING_REASSEMBLING: |
2670 | 72 | dissect_sccp_segmenting_reassembling_param(parameter_tvb, pinfo, sccp_tree, |
2671 | 72 | parameter_length); |
2672 | 72 | break; |
2673 | | |
2674 | 35 | case PARAMETER_RECEIVE_SEQUENCE_NUMBER: |
2675 | 35 | dissect_sccp_receive_sequence_number_param(parameter_tvb, pinfo, sccp_tree, |
2676 | 35 | parameter_length); |
2677 | 35 | break; |
2678 | | |
2679 | 29 | case PARAMETER_SEQUENCING_SEGMENTING: |
2680 | 29 | dissect_sccp_sequencing_segmenting_param(parameter_tvb, sccp_tree, |
2681 | 29 | parameter_length); |
2682 | 29 | break; |
2683 | | |
2684 | 47 | case PARAMETER_CREDIT: |
2685 | 47 | dissect_sccp_credit_param(parameter_tvb, pinfo, sccp_tree, parameter_length); |
2686 | 47 | break; |
2687 | | |
2688 | 36 | case PARAMETER_RELEASE_CAUSE: |
2689 | 36 | dissect_sccp_release_cause_param(parameter_tvb, pinfo, sccp_tree, parameter_length); |
2690 | 36 | break; |
2691 | | |
2692 | 118 | case PARAMETER_RETURN_CAUSE: |
2693 | 118 | dissect_sccp_return_cause_param(parameter_tvb, pinfo, sccp_tree, parameter_length); |
2694 | 118 | break; |
2695 | | |
2696 | 15 | case PARAMETER_RESET_CAUSE: |
2697 | 15 | dissect_sccp_reset_cause_param(parameter_tvb, pinfo, sccp_tree, parameter_length); |
2698 | 15 | break; |
2699 | | |
2700 | 29 | case PARAMETER_ERROR_CAUSE: |
2701 | 29 | dissect_sccp_error_cause_param(parameter_tvb, pinfo, sccp_tree, parameter_length); |
2702 | 29 | break; |
2703 | | |
2704 | 61 | case PARAMETER_REFUSAL_CAUSE: |
2705 | 61 | dissect_sccp_refusal_cause_param(parameter_tvb, pinfo, sccp_tree, parameter_length); |
2706 | 61 | break; |
2707 | | |
2708 | 165 | case PARAMETER_DATA: |
2709 | 165 | dissect_sccp_data_param(parameter_tvb, pinfo, tree, sccp_info->assoc); |
2710 | | |
2711 | | /* TODO? Re-adjust length of SCCP item since it may be sub-dissected */ |
2712 | | /* sccp_length = proto_item_get_len(sccp_item); |
2713 | | * sccp_length -= parameter_length; |
2714 | | * proto_item_set_len(sccp_item, sccp_length); |
2715 | | * |
2716 | | * except that proto_item_get_len() is *NOT* guaranteed to return |
2717 | | * a correct value - if the item has been "faked", it will be wrong |
2718 | | */ |
2719 | 165 | break; |
2720 | | |
2721 | 50 | case PARAMETER_SEGMENTATION: |
2722 | 50 | dissect_sccp_segmentation_param(parameter_tvb, pinfo, sccp_tree, parameter_length); |
2723 | 50 | break; |
2724 | | |
2725 | 74 | case PARAMETER_HOP_COUNTER: |
2726 | 74 | dissect_sccp_hop_counter_param(parameter_tvb, sccp_tree, parameter_length); |
2727 | 74 | break; |
2728 | | |
2729 | 68 | case PARAMETER_IMPORTANCE: |
2730 | 68 | if (decode_mtp3_standard != ANSI_STANDARD) |
2731 | 68 | dissect_sccp_importance_param(parameter_tvb, pinfo, sccp_tree, parameter_length); |
2732 | 0 | else |
2733 | 0 | dissect_sccp_unknown_param(parameter_tvb, sccp_tree, parameter_type, |
2734 | 0 | parameter_length); |
2735 | 68 | break; |
2736 | | |
2737 | 3 | case PARAMETER_LONG_DATA: |
2738 | 3 | dissect_sccp_data_param(parameter_tvb, pinfo, tree, sccp_info->assoc); |
2739 | 3 | break; |
2740 | | |
2741 | 7 | case PARAMETER_ISNI: |
2742 | 7 | if (decode_mtp3_standard != ANSI_STANDARD) |
2743 | 7 | dissect_sccp_unknown_param(parameter_tvb, sccp_tree, parameter_type, |
2744 | 7 | parameter_length); |
2745 | 0 | else |
2746 | 0 | dissect_sccp_isni_param(parameter_tvb, sccp_tree, parameter_length); |
2747 | 7 | break; |
2748 | | |
2749 | 365 | default: |
2750 | 365 | dissect_sccp_unknown_param(parameter_tvb, sccp_tree, parameter_type, |
2751 | 365 | parameter_length); |
2752 | 365 | break; |
2753 | 2.76k | } |
2754 | | |
2755 | 2.63k | return parameter_length; |
2756 | 2.76k | } |
2757 | | |
2758 | | /* FUNCTION dissect_sccp_variable_parameter(): |
2759 | | * Dissect a variable parameter given its type and offset into tvb. Length |
2760 | | * of the parameter is gotten from tvb[0]. |
2761 | | * Length returned is sum of (length + parameter). |
2762 | | */ |
2763 | | static uint16_t |
2764 | | dissect_sccp_variable_parameter(tvbuff_t *tvb, packet_info *pinfo, |
2765 | | proto_tree *sccp_tree, proto_tree *tree, |
2766 | | uint8_t parameter_type, int offset, sccp_decode_context_t* sccp_info) |
2767 | 2.09k | { |
2768 | 2.09k | int remaining_length; |
2769 | 2.09k | uint16_t parameter_length; |
2770 | 2.09k | uint8_t length_length; |
2771 | 2.09k | proto_item *pi; |
2772 | | |
2773 | 2.09k | if (parameter_type != PARAMETER_LONG_DATA) { |
2774 | 2.09k | parameter_length = tvb_get_uint8(tvb, offset); |
2775 | 2.09k | length_length = PARAMETER_LENGTH_LENGTH; |
2776 | 2.09k | } else { |
2777 | | /* Long data parameter has 16 bit length */ |
2778 | 3 | parameter_length = tvb_get_letohs(tvb, offset); |
2779 | 3 | length_length = PARAMETER_LONG_DATA_LENGTH_LENGTH; |
2780 | 3 | } |
2781 | | |
2782 | 2.09k | pi = proto_tree_add_uint_format(sccp_tree, hf_sccp_param_length, tvb, offset, |
2783 | 2.09k | length_length, parameter_length, "%s length: %d", |
2784 | 2.09k | val_to_str(parameter_type, sccp_parameter_values, |
2785 | 2.09k | "Unknown: %d"), |
2786 | 2.09k | parameter_length); |
2787 | 2.09k | remaining_length = tvb_reported_length_remaining(tvb, offset + length_length); |
2788 | 2.09k | if (parameter_type == PARAMETER_DATA && remaining_length > 255 && parameter_length == 255) { |
2789 | 3 | expert_add_info_format(pinfo, pi, &ei_sccp_externally_reassembled, "Possibly externally reassembled (remaining length %u > %u), check SCCP preferences", remaining_length, parameter_length); |
2790 | 3 | if (dt1_ignore_length) { |
2791 | 0 | parameter_length = remaining_length; |
2792 | 0 | } |
2793 | 2.09k | } else if (!sccp_show_length) { |
2794 | | /* The user doesn't want to see it... */ |
2795 | | /* Show the length anyway, though, if there was an error. */ |
2796 | 2.08k | proto_item_set_hidden(pi); |
2797 | 2.08k | } |
2798 | | |
2799 | 2.09k | offset += length_length; |
2800 | | |
2801 | 2.09k | dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree, parameter_type, offset, |
2802 | 2.09k | parameter_length, sccp_info); |
2803 | | |
2804 | 2.09k | return parameter_length + length_length; |
2805 | 2.09k | } |
2806 | | |
2807 | | /* FUNCTION dissect_sccp_optional_parameters(): |
2808 | | * Dissect all the optional parameters given the start of the optional |
2809 | | * parameters into tvb. Parameter types and lengths are read from tvb. |
2810 | | */ |
2811 | | static void |
2812 | | dissect_sccp_optional_parameters(tvbuff_t *tvb, packet_info *pinfo, |
2813 | | proto_tree *sccp_tree, proto_tree *tree, |
2814 | | int offset, sccp_decode_context_t* sccp_info) |
2815 | 206 | { |
2816 | 206 | uint8_t parameter_type; |
2817 | | |
2818 | 2.00k | while ((parameter_type = tvb_get_uint8(tvb, offset)) != |
2819 | 2.00k | PARAMETER_END_OF_OPTIONAL_PARAMETERS) { |
2820 | | |
2821 | 1.79k | offset += PARAMETER_TYPE_LENGTH; |
2822 | 1.79k | offset += dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree, |
2823 | 1.79k | parameter_type, offset, sccp_info); |
2824 | 1.79k | } |
2825 | | |
2826 | | /* Process end of optional parameters */ |
2827 | 206 | dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree, parameter_type, offset, |
2828 | 206 | END_OF_OPTIONAL_PARAMETERS_LENGTH, sccp_info); |
2829 | | |
2830 | 206 | } |
2831 | | |
2832 | | static sccp_msg_info_t * |
2833 | | new_ud_msg(packet_info *pinfo, uint32_t msg_type _U_) |
2834 | 82 | { |
2835 | 82 | sccp_msg_info_t *m = wmem_new0(pinfo->pool, sccp_msg_info_t); |
2836 | 82 | m->framenum = pinfo->num; |
2837 | 82 | m->data.ud.calling_gt = NULL; |
2838 | 82 | m->data.ud.called_gt = NULL; |
2839 | | |
2840 | 82 | return m; |
2841 | 82 | } |
2842 | | |
2843 | | static void build_assoc_tree(tvbuff_t *tvb, packet_info *pinfo, proto_tree *sccp_tree, |
2844 | | sccp_decode_context_t *sccp_info, unsigned msg_offset) |
2845 | 269 | { |
2846 | 269 | if (trace_sccp && sccp_info->assoc && (sccp_info->assoc != &no_assoc)) { |
2847 | 0 | proto_item *pi = proto_tree_add_uint(sccp_tree, hf_sccp_assoc_id, tvb, 0, 0, sccp_info->assoc->id); |
2848 | 0 | proto_item_set_generated(pi); |
2849 | 0 | proto_tree *pt = proto_item_add_subtree(pi, ett_sccp_assoc); |
2850 | 0 | if(sccp_info->assoc->imsi){ |
2851 | 0 | proto_item *pi2 = proto_tree_add_string(sccp_tree, hf_assoc_imsi, tvb, 0, 0, sccp_info->assoc->imsi); |
2852 | 0 | proto_item_set_generated(pi2); |
2853 | 0 | } |
2854 | 0 | if (sccp_info->assoc->msgs) { |
2855 | 0 | sccp_msg_info_t *m; |
2856 | 0 | for(m = sccp_info->assoc->msgs; m ; m = m->data.co.next) { |
2857 | 0 | pi = proto_tree_add_uint(pt, hf_sccp_assoc_msg, tvb, 0, 0, m->framenum); |
2858 | |
|
2859 | 0 | if (sccp_info->assoc->payload != SCCP_PLOAD_NONE) |
2860 | 0 | proto_item_append_text(pi," %s", val_to_str(sccp_info->assoc->payload, assoc_protos, "Unknown: %d")); |
2861 | |
|
2862 | 0 | if (m->data.co.label) |
2863 | 0 | proto_item_append_text(pi," %s", m->data.co.label); |
2864 | 0 | if (m->data.co.imsi) |
2865 | 0 | proto_item_append_text(pi, " %s", m->data.co.imsi); |
2866 | |
|
2867 | 0 | if ((m->framenum == pinfo->num) && (m->offset == msg_offset) ) { |
2868 | 0 | tap_queue_packet(sccp_tap, pinfo, m); |
2869 | 0 | proto_item_append_text(pi," (current)"); |
2870 | 0 | } |
2871 | 0 | proto_item_set_generated(pi); |
2872 | 0 | } |
2873 | 0 | } |
2874 | 0 | } |
2875 | 269 | } |
2876 | | |
2877 | | static int |
2878 | | dissect_xudt_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *sccp_tree, |
2879 | | proto_tree *tree, int offset, sccp_decode_context_t *sccp_info, |
2880 | | uint16_t *optional_pointer_p, uint16_t *orig_opt_ptr_p, |
2881 | | uint8_t pointer_length) |
2882 | 70 | { |
2883 | 70 | uint16_t variable_pointer1 = 0, variable_pointer2 = 0, variable_pointer3 = 0; |
2884 | 70 | uint16_t optional_pointer = 0, orig_opt_ptr = 0, optional_pointer1 = 0; |
2885 | 70 | uint8_t optional_param_type = 0; |
2886 | 70 | tvbuff_t *new_tvb = NULL; |
2887 | 70 | uint32_t source_local_ref = 0; |
2888 | 70 | unsigned msg_offset = tvb_offset_from_real_beginning(tvb); |
2889 | | |
2890 | | /* Macro for getting pointer to mandatory variable parameters */ |
2891 | 70 | #define VARIABLE_POINTER(var, hf_var, ptr_size) \ |
2892 | 352 | do { \ |
2893 | 352 | if (ptr_size == POINTER_LENGTH) \ |
2894 | 352 | var = tvb_get_uint8(tvb, offset); \ |
2895 | 352 | else \ |
2896 | 352 | var = tvb_get_letohs(tvb, offset); \ |
2897 | 352 | proto_tree_add_uint(sccp_tree, hf_var, tvb, \ |
2898 | 352 | offset, ptr_size, var); \ |
2899 | 352 | var += offset; \ |
2900 | 352 | if (ptr_size == POINTER_LENGTH_LONG) \ |
2901 | 352 | var += 1; \ |
2902 | 352 | offset += ptr_size; \ |
2903 | 352 | } while (0) |
2904 | | |
2905 | | /* Macro for getting pointer to optional parameters */ |
2906 | 70 | #define OPTIONAL_POINTER(ptr_size) \ |
2907 | 240 | do { \ |
2908 | 240 | if (ptr_size == POINTER_LENGTH) \ |
2909 | 240 | orig_opt_ptr = optional_pointer = tvb_get_uint8(tvb, offset); \ |
2910 | 240 | else \ |
2911 | 240 | orig_opt_ptr = optional_pointer = tvb_get_letohs(tvb, offset); \ |
2912 | 240 | proto_tree_add_uint(sccp_tree, hf_sccp_optional_pointer, tvb, \ |
2913 | 240 | offset, ptr_size, optional_pointer); \ |
2914 | 240 | optional_pointer += offset; \ |
2915 | 240 | if (ptr_size == POINTER_LENGTH_LONG) \ |
2916 | 240 | optional_pointer += 1; \ |
2917 | 240 | offset += ptr_size; \ |
2918 | 240 | } while (0) |
2919 | | |
2920 | | |
2921 | | /* Optional parameters are Segmentation and Importance |
2922 | | * NOTE 2 - Segmentation Should not be present in case of a single XUDT |
2923 | | * message. |
2924 | | */ |
2925 | | |
2926 | 70 | VARIABLE_POINTER(variable_pointer1, hf_sccp_variable_pointer1, pointer_length); |
2927 | 70 | VARIABLE_POINTER(variable_pointer2, hf_sccp_variable_pointer2, pointer_length); |
2928 | 70 | VARIABLE_POINTER(variable_pointer3, hf_sccp_variable_pointer3, pointer_length); |
2929 | 70 | OPTIONAL_POINTER(pointer_length); |
2930 | | |
2931 | 70 | sccp_info->assoc = get_sccp_assoc(pinfo, msg_offset, sccp_info); |
2932 | 70 | build_assoc_tree(tvb, pinfo, sccp_tree, sccp_info, msg_offset); |
2933 | | |
2934 | 70 | dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree, |
2935 | 70 | PARAMETER_CALLED_PARTY_ADDRESS, |
2936 | 70 | variable_pointer1, sccp_info); |
2937 | 70 | dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree, |
2938 | 70 | PARAMETER_CALLING_PARTY_ADDRESS, |
2939 | 70 | variable_pointer2, sccp_info); |
2940 | | |
2941 | | |
2942 | 70 | optional_pointer1 = optional_pointer; |
2943 | 298 | while((optional_param_type = tvb_get_uint8(tvb, optional_pointer1)) != PARAMETER_END_OF_OPTIONAL_PARAMETERS) { |
2944 | 236 | if (optional_param_type == PARAMETER_SEGMENTATION) |
2945 | 8 | break; |
2946 | 228 | optional_pointer1 += PARAMETER_TYPE_LENGTH; |
2947 | 228 | optional_pointer1 += tvb_get_uint8(tvb, optional_pointer1) + PARAMETER_LENGTH_LENGTH; |
2948 | 228 | } |
2949 | | |
2950 | 70 | if (tvb_get_uint8(tvb, optional_pointer1) == PARAMETER_SEGMENTATION) { |
2951 | 8 | if (!sccp_reassemble) { |
2952 | 0 | proto_tree_add_item(sccp_tree, hf_sccp_segmented_data, tvb, variable_pointer3, tvb_get_uint8(tvb, variable_pointer3)+1, ENC_NA); |
2953 | 8 | } else { |
2954 | 8 | uint8_t octet; |
2955 | 8 | bool more_frag = true; |
2956 | | |
2957 | | /* Get the first octet of parameter Segmentation, Ch 3.17 in Q.713 |
2958 | | * Bit 8 of octet 1 is used for First segment indication |
2959 | | * Bit 7 of octet 1 is used to keep in the message in sequence |
2960 | | * delivery option required by the SCCP user |
2961 | | * Bits 6 and 5 in octet 1 are spare bits. |
2962 | | * Bits 4-1 of octet 1 are used to indicate the number of |
2963 | | * remaining segments. |
2964 | | * The values 0000 to 1111 are possible; the value 0000 indicates |
2965 | | * the last segment. |
2966 | | */ |
2967 | 8 | octet = tvb_get_uint8(tvb, optional_pointer1+2); |
2968 | 8 | source_local_ref = tvb_get_letoh24(tvb, optional_pointer1+3); |
2969 | | |
2970 | 8 | if ((octet & 0x0f) == 0) |
2971 | 6 | more_frag = false; |
2972 | | |
2973 | 8 | new_tvb = sccp_reassemble_fragments(tvb, pinfo, tree, variable_pointer3, source_local_ref, more_frag, pointer_length); |
2974 | | |
2975 | 8 | if (new_tvb) |
2976 | 6 | dissect_sccp_data_param(new_tvb, pinfo, tree, sccp_info->assoc); |
2977 | 8 | } |
2978 | 62 | } else { |
2979 | 62 | dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree, |
2980 | 62 | (pointer_length == POINTER_LENGTH) ? PARAMETER_DATA : PARAMETER_LONG_DATA, |
2981 | 62 | variable_pointer3, sccp_info); |
2982 | 62 | } |
2983 | | |
2984 | 70 | *optional_pointer_p = optional_pointer; |
2985 | 70 | *orig_opt_ptr_p = orig_opt_ptr; |
2986 | 70 | return offset; |
2987 | 70 | } |
2988 | | |
2989 | | static int |
2990 | | dissect_sccp_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *sccp_tree, |
2991 | | proto_tree *tree) |
2992 | 281 | { |
2993 | 281 | uint16_t variable_pointer1 = 0, variable_pointer2 = 0, variable_pointer3 = 0; |
2994 | 281 | uint16_t optional_pointer = 0, orig_opt_ptr = 0; |
2995 | 281 | int offset = 0; |
2996 | 281 | tvbuff_t *new_tvb = NULL; |
2997 | 281 | uint32_t source_local_ref = 0; |
2998 | 281 | uint8_t more; |
2999 | 281 | unsigned msg_offset = tvb_offset_from_real_beginning(tvb); |
3000 | 281 | sccp_decode_context_t sccp_info = {0, INVALID_LR, INVALID_LR, NULL, NULL}; |
3001 | | |
3002 | | /* Extract the message type; all other processing is based on this */ |
3003 | 281 | sccp_info.message_type = tvb_get_uint8(tvb, SCCP_MSG_TYPE_OFFSET); |
3004 | 281 | offset = SCCP_MSG_TYPE_LENGTH; |
3005 | | |
3006 | | /* Do not change col_add_fstr() to col_append_fstr() here: we _want_ |
3007 | | * this call to overwrite whatever's currently in the INFO column (e.g., |
3008 | | * "DATA" from the SCTP dissector). |
3009 | | * |
3010 | | * If there's something there that should not be overwritten, whoever |
3011 | | * put that info there should call col_set_fence() to protect it. |
3012 | | */ |
3013 | 281 | col_add_fstr(pinfo->cinfo, COL_INFO, "%s ", |
3014 | 281 | val_to_str(sccp_info.message_type, sccp_message_type_acro_values, "Unknown: %d")); |
3015 | | |
3016 | 281 | if (sccp_tree) { |
3017 | | /* add the message type to the protocol tree */ |
3018 | 281 | proto_tree_add_uint(sccp_tree, hf_sccp_message_type, tvb, |
3019 | 281 | SCCP_MSG_TYPE_OFFSET, SCCP_MSG_TYPE_LENGTH, sccp_info.message_type); |
3020 | | |
3021 | 281 | }; |
3022 | | |
3023 | 281 | no_assoc.calling_dpc = 0; |
3024 | 281 | no_assoc.called_dpc = 0; |
3025 | 281 | no_assoc.calling_ssn = INVALID_SSN; |
3026 | 281 | no_assoc.called_ssn = INVALID_SSN; |
3027 | 281 | no_assoc.has_fw_key = false; |
3028 | 281 | no_assoc.has_bw_key = false; |
3029 | 281 | no_assoc.payload = SCCP_PLOAD_NONE; |
3030 | 281 | no_assoc.called_party = NULL; |
3031 | 281 | no_assoc.calling_party = NULL; |
3032 | 281 | no_assoc.extra_info = NULL; |
3033 | | |
3034 | 281 | switch (sccp_info.message_type) { |
3035 | 100 | case SCCP_MSG_TYPE_CR: |
3036 | | /* TTC and NTT (Japan) say that the connection-oriented messages are |
3037 | | * deleted (not standardized), but they appear to be used anyway, so |
3038 | | * we'll dissect it... |
3039 | | */ |
3040 | 100 | offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree, |
3041 | 100 | PARAMETER_SOURCE_LOCAL_REFERENCE, |
3042 | 100 | offset, SOURCE_LOCAL_REFERENCE_LENGTH, &sccp_info); |
3043 | 100 | offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree, |
3044 | 100 | PARAMETER_CLASS, offset, |
3045 | 100 | PROTOCOL_CLASS_LENGTH, &sccp_info); |
3046 | 100 | sccp_info.assoc = get_sccp_assoc(pinfo, msg_offset, &sccp_info); |
3047 | 100 | build_assoc_tree(tvb, pinfo, sccp_tree, &sccp_info, msg_offset); |
3048 | | |
3049 | 100 | VARIABLE_POINTER(variable_pointer1, hf_sccp_variable_pointer1, POINTER_LENGTH); |
3050 | 100 | OPTIONAL_POINTER(POINTER_LENGTH); |
3051 | | |
3052 | 100 | dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree, |
3053 | 100 | PARAMETER_CALLED_PARTY_ADDRESS, |
3054 | 100 | variable_pointer1, &sccp_info); |
3055 | 100 | break; |
3056 | | |
3057 | 54 | case SCCP_MSG_TYPE_CC: |
3058 | | /* TODO: connection has been established; theoretically we could keep |
3059 | | * keep track of the SLR/DLR with the called/calling from the CR and |
3060 | | * track the connection (e.g., on subsequent messages regarding this |
3061 | | * SLR we could set the global vars "call*_ssn" so data could get |
3062 | | * sub-dissected). |
3063 | | */ |
3064 | 54 | offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree, |
3065 | 54 | PARAMETER_DESTINATION_LOCAL_REFERENCE, |
3066 | 54 | offset, |
3067 | 54 | DESTINATION_LOCAL_REFERENCE_LENGTH, &sccp_info); |
3068 | 54 | offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree, |
3069 | 54 | PARAMETER_SOURCE_LOCAL_REFERENCE, |
3070 | 54 | offset, SOURCE_LOCAL_REFERENCE_LENGTH, &sccp_info); |
3071 | | |
3072 | 54 | sccp_info.assoc = get_sccp_assoc(pinfo, msg_offset, &sccp_info); |
3073 | 54 | build_assoc_tree(tvb, pinfo, sccp_tree, &sccp_info, msg_offset); |
3074 | | |
3075 | 54 | offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree, |
3076 | 54 | PARAMETER_CLASS, offset, |
3077 | 54 | PROTOCOL_CLASS_LENGTH, &sccp_info); |
3078 | 54 | OPTIONAL_POINTER(POINTER_LENGTH); |
3079 | 54 | break; |
3080 | | |
3081 | 8 | case SCCP_MSG_TYPE_CREF: |
3082 | 8 | offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree, |
3083 | 8 | PARAMETER_DESTINATION_LOCAL_REFERENCE, |
3084 | 8 | offset, |
3085 | 8 | DESTINATION_LOCAL_REFERENCE_LENGTH, &sccp_info); |
3086 | | |
3087 | 8 | sccp_info.assoc = get_sccp_assoc(pinfo, msg_offset, &sccp_info); |
3088 | 8 | build_assoc_tree(tvb, pinfo, sccp_tree, &sccp_info, msg_offset); |
3089 | | |
3090 | 8 | offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree, |
3091 | 8 | PARAMETER_REFUSAL_CAUSE, offset, |
3092 | 8 | REFUSAL_CAUSE_LENGTH, &sccp_info); |
3093 | 8 | OPTIONAL_POINTER(POINTER_LENGTH); |
3094 | 8 | break; |
3095 | | |
3096 | 8 | case SCCP_MSG_TYPE_RLSD: |
3097 | 8 | offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree, |
3098 | 8 | PARAMETER_DESTINATION_LOCAL_REFERENCE, |
3099 | 8 | offset, |
3100 | 8 | DESTINATION_LOCAL_REFERENCE_LENGTH, &sccp_info); |
3101 | 8 | offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree, |
3102 | 8 | PARAMETER_SOURCE_LOCAL_REFERENCE, |
3103 | 8 | offset, SOURCE_LOCAL_REFERENCE_LENGTH, &sccp_info); |
3104 | | |
3105 | 8 | sccp_info.assoc = get_sccp_assoc(pinfo, msg_offset, &sccp_info); |
3106 | 8 | build_assoc_tree(tvb, pinfo, sccp_tree, &sccp_info, msg_offset); |
3107 | | |
3108 | 8 | offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree, |
3109 | 8 | PARAMETER_RELEASE_CAUSE, offset, |
3110 | 8 | RELEASE_CAUSE_LENGTH, &sccp_info); |
3111 | | |
3112 | 8 | OPTIONAL_POINTER(POINTER_LENGTH); |
3113 | 8 | break; |
3114 | | |
3115 | 1 | case SCCP_MSG_TYPE_RLC: |
3116 | 1 | offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree, |
3117 | 1 | PARAMETER_DESTINATION_LOCAL_REFERENCE, |
3118 | 1 | offset, |
3119 | 1 | DESTINATION_LOCAL_REFERENCE_LENGTH, &sccp_info); |
3120 | 1 | offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree, |
3121 | 1 | PARAMETER_SOURCE_LOCAL_REFERENCE, |
3122 | 1 | offset, SOURCE_LOCAL_REFERENCE_LENGTH, &sccp_info); |
3123 | | |
3124 | 1 | sccp_info.assoc = get_sccp_assoc(pinfo, msg_offset, &sccp_info); |
3125 | 1 | build_assoc_tree(tvb, pinfo, sccp_tree, &sccp_info, msg_offset); |
3126 | 1 | break; |
3127 | | |
3128 | 5 | case SCCP_MSG_TYPE_DT1: |
3129 | 5 | { |
3130 | 5 | int remaining_length; |
3131 | 5 | source_local_ref = tvb_get_letoh24(tvb, offset); |
3132 | 5 | offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree, |
3133 | 5 | PARAMETER_DESTINATION_LOCAL_REFERENCE, |
3134 | 5 | offset, |
3135 | 5 | DESTINATION_LOCAL_REFERENCE_LENGTH, &sccp_info); |
3136 | | |
3137 | 5 | sccp_info.assoc = get_sccp_assoc(pinfo, msg_offset, &sccp_info); |
3138 | 5 | build_assoc_tree(tvb, pinfo, sccp_tree, &sccp_info, msg_offset); |
3139 | | |
3140 | 5 | more = tvb_get_uint8(tvb, offset) & SEGMENTING_REASSEMBLING_MASK; |
3141 | | |
3142 | 5 | offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree, |
3143 | 5 | PARAMETER_SEGMENTING_REASSEMBLING, |
3144 | 5 | offset, SEGMENTING_REASSEMBLING_LENGTH, &sccp_info); |
3145 | 5 | VARIABLE_POINTER(variable_pointer1, hf_sccp_variable_pointer1, POINTER_LENGTH); |
3146 | | |
3147 | | /* Reassemble */ |
3148 | 5 | if (!sccp_reassemble) { |
3149 | 0 | proto_tree_add_item(sccp_tree, hf_sccp_segmented_data, tvb, variable_pointer1, |
3150 | 0 | tvb_get_uint8(tvb, variable_pointer1)+1, ENC_NA); |
3151 | 0 | dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree, |
3152 | 0 | PARAMETER_DATA, variable_pointer1, &sccp_info); |
3153 | |
|
3154 | 5 | } else { |
3155 | 5 | remaining_length = tvb_reported_length_remaining(tvb, variable_pointer1 + 1); |
3156 | 5 | if(dt1_ignore_length && remaining_length > 255) { |
3157 | 0 | new_tvb = tvb_new_subset_length(tvb, variable_pointer1 + 1, remaining_length); |
3158 | 5 | } else { |
3159 | 5 | new_tvb = sccp_reassemble_fragments(tvb, pinfo, tree, variable_pointer1, source_local_ref, more, POINTER_LENGTH); |
3160 | 5 | } |
3161 | | |
3162 | 5 | if (new_tvb) |
3163 | 3 | dissect_sccp_data_param(new_tvb, pinfo, tree, sccp_info.assoc); |
3164 | 5 | } |
3165 | | |
3166 | | /* End reassemble */ |
3167 | 5 | break; |
3168 | 0 | } |
3169 | | |
3170 | 1 | case SCCP_MSG_TYPE_DT2: |
3171 | 1 | offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree, |
3172 | 1 | PARAMETER_DESTINATION_LOCAL_REFERENCE, |
3173 | 1 | offset, |
3174 | 1 | DESTINATION_LOCAL_REFERENCE_LENGTH, &sccp_info); |
3175 | | |
3176 | 1 | sccp_info.assoc = get_sccp_assoc(pinfo, msg_offset, &sccp_info); |
3177 | 1 | build_assoc_tree(tvb, pinfo, sccp_tree, &sccp_info, msg_offset); |
3178 | | |
3179 | 1 | offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree, |
3180 | 1 | PARAMETER_SEQUENCING_SEGMENTING, offset, |
3181 | 1 | SEQUENCING_SEGMENTING_LENGTH, &sccp_info); |
3182 | 1 | VARIABLE_POINTER(variable_pointer1, hf_sccp_variable_pointer1, POINTER_LENGTH); |
3183 | | |
3184 | 1 | dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree, |
3185 | 1 | PARAMETER_DATA, variable_pointer1, &sccp_info); |
3186 | | |
3187 | 1 | break; |
3188 | | |
3189 | 1 | case SCCP_MSG_TYPE_AK: |
3190 | 1 | offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree, |
3191 | 1 | PARAMETER_DESTINATION_LOCAL_REFERENCE, |
3192 | 1 | offset, |
3193 | 1 | DESTINATION_LOCAL_REFERENCE_LENGTH, &sccp_info); |
3194 | | |
3195 | 1 | sccp_info.assoc = get_sccp_assoc(pinfo, msg_offset, &sccp_info); |
3196 | 1 | build_assoc_tree(tvb, pinfo, sccp_tree, &sccp_info, msg_offset); |
3197 | | |
3198 | 1 | offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree, |
3199 | 1 | PARAMETER_RECEIVE_SEQUENCE_NUMBER, |
3200 | 1 | offset, RECEIVE_SEQUENCE_NUMBER_LENGTH, &sccp_info); |
3201 | 1 | offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree, |
3202 | 1 | PARAMETER_CREDIT, offset, CREDIT_LENGTH, &sccp_info); |
3203 | 1 | break; |
3204 | | |
3205 | 6 | case SCCP_MSG_TYPE_UDT: |
3206 | 6 | sccp_info.sccp_msg = new_ud_msg(pinfo, sccp_info.message_type); |
3207 | | |
3208 | 6 | offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree, |
3209 | 6 | PARAMETER_CLASS, offset, |
3210 | 6 | PROTOCOL_CLASS_LENGTH, &sccp_info); |
3211 | 6 | VARIABLE_POINTER(variable_pointer1, hf_sccp_variable_pointer1, POINTER_LENGTH); |
3212 | 6 | VARIABLE_POINTER(variable_pointer2, hf_sccp_variable_pointer2, POINTER_LENGTH); |
3213 | 6 | VARIABLE_POINTER(variable_pointer3, hf_sccp_variable_pointer3, POINTER_LENGTH); |
3214 | | |
3215 | 6 | sccp_info.assoc = get_sccp_assoc(pinfo, msg_offset, &sccp_info); |
3216 | 6 | build_assoc_tree(tvb, pinfo, sccp_tree, &sccp_info, msg_offset); |
3217 | | |
3218 | 6 | dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree, |
3219 | 6 | PARAMETER_CALLED_PARTY_ADDRESS, |
3220 | 6 | variable_pointer1, &sccp_info); |
3221 | 6 | dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree, |
3222 | 6 | PARAMETER_CALLING_PARTY_ADDRESS, |
3223 | 6 | variable_pointer2, &sccp_info); |
3224 | | |
3225 | 6 | dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree, PARAMETER_DATA, |
3226 | 6 | variable_pointer3, &sccp_info); |
3227 | 6 | break; |
3228 | | |
3229 | 6 | case SCCP_MSG_TYPE_UDTS: |
3230 | 6 | { |
3231 | 6 | bool save_in_error_pkt = pinfo->flags.in_error_pkt; |
3232 | 6 | pinfo->flags.in_error_pkt = true; |
3233 | | |
3234 | 6 | sccp_info.sccp_msg = new_ud_msg(pinfo, sccp_info.message_type); |
3235 | | |
3236 | 6 | offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree, |
3237 | 6 | PARAMETER_RETURN_CAUSE, offset, |
3238 | 6 | RETURN_CAUSE_LENGTH, &sccp_info); |
3239 | | |
3240 | 6 | VARIABLE_POINTER(variable_pointer1, hf_sccp_variable_pointer1, POINTER_LENGTH); |
3241 | 6 | VARIABLE_POINTER(variable_pointer2, hf_sccp_variable_pointer2, POINTER_LENGTH); |
3242 | 6 | VARIABLE_POINTER(variable_pointer3, hf_sccp_variable_pointer3, POINTER_LENGTH); |
3243 | | |
3244 | 6 | sccp_info.assoc = get_sccp_assoc(pinfo, msg_offset, &sccp_info); |
3245 | 6 | build_assoc_tree(tvb, pinfo, sccp_tree, &sccp_info, msg_offset); |
3246 | | |
3247 | 6 | dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree, |
3248 | 6 | PARAMETER_CALLED_PARTY_ADDRESS, |
3249 | 6 | variable_pointer1, &sccp_info); |
3250 | | |
3251 | 6 | dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree, |
3252 | 6 | PARAMETER_CALLING_PARTY_ADDRESS, |
3253 | 6 | variable_pointer2, &sccp_info); |
3254 | | |
3255 | 6 | dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree, PARAMETER_DATA, |
3256 | 6 | variable_pointer3, &sccp_info); |
3257 | 6 | pinfo->flags.in_error_pkt = save_in_error_pkt; |
3258 | 6 | break; |
3259 | 0 | } |
3260 | | |
3261 | 0 | case SCCP_MSG_TYPE_ED: |
3262 | 0 | offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree, |
3263 | 0 | PARAMETER_DESTINATION_LOCAL_REFERENCE, |
3264 | 0 | offset, |
3265 | 0 | DESTINATION_LOCAL_REFERENCE_LENGTH, &sccp_info); |
3266 | |
|
3267 | 0 | sccp_info.assoc = get_sccp_assoc(pinfo, msg_offset, &sccp_info); |
3268 | 0 | build_assoc_tree(tvb, pinfo, sccp_tree, &sccp_info, msg_offset); |
3269 | |
|
3270 | 0 | VARIABLE_POINTER(variable_pointer1, hf_sccp_variable_pointer1, POINTER_LENGTH); |
3271 | |
|
3272 | 0 | dissect_sccp_variable_parameter(tvb, pinfo, sccp_tree, tree, PARAMETER_DATA, |
3273 | 0 | variable_pointer1, &sccp_info); |
3274 | 0 | break; |
3275 | | |
3276 | 1 | case SCCP_MSG_TYPE_EA: |
3277 | 1 | offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree, |
3278 | 1 | PARAMETER_DESTINATION_LOCAL_REFERENCE, |
3279 | 1 | offset, |
3280 | 1 | DESTINATION_LOCAL_REFERENCE_LENGTH, &sccp_info); |
3281 | 1 | sccp_info.assoc = get_sccp_assoc(pinfo, msg_offset, &sccp_info); |
3282 | 1 | build_assoc_tree(tvb, pinfo, sccp_tree, &sccp_info, msg_offset); |
3283 | 1 | break; |
3284 | | |
3285 | 0 | case SCCP_MSG_TYPE_RSR: |
3286 | 0 | offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree, |
3287 | 0 | PARAMETER_DESTINATION_LOCAL_REFERENCE, |
3288 | 0 | offset, |
3289 | 0 | DESTINATION_LOCAL_REFERENCE_LENGTH, &sccp_info); |
3290 | 0 | offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree, |
3291 | 0 | PARAMETER_SOURCE_LOCAL_REFERENCE, |
3292 | 0 | offset, SOURCE_LOCAL_REFERENCE_LENGTH, &sccp_info); |
3293 | 0 | offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree, |
3294 | 0 | PARAMETER_RESET_CAUSE, offset, |
3295 | 0 | RESET_CAUSE_LENGTH, &sccp_info); |
3296 | 0 | sccp_info.assoc = get_sccp_assoc(pinfo, msg_offset, &sccp_info); |
3297 | 0 | build_assoc_tree(tvb, pinfo, sccp_tree, &sccp_info, msg_offset); |
3298 | 0 | break; |
3299 | | |
3300 | 1 | case SCCP_MSG_TYPE_RSC: |
3301 | 1 | offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree, |
3302 | 1 | PARAMETER_DESTINATION_LOCAL_REFERENCE, |
3303 | 1 | offset, |
3304 | 1 | DESTINATION_LOCAL_REFERENCE_LENGTH, &sccp_info); |
3305 | 1 | offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree, |
3306 | 1 | PARAMETER_SOURCE_LOCAL_REFERENCE, |
3307 | 1 | offset, SOURCE_LOCAL_REFERENCE_LENGTH, &sccp_info); |
3308 | 1 | sccp_info.assoc = get_sccp_assoc(pinfo, msg_offset, &sccp_info); |
3309 | 1 | build_assoc_tree(tvb, pinfo, sccp_tree, &sccp_info, msg_offset); |
3310 | 1 | break; |
3311 | | |
3312 | 2 | case SCCP_MSG_TYPE_ERR: |
3313 | 2 | offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree, |
3314 | 2 | PARAMETER_DESTINATION_LOCAL_REFERENCE, |
3315 | 2 | offset, |
3316 | 2 | DESTINATION_LOCAL_REFERENCE_LENGTH, &sccp_info); |
3317 | 2 | offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree, |
3318 | 2 | PARAMETER_ERROR_CAUSE, offset, |
3319 | 2 | ERROR_CAUSE_LENGTH, &sccp_info); |
3320 | 2 | sccp_info.assoc = get_sccp_assoc(pinfo, msg_offset, &sccp_info); |
3321 | 2 | build_assoc_tree(tvb, pinfo, sccp_tree, &sccp_info, msg_offset); |
3322 | 2 | break; |
3323 | | |
3324 | 7 | case SCCP_MSG_TYPE_IT: |
3325 | 7 | offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree, |
3326 | 7 | PARAMETER_DESTINATION_LOCAL_REFERENCE, |
3327 | 7 | offset, |
3328 | 7 | DESTINATION_LOCAL_REFERENCE_LENGTH, &sccp_info); |
3329 | 7 | offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree, |
3330 | 7 | PARAMETER_SOURCE_LOCAL_REFERENCE, |
3331 | 7 | offset, SOURCE_LOCAL_REFERENCE_LENGTH, &sccp_info); |
3332 | 7 | sccp_info.assoc = get_sccp_assoc(pinfo, msg_offset, &sccp_info); |
3333 | 7 | build_assoc_tree(tvb, pinfo, sccp_tree, &sccp_info, msg_offset); |
3334 | 7 | offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree, |
3335 | 7 | PARAMETER_CLASS, offset, |
3336 | 7 | PROTOCOL_CLASS_LENGTH, &sccp_info); |
3337 | 7 | offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree, |
3338 | 7 | PARAMETER_SEQUENCING_SEGMENTING, |
3339 | 7 | offset, SEQUENCING_SEGMENTING_LENGTH, &sccp_info); |
3340 | 7 | offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree, |
3341 | 7 | PARAMETER_CREDIT, offset, CREDIT_LENGTH, &sccp_info); |
3342 | 7 | break; |
3343 | | |
3344 | 41 | case SCCP_MSG_TYPE_XUDT: |
3345 | 41 | sccp_info.sccp_msg = new_ud_msg(pinfo, sccp_info.message_type); |
3346 | 41 | offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree, |
3347 | 41 | PARAMETER_CLASS, offset, |
3348 | 41 | PROTOCOL_CLASS_LENGTH, &sccp_info); |
3349 | 41 | offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree, |
3350 | 41 | PARAMETER_HOP_COUNTER, offset, |
3351 | 41 | HOP_COUNTER_LENGTH, &sccp_info); |
3352 | | |
3353 | 41 | offset = dissect_xudt_common(tvb, pinfo, sccp_tree, tree, offset, &sccp_info, |
3354 | 41 | &optional_pointer, &orig_opt_ptr, POINTER_LENGTH); |
3355 | 41 | break; |
3356 | | |
3357 | 24 | case SCCP_MSG_TYPE_XUDTS: |
3358 | 24 | { |
3359 | 24 | bool save_in_error_pkt = pinfo->flags.in_error_pkt; |
3360 | 24 | pinfo->flags.in_error_pkt = true; |
3361 | | |
3362 | 24 | sccp_info.sccp_msg = new_ud_msg(pinfo, sccp_info.message_type); |
3363 | 24 | offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree, |
3364 | 24 | PARAMETER_RETURN_CAUSE, offset, |
3365 | 24 | RETURN_CAUSE_LENGTH, &sccp_info); |
3366 | 24 | offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree, |
3367 | 24 | PARAMETER_HOP_COUNTER, offset, |
3368 | 24 | HOP_COUNTER_LENGTH, &sccp_info); |
3369 | | |
3370 | 24 | offset = dissect_xudt_common(tvb, pinfo, sccp_tree, tree, offset, &sccp_info, |
3371 | 24 | &optional_pointer, &orig_opt_ptr, POINTER_LENGTH); |
3372 | | |
3373 | 24 | pinfo->flags.in_error_pkt = save_in_error_pkt; |
3374 | 24 | break; |
3375 | 0 | } |
3376 | 1 | case SCCP_MSG_TYPE_LUDT: |
3377 | 1 | sccp_info.sccp_msg = new_ud_msg(pinfo, sccp_info.message_type); |
3378 | | |
3379 | 1 | offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree, |
3380 | 1 | PARAMETER_CLASS, offset, |
3381 | 1 | PROTOCOL_CLASS_LENGTH, &sccp_info); |
3382 | 1 | offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree, |
3383 | 1 | PARAMETER_HOP_COUNTER, offset, |
3384 | 1 | HOP_COUNTER_LENGTH, &sccp_info); |
3385 | | |
3386 | 1 | offset = dissect_xudt_common(tvb, pinfo, sccp_tree, tree, offset, &sccp_info, |
3387 | 1 | &optional_pointer, &orig_opt_ptr, POINTER_LENGTH_LONG); |
3388 | 1 | break; |
3389 | | |
3390 | 4 | case SCCP_MSG_TYPE_LUDTS: |
3391 | 4 | { |
3392 | 4 | bool save_in_error_pkt = pinfo->flags.in_error_pkt; |
3393 | 4 | pinfo->flags.in_error_pkt = true; |
3394 | | |
3395 | 4 | sccp_info.sccp_msg = new_ud_msg(pinfo, sccp_info.message_type); |
3396 | 4 | offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree, |
3397 | 4 | PARAMETER_RETURN_CAUSE, offset, |
3398 | 4 | RETURN_CAUSE_LENGTH, &sccp_info); |
3399 | 4 | offset += dissect_sccp_parameter(tvb, pinfo, sccp_tree, tree, |
3400 | 4 | PARAMETER_HOP_COUNTER, offset, |
3401 | 4 | HOP_COUNTER_LENGTH, &sccp_info); |
3402 | | |
3403 | 4 | offset = dissect_xudt_common(tvb, pinfo, sccp_tree, tree, offset, &sccp_info, |
3404 | 4 | &optional_pointer, &orig_opt_ptr, POINTER_LENGTH_LONG); |
3405 | | |
3406 | 4 | pinfo->flags.in_error_pkt = save_in_error_pkt; |
3407 | 4 | break; |
3408 | 0 | } |
3409 | 10 | default: |
3410 | 10 | dissect_sccp_unknown_message(tvb, sccp_tree); |
3411 | 281 | } |
3412 | | |
3413 | 236 | if (orig_opt_ptr) |
3414 | 206 | dissect_sccp_optional_parameters(tvb, pinfo, sccp_tree, tree, |
3415 | 206 | optional_pointer, &sccp_info); |
3416 | | |
3417 | 236 | return offset; |
3418 | 281 | } |
3419 | | |
3420 | | static int |
3421 | | dissect_sccp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) |
3422 | 281 | { |
3423 | 281 | proto_item *sccp_item = NULL; |
3424 | 281 | proto_tree *sccp_tree = NULL; |
3425 | 281 | const mtp3_addr_pc_t *mtp3_addr_p; |
3426 | | |
3427 | 281 | if ((pinfo->src.type == ss7pc_address_type) && |
3428 | 281 | ((mtp3_addr_p = (const mtp3_addr_pc_t *)pinfo->src.data)->type <= CHINESE_ITU_STANDARD)) { |
3429 | | /* |
3430 | | * Allow a protocol beneath to specify how the SCCP layer should be |
3431 | | * dissected. |
3432 | | * |
3433 | | * It is possible to have multiple sets of SCCP traffic some of which is |
3434 | | * ITU and some of which is ANSI. |
3435 | | * An example is A-interface traffic having ANSI MTP3/ANSI SCCP/3GPP2 IOS |
3436 | | * and at the same time ITU MTP3/ITU SCCP/ANSI TCAP/ANSI MAP. |
3437 | | */ |
3438 | 223 | decode_mtp3_standard = mtp3_addr_p->type; |
3439 | 223 | } else { |
3440 | 58 | decode_mtp3_standard = (Standard_Type)mtp3_standard; |
3441 | 58 | } |
3442 | | |
3443 | | /* Make entry in the Protocol column on summary display */ |
3444 | 281 | switch (decode_mtp3_standard) { |
3445 | 281 | case ITU_STANDARD: |
3446 | 281 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "SCCP (Int. ITU)"); |
3447 | 281 | break; |
3448 | 0 | case ANSI_STANDARD: |
3449 | 0 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "SCCP (ANSI)"); |
3450 | 0 | break; |
3451 | 0 | case CHINESE_ITU_STANDARD: |
3452 | 0 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "SCCP (Chin. ITU)"); |
3453 | 0 | break; |
3454 | 0 | case JAPAN_STANDARD: |
3455 | 0 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "SCCP (Japan)"); |
3456 | 0 | break; |
3457 | 281 | }; |
3458 | | |
3459 | | /* In the interest of speed, if "tree" is NULL, don't do any work not |
3460 | | necessary to generate protocol tree items. */ |
3461 | 281 | if (tree) { |
3462 | | /* create the sccp protocol tree */ |
3463 | 281 | sccp_item = proto_tree_add_item(tree, proto_sccp, tvb, 0, -1, ENC_NA); |
3464 | 281 | sccp_tree = proto_item_add_subtree(sccp_item, ett_sccp); |
3465 | 281 | } |
3466 | | |
3467 | | /* Set whether message is UPLINK, DOWNLINK, or of UNKNOWN direction */ |
3468 | | |
3469 | 281 | if (pinfo->src.type == ss7pc_address_type) { |
3470 | | /* |
3471 | | * XXX - we assume that the "data" pointers of the source and destination |
3472 | | * addresses are set to point to "mtp3_addr_pc_t" structures, so that |
3473 | | * we can safely cast them. |
3474 | | */ |
3475 | 223 | mtp3_addr_p = (const mtp3_addr_pc_t *)pinfo->src.data; |
3476 | | |
3477 | 223 | if (sccp_source_pc_global == mtp3_addr_p->pc) { |
3478 | 4 | pinfo->p2p_dir = P2P_DIR_SENT; |
3479 | 219 | } else { |
3480 | | /* assuming if src was SS7 PC then dst will be too */ |
3481 | 219 | mtp3_addr_p = (const mtp3_addr_pc_t *)pinfo->dst.data; |
3482 | | |
3483 | 219 | if (sccp_source_pc_global == mtp3_addr_p->pc) |
3484 | 3 | { |
3485 | 3 | pinfo->p2p_dir = P2P_DIR_RECV; |
3486 | 216 | } else { |
3487 | 216 | pinfo->p2p_dir = P2P_DIR_UNKNOWN; |
3488 | 216 | } |
3489 | 219 | } |
3490 | 223 | } |
3491 | | |
3492 | | /* dissect the message */ |
3493 | 281 | dissect_sccp_message(tvb, pinfo, sccp_tree, tree); |
3494 | 281 | return tvb_captured_length(tvb); |
3495 | 281 | } |
3496 | | |
3497 | | /*** SccpUsers Table **/ |
3498 | | |
3499 | | static struct _sccp_ul { |
3500 | | unsigned id; |
3501 | | bool uses_tcap; |
3502 | | dissector_handle_t *handlep; |
3503 | | } user_list[] = { |
3504 | | |
3505 | | {SCCP_USER_DATA, false, &data_handle}, |
3506 | | {SCCP_USER_TCAP, false, &tcap_handle}, |
3507 | | {SCCP_USER_RANAP, false, &ranap_handle}, |
3508 | | {SCCP_USER_BSSAP, false, &bssap_handle}, |
3509 | | {SCCP_USER_GSMMAP, true, &gsmmap_handle}, |
3510 | | {SCCP_USER_CAMEL, true, &camel_handle}, |
3511 | | {SCCP_USER_INAP, true, &inap_handle}, |
3512 | | {SCCP_USER_BSAP, false, &bsap_handle}, |
3513 | | {SCCP_USER_BSSAP_LE, false, &bssap_le_handle}, |
3514 | | {SCCP_USER_BSSAP_PLUS, false, &bssap_plus_handle}, |
3515 | | {0, false, NULL} |
3516 | | }; |
3517 | | |
3518 | | static bool |
3519 | | sccp_users_update_cb(void *r, char **err) |
3520 | 0 | { |
3521 | 0 | sccp_user_t *u = (sccp_user_t *)r; |
3522 | 0 | struct _sccp_ul *c; |
3523 | 0 | range_t *empty; |
3524 | |
|
3525 | 0 | empty = range_empty(NULL); |
3526 | 0 | if (ranges_are_equal(u->called_pc, empty)) { |
3527 | 0 | *err = g_strdup("Must specify a PC"); |
3528 | 0 | wmem_free(NULL, empty); |
3529 | 0 | return false; |
3530 | 0 | } |
3531 | | |
3532 | 0 | if (ranges_are_equal(u->called_ssn, empty)) { |
3533 | 0 | *err = g_strdup("Must specify an SSN"); |
3534 | 0 | wmem_free(NULL, empty); |
3535 | 0 | return false; |
3536 | 0 | } |
3537 | | |
3538 | 0 | wmem_free(NULL, empty); |
3539 | 0 | for (c=user_list; c->handlep; c++) { |
3540 | 0 | if (c->id == u->user) { |
3541 | 0 | u->uses_tcap = c->uses_tcap; |
3542 | 0 | u->handlep = c->handlep; |
3543 | 0 | return true; |
3544 | 0 | } |
3545 | 0 | } |
3546 | | |
3547 | 0 | u->uses_tcap = false; |
3548 | 0 | u->handlep = &data_handle; |
3549 | 0 | return true; |
3550 | 0 | } |
3551 | | |
3552 | | static void * |
3553 | | sccp_users_copy_cb(void *n, const void *o, size_t siz _U_) |
3554 | 0 | { |
3555 | 0 | const sccp_user_t *u = (const sccp_user_t *)o; |
3556 | 0 | sccp_user_t *un = (sccp_user_t *)n; |
3557 | |
|
3558 | 0 | un->ni = u->ni; |
3559 | 0 | un->user = u->user; |
3560 | 0 | un->uses_tcap = u->uses_tcap; |
3561 | 0 | un->handlep = u->handlep; |
3562 | |
|
3563 | 0 | if (u->called_pc) |
3564 | 0 | un->called_pc = range_copy(NULL, u->called_pc); |
3565 | 0 | if (u->called_ssn) |
3566 | 0 | un->called_ssn = range_copy(NULL, u->called_ssn); |
3567 | |
|
3568 | 0 | return n; |
3569 | 0 | } |
3570 | | |
3571 | | static void |
3572 | | sccp_users_free_cb(void *r) |
3573 | 0 | { |
3574 | 0 | sccp_user_t *u = (sccp_user_t *)r; |
3575 | 0 | if (u->called_pc) wmem_free(NULL, u->called_pc); |
3576 | 0 | if (u->called_ssn) wmem_free(NULL, u->called_ssn); |
3577 | 0 | } |
3578 | | |
3579 | | |
3580 | | UAT_DEC_CB_DEF(sccp_users, ni, sccp_user_t) |
3581 | | UAT_RANGE_CB_DEF(sccp_users, called_pc, sccp_user_t) |
3582 | | UAT_RANGE_CB_DEF(sccp_users, called_ssn, sccp_user_t) |
3583 | | UAT_VS_DEF(sccp_users, user, sccp_user_t, unsigned, SCCP_USER_DATA, "Data") |
3584 | | |
3585 | | /** End SccpUsersTable **/ |
3586 | | |
3587 | | |
3588 | | static void |
3589 | | init_sccp(void) |
3590 | 14 | { |
3591 | 14 | next_assoc_id = 1; |
3592 | 14 | sccp_reassembly_id_next = 1; |
3593 | 14 | } |
3594 | | |
3595 | | /* Register the protocol with Wireshark */ |
3596 | | void |
3597 | | proto_register_sccp(void) |
3598 | 14 | { |
3599 | | /* Setup list of header fields */ |
3600 | 14 | static hf_register_info hf[] = { |
3601 | 14 | { &hf_sccp_message_type, |
3602 | 14 | { "Message Type", "sccp.message_type", |
3603 | 14 | FT_UINT8, BASE_HEX, VALS(sccp_message_type_values), 0x0, |
3604 | 14 | NULL, HFILL} |
3605 | 14 | }, |
3606 | 14 | { &hf_sccp_variable_pointer1, |
3607 | 14 | { "Pointer to first Mandatory Variable parameter", "sccp.variable_pointer1", |
3608 | 14 | FT_UINT16, BASE_DEC, NULL, 0x0, |
3609 | 14 | NULL, HFILL} |
3610 | 14 | }, |
3611 | 14 | { &hf_sccp_variable_pointer2, |
3612 | 14 | { "Pointer to second Mandatory Variable parameter", "sccp.variable_pointer2", |
3613 | 14 | FT_UINT16, BASE_DEC, NULL, 0x0, |
3614 | 14 | NULL, HFILL} |
3615 | 14 | }, |
3616 | 14 | { &hf_sccp_variable_pointer3, |
3617 | 14 | { "Pointer to third Mandatory Variable parameter", "sccp.variable_pointer3", |
3618 | 14 | FT_UINT16, BASE_DEC, NULL, 0x0, |
3619 | 14 | NULL, HFILL} |
3620 | 14 | }, |
3621 | 14 | { &hf_sccp_optional_pointer, |
3622 | 14 | { "Pointer to Optional parameter", "sccp.optional_pointer", |
3623 | 14 | FT_UINT16, BASE_DEC, NULL, 0x0, |
3624 | 14 | NULL, HFILL} |
3625 | 14 | }, |
3626 | 14 | { &hf_sccp_param_length, |
3627 | 14 | { "Variable parameter length", "sccp.parameter_length", |
3628 | 14 | FT_UINT16, BASE_DEC, NULL, 0x0, |
3629 | 14 | NULL, HFILL} |
3630 | 14 | }, |
3631 | 14 | { &hf_sccp_ssn, |
3632 | 14 | { "Called or Calling SubSystem Number", "sccp.ssn", |
3633 | 14 | FT_UINT8, BASE_DEC, VALS(sccp_ssn_values), 0x0, |
3634 | 14 | NULL, HFILL} |
3635 | 14 | }, |
3636 | 14 | { &hf_sccp_gt_digits, |
3637 | 14 | { "Called or Calling GT Digits", "sccp.digits", |
3638 | 14 | FT_STRING, BASE_NONE, NULL, 0x0, |
3639 | 14 | NULL, HFILL } |
3640 | 14 | }, |
3641 | 14 | { &hf_sccp_called_ansi_national_indicator, |
3642 | 14 | { "National Indicator", "sccp.called.ni", |
3643 | 14 | FT_UINT8, BASE_HEX, VALS(sccp_ansi_national_indicator_values), ANSI_NATIONAL_MASK, |
3644 | 14 | NULL, HFILL} |
3645 | 14 | }, |
3646 | 14 | { &hf_sccp_called_itu_natl_use_bit, |
3647 | 14 | { "Reserved for national use", "sccp.called.reserved", |
3648 | 14 | FT_UINT8, BASE_HEX, NULL, ITU_RESERVED_MASK, |
3649 | 14 | NULL, HFILL} |
3650 | 14 | }, |
3651 | 14 | { &hf_sccp_called_routing_indicator, |
3652 | 14 | { "Routing Indicator", "sccp.called.ri", |
3653 | 14 | FT_UINT8, BASE_HEX, VALS(sccp_routing_indicator_values), ROUTING_INDICATOR_MASK, |
3654 | 14 | NULL, HFILL} |
3655 | 14 | }, |
3656 | 14 | { &hf_sccp_called_itu_global_title_indicator, |
3657 | 14 | { "Global Title Indicator", "sccp.called.gti", |
3658 | 14 | FT_UINT8, BASE_HEX, VALS(sccp_itu_global_title_indicator_values), GTI_MASK, |
3659 | 14 | NULL, HFILL} |
3660 | 14 | }, |
3661 | 14 | { &hf_sccp_called_ansi_global_title_indicator, |
3662 | 14 | { "Global Title Indicator", "sccp.called.gti", |
3663 | 14 | FT_UINT8, BASE_HEX, VALS(sccp_ansi_global_title_indicator_values), GTI_MASK, |
3664 | 14 | NULL, HFILL} |
3665 | 14 | }, |
3666 | 14 | { &hf_sccp_called_itu_ssn_indicator, |
3667 | 14 | { "SubSystem Number Indicator", "sccp.called.ssni", |
3668 | 14 | FT_UINT8, BASE_HEX, VALS(sccp_ai_ssni_values), ITU_SSN_INDICATOR_MASK, |
3669 | 14 | NULL, HFILL} |
3670 | 14 | }, |
3671 | 14 | { &hf_sccp_called_itu_point_code_indicator, |
3672 | 14 | { "Point Code Indicator", "sccp.called.pci", |
3673 | 14 | FT_UINT8, BASE_HEX, VALS(sccp_ai_pci_values), ITU_PC_INDICATOR_MASK, |
3674 | 14 | NULL, HFILL} |
3675 | 14 | }, |
3676 | 14 | { &hf_sccp_called_ansi_ssn_indicator, |
3677 | 14 | { "SubSystem Number Indicator", "sccp.called.ssni", |
3678 | 14 | FT_UINT8, BASE_HEX, VALS(sccp_ai_ssni_values), ANSI_SSN_INDICATOR_MASK, |
3679 | 14 | NULL, HFILL} |
3680 | 14 | }, |
3681 | 14 | { &hf_sccp_called_ansi_point_code_indicator, |
3682 | 14 | { "Point Code Indicator", "sccp.called.pci", |
3683 | 14 | FT_UINT8, BASE_HEX, VALS(sccp_ai_pci_values), ANSI_PC_INDICATOR_MASK, |
3684 | 14 | NULL, HFILL} |
3685 | 14 | }, |
3686 | 14 | { &hf_sccp_called_ssn, |
3687 | 14 | { "SubSystem Number", "sccp.called.ssn", |
3688 | 14 | FT_UINT8, BASE_DEC, VALS(sccp_ssn_values), 0x0, |
3689 | 14 | NULL, HFILL} |
3690 | 14 | }, |
3691 | 14 | { &hf_sccp_called_itu_pc, |
3692 | 14 | { "PC", "sccp.called.pc", |
3693 | 14 | FT_UINT16, BASE_DEC, NULL, ITU_PC_MASK, |
3694 | 14 | NULL, HFILL} |
3695 | 14 | }, |
3696 | 14 | { &hf_sccp_called_ansi_pc, |
3697 | 14 | { "PC", "sccp.called.ansi_pc", |
3698 | 14 | FT_STRING, BASE_NONE, NULL, 0x0, |
3699 | 14 | NULL, HFILL} |
3700 | 14 | }, |
3701 | 14 | { &hf_sccp_called_chinese_pc, |
3702 | 14 | { "PC", "sccp.called.chinese_pc", |
3703 | 14 | FT_STRING, BASE_NONE, NULL, 0x0, |
3704 | 14 | NULL, HFILL} |
3705 | 14 | }, |
3706 | 14 | { &hf_sccp_called_japan_pc, |
3707 | 14 | { "PC", "sccp.called.pc", |
3708 | 14 | FT_UINT16, BASE_DEC, NULL, 0x0, |
3709 | 14 | NULL, HFILL} |
3710 | 14 | }, |
3711 | 14 | { &hf_sccp_called_pc_network, |
3712 | 14 | { "PC Network", "sccp.called.network", |
3713 | 14 | FT_UINT24, BASE_DEC, NULL, ANSI_NETWORK_MASK, |
3714 | 14 | NULL, HFILL } |
3715 | 14 | }, |
3716 | 14 | { &hf_sccp_called_pc_cluster, |
3717 | 14 | { "PC Cluster", "sccp.called.cluster", |
3718 | 14 | FT_UINT24, BASE_DEC, NULL, ANSI_CLUSTER_MASK, |
3719 | 14 | NULL, HFILL } |
3720 | 14 | }, |
3721 | 14 | { &hf_sccp_called_pc_member, |
3722 | 14 | { "PC Member", "sccp.called.member", |
3723 | 14 | FT_UINT24, BASE_DEC, NULL, ANSI_MEMBER_MASK, |
3724 | 14 | NULL, HFILL } |
3725 | 14 | }, |
3726 | 14 | { &hf_sccp_called_gt_nai, |
3727 | 14 | { "Nature of Address Indicator", "sccp.called.nai", |
3728 | 14 | FT_UINT8, BASE_HEX, VALS(sccp_nai_values), GT_NAI_MASK, |
3729 | 14 | NULL, HFILL } |
3730 | 14 | }, |
3731 | 14 | { &hf_sccp_called_gt_oe, |
3732 | 14 | { "Odd/Even Indicator", "sccp.called.oe", |
3733 | 14 | FT_UINT8, BASE_HEX, VALS(sccp_oe_values), GT_OE_MASK, |
3734 | 14 | NULL, HFILL } |
3735 | 14 | }, |
3736 | 14 | { &hf_sccp_called_gt_tt, |
3737 | 14 | { "Translation Type", "sccp.called.tt", |
3738 | 14 | FT_UINT8, BASE_HEX_DEC, NULL, 0x0, |
3739 | 14 | NULL, HFILL } |
3740 | 14 | }, |
3741 | 14 | { &hf_sccp_called_gt_np, |
3742 | 14 | { "Numbering Plan", "sccp.called.np", |
3743 | 14 | FT_UINT8, BASE_HEX, VALS(sccp_np_values), GT_NP_MASK, |
3744 | 14 | NULL, HFILL } |
3745 | 14 | }, |
3746 | 14 | { &hf_sccp_called_gt_es, |
3747 | 14 | { "Encoding Scheme", "sccp.called.es", |
3748 | 14 | FT_UINT8, BASE_HEX, VALS(sccp_es_values), GT_ES_MASK, |
3749 | 14 | NULL, HFILL } |
3750 | 14 | }, |
3751 | 14 | { &hf_sccp_called_gt_digits, |
3752 | 14 | { "Called Party Digits", "sccp.called.digits", |
3753 | 14 | FT_STRING, BASE_NONE, NULL, 0x0, |
3754 | 14 | NULL, HFILL } |
3755 | 14 | }, |
3756 | 14 | { &hf_sccp_called_gt_digits_length, |
3757 | 14 | { "Number of Called Party Digits", "sccp.called.digits.length", |
3758 | 14 | FT_UINT8, BASE_DEC, NULL, 0x0, |
3759 | 14 | NULL, HFILL } |
3760 | 14 | }, |
3761 | 14 | { &hf_sccp_calling_ansi_national_indicator, |
3762 | 14 | { "National Indicator", "sccp.calling.ni", |
3763 | 14 | FT_UINT8, BASE_HEX, VALS(sccp_ansi_national_indicator_values), ANSI_NATIONAL_MASK, |
3764 | 14 | NULL, HFILL} |
3765 | 14 | }, |
3766 | 14 | { &hf_sccp_calling_itu_natl_use_bit, |
3767 | 14 | { "Reserved for national use", "sccp.calling.reserved", |
3768 | 14 | FT_UINT8, BASE_HEX, NULL, ITU_RESERVED_MASK, |
3769 | 14 | NULL, HFILL} |
3770 | 14 | }, |
3771 | 14 | { &hf_sccp_calling_routing_indicator, |
3772 | 14 | { "Routing Indicator", "sccp.calling.ri", |
3773 | 14 | FT_UINT8, BASE_HEX, VALS(sccp_routing_indicator_values), ROUTING_INDICATOR_MASK, |
3774 | 14 | NULL, HFILL} |
3775 | 14 | }, |
3776 | 14 | { &hf_sccp_calling_itu_global_title_indicator, |
3777 | 14 | { "Global Title Indicator", "sccp.calling.gti", |
3778 | 14 | FT_UINT8, BASE_HEX, VALS(sccp_itu_global_title_indicator_values), GTI_MASK, |
3779 | 14 | NULL, HFILL} |
3780 | 14 | }, |
3781 | 14 | { &hf_sccp_calling_ansi_global_title_indicator, |
3782 | 14 | { "Global Title Indicator", "sccp.calling.gti", |
3783 | 14 | FT_UINT8, BASE_HEX, VALS(sccp_ansi_global_title_indicator_values), GTI_MASK, |
3784 | 14 | NULL, HFILL} |
3785 | 14 | }, |
3786 | 14 | { &hf_sccp_calling_itu_ssn_indicator, |
3787 | 14 | { "SubSystem Number Indicator", "sccp.calling.ssni", |
3788 | 14 | FT_UINT8, BASE_HEX, VALS(sccp_ai_ssni_values), ITU_SSN_INDICATOR_MASK, |
3789 | 14 | NULL, HFILL} |
3790 | 14 | }, |
3791 | 14 | { &hf_sccp_calling_itu_point_code_indicator, |
3792 | 14 | { "Point Code Indicator", "sccp.calling.pci", |
3793 | 14 | FT_UINT8, BASE_HEX, VALS(sccp_ai_pci_values), ITU_PC_INDICATOR_MASK, |
3794 | 14 | NULL, HFILL} |
3795 | 14 | }, |
3796 | 14 | { &hf_sccp_calling_ansi_ssn_indicator, |
3797 | 14 | { "SubSystem Number Indicator", "sccp.calling.ssni", |
3798 | 14 | FT_UINT8, BASE_HEX, VALS(sccp_ai_ssni_values), ANSI_SSN_INDICATOR_MASK, |
3799 | 14 | NULL, HFILL} |
3800 | 14 | }, |
3801 | 14 | { &hf_sccp_calling_ansi_point_code_indicator, |
3802 | 14 | { "Point Code Indicator", "sccp.calling.pci", |
3803 | 14 | FT_UINT8, BASE_HEX, VALS(sccp_ai_pci_values), ANSI_PC_INDICATOR_MASK, |
3804 | 14 | NULL, HFILL} |
3805 | 14 | }, |
3806 | 14 | { &hf_sccp_calling_ssn, |
3807 | 14 | { "SubSystem Number", "sccp.calling.ssn", |
3808 | 14 | FT_UINT8, BASE_DEC, VALS(sccp_ssn_values), 0x0, |
3809 | 14 | NULL, HFILL} |
3810 | 14 | }, |
3811 | 14 | { &hf_sccp_calling_itu_pc, |
3812 | 14 | { "PC", "sccp.calling.pc", |
3813 | 14 | FT_UINT16, BASE_DEC, NULL, ITU_PC_MASK, |
3814 | 14 | NULL, HFILL} |
3815 | 14 | }, |
3816 | 14 | { &hf_sccp_calling_ansi_pc, |
3817 | 14 | { "PC", "sccp.calling.ansi_pc", |
3818 | 14 | FT_STRING, BASE_NONE, NULL, 0x0, |
3819 | 14 | NULL, HFILL} |
3820 | 14 | }, |
3821 | 14 | { &hf_sccp_calling_chinese_pc, |
3822 | 14 | { "PC", "sccp.calling.chinese_pc", |
3823 | 14 | FT_STRING, BASE_NONE, NULL, 0x0, |
3824 | 14 | NULL, HFILL} |
3825 | 14 | }, |
3826 | 14 | { &hf_sccp_calling_japan_pc, |
3827 | 14 | { "PC", "sccp.calling.pc", |
3828 | 14 | FT_UINT16, BASE_DEC, NULL, 0x0, |
3829 | 14 | NULL, HFILL} |
3830 | 14 | }, |
3831 | 14 | { &hf_sccp_calling_pc_network, |
3832 | 14 | { "PC Network", "sccp.calling.network", |
3833 | 14 | FT_UINT24, BASE_DEC, NULL, ANSI_NETWORK_MASK, |
3834 | 14 | NULL, HFILL } |
3835 | 14 | }, |
3836 | 14 | { &hf_sccp_calling_pc_cluster, |
3837 | 14 | { "PC Cluster", "sccp.calling.cluster", |
3838 | 14 | FT_UINT24, BASE_DEC, NULL, ANSI_CLUSTER_MASK, |
3839 | 14 | NULL, HFILL } |
3840 | 14 | }, |
3841 | 14 | { &hf_sccp_calling_pc_member, |
3842 | 14 | { "PC Member", "sccp.calling.member", |
3843 | 14 | FT_UINT24, BASE_DEC, NULL, ANSI_MEMBER_MASK, |
3844 | 14 | NULL, HFILL } |
3845 | 14 | }, |
3846 | 14 | { &hf_sccp_calling_gt_nai, |
3847 | 14 | { "Nature of Address Indicator", "sccp.calling.nai", |
3848 | 14 | FT_UINT8, BASE_HEX, VALS(sccp_nai_values), GT_NAI_MASK, |
3849 | 14 | NULL, HFILL } |
3850 | 14 | }, |
3851 | 14 | { &hf_sccp_calling_gt_oe, |
3852 | 14 | { "Odd/Even Indicator", "sccp.calling.oe", |
3853 | 14 | FT_UINT8, BASE_HEX, VALS(sccp_oe_values), GT_OE_MASK, |
3854 | 14 | NULL, HFILL } |
3855 | 14 | }, |
3856 | 14 | { &hf_sccp_calling_gt_tt, |
3857 | 14 | { "Translation Type", "sccp.calling.tt", |
3858 | 14 | FT_UINT8, BASE_HEX_DEC, NULL, 0x0, |
3859 | 14 | NULL, HFILL } |
3860 | 14 | }, |
3861 | 14 | { &hf_sccp_calling_gt_np, |
3862 | 14 | { "Numbering Plan", "sccp.calling.np", |
3863 | 14 | FT_UINT8, BASE_HEX, VALS(sccp_np_values), GT_NP_MASK, |
3864 | 14 | NULL, HFILL } |
3865 | 14 | }, |
3866 | 14 | { &hf_sccp_calling_gt_es, |
3867 | 14 | { "Encoding Scheme", "sccp.calling.es", |
3868 | 14 | FT_UINT8, BASE_HEX, VALS(sccp_es_values), GT_ES_MASK, |
3869 | 14 | NULL, HFILL } |
3870 | 14 | }, |
3871 | 14 | { &hf_sccp_calling_gt_digits, |
3872 | 14 | { "Calling Party Digits", "sccp.calling.digits", |
3873 | 14 | FT_STRING, BASE_NONE, NULL, 0x0, |
3874 | 14 | NULL, HFILL } |
3875 | 14 | }, |
3876 | 14 | { &hf_sccp_calling_gt_digits_length, |
3877 | 14 | { "Number of Calling Party Digits", "sccp.calling.digits.length", |
3878 | 14 | FT_UINT8, BASE_DEC, NULL, 0x0, |
3879 | 14 | NULL, HFILL } |
3880 | 14 | }, |
3881 | 14 | { &hf_sccp_dlr, |
3882 | 14 | { "Destination Local Reference", "sccp.dlr", |
3883 | 14 | FT_UINT24, BASE_HEX, NULL, 0x0, |
3884 | 14 | NULL, HFILL} |
3885 | 14 | }, |
3886 | 14 | { &hf_sccp_slr, |
3887 | 14 | { "Source Local Reference", "sccp.slr", |
3888 | 14 | FT_UINT24, BASE_HEX, NULL, 0x0, |
3889 | 14 | NULL, HFILL} |
3890 | 14 | }, |
3891 | 14 | { &hf_sccp_lr, |
3892 | 14 | { "Local Reference", "sccp.lr", |
3893 | 14 | FT_UINT24, BASE_HEX, NULL, 0x0, |
3894 | 14 | NULL, HFILL} |
3895 | 14 | }, |
3896 | 14 | { &hf_sccp_class, |
3897 | 14 | { "Class", "sccp.class", |
3898 | 14 | FT_UINT8, BASE_HEX, NULL, CLASS_CLASS_MASK, |
3899 | 14 | NULL, HFILL} |
3900 | 14 | }, |
3901 | 14 | { &hf_sccp_handling, |
3902 | 14 | { "Message handling", "sccp.handling", |
3903 | 14 | FT_UINT8, BASE_HEX, VALS(sccp_class_handling_values), CLASS_SPARE_HANDLING_MASK, |
3904 | 14 | NULL, HFILL} |
3905 | 14 | }, |
3906 | 14 | { &hf_sccp_more, |
3907 | 14 | { "More data", "sccp.more", |
3908 | 14 | FT_UINT8, BASE_HEX, VALS(sccp_segmenting_reassembling_values), SEGMENTING_REASSEMBLING_MASK, |
3909 | 14 | NULL, HFILL} |
3910 | 14 | }, |
3911 | 14 | { &hf_sccp_rsn, |
3912 | 14 | { "Receive Sequence Number", "sccp.rsn", |
3913 | 14 | FT_UINT8, BASE_HEX, NULL, RSN_MASK, |
3914 | 14 | NULL, HFILL} |
3915 | 14 | }, |
3916 | 14 | { &hf_sccp_sequencing_segmenting_ssn, |
3917 | 14 | { "Sequencing Segmenting: Send Sequence Number", "sccp.sequencing_segmenting.ssn", |
3918 | 14 | FT_UINT8, BASE_HEX, NULL, SEND_SEQUENCE_NUMBER_MASK, |
3919 | 14 | NULL, HFILL} |
3920 | 14 | }, |
3921 | 14 | { &hf_sccp_sequencing_segmenting_rsn, |
3922 | 14 | { "Sequencing Segmenting: Receive Sequence Number", "sccp.sequencing_segmenting.rsn", |
3923 | 14 | FT_UINT8, BASE_HEX, NULL, RECEIVE_SEQUENCE_NUMBER_MASK, |
3924 | 14 | NULL, HFILL} |
3925 | 14 | }, |
3926 | 14 | { &hf_sccp_sequencing_segmenting_more, |
3927 | 14 | { "Sequencing Segmenting: More", "sccp.sequencing_segmenting.more", |
3928 | 14 | FT_UINT8, BASE_HEX, VALS(sccp_segmenting_reassembling_values), SEQUENCING_SEGMENTING_MORE_MASK, |
3929 | 14 | NULL, HFILL} |
3930 | 14 | }, |
3931 | 14 | { &hf_sccp_credit, |
3932 | 14 | { "Credit", "sccp.credit", |
3933 | 14 | FT_UINT8, BASE_HEX, NULL, 0x0, |
3934 | 14 | NULL, HFILL} |
3935 | 14 | }, |
3936 | 14 | { &hf_sccp_release_cause, |
3937 | 14 | { "Release Cause", "sccp.release_cause", |
3938 | 14 | FT_UINT8, BASE_HEX, VALS(sccp_release_cause_values), 0x0, |
3939 | 14 | NULL, HFILL} |
3940 | 14 | }, |
3941 | 14 | { &hf_sccp_return_cause, |
3942 | 14 | { "Return Cause", "sccp.return_cause", |
3943 | 14 | FT_UINT8, BASE_HEX, VALS(sccp_return_cause_values), 0x0, |
3944 | 14 | NULL, HFILL} |
3945 | 14 | }, |
3946 | 14 | { &hf_sccp_reset_cause, |
3947 | 14 | { "Reset Cause", "sccp.reset_cause", |
3948 | 14 | FT_UINT8, BASE_HEX, VALS(sccp_reset_cause_values), 0x0, |
3949 | 14 | NULL, HFILL} |
3950 | 14 | }, |
3951 | 14 | { &hf_sccp_error_cause, |
3952 | 14 | { "Error Cause", "sccp.error_cause", |
3953 | 14 | FT_UINT8, BASE_HEX, VALS(sccp_error_cause_values), 0x0, |
3954 | 14 | NULL, HFILL} |
3955 | 14 | }, |
3956 | 14 | { &hf_sccp_refusal_cause, |
3957 | 14 | { "Refusal Cause", "sccp.refusal_cause", |
3958 | 14 | FT_UINT8, BASE_HEX, VALS(sccp_refusal_cause_values), 0x0, |
3959 | 14 | NULL, HFILL} |
3960 | 14 | }, |
3961 | 14 | { &hf_sccp_segmentation_first, |
3962 | 14 | { "Segmentation: First", "sccp.segmentation.first", |
3963 | 14 | FT_UINT8, BASE_HEX, VALS(sccp_segmentation_first_segment_values), SEGMENTATION_FIRST_SEGMENT_MASK, |
3964 | 14 | NULL, HFILL} |
3965 | 14 | }, |
3966 | 14 | { &hf_sccp_segmentation_class, |
3967 | 14 | { "Segmentation: Class", "sccp.segmentation.class", |
3968 | 14 | FT_UINT8, BASE_HEX, VALS(sccp_segmentation_class_values), SEGMENTATION_CLASS_MASK, |
3969 | 14 | NULL, HFILL} |
3970 | 14 | }, |
3971 | 14 | { &hf_sccp_segmentation_remaining, |
3972 | 14 | { "Segmentation: Remaining", "sccp.segmentation.remaining", |
3973 | 14 | FT_UINT8, BASE_HEX, NULL, SEGMENTATION_REMAINING_MASK, |
3974 | 14 | NULL, HFILL} |
3975 | 14 | }, |
3976 | 14 | { &hf_sccp_segmentation_slr, |
3977 | 14 | { "Segmentation: Source Local Reference", "sccp.segmentation.slr", |
3978 | 14 | FT_UINT24, BASE_HEX, NULL, 0x0, |
3979 | 14 | NULL, HFILL} |
3980 | 14 | }, |
3981 | 14 | { &hf_sccp_hop_counter, |
3982 | 14 | { "Hop Counter", "sccp.hops", |
3983 | 14 | FT_UINT8, BASE_HEX, NULL, 0x0, |
3984 | 14 | NULL, HFILL} |
3985 | 14 | }, |
3986 | 14 | { &hf_sccp_importance, |
3987 | 14 | { "Importance", "sccp.importance", |
3988 | 14 | FT_UINT8, BASE_HEX, NULL, IMPORTANCE_IMPORTANCE_MASK, |
3989 | 14 | NULL, HFILL} |
3990 | 14 | }, |
3991 | | /* ISNI is ANSI only */ |
3992 | 14 | { &hf_sccp_ansi_isni_mi, |
3993 | 14 | { "ISNI Mark for Identification Indicator", "sccp.isni.mi", |
3994 | 14 | FT_UINT8, BASE_HEX, VALS(sccp_isni_mark_for_id_values), ANSI_ISNI_MI_MASK, |
3995 | 14 | NULL, HFILL} |
3996 | 14 | }, |
3997 | 14 | { &hf_sccp_ansi_isni_iri, |
3998 | 14 | { "ISNI Routing Indicator", "sccp.isni.iri", |
3999 | 14 | FT_UINT8, BASE_HEX, VALS(sccp_isni_iri_values), ANSI_ISNI_IRI_MASK, |
4000 | 14 | NULL, HFILL} |
4001 | 14 | }, |
4002 | 14 | { &hf_sccp_ansi_isni_ti, |
4003 | 14 | { "ISNI Type Indicator", "sccp.isni.ti", |
4004 | 14 | FT_UINT8, BASE_HEX, VALS(sccp_isni_ti_values), ANSI_ISNI_TI_MASK, |
4005 | 14 | NULL, HFILL} |
4006 | 14 | }, |
4007 | 14 | { &hf_sccp_ansi_isni_netspec, |
4008 | 14 | { "ISNI Network Specific (Type 1)", "sccp.isni.netspec", |
4009 | 14 | FT_UINT8, BASE_HEX, NULL, ANSI_ISNI_NETSPEC_MASK, |
4010 | 14 | NULL, HFILL} |
4011 | 14 | }, |
4012 | 14 | { &hf_sccp_ansi_isni_counter, |
4013 | 14 | { "ISNI Counter", "sccp.isni.counter", |
4014 | 14 | FT_UINT8, BASE_DEC, NULL, ANSI_ISNI_COUNTER_MASK, |
4015 | 14 | NULL, HFILL} |
4016 | 14 | }, |
4017 | 14 | { &hf_sccp_ansi_isni_network, |
4018 | 14 | { "Network ID network", "sccp.isni.network", |
4019 | 14 | FT_UINT8, BASE_DEC, NULL, 0x0, |
4020 | 14 | NULL, HFILL} |
4021 | 14 | }, |
4022 | 14 | { &hf_sccp_ansi_isni_cluster, |
4023 | 14 | { "Network ID cluster", "sccp.isni.cluster", |
4024 | 14 | FT_UINT8, BASE_DEC, NULL, 0x0, |
4025 | 14 | NULL, HFILL} |
4026 | 14 | }, |
4027 | 14 | {&hf_sccp_xudt_msg_fragments, |
4028 | 14 | { "Message fragments", "sccp.msg.fragments", |
4029 | 14 | FT_NONE, BASE_NONE, NULL, 0x00, |
4030 | 14 | NULL, HFILL } |
4031 | 14 | }, |
4032 | 14 | {&hf_sccp_xudt_msg_fragment, |
4033 | 14 | { "Message fragment", "sccp.msg.fragment", |
4034 | 14 | FT_FRAMENUM, BASE_NONE, NULL, 0x00, |
4035 | 14 | NULL, HFILL } |
4036 | 14 | }, |
4037 | 14 | {&hf_sccp_xudt_msg_fragment_overlap, |
4038 | 14 | { "Message fragment overlap", "sccp.msg.fragment.overlap", |
4039 | 14 | FT_BOOLEAN, BASE_NONE, NULL, 0x0, |
4040 | 14 | NULL, HFILL } |
4041 | 14 | }, |
4042 | 14 | {&hf_sccp_xudt_msg_fragment_overlap_conflicts, |
4043 | 14 | { "Message fragment overlapping with conflicting data", "sccp.msg.fragment.overlap.conflicts", |
4044 | 14 | FT_BOOLEAN, BASE_NONE, NULL, 0x0, |
4045 | 14 | NULL, HFILL } |
4046 | 14 | }, |
4047 | 14 | {&hf_sccp_xudt_msg_fragment_multiple_tails, |
4048 | 14 | { "Message has multiple tail fragments", "sccp.msg.fragment.multiple_tails", |
4049 | 14 | FT_BOOLEAN, BASE_NONE, NULL, 0x0, |
4050 | 14 | NULL, HFILL } |
4051 | 14 | }, |
4052 | 14 | {&hf_sccp_xudt_msg_fragment_too_long_fragment, |
4053 | 14 | { "Message fragment too long", "sccp.msg.fragment.too_long_fragment", |
4054 | 14 | FT_BOOLEAN, BASE_NONE, NULL, 0x0, |
4055 | 14 | NULL, HFILL } |
4056 | 14 | }, |
4057 | 14 | {&hf_sccp_xudt_msg_fragment_error, |
4058 | 14 | { "Message defragmentation error", "sccp.msg.fragment.error", |
4059 | 14 | FT_FRAMENUM, BASE_NONE, NULL, 0x00, |
4060 | 14 | NULL, HFILL } |
4061 | 14 | }, |
4062 | 14 | {&hf_sccp_xudt_msg_fragment_count, |
4063 | 14 | { "Message fragment count", "sccp.msg.fragment.count", |
4064 | 14 | FT_UINT32, BASE_DEC, NULL, 0x00, |
4065 | 14 | NULL, HFILL } |
4066 | 14 | }, |
4067 | 14 | {&hf_sccp_xudt_msg_reassembled_in, |
4068 | 14 | { "Reassembled in", "sccp.msg.reassembled.in", |
4069 | 14 | FT_FRAMENUM, BASE_NONE, NULL, 0x00, |
4070 | 14 | NULL, HFILL } |
4071 | 14 | }, |
4072 | 14 | {&hf_sccp_xudt_msg_reassembled_length, |
4073 | 14 | { "Reassembled SCCP length", "sccp.msg.reassembled.length", |
4074 | 14 | FT_UINT32, BASE_DEC, NULL, 0x00, |
4075 | 14 | NULL, HFILL } |
4076 | 14 | }, |
4077 | 14 | { &hf_sccp_assoc_id, |
4078 | 14 | { "Association ID", "sccp.assoc.id", |
4079 | 14 | FT_UINT32, BASE_DEC, NULL, 0x0, |
4080 | 14 | NULL, HFILL} |
4081 | 14 | }, |
4082 | 14 | {&hf_sccp_assoc_msg, |
4083 | 14 | { "Message in frame", "sccp.assoc.msg", |
4084 | 14 | FT_FRAMENUM, BASE_NONE, NULL, 0x00, |
4085 | 14 | NULL, HFILL } |
4086 | 14 | }, |
4087 | 14 | {&hf_sccp_segmented_data, |
4088 | 14 | { "Segmented Data", "sccp.segmented_data", |
4089 | 14 | FT_BYTES, BASE_NONE, NULL, 0x00, |
4090 | 14 | NULL, HFILL } |
4091 | 14 | }, |
4092 | 14 | {&hf_sccp_linked_dissector, |
4093 | 14 | { "Linked dissector", "sccp.linked_dissector", |
4094 | 14 | FT_STRING, BASE_NONE, NULL, 0x00, |
4095 | 14 | NULL, HFILL } |
4096 | 14 | }, |
4097 | 14 | {&hf_sccp_end_optional_param, |
4098 | 14 | { "End of Optional", "sccp.end_optional_param", |
4099 | 14 | FT_NONE, BASE_NONE, NULL, 0x00, |
4100 | 14 | NULL, HFILL } |
4101 | 14 | }, |
4102 | 14 | {&hf_sccp_unknown_message, |
4103 | 14 | { "Unknown message", "sccp.unknown_message", |
4104 | 14 | FT_BYTES, BASE_NONE, NULL, 0x00, |
4105 | 14 | NULL, HFILL } |
4106 | 14 | }, |
4107 | 14 | {&hf_sccp_unknown_parameter, |
4108 | 14 | { "Unknown parameter", "sccp.unknown_parameter", |
4109 | 14 | FT_BYTES, BASE_NONE, NULL, 0x00, |
4110 | 14 | NULL, HFILL } |
4111 | 14 | }, |
4112 | 14 | }; |
4113 | | |
4114 | | /* Setup protocol subtree array */ |
4115 | 14 | static int *ett[] = { |
4116 | 14 | &ett_sccp, |
4117 | 14 | &ett_sccp_called, |
4118 | 14 | &ett_sccp_called_ai, |
4119 | 14 | &ett_sccp_called_pc, |
4120 | 14 | &ett_sccp_called_gt, |
4121 | 14 | &ett_sccp_called_gt_digits, |
4122 | 14 | &ett_sccp_calling, |
4123 | 14 | &ett_sccp_calling_ai, |
4124 | 14 | &ett_sccp_calling_pc, |
4125 | 14 | &ett_sccp_calling_gt, |
4126 | 14 | &ett_sccp_calling_gt_digits, |
4127 | 14 | &ett_sccp_sequencing_segmenting, |
4128 | 14 | &ett_sccp_segmentation, |
4129 | 14 | &ett_sccp_ansi_isni_routing_control, |
4130 | 14 | &ett_sccp_xudt_msg_fragment, |
4131 | 14 | &ett_sccp_xudt_msg_fragments, |
4132 | 14 | &ett_sccp_assoc |
4133 | 14 | }; |
4134 | | |
4135 | 14 | static ei_register_info ei[] = { |
4136 | 14 | { &ei_sccp_wrong_length, { "sccp.wrong_length", PI_MALFORMED, PI_ERROR, "Wrong length indicated.", EXPFILL }}, |
4137 | 14 | { &ei_sccp_international_standard_address, { "sccp.international_standard_address", PI_MALFORMED, PI_WARN, |
4138 | 14 | "Address is coded to international standards. This doesn't normally happen in ANSI networks.", EXPFILL }}, |
4139 | 14 | { &ei_sccp_no_ssn_present, { "sccp.ssn.not_present", PI_PROTOCOL, PI_WARN, "Message is routed on SSN, but SSN is not present", EXPFILL }}, |
4140 | 14 | { &ei_sccp_ssn_zero, { "sccp.ssn.is_zero", PI_PROTOCOL, PI_WARN, "Message is routed on SSN, but SSN is zero (unspecified)", EXPFILL }}, |
4141 | 14 | { &ei_sccp_class_unexpected, { "sccp.class_unexpected", PI_MALFORMED, PI_ERROR, "Unexpected message class for this message type", EXPFILL }}, |
4142 | 14 | { &ei_sccp_handling_invalid, { "sccp.handling_invalid", PI_MALFORMED, PI_ERROR, "Invalid message handling", EXPFILL }}, |
4143 | 14 | { &ei_sccp_gt_digits_missing, { "sccp.gt_digits_missing", PI_MALFORMED, PI_ERROR, "Address digits missing", EXPFILL }}, |
4144 | 14 | { &ei_sccp_externally_reassembled, { "sccp.externally_reassembled", PI_ASSUMPTION, PI_NOTE, "Possibly externally reassembled (remaining length > 255 bytes), enable in SCCP preferences", EXPFILL }}, |
4145 | 14 | }; |
4146 | | |
4147 | | /* Decode As handling */ |
4148 | 14 | static build_valid_func sccp_da_build_value[1] = {sccp_value}; |
4149 | 14 | static decode_as_value_t sccp_da_values = {sccp_prompt, 1, sccp_da_build_value}; |
4150 | 14 | static decode_as_t sccp_da = {"sccp", "sccp.ssn", 1, 0, &sccp_da_values, NULL, NULL, |
4151 | 14 | decode_as_default_populate_list, decode_as_default_reset, decode_as_default_change, NULL}; |
4152 | | |
4153 | 14 | module_t *sccp_module; |
4154 | 14 | expert_module_t* expert_sccp; |
4155 | | |
4156 | 14 | static uat_field_t users_flds[] = { |
4157 | 14 | UAT_FLD_DEC(sccp_users, ni, "Network Indicator", "Network Indicator"), |
4158 | 14 | UAT_FLD_RANGE(sccp_users, called_pc, "Called DPCs", 0xFFFFFF, "DPCs for which this protocol is to be used"), |
4159 | 14 | UAT_FLD_RANGE(sccp_users, called_ssn, "Called SSNs", 255, "Called SSNs for which this protocol is to be used"), |
4160 | 14 | UAT_FLD_VS(sccp_users, user, "User protocol", sccp_users_vals, "The User Protocol"), |
4161 | 14 | UAT_END_FIELDS |
4162 | 14 | }; |
4163 | | |
4164 | | |
4165 | 14 | uat_t *users_uat = uat_new("SCCP Users Table", sizeof(sccp_user_t), |
4166 | 14 | "sccp_users", true, &sccp_users, |
4167 | 14 | &num_sccp_users, UAT_AFFECTS_DISSECTION, |
4168 | 14 | "ChSccpUsers", sccp_users_copy_cb, |
4169 | 14 | sccp_users_update_cb, sccp_users_free_cb, |
4170 | 14 | NULL, NULL, users_flds ); |
4171 | | |
4172 | | /* Register the protocol name and description */ |
4173 | 14 | proto_sccp = proto_register_protocol("Signalling Connection Control Part", "SCCP", "sccp"); |
4174 | | |
4175 | 14 | sccp_handle = register_dissector("sccp", dissect_sccp, proto_sccp); |
4176 | | |
4177 | | /* Required function calls to register the header fields and subtrees used */ |
4178 | 14 | proto_register_field_array(proto_sccp, hf, array_length(hf)); |
4179 | 14 | proto_register_subtree_array(ett, array_length(ett)); |
4180 | 14 | expert_sccp = expert_register_protocol(proto_sccp); |
4181 | 14 | expert_register_field_array(expert_sccp, ei, array_length(ei)); |
4182 | | |
4183 | 14 | sccp_ssn_dissector_table = register_dissector_table("sccp.ssn", "SCCP SSN", proto_sccp, FT_UINT8, BASE_DEC); |
4184 | | |
4185 | 14 | heur_subdissector_list = register_heur_dissector_list_with_description("sccp", "SCCP Data fallback", proto_sccp); |
4186 | | |
4187 | 14 | sccp_module = prefs_register_protocol(proto_sccp, proto_reg_handoff_sccp); |
4188 | | |
4189 | 14 | prefs_register_uint_preference(sccp_module, "source_pc", |
4190 | 14 | "Source PC (in hex)", |
4191 | 14 | "The source point code (usually MSC) (to determine whether message is uplink or downlink)", |
4192 | 14 | 16, &sccp_source_pc_global); |
4193 | | |
4194 | 14 | prefs_register_bool_preference(sccp_module, "show_length", "Show length", |
4195 | 14 | "Show parameter length in the protocol tree", |
4196 | 14 | &sccp_show_length); |
4197 | | |
4198 | 14 | prefs_register_bool_preference(sccp_module, "defragment_xudt", |
4199 | 14 | "Reassemble SCCP messages", |
4200 | 14 | "Whether SCCP messages should be reassembled", |
4201 | 14 | &sccp_reassemble); |
4202 | | |
4203 | 14 | prefs_register_bool_preference(sccp_module, "trace_sccp", |
4204 | 14 | "Trace Associations", |
4205 | 14 | "Whether to keep information about messages and their associations", |
4206 | 14 | &trace_sccp); |
4207 | | |
4208 | | |
4209 | 14 | prefs_register_bool_preference(sccp_module, "show_more_info", |
4210 | 14 | "Show key parameters in Info Column", |
4211 | 14 | "Show SLR, DLR, and CAUSE Parameters in the Information Column of the Summary", |
4212 | 14 | &show_key_params); |
4213 | | |
4214 | | |
4215 | 14 | prefs_register_uat_preference(sccp_module, "users_table", "Users Table", |
4216 | 14 | "A table that enumerates user protocols to be used against specific PCs and SSNs", |
4217 | 14 | users_uat); |
4218 | | |
4219 | 14 | prefs_register_bool_preference(sccp_module, "set_addresses", "Set source and destination GT addresses", |
4220 | 14 | "Set the source and destination addresses to the GT digits (if present)." |
4221 | 14 | " This may affect TCAP's ability to recognize which messages belong to which TCAP session.", |
4222 | 14 | &set_addresses); |
4223 | | |
4224 | 14 | prefs_register_dissector_preference(sccp_module, "default_payload", "Default Payload", |
4225 | 14 | "The dissector which should be used to dissect the payload if nothing else has claimed it", |
4226 | 14 | &default_payload); |
4227 | | |
4228 | 14 | prefs_register_bool_preference(sccp_module, "dt1_ignore_length", "Dissect data past 255 byte limit", |
4229 | 14 | "Use all bytes for data payload. Overcome 255 bytes limit of SCCP standard." |
4230 | 14 | " (Some tracing tools externally reassemble segmented data.)", |
4231 | 14 | &dt1_ignore_length); |
4232 | | |
4233 | 14 | register_init_routine(&init_sccp); |
4234 | 14 | reassembly_table_register(&sccp_xudt_msg_reassembly_table, |
4235 | 14 | &addresses_reassembly_table_functions); |
4236 | | |
4237 | 14 | assocs = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope()); |
4238 | | |
4239 | 14 | sccp_reassembly_ids = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope()); |
4240 | 14 | sccp_reassembly_id_map = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), |
4241 | 14 | g_int64_hash, g_int64_equal); |
4242 | | |
4243 | 14 | sccp_tap = register_tap("sccp"); |
4244 | | |
4245 | 14 | register_decode_as(&sccp_da); |
4246 | 14 | } |
4247 | | |
4248 | | void |
4249 | | proto_reg_handoff_sccp(void) |
4250 | 14 | { |
4251 | 14 | static bool initialised = false; |
4252 | | |
4253 | 14 | if (!initialised) { |
4254 | 14 | dissector_add_uint("wtap_encap", WTAP_ENCAP_SCCP, sccp_handle); |
4255 | 14 | dissector_add_uint("mtp3.service_indicator", MTP_SI_SCCP, sccp_handle); |
4256 | 14 | dissector_add_string("tali.opcode", "sccp", sccp_handle); |
4257 | | |
4258 | 14 | data_handle = find_dissector("data"); |
4259 | 14 | tcap_handle = find_dissector_add_dependency("tcap", proto_sccp); |
4260 | 14 | ranap_handle = find_dissector_add_dependency("ranap", proto_sccp); |
4261 | 14 | bssap_handle = find_dissector_add_dependency("bssap", proto_sccp); |
4262 | 14 | gsmmap_handle = find_dissector_add_dependency("gsm_map_sccp", proto_sccp); |
4263 | 14 | camel_handle = find_dissector_add_dependency("camel", proto_sccp); |
4264 | 14 | inap_handle = find_dissector_add_dependency("inap", proto_sccp); |
4265 | 14 | bsap_handle = find_dissector_add_dependency("bsap", proto_sccp); |
4266 | 14 | bssap_le_handle = find_dissector_add_dependency("bssap_le", proto_sccp); |
4267 | 14 | bssap_plus_handle = find_dissector_add_dependency("bssap_plus", proto_sccp); |
4268 | | |
4269 | 14 | ss7pc_address_type = address_type_get_by_name("AT_SS7PC"); |
4270 | | |
4271 | 14 | initialised = true; |
4272 | 14 | hf_assoc_imsi = proto_registrar_get_id_byname("e212.assoc.imsi"); |
4273 | 14 | } |
4274 | | |
4275 | 14 | default_handle = find_dissector(default_payload); |
4276 | 14 | } |
4277 | | |
4278 | | /* |
4279 | | * Editor modelines - https://www.wireshark.org/tools/modelines.html |
4280 | | * |
4281 | | * Local Variables: |
4282 | | * c-basic-offset: 2 |
4283 | | * tab-width: 8 |
4284 | | * indent-tabs-mode: nil |
4285 | | * End: |
4286 | | * |
4287 | | * ex: set shiftwidth=2 tabstop=8 expandtab: |
4288 | | * :indentSize=2:tabSize=8:noTabs=true: |
4289 | | */ |