/src/wireshark/epan/dissectors/packet-mtp3.c
Line | Count | Source |
1 | | /* packet-mtp3.c |
2 | | * Routines for Message Transfer Part Level 3 dissection |
3 | | * |
4 | | * It is (hopefully) compliant to: |
5 | | * ANSI T1.111.4-1996 |
6 | | * ITU-T Q.704 7/1996 |
7 | | * GF 001-9001 (Chinese ITU variant) |
8 | | * JT-Q704 and NTT-Q704 (Japan) |
9 | | * |
10 | | * Note that the division of the Japan SLS into the SLC and A/B bit (for |
11 | | * management messages) is not done. |
12 | | * |
13 | | * Copyright 2001, Michael Tuexen <tuexen [AT] fh-muenster.de> |
14 | | * Updated for ANSI, Chinese ITU, and Japan support by |
15 | | * Jeff Morriss <jeff.morriss.ws [AT] gmail.com> |
16 | | * |
17 | | * Wireshark - Network traffic analyzer |
18 | | * By Gerald Combs <gerald@wireshark.org> |
19 | | * Copyright 1998 Gerald Combs |
20 | | * |
21 | | * Copied from README.developer |
22 | | * |
23 | | * SPDX-License-Identifier: GPL-2.0-or-later |
24 | | */ |
25 | | |
26 | | #include "config.h" |
27 | | |
28 | | #include <epan/packet.h> |
29 | | #include <epan/stat_tap_ui.h> |
30 | | #include <epan/tap.h> |
31 | | #include <epan/prefs.h> |
32 | | #include <epan/address_types.h> |
33 | | #include <wiretap/wtap.h> |
34 | | #include <epan/addr_resolv.h> |
35 | | |
36 | | #include <wsutil/array.h> |
37 | | |
38 | | #include "packet-q708.h" |
39 | | #include "packet-sccp.h" |
40 | | #include "packet-frame.h" |
41 | | |
42 | | void proto_register_mtp3(void); |
43 | | void proto_reg_handoff_mtp3(void); |
44 | | |
45 | | /* Initialize the protocol and registered fields */ |
46 | | static int proto_mtp3; |
47 | | |
48 | | static int mtp3_tap; |
49 | | |
50 | | static dissector_handle_t mtp3_handle; |
51 | | |
52 | | static module_t *mtp3_module; |
53 | | |
54 | | static int hf_mtp3_service_indicator; |
55 | | static int hf_mtp3_network_indicator; |
56 | | static int hf_mtp3_itu_spare; |
57 | | static int hf_mtp3_itu_priority; |
58 | | static int hf_mtp3_ansi_priority; |
59 | | static int hf_mtp3_itu_pc; |
60 | | static int hf_mtp3_24bit_pc; |
61 | | static int hf_mtp3_itu_opc; |
62 | | static int hf_mtp3_24bit_opc; |
63 | | static int hf_mtp3_ansi_opc; |
64 | | static int hf_mtp3_chinese_opc; |
65 | | static int hf_mtp3_opc_network; |
66 | | static int hf_mtp3_opc_cluster; |
67 | | static int hf_mtp3_opc_member; |
68 | | static int hf_mtp3_itu_dpc; |
69 | | static int hf_mtp3_24bit_dpc; |
70 | | static int hf_mtp3_ansi_dpc; |
71 | | static int hf_mtp3_chinese_dpc; |
72 | | static int hf_mtp3_dpc_network; |
73 | | static int hf_mtp3_dpc_cluster; |
74 | | static int hf_mtp3_dpc_member; |
75 | | static int hf_mtp3_itu_sls; |
76 | | static int hf_mtp3_ansi_5_bit_sls; |
77 | | static int hf_mtp3_ansi_8_bit_sls; |
78 | | static int hf_mtp3_chinese_itu_sls; |
79 | | static int hf_mtp3_japan_dpc; |
80 | | static int hf_mtp3_japan_opc; |
81 | | static int hf_mtp3_japan_pc; |
82 | | static int hf_mtp3_japan_4_bit_sls; |
83 | | static int hf_mtp3_japan_4_bit_sls_spare; |
84 | | static int hf_mtp3_japan_5_bit_sls; |
85 | | static int hf_mtp3_japan_5_bit_sls_spare; |
86 | | static int hf_mtp3_heuristic_standard; |
87 | | |
88 | | /* Initialize the subtree pointers */ |
89 | | static int ett_mtp3; |
90 | | static int ett_mtp3_sio; |
91 | | static int ett_mtp3_label; |
92 | | static int ett_mtp3_label_dpc; |
93 | | static int ett_mtp3_label_opc; |
94 | | |
95 | | static dissector_table_t mtp3_sio_dissector_table; |
96 | | |
97 | | static int mtp3_address_type = -1; |
98 | | |
99 | | typedef enum { |
100 | | ITU_PC_STRUCTURE_NONE = 1, |
101 | | ITU_PC_STRUCTURE_3_8_3 = 2, |
102 | | ITU_PC_STRUCTURE_4_3_4_3 = 3 |
103 | | } ITU_PC_Structure_Type; |
104 | | |
105 | | typedef enum { |
106 | | JAPAN_PC_STRUCTURE_NONE = 1, |
107 | | JAPAN_PC_STRUCTURE_7_4_5 = 2, |
108 | | JAPAN_PC_STRUCTURE_3_4_4_5 = 3 |
109 | | } JAPAN_PC_Structure_Type; |
110 | | |
111 | | static int itu_pc_structure = ITU_PC_STRUCTURE_NONE; |
112 | | static int japan_pc_structure = JAPAN_PC_STRUCTURE_NONE; |
113 | | |
114 | | #include "packet-mtp3.h" |
115 | | |
116 | | int mtp3_standard = ITU_STANDARD; |
117 | | bool mtp3_heuristic_standard; |
118 | | |
119 | | static int pref_mtp3_standard; |
120 | | |
121 | | const value_string mtp3_standard_vals[] = { |
122 | | { ITU_STANDARD, "ITU_STANDARD" }, |
123 | | { ANSI_STANDARD, "ANSI_STANDARD" }, |
124 | | { CHINESE_ITU_STANDARD, "CHINESE_ITU_STANDARD" }, |
125 | | { JAPAN_STANDARD, "JAPAN_STANDARD" }, |
126 | | { 0, NULL } |
127 | | }; |
128 | | |
129 | | static bool mtp3_use_ansi_5_bit_sls; |
130 | | static bool mtp3_use_japan_5_bit_sls; |
131 | | static bool mtp3_show_itu_priority; |
132 | | static int mtp3_addr_fmt = MTP3_ADDR_FMT_DASHED; |
133 | | |
134 | 10.2k | #define SIO_LENGTH 1 |
135 | 0 | #define SLS_LENGTH 1 |
136 | 12.4k | #define SIO_OFFSET 0 |
137 | 5.81k | #define ROUTING_LABEL_OFFSET (SIO_OFFSET + SIO_LENGTH) |
138 | | |
139 | 6.55k | #define ITU_ROUTING_LABEL_LENGTH 4 |
140 | 1.47k | #define ITU_HEADER_LENGTH (SIO_LENGTH + ITU_ROUTING_LABEL_LENGTH) |
141 | | |
142 | | #define ITU_SLS_OFFSET (SIO_OFFSET + ITU_HEADER_LENGTH - SLS_LENGTH) |
143 | 739 | #define ITU_MTP_PAYLOAD_OFFSET (SIO_OFFSET + ITU_HEADER_LENGTH) |
144 | | |
145 | 0 | #define ANSI_ROUTING_LABEL_LENGTH (ANSI_PC_LENGTH + ANSI_PC_LENGTH + SLS_LENGTH) |
146 | 0 | #define ANSI_HEADER_LENGTH (SIO_LENGTH + ANSI_ROUTING_LABEL_LENGTH) |
147 | | |
148 | 0 | #define ANSI_DPC_OFFSET ROUTING_LABEL_OFFSET |
149 | 0 | #define ANSI_OPC_OFFSET (ANSI_DPC_OFFSET + ANSI_PC_LENGTH) |
150 | 0 | #define ANSI_SLS_OFFSET (ANSI_OPC_OFFSET + ANSI_PC_LENGTH) |
151 | 0 | #define ANSI_MTP_PAYLOAD_OFFSET (SIO_OFFSET + ANSI_HEADER_LENGTH) |
152 | | |
153 | 0 | #define JAPAN_SLS_SPARE_LENGTH 1 |
154 | 0 | #define JAPAN_ROUTING_LABEL_LENGTH (JAPAN_PC_LENGTH + JAPAN_PC_LENGTH + JAPAN_SLS_SPARE_LENGTH) |
155 | 0 | #define JAPAN_HEADER_LENGTH (SIO_LENGTH + JAPAN_ROUTING_LABEL_LENGTH) |
156 | | |
157 | 0 | #define JAPAN_OPC_OFFSET (ROUTING_LABEL_OFFSET + JAPAN_PC_LENGTH) |
158 | 0 | #define JAPAN_SLS_OFFSET (JAPAN_OPC_OFFSET + JAPAN_PC_LENGTH) |
159 | | #define JAPAN_SPARE_OFFSET (ROUTING_LABEL_OFFSET + JAPAN_ROUTING_LABEL_LENGTH) |
160 | 0 | #define JAPAN_MTP_PAYLOAD_OFFSET (SIO_OFFSET + JAPAN_HEADER_LENGTH) |
161 | | |
162 | 2.23k | #define SERVICE_INDICATOR_MASK 0x0F |
163 | 42 | #define SPARE_MASK 0x30 |
164 | 14 | #define ANSI_PRIORITY_MASK SPARE_MASK |
165 | 1.49k | #define NETWORK_INDICATOR_MASK 0xC0 |
166 | 753 | #define ITU_DPC_MASK 0x00003FFF |
167 | 753 | #define ITU_OPC_MASK 0x0FFFC000 |
168 | 14 | #define ITU_SLS_MASK 0xF0000000 |
169 | | |
170 | 14 | #define ANSI_5BIT_SLS_MASK 0x1F |
171 | 14 | #define ANSI_8BIT_SLS_MASK 0x0 |
172 | 14 | #define CHINESE_ITU_SLS_MASK 0xF |
173 | 14 | #define JAPAN_4_BIT_SLS_MASK 0xF |
174 | 14 | #define JAPAN_4_BIT_SLS_SPARE_MASK 0xF0 |
175 | 14 | #define JAPAN_5_BIT_SLS_MASK 0x1F |
176 | 14 | #define JAPAN_5_BIT_SLS_SPARE_MASK 0xE0 |
177 | | |
178 | | /* the higher values are taken from the M3UA RFC */ |
179 | | static const value_string mtp3_service_indicator_code_vals[] = { |
180 | | { MTP_SI_SNM, "Signalling Network Management Message (SNM)" }, |
181 | | { MTP_SI_MTN, "Maintenance Regular Message (MTN)" }, |
182 | | { MTP_SI_MTNS, "Maintenance Special Message (MTNS)" }, |
183 | | { MTP_SI_SCCP, "SCCP" }, |
184 | | { MTP_SI_TUP, "TUP" }, |
185 | | { MTP_SI_ISUP, "ISUP" }, |
186 | | { MTP_SI_DUP_CC, "DUP (call and circuit related messages)" }, |
187 | | { MTP_SI_DUP_FAC, "DUP (facility registration and cancellation message)" }, |
188 | | { MTP_SI_MTP_TEST, "MTP testing user part" }, |
189 | | { MTP_SI_ISUP_B, "Broadband ISUP" }, |
190 | | { MTP_SI_ISUP_S, "Satellite ISUP" }, |
191 | | { 0xb, "Spare" }, |
192 | | { MTP_SI_AAL2, "AAL type2 Signaling" }, |
193 | | { MTP_SI_BICC, "Bearer Independent Call Control (BICC)" }, |
194 | | { MTP_SI_GCP, "Gateway Control Protocol" }, |
195 | | { 0xf, "Spare" }, |
196 | | { 0, NULL } |
197 | | }; |
198 | | |
199 | | const value_string mtp3_service_indicator_code_short_vals[] = { |
200 | | { MTP_SI_SNM, "SNM" }, |
201 | | { MTP_SI_MTN, "MTN" }, |
202 | | { MTP_SI_MTNS, "MTNS" }, |
203 | | { MTP_SI_SCCP, "SCCP" }, |
204 | | { MTP_SI_TUP, "TUP" }, |
205 | | { MTP_SI_ISUP, "ISUP" }, |
206 | | { MTP_SI_DUP_CC, "DUP (CC)" }, |
207 | | { MTP_SI_DUP_FAC, "DUP (FAC/CANC)" }, |
208 | | { MTP_SI_MTP_TEST, "MTP Test" }, |
209 | | { MTP_SI_ISUP_B, "ISUP-b" }, |
210 | | { MTP_SI_ISUP_S, "ISUP-s" }, |
211 | | { MTP_SI_AAL2, "AAL type 2" }, |
212 | | { MTP_SI_BICC, "BICC" }, |
213 | | { MTP_SI_GCP, "GCP" }, |
214 | | { 0, NULL } |
215 | | }; |
216 | | |
217 | | const value_string mtp3_network_indicator_vals[] = { |
218 | | { MTP3_NI_INT0, "International network" }, |
219 | | { MTP3_NI_INT1, "Spare (for international use only)" }, |
220 | | { MTP3_NI_NAT0, "National network" }, |
221 | | { MTP3_NI_NAT1, "Reserved for national use" }, |
222 | | { 0, NULL } |
223 | | }; |
224 | | |
225 | | |
226 | | /* |
227 | | * helper routine to format a point code in structured form |
228 | | */ |
229 | | |
230 | | char* |
231 | | mtp3_pc_to_str(wmem_allocator_t* allocator, const uint32_t pc) |
232 | 0 | { |
233 | 0 | switch (mtp3_standard) |
234 | 0 | { |
235 | 0 | case ITU_STANDARD: |
236 | 0 | switch (itu_pc_structure) { |
237 | 0 | case ITU_PC_STRUCTURE_NONE: |
238 | 0 | return wmem_strdup_printf(allocator, "%u", pc); |
239 | | |
240 | 0 | case ITU_PC_STRUCTURE_3_8_3: |
241 | | /* this format is used in international ITU networks */ |
242 | 0 | return wmem_strdup_printf(allocator, "%u-%u-%u", (pc & 0x3800)>>11, (pc & 0x7f8) >> 3, (pc & 0x07) >> 0); |
243 | | |
244 | 0 | case ITU_PC_STRUCTURE_4_3_4_3: |
245 | | /* this format is used in some national ITU networks, the German one for example. */ |
246 | 0 | return wmem_strdup_printf(allocator, "%u-%u-%u-%u", (pc & 0x3c00) >>10, (pc & 0x0380) >> 7, (pc & 0x0078) >> 3, (pc & 0x0007) >> 0); |
247 | | |
248 | 0 | default: |
249 | 0 | DISSECTOR_ASSERT_NOT_REACHED(); |
250 | 0 | return wmem_strdup(allocator, ""); |
251 | 0 | } |
252 | 0 | break; |
253 | 0 | case ANSI_STANDARD: |
254 | 0 | case CHINESE_ITU_STANDARD: |
255 | 0 | return wmem_strdup_printf(allocator, "%u-%u-%u", (pc & ANSI_NETWORK_MASK) >> 16, (pc & ANSI_CLUSTER_MASK) >> 8, (pc & ANSI_MEMBER_MASK)); |
256 | | |
257 | 0 | case JAPAN_STANDARD: |
258 | 0 | switch (japan_pc_structure) { |
259 | 0 | case JAPAN_PC_STRUCTURE_NONE: |
260 | 0 | return wmem_strdup_printf(allocator, "%u", pc); |
261 | | |
262 | 0 | case JAPAN_PC_STRUCTURE_7_4_5: |
263 | | /* This format is specified by NTT */ |
264 | 0 | return wmem_strdup_printf(allocator, "%u-%u-%u", (pc & 0xfe00)>>9, (pc & 0x1e0)>>5, (pc & 0x1f)); |
265 | | |
266 | 0 | case JAPAN_PC_STRUCTURE_3_4_4_5: |
267 | | /* Where does this format come from? */ |
268 | 0 | return wmem_strdup_printf(allocator, "%u-%u-%u-%u", (pc & 0xe000)>>13, (pc & 0x1e00)>>9, (pc & 0x1e0)>>5, (pc & 0x1f)); |
269 | | |
270 | 0 | default: |
271 | 0 | DISSECTOR_ASSERT_NOT_REACHED(); |
272 | 0 | return wmem_strdup(allocator, ""); |
273 | 0 | } |
274 | 0 | break; |
275 | 0 | default: |
276 | 0 | DISSECTOR_ASSERT_NOT_REACHED(); |
277 | 0 | return wmem_strdup(allocator, ""); |
278 | 0 | } |
279 | 0 | } |
280 | | |
281 | | bool |
282 | | mtp3_pc_structured(void) |
283 | 1.48k | { |
284 | 1.48k | if ((mtp3_standard == ITU_STANDARD) && (itu_pc_structure == ITU_PC_STRUCTURE_NONE)) |
285 | 1.48k | return false; |
286 | 0 | else if ((mtp3_standard == JAPAN_STANDARD) && (japan_pc_structure == JAPAN_PC_STRUCTURE_NONE)) |
287 | 0 | return false; |
288 | 0 | else |
289 | 0 | return true; |
290 | 1.48k | } |
291 | | |
292 | | /* |
293 | | * helper routine to format address to string |
294 | | */ |
295 | | |
296 | | static char* |
297 | | mtp3_addr_to_str_wmem(wmem_allocator_t* allocator, const mtp3_addr_pc_t *addr_pc_p) |
298 | 0 | { |
299 | 0 | switch (mtp3_addr_fmt) |
300 | 0 | { |
301 | 0 | case MTP3_ADDR_FMT_DEC: |
302 | 0 | switch (addr_pc_p->type) |
303 | 0 | { |
304 | 0 | case ITU_STANDARD: |
305 | 0 | return wmem_strdup_printf(allocator, "%u", addr_pc_p->pc & ITU_PC_MASK); |
306 | 0 | case JAPAN_STANDARD: |
307 | 0 | return wmem_strdup_printf(allocator, "%u", addr_pc_p->pc & JAPAN_PC_MASK); |
308 | 0 | default: |
309 | | /* assuming 24-bit */ |
310 | 0 | return wmem_strdup_printf(allocator, "%u", addr_pc_p->pc & ANSI_PC_MASK); |
311 | 0 | } |
312 | 0 | break; |
313 | | |
314 | 0 | case MTP3_ADDR_FMT_HEX: |
315 | 0 | switch (addr_pc_p->type) |
316 | 0 | { |
317 | 0 | case ITU_STANDARD: |
318 | 0 | return wmem_strdup_printf(allocator, "%x", addr_pc_p->pc & ITU_PC_MASK); |
319 | 0 | case JAPAN_STANDARD: |
320 | 0 | return wmem_strdup_printf(allocator, "%x", addr_pc_p->pc & JAPAN_PC_MASK); |
321 | 0 | default: |
322 | | /* assuming 24-bit */ |
323 | 0 | return wmem_strdup_printf(allocator, "%x", addr_pc_p->pc & ANSI_PC_MASK); |
324 | 0 | } |
325 | 0 | break; |
326 | | |
327 | 0 | case MTP3_ADDR_FMT_NI_DEC: |
328 | 0 | switch (addr_pc_p->type) |
329 | 0 | { |
330 | 0 | case ITU_STANDARD: |
331 | 0 | return wmem_strdup_printf(allocator, "%u:%u", addr_pc_p->ni, addr_pc_p->pc & ITU_PC_MASK); |
332 | 0 | case JAPAN_STANDARD: |
333 | 0 | return wmem_strdup_printf(allocator, "%u:%u", addr_pc_p->ni, addr_pc_p->pc & JAPAN_PC_MASK); |
334 | 0 | default: |
335 | | /* assuming 24-bit */ |
336 | 0 | return wmem_strdup_printf(allocator, "%u:%u", addr_pc_p->ni, addr_pc_p->pc & ANSI_PC_MASK); |
337 | 0 | } |
338 | 0 | break; |
339 | | |
340 | 0 | case MTP3_ADDR_FMT_NI_HEX: |
341 | 0 | switch (addr_pc_p->type) |
342 | 0 | { |
343 | 0 | case ITU_STANDARD: |
344 | 0 | return wmem_strdup_printf(allocator, "%u:%x", addr_pc_p->ni, addr_pc_p->pc & ITU_PC_MASK); |
345 | 0 | case JAPAN_STANDARD: |
346 | 0 | return wmem_strdup_printf(allocator, "%u:%x", addr_pc_p->ni, addr_pc_p->pc & JAPAN_PC_MASK); |
347 | 0 | default: |
348 | | /* assuming 24-bit */ |
349 | 0 | return wmem_strdup_printf(allocator, "%u:%x", addr_pc_p->ni, addr_pc_p->pc & ANSI_PC_MASK); |
350 | 0 | } |
351 | 0 | break; |
352 | | |
353 | 0 | default: |
354 | | /* FALLTHRU */ |
355 | |
|
356 | 0 | case MTP3_ADDR_FMT_DASHED: |
357 | 0 | return mtp3_pc_to_str(allocator, addr_pc_p->pc); |
358 | 0 | } |
359 | 0 | } |
360 | | |
361 | | uint32_t |
362 | 455 | mtp3_pc_hash(const mtp3_addr_pc_t *addr_pc_p) { |
363 | 455 | uint32_t pc; |
364 | | |
365 | 455 | switch (addr_pc_p->type) |
366 | 455 | { |
367 | 455 | case ITU_STANDARD: |
368 | 455 | pc = (addr_pc_p->pc & ITU_PC_MASK) | ((addr_pc_p->ni % 4) << 14) ; |
369 | 455 | break; |
370 | 0 | default: |
371 | | /* assuming 24-bit */ |
372 | 0 | pc = (addr_pc_p->pc & ANSI_PC_MASK) | ((addr_pc_p->ni) << 24) ; |
373 | 0 | break; |
374 | 455 | } |
375 | | |
376 | 455 | return pc; |
377 | 455 | } |
378 | | |
379 | | static int mtp3_addr_to_str(const address* addr, char *buf, int buf_len) |
380 | 0 | { |
381 | 0 | char* tmp = mtp3_addr_to_str_wmem(NULL, (const mtp3_addr_pc_t*)addr->data); |
382 | 0 | memcpy(buf, tmp, MIN(buf_len, (int)(strlen(tmp)+1))); |
383 | 0 | wmem_free(NULL, tmp); |
384 | 0 | return (int)(strlen(buf)+1); |
385 | 0 | } |
386 | | |
387 | | static int mtp3_str_addr_len(const address* addr _U_) |
388 | 0 | { |
389 | 0 | return 50; |
390 | 0 | } |
391 | | |
392 | | static const char* mtp3_addr_col_filter_str(const address* addr _U_, bool is_src) |
393 | 0 | { |
394 | 0 | if (is_src) |
395 | 0 | return "mtp3.opc"; |
396 | | |
397 | 0 | return "mtp3.dpc"; |
398 | 0 | } |
399 | | |
400 | | static int mtp3_addr_len(void) |
401 | 1.47k | { |
402 | 1.47k | return sizeof(mtp3_addr_pc_t); |
403 | 1.47k | } |
404 | | |
405 | | static const char* mtp3_addr_name_res_str(const address* addr) |
406 | 0 | { |
407 | 0 | const mtp3_addr_pc_t *mtp3_addr = (const mtp3_addr_pc_t *)addr->data; |
408 | 0 | const char *tmp; |
409 | |
|
410 | 0 | tmp = get_hostname_ss7pc(mtp3_addr->ni, mtp3_addr->pc); |
411 | |
|
412 | 0 | if (tmp[0] == '\0') { |
413 | 0 | char* str = mtp3_addr_to_str_wmem(NULL, mtp3_addr); |
414 | 0 | fill_unresolved_ss7pc(str, mtp3_addr->ni, mtp3_addr->pc); |
415 | 0 | wmem_free(NULL, str); |
416 | 0 | return get_hostname_ss7pc(mtp3_addr->ni, mtp3_addr->pc); |
417 | 0 | } |
418 | 0 | return tmp; |
419 | |
|
420 | 0 | } |
421 | | |
422 | | static int mtp3_addr_name_res_len(void) |
423 | 0 | { |
424 | 0 | return MAXNAMELEN; |
425 | 0 | } |
426 | | |
427 | | |
428 | | |
429 | | |
430 | | /* Common function for dissecting 3-byte (ANSI or China) PCs. */ |
431 | | void |
432 | | dissect_mtp3_3byte_pc(tvbuff_t *tvb, packet_info* pinfo, unsigned offset, proto_tree *tree, int ett_pc, int hf_pc_string, int hf_pc_network, |
433 | | int hf_pc_cluster, int hf_pc_member, int hf_dpc, int hf_pc) |
434 | 0 | { |
435 | 0 | uint32_t pc; |
436 | 0 | proto_item *pc_item, *hidden_item; |
437 | 0 | proto_tree *pc_tree; |
438 | 0 | char* pc_string; |
439 | |
|
440 | 0 | pc = tvb_get_letoh24(tvb, offset); |
441 | 0 | pc_string = mtp3_pc_to_str(pinfo->pool, pc); |
442 | 0 | pc_item = proto_tree_add_string(tree, hf_pc_string, tvb, offset, ANSI_PC_LENGTH, pc_string); |
443 | | |
444 | | /* Add alternate formats of the PC |
445 | | * NOTE: each of these formats is shown to the user, |
446 | | * so I think that using hidden fields in this case is OK. |
447 | | */ |
448 | 0 | pc_string = wmem_strdup_printf(pinfo->pool, "%u", pc); |
449 | 0 | proto_item_append_text(pc_item, " (%s)", pc_string); |
450 | 0 | hidden_item = proto_tree_add_string(tree, hf_pc_string, tvb, offset, ANSI_PC_LENGTH, pc_string); |
451 | 0 | proto_item_set_hidden(hidden_item); |
452 | |
|
453 | 0 | pc_string = wmem_strdup_printf(pinfo->pool, "0x%x", pc); |
454 | 0 | proto_item_append_text(pc_item, " (%s)", pc_string); |
455 | 0 | hidden_item = proto_tree_add_string(tree, hf_pc_string, tvb, offset, ANSI_PC_LENGTH, pc_string); |
456 | 0 | proto_item_set_hidden(hidden_item); |
457 | |
|
458 | 0 | pc_tree = proto_item_add_subtree(pc_item, ett_pc); |
459 | |
|
460 | 0 | proto_tree_add_uint(pc_tree, hf_pc_network, tvb, offset + ANSI_NETWORK_OFFSET, ANSI_NCM_LENGTH, pc); |
461 | 0 | proto_tree_add_uint(pc_tree, hf_pc_cluster, tvb, offset + ANSI_CLUSTER_OFFSET, ANSI_NCM_LENGTH, pc); |
462 | 0 | proto_tree_add_uint(pc_tree, hf_pc_member, tvb, offset + ANSI_MEMBER_OFFSET, ANSI_NCM_LENGTH, pc); |
463 | | |
464 | | /* add full integer values of DPC as hidden for filtering purposes */ |
465 | 0 | if (hf_dpc) { |
466 | 0 | hidden_item = proto_tree_add_uint(pc_tree, hf_dpc, tvb, offset, ANSI_PC_LENGTH, pc); |
467 | 0 | proto_item_set_hidden(hidden_item); |
468 | 0 | } |
469 | 0 | if (hf_pc) { |
470 | 0 | hidden_item = proto_tree_add_uint(pc_tree, hf_pc, tvb, offset, ANSI_PC_LENGTH, pc); |
471 | 0 | proto_item_set_hidden(hidden_item); |
472 | 0 | } |
473 | 0 | } |
474 | | |
475 | | static void |
476 | | dissect_mtp3_sio(tvbuff_t *tvb, proto_tree *mtp3_tree, |
477 | | mtp3_addr_pc_t *mtp3_addr_opc, mtp3_addr_pc_t *mtp3_addr_dpc) |
478 | 739 | { |
479 | 739 | uint8_t sio; |
480 | 739 | proto_tree *sio_tree; |
481 | | |
482 | 739 | sio_tree = proto_tree_add_subtree(mtp3_tree, tvb, SIO_OFFSET, SIO_LENGTH, ett_mtp3_sio, NULL, "Service information octet"); |
483 | | |
484 | 739 | sio = tvb_get_uint8(tvb, SIO_OFFSET); |
485 | 739 | proto_tree_add_uint(sio_tree, hf_mtp3_network_indicator, tvb, SIO_OFFSET, SIO_LENGTH, sio); |
486 | | |
487 | 739 | mtp3_addr_opc->ni = (sio & NETWORK_INDICATOR_MASK) >> 6; |
488 | 739 | mtp3_addr_dpc->ni = (sio & NETWORK_INDICATOR_MASK) >> 6; |
489 | | |
490 | 739 | switch(mtp3_standard){ |
491 | 0 | case ANSI_STANDARD: |
492 | 0 | proto_tree_add_uint(sio_tree, hf_mtp3_ansi_priority, tvb, SIO_OFFSET, SIO_LENGTH, sio); |
493 | 0 | break; |
494 | 739 | case ITU_STANDARD: |
495 | 739 | case CHINESE_ITU_STANDARD: |
496 | 739 | if (mtp3_show_itu_priority) |
497 | 0 | proto_tree_add_uint(sio_tree, hf_mtp3_itu_priority, tvb, SIO_OFFSET, SIO_LENGTH, sio); |
498 | 739 | else |
499 | 739 | proto_tree_add_uint(sio_tree, hf_mtp3_itu_spare, tvb, SIO_OFFSET, SIO_LENGTH, sio); |
500 | 739 | break; |
501 | 0 | case JAPAN_STANDARD: |
502 | | /* The Japan variant has priority but it's on the LI which belongs to |
503 | | * layer 2. Not sure what we can do about that... |
504 | | */ |
505 | 0 | proto_tree_add_uint(sio_tree, hf_mtp3_itu_spare, tvb, SIO_OFFSET, SIO_LENGTH, sio); |
506 | 0 | break; |
507 | 739 | } |
508 | | |
509 | 739 | proto_tree_add_uint(sio_tree, hf_mtp3_service_indicator, tvb, SIO_OFFSET, SIO_LENGTH, sio); |
510 | 739 | } |
511 | | |
512 | | static void |
513 | | dissect_mtp3_routing_label(tvbuff_t *tvb, packet_info *pinfo, proto_tree *mtp3_tree, |
514 | | mtp3_addr_pc_t *mtp3_addr_opc, mtp3_addr_pc_t *mtp3_addr_dpc) |
515 | 739 | { |
516 | 739 | uint32_t label, dpc, opc; |
517 | 739 | proto_item *label_dpc_item, *label_opc_item; |
518 | 739 | proto_item *hidden_item; |
519 | 739 | proto_tree *label_tree; |
520 | 739 | proto_tree *pc_subtree; |
521 | 739 | int hf_dpc_string; |
522 | 739 | int hf_opc_string; |
523 | | |
524 | | |
525 | 739 | switch (mtp3_standard) { |
526 | 739 | case ITU_STANDARD: |
527 | 739 | label_tree = proto_tree_add_subtree(mtp3_tree, tvb, ROUTING_LABEL_OFFSET, ITU_ROUTING_LABEL_LENGTH, ett_mtp3_label, NULL, "Routing label"); |
528 | | |
529 | 739 | label = tvb_get_letohl(tvb, ROUTING_LABEL_OFFSET); |
530 | | |
531 | 739 | opc = (label & ITU_OPC_MASK) >> 14; |
532 | 739 | dpc = label & ITU_DPC_MASK; |
533 | | |
534 | 739 | hidden_item = proto_tree_add_uint(label_tree, hf_mtp3_itu_pc, tvb, ROUTING_LABEL_OFFSET, ITU_ROUTING_LABEL_LENGTH, opc); |
535 | 739 | proto_item_set_hidden(hidden_item); |
536 | 739 | hidden_item = proto_tree_add_uint(label_tree, hf_mtp3_itu_pc, tvb, ROUTING_LABEL_OFFSET, ITU_ROUTING_LABEL_LENGTH, dpc); |
537 | 739 | proto_item_set_hidden(hidden_item); |
538 | | |
539 | 739 | label_dpc_item = proto_tree_add_uint(label_tree, hf_mtp3_itu_dpc, tvb, ROUTING_LABEL_OFFSET, ITU_ROUTING_LABEL_LENGTH, label); |
540 | 739 | if (mtp3_pc_structured()) |
541 | 0 | proto_item_append_text(label_dpc_item, " (%s)", mtp3_pc_to_str(pinfo->pool, dpc)); |
542 | | |
543 | 739 | if(mtp3_addr_dpc->ni == MTP3_NI_INT0) { |
544 | 320 | pc_subtree = proto_item_add_subtree(label_dpc_item, ett_mtp3_label_dpc); |
545 | 320 | analyze_q708_ispc(tvb, pc_subtree, ROUTING_LABEL_OFFSET, ITU_ROUTING_LABEL_LENGTH, dpc); |
546 | 320 | } |
547 | | |
548 | | |
549 | 739 | label_opc_item = proto_tree_add_uint(label_tree, hf_mtp3_itu_opc, tvb, ROUTING_LABEL_OFFSET, ITU_ROUTING_LABEL_LENGTH, label); |
550 | 739 | if (mtp3_pc_structured()) |
551 | 0 | proto_item_append_text(label_opc_item, " (%s)", mtp3_pc_to_str(pinfo->pool, opc)); |
552 | | |
553 | 739 | if(mtp3_addr_opc->ni == MTP3_NI_INT0) { |
554 | 320 | pc_subtree = proto_item_add_subtree(label_opc_item, ett_mtp3_label_opc); |
555 | 320 | analyze_q708_ispc(tvb, pc_subtree, ROUTING_LABEL_OFFSET, ITU_ROUTING_LABEL_LENGTH, opc); |
556 | 320 | } |
557 | | |
558 | 739 | proto_tree_add_uint(label_tree, hf_mtp3_itu_sls, tvb, ROUTING_LABEL_OFFSET, ITU_ROUTING_LABEL_LENGTH, label); |
559 | 739 | break; |
560 | | |
561 | 0 | case ANSI_STANDARD: |
562 | 0 | case CHINESE_ITU_STANDARD: |
563 | 0 | if (mtp3_standard == ANSI_STANDARD) |
564 | 0 | { |
565 | 0 | hf_dpc_string = hf_mtp3_ansi_dpc; |
566 | 0 | hf_opc_string = hf_mtp3_ansi_opc; |
567 | 0 | } else /* CHINESE_ITU_STANDARD */ { |
568 | 0 | hf_dpc_string = hf_mtp3_chinese_dpc; |
569 | 0 | hf_opc_string = hf_mtp3_chinese_opc; |
570 | 0 | } |
571 | | |
572 | | /* Create the Routing Label Tree */ |
573 | 0 | label_tree = proto_tree_add_subtree(mtp3_tree, tvb, ROUTING_LABEL_OFFSET, ANSI_ROUTING_LABEL_LENGTH, ett_mtp3_label, NULL, "Routing label"); |
574 | | |
575 | | /* create and fill the DPC tree */ |
576 | 0 | dissect_mtp3_3byte_pc(tvb, pinfo, ANSI_DPC_OFFSET, label_tree, ett_mtp3_label_dpc, hf_dpc_string, hf_mtp3_dpc_network, |
577 | 0 | hf_mtp3_dpc_cluster, hf_mtp3_dpc_member, hf_mtp3_24bit_dpc, hf_mtp3_24bit_pc); |
578 | | /* Store dpc for mtp3_addr below */ |
579 | 0 | dpc = tvb_get_letoh24(tvb, ANSI_DPC_OFFSET); |
580 | | |
581 | | /* create and fill the OPC tree */ |
582 | 0 | dissect_mtp3_3byte_pc(tvb, pinfo, ANSI_OPC_OFFSET, label_tree, ett_mtp3_label_opc, hf_opc_string, hf_mtp3_opc_network, |
583 | 0 | hf_mtp3_opc_cluster, hf_mtp3_opc_member, hf_mtp3_24bit_opc, hf_mtp3_24bit_pc); |
584 | | /* Store opc for mtp3_addr below */ |
585 | 0 | opc = tvb_get_letoh24(tvb, ANSI_OPC_OFFSET); |
586 | | |
587 | | /* SLS */ |
588 | 0 | if (mtp3_standard == ANSI_STANDARD) { |
589 | 0 | if (mtp3_use_ansi_5_bit_sls) |
590 | 0 | proto_tree_add_item(label_tree, hf_mtp3_ansi_5_bit_sls, tvb, ANSI_SLS_OFFSET, SLS_LENGTH, ENC_LITTLE_ENDIAN); |
591 | 0 | else |
592 | 0 | proto_tree_add_item(label_tree, hf_mtp3_ansi_8_bit_sls, tvb, ANSI_SLS_OFFSET, SLS_LENGTH, ENC_LITTLE_ENDIAN); |
593 | 0 | } else /* CHINESE_ITU_STANDARD */ { |
594 | 0 | proto_tree_add_item(label_tree, hf_mtp3_chinese_itu_sls, tvb, ANSI_SLS_OFFSET, SLS_LENGTH, ENC_LITTLE_ENDIAN); |
595 | 0 | } |
596 | 0 | break; |
597 | | |
598 | 0 | case JAPAN_STANDARD: |
599 | 0 | label_tree = proto_tree_add_subtree(mtp3_tree, tvb, ROUTING_LABEL_OFFSET, JAPAN_ROUTING_LABEL_LENGTH, ett_mtp3_label, NULL, "Routing label"); |
600 | |
|
601 | 0 | label_dpc_item = proto_tree_add_item(label_tree, hf_mtp3_japan_dpc, tvb, ROUTING_LABEL_OFFSET, JAPAN_PC_LENGTH, ENC_LITTLE_ENDIAN); |
602 | 0 | dpc = tvb_get_letohs(tvb, ROUTING_LABEL_OFFSET); |
603 | 0 | if (mtp3_pc_structured()) { |
604 | 0 | proto_item_append_text(label_dpc_item, " (%s)", mtp3_pc_to_str(pinfo->pool, dpc)); |
605 | 0 | } |
606 | |
|
607 | 0 | label_opc_item = proto_tree_add_item(label_tree, hf_mtp3_japan_opc, tvb, JAPAN_OPC_OFFSET, JAPAN_PC_LENGTH, ENC_LITTLE_ENDIAN); |
608 | 0 | opc = tvb_get_letohs(tvb, JAPAN_OPC_OFFSET); |
609 | 0 | if (mtp3_pc_structured()) { |
610 | 0 | proto_item_append_text(label_opc_item, " (%s)", mtp3_pc_to_str(pinfo->pool, opc)); |
611 | 0 | } |
612 | |
|
613 | 0 | hidden_item = proto_tree_add_item(label_tree, hf_mtp3_japan_pc, tvb, ROUTING_LABEL_OFFSET, JAPAN_PC_LENGTH, ENC_LITTLE_ENDIAN); |
614 | 0 | proto_item_set_hidden(hidden_item); |
615 | 0 | hidden_item = proto_tree_add_item(label_tree, hf_mtp3_japan_pc, tvb, JAPAN_OPC_OFFSET, JAPAN_PC_LENGTH, ENC_LITTLE_ENDIAN); |
616 | 0 | proto_item_set_hidden(hidden_item); |
617 | |
|
618 | 0 | if (mtp3_use_japan_5_bit_sls) { |
619 | 0 | proto_tree_add_item(label_tree, hf_mtp3_japan_5_bit_sls, tvb, JAPAN_SLS_OFFSET, JAPAN_SLS_SPARE_LENGTH, ENC_LITTLE_ENDIAN); |
620 | 0 | proto_tree_add_item(label_tree, hf_mtp3_japan_5_bit_sls_spare, tvb, JAPAN_SLS_OFFSET, JAPAN_SLS_SPARE_LENGTH, ENC_LITTLE_ENDIAN); |
621 | 0 | } else { |
622 | 0 | proto_tree_add_item(label_tree, hf_mtp3_japan_4_bit_sls, tvb, JAPAN_SLS_OFFSET, JAPAN_SLS_SPARE_LENGTH, ENC_LITTLE_ENDIAN); |
623 | 0 | proto_tree_add_item(label_tree, hf_mtp3_japan_4_bit_sls_spare, tvb, JAPAN_SLS_OFFSET, JAPAN_SLS_SPARE_LENGTH, ENC_LITTLE_ENDIAN); |
624 | 0 | } |
625 | |
|
626 | 0 | break; |
627 | 0 | default: |
628 | 0 | DISSECTOR_ASSERT_NOT_REACHED(); |
629 | 739 | } |
630 | | |
631 | 739 | mtp3_addr_opc->type = (Standard_Type)mtp3_standard; |
632 | 739 | mtp3_addr_opc->pc = opc; |
633 | 739 | set_address(&pinfo->src, mtp3_address_type, mtp3_addr_len(), (uint8_t *) mtp3_addr_opc); |
634 | | |
635 | 739 | mtp3_addr_dpc->type = (Standard_Type)mtp3_standard; |
636 | 739 | mtp3_addr_dpc->pc = dpc; |
637 | 739 | set_address(&pinfo->dst, mtp3_address_type, mtp3_addr_len(), (uint8_t *) mtp3_addr_dpc); |
638 | 739 | } |
639 | | |
640 | | static void |
641 | | dissect_mtp3_payload(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) |
642 | 739 | { |
643 | 739 | uint8_t sio; |
644 | 739 | uint8_t service_indicator; |
645 | 739 | tvbuff_t *payload_tvb = NULL; |
646 | | |
647 | 739 | sio = tvb_get_uint8(tvb, SIO_OFFSET); |
648 | 739 | service_indicator = sio & SERVICE_INDICATOR_MASK; |
649 | | |
650 | 739 | switch (mtp3_standard) { |
651 | 739 | case ITU_STANDARD: |
652 | 739 | payload_tvb = tvb_new_subset_remaining(tvb, ITU_MTP_PAYLOAD_OFFSET); |
653 | 739 | break; |
654 | 0 | case ANSI_STANDARD: |
655 | 0 | case CHINESE_ITU_STANDARD: |
656 | 0 | payload_tvb = tvb_new_subset_remaining(tvb, ANSI_MTP_PAYLOAD_OFFSET); |
657 | 0 | break; |
658 | 0 | case JAPAN_STANDARD: |
659 | 0 | payload_tvb = tvb_new_subset_remaining(tvb, JAPAN_MTP_PAYLOAD_OFFSET); |
660 | 0 | break; |
661 | 0 | default: |
662 | 0 | DISSECTOR_ASSERT_NOT_REACHED(); |
663 | 739 | } |
664 | | |
665 | 739 | col_set_str(pinfo->cinfo, COL_INFO, "DATA "); |
666 | | |
667 | 739 | if (!dissector_try_uint(mtp3_sio_dissector_table, service_indicator, payload_tvb, pinfo, tree)) |
668 | 3 | call_data_dissector(payload_tvb, pinfo, tree); |
669 | 739 | } |
670 | | |
671 | | static unsigned |
672 | | heur_mtp3_standard(tvbuff_t *tvb, packet_info *pinfo, uint8_t si) |
673 | 0 | { |
674 | 0 | tvbuff_t *payload; |
675 | |
|
676 | 0 | switch (si) { |
677 | 0 | case MTP_SI_SCCP: |
678 | 0 | { |
679 | 0 | payload = tvb_new_subset_remaining(tvb, ITU_HEADER_LENGTH); |
680 | 0 | if (looks_like_valid_sccp(pinfo->num, payload, ITU_STANDARD)) { |
681 | 0 | return ITU_STANDARD; |
682 | 0 | } |
683 | 0 | payload = tvb_new_subset_remaining(tvb, ANSI_HEADER_LENGTH); |
684 | 0 | if (looks_like_valid_sccp(pinfo->num, payload, ANSI_STANDARD)) { |
685 | 0 | return ANSI_STANDARD; |
686 | 0 | } |
687 | 0 | payload = tvb_new_subset_remaining(tvb, ANSI_HEADER_LENGTH); |
688 | 0 | if (looks_like_valid_sccp(pinfo->num, payload, CHINESE_ITU_STANDARD)) { |
689 | 0 | return CHINESE_ITU_STANDARD; |
690 | 0 | } |
691 | 0 | payload = tvb_new_subset_remaining(tvb, JAPAN_HEADER_LENGTH); |
692 | 0 | if (looks_like_valid_sccp(pinfo->num, payload, JAPAN_STANDARD)) { |
693 | 0 | return JAPAN_STANDARD; |
694 | 0 | } |
695 | | |
696 | 0 | return HEURISTIC_FAILED_STANDARD; |
697 | |
|
698 | 0 | } |
699 | 0 | default: |
700 | 0 | return HEURISTIC_FAILED_STANDARD; |
701 | 0 | } |
702 | |
|
703 | 0 | } |
704 | | |
705 | | static void |
706 | | reset_mtp3_standard(void) |
707 | 0 | { |
708 | 0 | mtp3_standard = pref_mtp3_standard; |
709 | 0 | } |
710 | | |
711 | | /* Code to actually dissect the packets */ |
712 | | static int |
713 | | dissect_mtp3(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) |
714 | 739 | { |
715 | 739 | mtp3_tap_rec_t* tap_rec = wmem_new0(pinfo->pool, mtp3_tap_rec_t); |
716 | 739 | int heuristic_standard; |
717 | 739 | uint8_t si; |
718 | 739 | mtp3_addr_pc_t* mtp3_addr_dpc; |
719 | 739 | mtp3_addr_pc_t* mtp3_addr_opc; |
720 | | |
721 | | /* Set up structures needed to add the protocol subtree and manage it */ |
722 | 739 | proto_item *mtp3_item = NULL, *gen_item; |
723 | 739 | proto_tree *mtp3_tree; |
724 | | |
725 | 739 | pref_mtp3_standard = mtp3_standard; |
726 | | |
727 | 739 | mtp3_item = proto_tree_add_item(tree, proto_mtp3, tvb, 0, -1, ENC_NA); |
728 | | |
729 | 739 | si = tvb_get_uint8(tvb, SIO_OFFSET) & SERVICE_INDICATOR_MASK; |
730 | 739 | if (mtp3_heuristic_standard) { |
731 | 0 | heuristic_standard = heur_mtp3_standard(tvb, pinfo, si); |
732 | 0 | if (heuristic_standard == HEURISTIC_FAILED_STANDARD) { |
733 | 0 | gen_item = proto_tree_add_uint_format(tree, hf_mtp3_heuristic_standard, tvb, 0, 0, mtp3_standard, |
734 | 0 | "Could not determine Heuristic using %s", val_to_str_const(mtp3_standard, mtp3_standard_vals, "unknown")); |
735 | 0 | } else { |
736 | 0 | gen_item = proto_tree_add_uint_format(tree, hf_mtp3_heuristic_standard, tvb, 0, 0, heuristic_standard, |
737 | 0 | "%s", val_to_str_const(heuristic_standard, mtp3_standard_vals, "unknown")); |
738 | 0 | mtp3_standard = heuristic_standard; |
739 | | |
740 | | /* Register a frame-end routine to ensure mtp3_standard is set |
741 | | * back even if an exception is thrown. |
742 | | */ |
743 | 0 | register_frame_end_routine(pinfo, reset_mtp3_standard); |
744 | 0 | } |
745 | 0 | proto_item_set_generated(gen_item); |
746 | 0 | } |
747 | | |
748 | | /* Make entries in Protocol column on summary display */ |
749 | 739 | switch(mtp3_standard) { |
750 | 739 | case ITU_STANDARD: |
751 | 739 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "MTP3 (Int. ITU)"); |
752 | 739 | proto_item_set_len(mtp3_item, ITU_HEADER_LENGTH); |
753 | 739 | break; |
754 | 0 | case ANSI_STANDARD: |
755 | 0 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "MTP3 (ANSI)"); |
756 | 0 | proto_item_set_len(mtp3_item, ANSI_HEADER_LENGTH); |
757 | 0 | break; |
758 | 0 | case CHINESE_ITU_STANDARD: |
759 | 0 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "MTP3 (Chin. ITU)"); |
760 | 0 | proto_item_set_len(mtp3_item, ANSI_HEADER_LENGTH); |
761 | 0 | break; |
762 | 0 | case JAPAN_STANDARD: |
763 | 0 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "MTP3 (Japan)"); |
764 | 0 | proto_item_set_len(mtp3_item, JAPAN_HEADER_LENGTH); |
765 | 0 | break; |
766 | 739 | }; |
767 | | |
768 | | /* create display subtree for the protocol */ |
769 | 739 | mtp3_tree = proto_item_add_subtree(mtp3_item, ett_mtp3); |
770 | | |
771 | 739 | mtp3_addr_opc = wmem_new0(pinfo->pool, mtp3_addr_pc_t); |
772 | 739 | mtp3_addr_dpc = wmem_new0(pinfo->pool, mtp3_addr_pc_t); |
773 | | |
774 | | /* Dissect the packet (even if !tree so can call sub-dissectors and update |
775 | | * the source and destination address columns) */ |
776 | 739 | dissect_mtp3_sio(tvb, mtp3_tree, mtp3_addr_opc, mtp3_addr_dpc); |
777 | 739 | dissect_mtp3_routing_label(tvb, pinfo, mtp3_tree, mtp3_addr_opc, mtp3_addr_dpc); |
778 | | |
779 | 739 | memcpy(&(tap_rec->addr_opc), mtp3_addr_opc, sizeof(mtp3_addr_pc_t)); |
780 | 739 | memcpy(&(tap_rec->addr_dpc), mtp3_addr_dpc, sizeof(mtp3_addr_pc_t)); |
781 | | |
782 | 739 | tap_rec->mtp3_si_code = (tvb_get_uint8(tvb, SIO_OFFSET) & SERVICE_INDICATOR_MASK); |
783 | 739 | tap_rec->size = tvb_reported_length(tvb); |
784 | | |
785 | 739 | tap_queue_packet(mtp3_tap, pinfo, tap_rec); |
786 | | |
787 | 739 | dissect_mtp3_payload(tvb, pinfo, tree); |
788 | | |
789 | 739 | mtp3_standard = pref_mtp3_standard; |
790 | 739 | return tvb_captured_length(tvb); |
791 | 739 | } |
792 | | |
793 | | /* TAP STAT INFO */ |
794 | | |
795 | | typedef enum |
796 | | { |
797 | | OPC_COLUMN, |
798 | | DPC_COLUMN, |
799 | | SI_COLUMN, |
800 | | NUM_MSUS_COLUMN, |
801 | | NUM_BYTES_COLUMN, |
802 | | AVG_BYTES_COLUMN |
803 | | } mtp3_stat_columns; |
804 | | |
805 | | static stat_tap_table_item mtp3_stat_fields[] = { |
806 | | {TABLE_ITEM_STRING, TAP_ALIGN_LEFT, "OPC", "%-25s"}, |
807 | | {TABLE_ITEM_STRING, TAP_ALIGN_LEFT, "DPC", "%-25s"}, |
808 | | {TABLE_ITEM_STRING, TAP_ALIGN_LEFT, "SI", "%-25s"}, |
809 | | {TABLE_ITEM_UINT, TAP_ALIGN_RIGHT, "MSUs", "%d"}, |
810 | | {TABLE_ITEM_UINT, TAP_ALIGN_RIGHT, "Bytes", "%d"}, |
811 | | {TABLE_ITEM_FLOAT, TAP_ALIGN_RIGHT, "Avg Bytes", "%f"}, |
812 | | }; |
813 | | |
814 | | static void mtp3_stat_init(stat_tap_table_ui* new_stat) |
815 | 0 | { |
816 | 0 | const char *table_name = "MTP3 Statistics"; |
817 | 0 | int num_fields = array_length(mtp3_stat_fields); |
818 | 0 | stat_tap_table *table; |
819 | |
|
820 | 0 | table = stat_tap_find_table(new_stat, table_name); |
821 | 0 | if (table) { |
822 | 0 | if (new_stat->stat_tap_reset_table_cb) { |
823 | 0 | new_stat->stat_tap_reset_table_cb(table); |
824 | 0 | } |
825 | 0 | return; |
826 | 0 | } |
827 | | |
828 | 0 | table = stat_tap_init_table(table_name, num_fields, 0, NULL); |
829 | 0 | stat_tap_add_table(new_stat, table); |
830 | 0 | } |
831 | | |
832 | | static tap_packet_status |
833 | | mtp3_stat_packet(void *tapdata, packet_info *pinfo, epan_dissect_t *edt _U_, const void *m3tr_ptr, tap_flags_t flags _U_) |
834 | 0 | { |
835 | 0 | stat_data_t* stat_data = (stat_data_t*)tapdata; |
836 | 0 | const mtp3_tap_rec_t *m3tr = (const mtp3_tap_rec_t *)m3tr_ptr; |
837 | 0 | bool found = false; |
838 | 0 | unsigned element; |
839 | 0 | stat_tap_table* table; |
840 | 0 | stat_tap_table_item_type* item_data; |
841 | 0 | unsigned msu_count; |
842 | 0 | unsigned byte_count; |
843 | 0 | double avg_bytes = 0.0; |
844 | |
|
845 | 0 | if (m3tr->mtp3_si_code >= MTP3_NUM_SI_CODE) |
846 | 0 | { |
847 | | /* |
848 | | * we thought this si_code was not used ? |
849 | | * is MTP3_NUM_SI_CODE out of date ? |
850 | | */ |
851 | 0 | return TAP_PACKET_DONT_REDRAW; |
852 | 0 | } |
853 | | |
854 | | /* |
855 | | * look for opc/dpc pair |
856 | | */ |
857 | 0 | table = g_array_index(stat_data->stat_tap_data->tables, stat_tap_table*, 0); |
858 | 0 | for (element = 0; element < table->num_elements; element++) |
859 | 0 | { |
860 | 0 | stat_tap_table_item_type *opc_data, *dpc_data, *si_data; |
861 | 0 | opc_data = stat_tap_get_field_data(table, element, OPC_COLUMN); |
862 | 0 | dpc_data = stat_tap_get_field_data(table, element, DPC_COLUMN); |
863 | 0 | si_data = stat_tap_get_field_data(table, element, SI_COLUMN); |
864 | |
|
865 | 0 | if (memcmp(&m3tr->addr_opc, opc_data->user_data.ptr_value, sizeof(mtp3_addr_pc_t)) == 0) |
866 | 0 | { |
867 | 0 | if (memcmp(&m3tr->addr_dpc, dpc_data->user_data.ptr_value, sizeof(mtp3_addr_pc_t)) == 0) |
868 | 0 | { |
869 | 0 | if (m3tr->mtp3_si_code == si_data->user_data.uint_value) |
870 | 0 | { |
871 | 0 | found = true; |
872 | 0 | break; |
873 | 0 | } |
874 | 0 | } |
875 | 0 | } |
876 | 0 | } |
877 | |
|
878 | 0 | if (!found) { |
879 | | /* Add a new row */ |
880 | | /* XXX The old version added a row per SI. */ |
881 | 0 | int num_fields = array_length(mtp3_stat_fields); |
882 | 0 | stat_tap_table_item_type items[array_length(mtp3_stat_fields)]; |
883 | 0 | const char *sis; |
884 | 0 | char *col_str; |
885 | |
|
886 | 0 | memset(items, 0, sizeof(items)); |
887 | |
|
888 | 0 | items[OPC_COLUMN].type = TABLE_ITEM_STRING; |
889 | 0 | items[DPC_COLUMN].type = TABLE_ITEM_STRING; |
890 | 0 | items[SI_COLUMN].type = TABLE_ITEM_STRING; |
891 | 0 | items[NUM_MSUS_COLUMN].type = TABLE_ITEM_UINT; |
892 | 0 | items[NUM_BYTES_COLUMN].type = TABLE_ITEM_UINT; |
893 | 0 | items[AVG_BYTES_COLUMN].type = TABLE_ITEM_FLOAT; |
894 | |
|
895 | 0 | stat_tap_init_table_row(table, element, num_fields, items); |
896 | |
|
897 | 0 | item_data = stat_tap_get_field_data(table, element, OPC_COLUMN); |
898 | 0 | item_data->value.string_value = g_strdup(mtp3_addr_to_str_wmem(pinfo->pool, &m3tr->addr_opc)); |
899 | 0 | item_data->user_data.ptr_value = g_memdup2(&m3tr->addr_opc, sizeof(mtp3_tap_rec_t)); |
900 | 0 | stat_tap_set_field_data(table, element, OPC_COLUMN, item_data); |
901 | |
|
902 | 0 | item_data = stat_tap_get_field_data(table, element, DPC_COLUMN); |
903 | 0 | item_data->value.string_value = g_strdup(mtp3_addr_to_str_wmem(pinfo->pool, &m3tr->addr_dpc)); |
904 | 0 | item_data->user_data.ptr_value = g_memdup2(&m3tr->addr_dpc, sizeof(mtp3_tap_rec_t)); |
905 | 0 | stat_tap_set_field_data(table, element, DPC_COLUMN, item_data); |
906 | |
|
907 | 0 | sis = try_val_to_str(m3tr->mtp3_si_code, mtp3_service_indicator_code_short_vals); |
908 | 0 | if (sis) { |
909 | 0 | col_str = g_strdup(sis); |
910 | 0 | } else { |
911 | 0 | col_str = ws_strdup_printf("Unknown service indicator %d", m3tr->mtp3_si_code); |
912 | 0 | } |
913 | |
|
914 | 0 | item_data = stat_tap_get_field_data(table, element, SI_COLUMN); |
915 | 0 | item_data->value.string_value = col_str; |
916 | 0 | item_data->user_data.uint_value = m3tr->mtp3_si_code; |
917 | 0 | stat_tap_set_field_data(table, element, SI_COLUMN, item_data); |
918 | 0 | } |
919 | |
|
920 | 0 | item_data = stat_tap_get_field_data(table, element, NUM_MSUS_COLUMN); |
921 | 0 | item_data->value.uint_value++; |
922 | 0 | msu_count = item_data->value.uint_value; |
923 | 0 | stat_tap_set_field_data(table, element, NUM_MSUS_COLUMN, item_data); |
924 | |
|
925 | 0 | item_data = stat_tap_get_field_data(table, element, NUM_BYTES_COLUMN); |
926 | 0 | item_data->value.uint_value += m3tr->size; |
927 | 0 | byte_count = item_data->value.uint_value; |
928 | 0 | stat_tap_set_field_data(table, element, NUM_BYTES_COLUMN, item_data); |
929 | |
|
930 | 0 | if (msu_count > 0) { |
931 | 0 | avg_bytes = (double) byte_count / msu_count; |
932 | 0 | } |
933 | 0 | item_data = stat_tap_get_field_data(table, element, AVG_BYTES_COLUMN); |
934 | 0 | item_data->value.float_value = avg_bytes; |
935 | 0 | stat_tap_set_field_data(table, element, AVG_BYTES_COLUMN, item_data); |
936 | |
|
937 | 0 | return TAP_PACKET_REDRAW; |
938 | 0 | } |
939 | | |
940 | | static void |
941 | | mtp3_stat_reset(stat_tap_table* table) |
942 | 0 | { |
943 | 0 | unsigned element; |
944 | 0 | stat_tap_table_item_type* item_data; |
945 | |
|
946 | 0 | for (element = 0; element < table->num_elements; element++) |
947 | 0 | { |
948 | 0 | item_data = stat_tap_get_field_data(table, element, NUM_MSUS_COLUMN); |
949 | 0 | item_data->value.uint_value = 0; |
950 | 0 | stat_tap_set_field_data(table, element, NUM_MSUS_COLUMN, item_data); |
951 | |
|
952 | 0 | item_data = stat_tap_get_field_data(table, element, NUM_BYTES_COLUMN); |
953 | 0 | item_data->value.uint_value = 0; |
954 | 0 | stat_tap_set_field_data(table, element, NUM_BYTES_COLUMN, item_data); |
955 | 0 | } |
956 | 0 | } |
957 | | |
958 | | static void |
959 | | mtp3_stat_free_table_item(stat_tap_table* table _U_, unsigned row _U_, unsigned column, stat_tap_table_item_type* field_data) |
960 | 0 | { |
961 | 0 | switch(column) { |
962 | 0 | case OPC_COLUMN: |
963 | 0 | case DPC_COLUMN: |
964 | 0 | g_free((char*)field_data->user_data.ptr_value); |
965 | | /* Fall through */ |
966 | 0 | case SI_COLUMN: |
967 | 0 | g_free((char*)field_data->value.string_value); |
968 | 0 | break; |
969 | 0 | default: |
970 | 0 | break; |
971 | 0 | } |
972 | 0 | } |
973 | | |
974 | | |
975 | | void |
976 | | proto_register_mtp3(void) |
977 | 14 | { |
978 | | |
979 | | /* Setup list of header fields See Section 1.6.1 for details*/ |
980 | 14 | static hf_register_info hf[] = { |
981 | 14 | { &hf_mtp3_service_indicator, { "Service indicator", "mtp3.service_indicator", FT_UINT8, BASE_HEX, VALS(mtp3_service_indicator_code_vals), SERVICE_INDICATOR_MASK, NULL, HFILL }}, |
982 | 14 | { &hf_mtp3_network_indicator, { "Network indicator", "mtp3.network_indicator", FT_UINT8, BASE_HEX, VALS(mtp3_network_indicator_vals), NETWORK_INDICATOR_MASK, NULL, HFILL }}, |
983 | 14 | { &hf_mtp3_itu_spare, { "Spare", "mtp3.spare", FT_UINT8, BASE_HEX, NULL, SPARE_MASK, NULL, HFILL }}, |
984 | 14 | { &hf_mtp3_itu_priority, { "ITU priority", "mtp3.priority", FT_UINT8, BASE_DEC, NULL, SPARE_MASK, NULL, HFILL }}, |
985 | 14 | { &hf_mtp3_ansi_priority, { "ANSI Priority", "mtp3.priority", FT_UINT8, BASE_DEC, NULL, ANSI_PRIORITY_MASK, NULL, HFILL }}, |
986 | 14 | { &hf_mtp3_itu_opc, { "OPC", "mtp3.opc", FT_UINT32, BASE_DEC, NULL, ITU_OPC_MASK, NULL, HFILL }}, |
987 | 14 | { &hf_mtp3_itu_pc, { "PC", "mtp3.pc", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
988 | 14 | { &hf_mtp3_24bit_pc, { "PC", "mtp3.pc", FT_UINT32, BASE_DEC, NULL, ANSI_PC_MASK, NULL, HFILL }}, |
989 | 14 | { &hf_mtp3_24bit_opc, { "OPC", "mtp3.opc", FT_UINT32, BASE_DEC, NULL, ANSI_PC_MASK, NULL, HFILL }}, |
990 | 14 | { &hf_mtp3_ansi_opc, { "OPC", "mtp3.ansi_opc", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }}, |
991 | 14 | { &hf_mtp3_chinese_opc, { "OPC", "mtp3.chinese_opc", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }}, |
992 | 14 | { &hf_mtp3_opc_network, { "OPC Network", "mtp3.opc.network", FT_UINT24, BASE_DEC, NULL, ANSI_NETWORK_MASK, NULL, HFILL }}, |
993 | 14 | { &hf_mtp3_opc_cluster, { "OPC Cluster", "mtp3.opc.cluster", FT_UINT24, BASE_DEC, NULL, ANSI_CLUSTER_MASK, NULL, HFILL }}, |
994 | 14 | { &hf_mtp3_opc_member, { "OPC Member", "mtp3.opc.member", FT_UINT24, BASE_DEC, NULL, ANSI_MEMBER_MASK, NULL, HFILL }}, |
995 | 14 | { &hf_mtp3_japan_opc, { "OPC", "mtp3.opc", FT_UINT16, BASE_DEC, NULL, JAPAN_PC_MASK, NULL, HFILL }}, |
996 | 14 | { &hf_mtp3_japan_pc, { "PC", "mtp3.pc", FT_UINT16, BASE_DEC, NULL, JAPAN_PC_MASK, NULL, HFILL }}, |
997 | 14 | { &hf_mtp3_itu_dpc, { "DPC", "mtp3.dpc", FT_UINT32, BASE_DEC, NULL, ITU_DPC_MASK, NULL, HFILL }}, |
998 | 14 | { &hf_mtp3_24bit_dpc, { "DPC", "mtp3.dpc", FT_UINT32, BASE_DEC, NULL, ANSI_PC_MASK, NULL, HFILL }}, |
999 | 14 | { &hf_mtp3_ansi_dpc, { "DPC", "mtp3.ansi_dpc", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }}, |
1000 | 14 | { &hf_mtp3_chinese_dpc, { "DPC", "mtp3.chinese_dpc", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }}, |
1001 | 14 | { &hf_mtp3_dpc_network, { "DPC Network", "mtp3.dpc.network", FT_UINT24, BASE_DEC, NULL, ANSI_NETWORK_MASK, NULL, HFILL }}, |
1002 | 14 | { &hf_mtp3_dpc_cluster, { "DPC Cluster", "mtp3.dpc.cluster", FT_UINT24, BASE_DEC, NULL, ANSI_CLUSTER_MASK, NULL, HFILL }}, |
1003 | 14 | { &hf_mtp3_dpc_member, { "DPC Member", "mtp3.dpc.member", FT_UINT24, BASE_DEC, NULL, ANSI_MEMBER_MASK, NULL, HFILL }}, |
1004 | 14 | { &hf_mtp3_japan_dpc, { "DPC", "mtp3.dpc", FT_UINT16, BASE_DEC, NULL, JAPAN_PC_MASK, NULL, HFILL }}, |
1005 | 14 | { &hf_mtp3_itu_sls, { "Signalling Link Selector", "mtp3.sls", FT_UINT32, BASE_DEC, NULL, ITU_SLS_MASK, NULL, HFILL }}, |
1006 | 14 | { &hf_mtp3_japan_4_bit_sls, { "Signalling Link Selector", "mtp3.sls", FT_UINT8, BASE_DEC, NULL, JAPAN_4_BIT_SLS_MASK, NULL, HFILL }}, |
1007 | 14 | { &hf_mtp3_japan_4_bit_sls_spare, { "SLS Spare", "mtp3.sls_spare", FT_UINT8, BASE_HEX, NULL, JAPAN_4_BIT_SLS_SPARE_MASK, NULL, HFILL }}, |
1008 | 14 | { &hf_mtp3_japan_5_bit_sls, { "Signalling Link Selector", "mtp3.sls", FT_UINT8, BASE_DEC, NULL, JAPAN_5_BIT_SLS_MASK, NULL, HFILL }}, |
1009 | 14 | { &hf_mtp3_japan_5_bit_sls_spare, { "SLS Spare", "mtp3.sls_spare", FT_UINT8, BASE_HEX, NULL, JAPAN_5_BIT_SLS_SPARE_MASK, NULL, HFILL }}, |
1010 | 14 | { &hf_mtp3_ansi_5_bit_sls, { "Signalling Link Selector", "mtp3.sls", FT_UINT8, BASE_DEC, NULL, ANSI_5BIT_SLS_MASK, NULL, HFILL }}, |
1011 | 14 | { &hf_mtp3_ansi_8_bit_sls, { "Signalling Link Selector", "mtp3.sls", FT_UINT8, BASE_DEC, NULL, ANSI_8BIT_SLS_MASK, NULL, HFILL }}, |
1012 | 14 | { &hf_mtp3_chinese_itu_sls, { "Signalling Link Selector", "mtp3.sls", FT_UINT8, BASE_DEC, NULL, CHINESE_ITU_SLS_MASK, NULL, HFILL }}, |
1013 | 14 | { &hf_mtp3_heuristic_standard, { "Heuristic standard", "mtp3.heuristic_standard",FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
1014 | 14 | }; |
1015 | | |
1016 | | /* Setup protocol subtree array */ |
1017 | 14 | static int *ett[] = { |
1018 | 14 | &ett_mtp3, |
1019 | 14 | &ett_mtp3_sio, |
1020 | 14 | &ett_mtp3_label, |
1021 | 14 | &ett_mtp3_label_dpc, |
1022 | 14 | &ett_mtp3_label_opc |
1023 | 14 | }; |
1024 | | |
1025 | 14 | static const enum_val_t mtp3_options[] = { |
1026 | 14 | { "itu", "ITU", ITU_STANDARD }, |
1027 | 14 | { "ansi", "ANSI", ANSI_STANDARD }, |
1028 | 14 | { "chinese-itu", "Chinese ITU", CHINESE_ITU_STANDARD }, |
1029 | 14 | { "japan", "Japan", JAPAN_STANDARD }, |
1030 | 14 | { NULL, NULL, 0 } |
1031 | 14 | }; |
1032 | | |
1033 | 14 | static const enum_val_t mtp3_addr_fmt_str_e[] = { |
1034 | 14 | { "decimal", "Decimal", MTP3_ADDR_FMT_DEC }, |
1035 | 14 | { "hexadecimal", "Hexadecimal", MTP3_ADDR_FMT_HEX }, |
1036 | 14 | { "ni-decimal", "NI-Decimal", MTP3_ADDR_FMT_NI_DEC }, |
1037 | 14 | { "ni-hexadecimal", "NI-Hexadecimal", MTP3_ADDR_FMT_NI_HEX }, |
1038 | 14 | { "dashed", "Dashed", MTP3_ADDR_FMT_DASHED }, |
1039 | 14 | { NULL, NULL, 0 } |
1040 | 14 | }; |
1041 | | |
1042 | 14 | static const enum_val_t itu_pc_structures[] = { |
1043 | 14 | { "unstructured", "Unstructured", ITU_PC_STRUCTURE_NONE}, |
1044 | 14 | { "3-8-3", "3-8-3", ITU_PC_STRUCTURE_3_8_3 }, |
1045 | 14 | { "4-3-4-3", "4-3-4-3", ITU_PC_STRUCTURE_4_3_4_3 }, |
1046 | 14 | { NULL, NULL, 0 } |
1047 | 14 | }; |
1048 | | |
1049 | 14 | static const enum_val_t japan_pc_structures[] = { |
1050 | 14 | { "unstructured", "Unstructured", JAPAN_PC_STRUCTURE_NONE}, |
1051 | 14 | { "7-4-5", "7-4-5", JAPAN_PC_STRUCTURE_7_4_5 }, |
1052 | 14 | { "3-4-4-5", "3-4-4-5", JAPAN_PC_STRUCTURE_3_4_4_5 }, |
1053 | 14 | { NULL, NULL, 0 } |
1054 | 14 | }; |
1055 | | |
1056 | 14 | static tap_param mtp3_stat_params[] = { |
1057 | 14 | { PARAM_FILTER, "filter", "Filter", NULL, true } |
1058 | 14 | }; |
1059 | | |
1060 | 14 | static stat_tap_table_ui mtp3_stat_table = { |
1061 | 14 | REGISTER_TELEPHONY_GROUP_MTP3, |
1062 | 14 | "MTP3 Statistics", |
1063 | 14 | "mtp3", |
1064 | 14 | "mtp3,msus", |
1065 | 14 | mtp3_stat_init, |
1066 | 14 | mtp3_stat_packet, |
1067 | 14 | mtp3_stat_reset, |
1068 | 14 | mtp3_stat_free_table_item, |
1069 | 14 | NULL, |
1070 | 14 | array_length(mtp3_stat_fields), mtp3_stat_fields, |
1071 | 14 | array_length(mtp3_stat_params), mtp3_stat_params, |
1072 | 14 | NULL, |
1073 | 14 | 0 |
1074 | 14 | }; |
1075 | | |
1076 | | /* Register the protocol name and description */ |
1077 | 14 | proto_mtp3 = proto_register_protocol("Message Transfer Part Level 3", |
1078 | 14 | "MTP3", "mtp3"); |
1079 | 14 | mtp3_handle = register_dissector("mtp3", dissect_mtp3, proto_mtp3); |
1080 | | |
1081 | | /* Required function calls to register the header fields and subtrees used */ |
1082 | 14 | proto_register_field_array(proto_mtp3, hf, array_length(hf)); |
1083 | 14 | proto_register_subtree_array(ett, array_length(ett)); |
1084 | | |
1085 | 14 | mtp3_sio_dissector_table = register_dissector_table("mtp3.service_indicator", |
1086 | 14 | "MTP3 Service indicator", |
1087 | 14 | proto_mtp3, FT_UINT8, BASE_HEX); |
1088 | | |
1089 | 14 | mtp3_address_type = address_type_dissector_register("AT_SS7PC", "SS7 Point Code", mtp3_addr_to_str, mtp3_str_addr_len, NULL, mtp3_addr_col_filter_str, |
1090 | 14 | mtp3_addr_len, mtp3_addr_name_res_str, mtp3_addr_name_res_len); |
1091 | | |
1092 | | |
1093 | 14 | mtp3_tap = register_tap("mtp3"); |
1094 | | |
1095 | 14 | mtp3_module = prefs_register_protocol(proto_mtp3, NULL); |
1096 | | |
1097 | 14 | prefs_register_bool_preference(mtp3_module, "heuristic_standard", |
1098 | 14 | "Try to determine the MTP3 standard heuristically", |
1099 | 14 | "This only works for SCCP traffic for now", |
1100 | 14 | &mtp3_heuristic_standard); |
1101 | | |
1102 | 14 | prefs_register_enum_preference(mtp3_module, "standard", "MTP3 standard", |
1103 | 14 | "The SS7 standard used in MTP3 packets", |
1104 | 14 | &mtp3_standard, mtp3_options, false); |
1105 | | |
1106 | 14 | prefs_register_enum_preference(mtp3_module, "itu_pc_structure", "ITU Pointcode structure", |
1107 | 14 | "The structure of the pointcodes in ITU networks", |
1108 | 14 | &itu_pc_structure, itu_pc_structures, false); |
1109 | | |
1110 | 14 | prefs_register_enum_preference(mtp3_module, "japan_pc_structure", "Japan Pointcode structure", |
1111 | 14 | "The structure of the pointcodes in Japan networks", |
1112 | 14 | &japan_pc_structure, japan_pc_structures, false); |
1113 | | |
1114 | 14 | prefs_register_bool_preference(mtp3_module, "ansi_5_bit_sls", |
1115 | 14 | "Use 5-bit SLS (ANSI only)", |
1116 | 14 | "Use 5-bit (instead of 8-bit) SLS in ANSI MTP3 packets", |
1117 | 14 | &mtp3_use_ansi_5_bit_sls); |
1118 | | |
1119 | 14 | prefs_register_bool_preference(mtp3_module, "japan_5_bit_sls", |
1120 | 14 | "Use 5-bit SLS (Japan only)", |
1121 | 14 | "Use 5-bit (instead of 4-bit) SLS in Japan MTP3 packets", |
1122 | 14 | &mtp3_use_japan_5_bit_sls); |
1123 | | |
1124 | 14 | prefs_register_enum_preference(mtp3_module, "addr_format", "Address Format", |
1125 | 14 | "Format for point code in the address columns", |
1126 | 14 | &mtp3_addr_fmt, mtp3_addr_fmt_str_e, false); |
1127 | | |
1128 | 14 | prefs_register_bool_preference(mtp3_module, "itu_priority", |
1129 | 14 | "Show MSU priority (national option, ITU and China ITU only)", |
1130 | 14 | "Decode the spare bits of the SIO as the MSU priority (a national option in ITU)", |
1131 | 14 | &mtp3_show_itu_priority); |
1132 | | |
1133 | 14 | register_stat_tap_table_ui(&mtp3_stat_table); |
1134 | | |
1135 | 14 | register_external_value_string("mtp3_service_indicator_code_short_vals", mtp3_service_indicator_code_short_vals); |
1136 | 14 | } |
1137 | | |
1138 | | void |
1139 | | proto_reg_handoff_mtp3(void) |
1140 | 14 | { |
1141 | 14 | dissector_add_uint("wtap_encap", WTAP_ENCAP_MTP3, mtp3_handle); |
1142 | 14 | dissector_add_string("tali.opcode", "mtp3", mtp3_handle); |
1143 | 14 | } |
1144 | | |
1145 | | /* |
1146 | | * Editor modelines - https://www.wireshark.org/tools/modelines.html |
1147 | | * |
1148 | | * Local Variables: |
1149 | | * c-basic-offset: 2 |
1150 | | * tab-width: 8 |
1151 | | * indent-tabs-mode: nil |
1152 | | * End: |
1153 | | * |
1154 | | * ex: set shiftwidth=2 tabstop=8 expandtab: |
1155 | | * :indentSize=2:tabSize=8:noTabs=true: |
1156 | | */ |