1 /* packet-mtp3mg.c
2  * Routines for Message Transfer Part Level 3 Management and Test dissection
3  *
4  * It is (hopefully) compliant to:
5  *   ANSI T1.111.4-1996
6  *   ITU-T Q.704 7/1996
7  *   ITU-T Q.707 7/1996 and ANSI T1.111.7-1996 (for SLT message formats)
8  *   portions of ITU-T Q.2210 7/1996 (for XCO/XCA message formats)
9  *   GF 001-9001 (Chinese ITU variant)
10  *   JT-Q704, JT-Q707v2, and NTT-Q704 (Japan)
11  *
12  *   Note that the division of the Japan SLS into the SLC and A/B bit is not
13  *   done.
14  *
15  * Copyright 2003, 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 packet-mtp3.c
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/expert.h>
30 
31 #include <wsutil/str_util.h>
32 
33 #include "packet-mtp3.h"
34 
35 void proto_register_mtp3mg(void);
36 void proto_reg_handoff_mtp3mg(void);
37 
38 #define H0H1_LENGTH 1
39 #define H0_MASK     0x0f
40 #define H1_MASK     0xf0
41 #define H1_SHIFT    4
42 
43 #define H0_CHM 0x01
44 #define H0_ECM 0x02
45 #define H0_FCM 0x03
46 #define H0_TFM 0x04
47 #define H0_RSM 0x05
48 #define H0_MIM 0x06     /* not used in Japan */
49 #define H0_TRM 0x07     /* not used in Japan */
50 #define H0_DLM 0x08     /* not used in Japan */
51 #define H0_UFC 0x0a     /* not used in Japan */
52 static const value_string h0_message_type_values[] = {
53   { H0_CHM, "Changeover and changeback messages" },
54   { H0_ECM, "Emergency changeover messages" },
55   { H0_FCM, "Transfer-controlled and signalling route set congestion messages" },
56   { H0_TFM, "Transfer prohibited-allowed-restricted messages" },
57   { H0_RSM, "Signalling-route-set-test messages" },
58   { H0_MIM, "Management inhibit messages" },
59   { H0_TRM, "Traffic restart messages" },
60   { H0_DLM, "Signalling-data-link-connection messages" },
61   { H0_UFC, "User part flow control messages" },
62   { 0,      NULL } };
63 
64 #define TEST_H0_SLT 0x1
65 static const value_string test_h0_message_type_values[] = {
66   { TEST_H0_SLT, "Test messages" },
67   { 0,           NULL } };
68 
69 #define CHM_H1_COO 0x01
70 #define CHM_H1_COA 0x02
71 #define CHM_H1_XCO 0x03
72 #define CHM_H1_XCA 0x04
73 #define CHM_H1_CBD 0x05
74 #define CHM_H1_CBA 0x06
75 static const value_string chm_h1_message_type_values[] = {
76   { CHM_H1_COO, "Changeover-order signal" },
77   { CHM_H1_COA, "Changeover-ack signal" },
78   { CHM_H1_XCO, "Extended changeover-order signal" },
79   { CHM_H1_XCA, "Extended changeover-ack signal" },
80   { CHM_H1_CBD, "Changeback-declaration signal" },
81   { CHM_H1_CBA, "Changeback-ack signal" },
82   { 0,          NULL } };
83 
84 /* Same as above but in acronym form (for the Info column) */
85 static const value_string chm_h1_message_type_acro_values[] = {
86   { CHM_H1_COO, "COO" },
87   { CHM_H1_COA, "COA" },
88   { CHM_H1_XCO, "XCO" },
89   { CHM_H1_XCA, "XCA" },
90   { CHM_H1_CBD, "CBD" },
91   { CHM_H1_CBA, "CBA" },
92   { 0,          NULL } };
93 
94 #define ECM_H1_ECO 0x01
95 #define ECM_H1_ECA 0x02
96 static const value_string ecm_h1_message_type_values[] = {
97   { ECM_H1_ECO, "Emergency-changeover-order signal" },
98   { ECM_H1_ECA, "Emergency-changeover-ack signal" },
99   { 0,          NULL } };
100 
101 /* Same as above but in acronym form (for the Info column) */
102 static const value_string ecm_h1_message_type_acro_values[] = {
103   { ECM_H1_ECO, "ECO" },
104   { ECM_H1_ECA, "ECA" },
105   { 0,          NULL } };
106 
107 #define FCM_H1_RCT 0x01
108 #define FCM_H1_TFC 0x02
109 static const value_string fcm_h1_message_type_values[] = {
110   { FCM_H1_RCT, "Signalling-route-set-congestion-test signal" },
111   { FCM_H1_TFC, "Transfer-controlled signal" },
112   { 0,          NULL } };
113 
114 /* Same as above but in acronym form (for the Info column) */
115 static const value_string fcm_h1_message_type_acro_values[] = {
116   { FCM_H1_RCT, "RCT" },
117   { FCM_H1_TFC, "TFC" },
118   { 0,          NULL } };
119 
120 #define TFM_H1_TFP 0x01
121 #define TFM_H1_TCP 0x02 /* ANSI only */
122 #define TFM_H1_TFR 0x03
123 #define TFM_H1_TCR 0x04 /* ANSI only */
124 #define TFM_H1_TFA 0x05
125 #define TFM_H1_TCA 0x06 /* ANSI only */
126 static const value_string tfm_h1_message_type_values[] = {
127   { TFM_H1_TFP, "Transfer-prohibited signal" },
128   { TFM_H1_TCP, "Transfer-cluster-prohibited signal (ANSI only)" },
129   { TFM_H1_TFR, "Transfer-restricted signal" },
130   { TFM_H1_TCR, "Transfer-cluster-restricted signal (ANSI only)" },
131   { TFM_H1_TFA, "Transfer-allowed signal" },
132   { TFM_H1_TCA, "Transfer-cluster-allowed signal (ANSI only)" },
133   { 0,          NULL } };
134 
135 /* Same as above but in acronym form (for the Info column) */
136 static const value_string tfm_h1_message_type_acro_values[] = {
137   { TFM_H1_TFP, "TFP" },
138   { TFM_H1_TCP, "TCP" },
139   { TFM_H1_TFR, "TFR" },
140   { TFM_H1_TCR, "TCR" },
141   { TFM_H1_TFA, "TFA" },
142   { TFM_H1_TCA, "TCA" },
143   { 0,          NULL } };
144 
145 #define RSM_H1_RST 0x01
146 #define RSM_H1_RSR 0x02
147 #define RSM_H1_RCP 0x03 /* ANSI only */
148 #define RSM_H1_RCR 0x04 /* ANSI only */
149 static const value_string rsm_h1_message_type_values[] = {
150   { RSM_H1_RST, "Signalling-route-set-test prohibited signal" },
151   { RSM_H1_RSR, "Signalling-route-set-test restricted signal" },
152   { RSM_H1_RCP, "Signalling-route-set-test cluster-prohibited signal (ANSI only)" },
153   { RSM_H1_RCR, "Signalling-route-set-test cluster-restricted signal (ANSI only)" },
154   { 0,          NULL } };
155 
156 /* Same as above but in acronym form (for the Info column) */
157 static const value_string rsm_h1_message_type_acro_values[] = {
158   { RSM_H1_RST, "RST" },
159   { RSM_H1_RSR, "RSR" },
160   { RSM_H1_RCP, "RCP" },
161   { RSM_H1_RCR, "RCR" },
162   { 0,          NULL } };
163 
164 #define MIM_H1_LIN 0x01
165 #define MIM_H1_LUN 0x02
166 #define MIM_H1_LIA 0x03
167 #define MIM_H1_LUA 0x04
168 #define MIM_H1_LID 0x05
169 #define MIM_H1_LFU 0x06
170 #define MIM_H1_LLT 0x07 /* LLI in ANSI */
171 #define MIM_H1_LRT 0x08 /* LRI in ANSI */
172 static const value_string mim_h1_message_type_values[] = {
173   { MIM_H1_LIN, "Link inhibit signal" },
174   { MIM_H1_LUN, "Link uninhibit signal" },
175   { MIM_H1_LIA, "Link inhibit ack signal" },
176   { MIM_H1_LUA, "Link uninhibit ack signal" },
177   { MIM_H1_LID, "Link inhibit denied signal" },
178   { MIM_H1_LFU, "Link forced uninhibit signal" },
179   { MIM_H1_LLT, "Link local inhibit test signal" },
180   { MIM_H1_LRT, "Link remote inhibit test signal" },
181   { 0,          NULL } };
182 
183 /* Same as above but in acronym form (for the Info column) */
184 static const value_string mim_h1_message_type_acro_values[] = {
185   { MIM_H1_LIN, "LIN" },
186   { MIM_H1_LUN, "LUN" },
187   { MIM_H1_LIA, "LIA" },
188   { MIM_H1_LUA, "LUA" },
189   { MIM_H1_LID, "LID" },
190   { MIM_H1_LFU, "LFU" },
191   { MIM_H1_LLT, "LLT (LLI)" },
192   { MIM_H1_LRT, "LRT (LRI)" },
193   { 0,          NULL } };
194 
195 #define TRM_H1_TRA 0x01
196 #define TRM_H1_TRW 0x02 /* ANSI only */
197 static const value_string trm_h1_message_type_values[] = {
198   { TRM_H1_TRA, "Traffic-restart-allowed signal" },
199   { TRM_H1_TRW, "Traffic-restart-waiting signal (ANSI only)" },
200   { 0,          NULL } };
201 
202 /* Same as above but in acronym form (for the Info column) */
203 static const value_string trm_h1_message_type_acro_values[] = {
204   { TRM_H1_TRA, "TRA" },
205   { TRM_H1_TRW, "TRW" },
206   { 0,          NULL } };
207 
208 #define DLM_H1_DLC 0x01
209 #define DLM_H1_CSS 0x02
210 #define DLM_H1_CNS 0x03
211 #define DLM_H1_CNP 0x04
212 static const value_string dlm_h1_message_type_values[] = {
213   { DLM_H1_DLC, "Signalling-data-link-connection-order signal" },
214   { DLM_H1_CSS, "Connection-successful signal" },
215   { DLM_H1_CNS, "Connection-not-successful signal" },
216   { DLM_H1_CNP, "Connection-not-possible signal" },
217   { 0,          NULL } };
218 
219 /* Same as above but in acronym form (for the Info column) */
220 static const value_string dlm_h1_message_type_acro_values[] = {
221   { DLM_H1_DLC, "DLC" },
222   { DLM_H1_CSS, "CSS" },
223   { DLM_H1_CNS, "CNS" },
224   { DLM_H1_CNP, "CNP" },
225   { 0,          NULL } };
226 
227 #define UFC_H1_UPU 0x01
228 static const value_string ufc_h1_message_type_values[] = {
229   { UFC_H1_UPU, "User part unavailable signal" },
230   { 0,          NULL } };
231 
232 /* Same as above but in acronym form (for the Info column) */
233 static const value_string ufc_h1_message_type_acro_values[] = {
234   { UFC_H1_UPU, "UPU" },
235   { 0,          NULL } };
236 
237 static const value_string upu_cause_values[] = {
238   { 0x0, "Unknown" },
239   { 0x1, "Unequipped remote user" },
240   { 0x2, "Inaccessible remote user" },
241   { 0,   NULL } };
242 
243 #define TEST_H1_SLTM 0x1
244 #define TEST_H1_SLTA 0x2
245 static const value_string test_h1_message_type_values[] = {
246   { TEST_H1_SLTM, "Signalling link test message" },
247   { TEST_H1_SLTA, "Signalling link test acknowledgement message" },
248   { 0,            NULL } };
249 
250 /* Same as above but in acronym form (for the Info column) */
251 static const value_string test_h1_message_type_acro_values[] = {
252   { TEST_H1_SLTM, "SLTM" },
253   { TEST_H1_SLTA, "SLTA" },
254   { 0,            NULL } };
255 
256 #define JAPAN_TEST_SRT 0x23
257 #define JAPAN_TEST_SRA 0x84
258 static const value_string japan_test_message_type_values[] = {
259   { JAPAN_TEST_SRT, "Signalling routing test message" },
260   { JAPAN_TEST_SRA, "Signalling routing test acknowledgement message" },
261   { 0,              NULL } };
262 
263 /* Same as above but in acronym form (for the Info column) */
264 static const value_string japan_test_message_type_acro_values[] = {
265   { JAPAN_TEST_SRT, "SRT" },
266   { JAPAN_TEST_SRA, "SRA" },
267   { 0,              NULL } };
268 
269 #define ANSI_COO_LENGTH    2
270 #define ANSI_COO_SLC_MASK  0x000f
271 #define ANSI_COO_FSN_MASK  0x07f0
272 #define ITU_COO_LENGTH     1
273 #define ITU_COO_FSN_MASK   0x007f
274 #define ANSI_XCO_LENGTH    4
275 #define ANSI_XCO_SLC_MASK  0x0000000f
276 #define ANSI_XCO_FSN_MASK  0x0ffffff0
277 #define ITU_XCO_LENGTH     3
278 #define ANSI_CBD_LENGTH    2
279 #define ANSI_CBD_SLC_MASK  0x000f
280 #define ANSI_CBD_CBC_MASK  0x0ff0
281 #define ITU_CBD_LENGTH     1
282 #define JAPAN_CBD_CBC_MASK 0x3
283 
284 #define ANSI_ECO_LENGTH   1
285 #define ANSI_ECO_SLC_MASK 0x0f
286 
287 #define ANSI_TFC_STATUS_LENGTH       1
288 #define ANSI_TFC_STATUS_OFFSET       ANSI_PC_LENGTH
289 #define ANSI_TFC_STATUS_MASK         0x03
290 #define ITU_TFC_STATUS_LENGTH        ITU_PC_LENGTH
291 #define ITU_TFC_STATUS_MASK          0xc000
292 #define JAPAN_TFC_SPARE_OFFSET        0
293 #define JAPAN_TFC_SPARE_LENGTH        1
294 #define JAPAN_TFC_APC_OFFSET          JAPAN_TFC_SPARE_LENGTH
295 #define JAPAN_TFC_STATUS_OFFSET       (JAPAN_TFC_SPARE_LENGTH + JAPAN_PC_LENGTH)
296 #define JAPAN_TFC_STATUS_LENGTH       1
297 #define JAPAN_TFC_STATUS_MASK         0x03
298 #define JAPAN_TFC_STATUS_SPARE_MASK   0xfc
299 
300 #define JAPAN_TFM_COUNT_OFFSET 0
301 #define JAPAN_TFM_COUNT_LENGTH 1
302 
303 #define ANSI_MIM_LENGTH   1
304 #define ANSI_MIM_SLC_MASK 0x0f
305 
306 #define ANSI_DLC_LENGTH    3
307 #define ANSI_DLC_SLC_MASK  0x0000f
308 #define ANSI_DLC_LINK_MASK 0x3fff0
309 #define ITU_DLC_LENGTH     2
310 #define ITU_DLC_LINK_MASK  0x0fff
311 
312 #define ANSI_UPU_USER_OFFSET ANSI_PC_LENGTH
313 #define UPU_USER_LENGTH      1
314 #define UPU_USER_MASK        0x0f
315 #define UPU_CAUSE_MASK       0xf0
316 #define ITU_UPU_USER_OFFSET  ITU_PC_LENGTH
317 
318 #define TEST_LENGTH         1
319 #define TEST_LENGTH_MASK    0xf0
320 #define TEST_LENGTH_SHIFT   4
321 #define TEST_PATTERN_OFFSET TEST_LENGTH
322 #define ANSI_TEST_SLC_MASK  0x000f
323 
324 #define JAPAN_SPARE_LENGTH 1
325 #define JAPAN_H0H1_OFFSET JAPAN_SPARE_LENGTH
326 
327 #define JAPAN_TEST_SPARE_OFFSET   JAPAN_SPARE_LENGTH + H0H1_LENGTH
328 #define JAPAN_TEST_SPARE_LENGTH   1
329 #define JAPAN_TEST_PATTERN_OFFSET (JAPAN_TEST_SPARE_OFFSET + JAPAN_TEST_SPARE_LENGTH)
330 #define JAPAN_TEST_PATTERN_LENGTH 2
331 #define JAPAN_TEST_PATTERN 0x7711
332 
333 
334 /* This list is slightly different from that in packet-mtp3.c */
335 static const value_string service_indicator_code_vals[] = {
336         { 0x0,  "Spare" },
337         { 0x1,  "Spare"},
338         { 0x2,  "Spare" },
339         { 0x3,  "SCCP" },
340         { 0x4,  "TUP" },
341         { 0x5,  "ISUP" },
342         { 0x6,  "DUP (call and circuit related messages)" },
343         { 0x7,  "DUP (facility registration and cancellation message)" },
344         { 0x8,  "MTP testing user part" },
345         { 0x9,  "ISUP-b" },
346         { 0xa,  "ISUP-s" },
347         { 0xb,  "Spare" },
348         { 0xc,  "Spare" },
349         { 0xd,  "Spare" },
350         { 0xe,  "Spare" },
351         { 0xf,  "Spare" },
352         { 0,    NULL }
353 };
354 
355 /* Initialize the protocol and registered fields */
356 static int proto_mtp3mg  = -1;
357 static int hf_mtp3mg_h0 = -1;
358 static int hf_mtp3mg_chm_h1 = -1;
359 static int hf_mtp3mg_ecm_h1 = -1;
360 static int hf_mtp3mg_fcm_h1 = -1;
361 static int hf_mtp3mg_tfm_h1 = -1;
362 static int hf_mtp3mg_rsm_h1 = -1;
363 static int hf_mtp3mg_mim_h1 = -1;
364 static int hf_mtp3mg_trm_h1 = -1;
365 static int hf_mtp3mg_dlm_h1 = -1;
366 static int hf_mtp3mg_ufc_h1 = -1;
367 static int hf_mtp3mg_coo_ansi_slc = -1;
368 static int hf_mtp3mg_coo_ansi_fsn = -1;
369 static int hf_mtp3mg_coo_itu_fsn = -1;
370 static int hf_mtp3mg_xco_ansi_slc = -1;
371 static int hf_mtp3mg_xco_ansi_fsn = -1;
372 static int hf_mtp3mg_xco_itu_fsn = -1;
373 static int hf_mtp3mg_cbd_ansi_slc = -1;
374 static int hf_mtp3mg_cbd_ansi_cbc = -1;
375 static int hf_mtp3mg_cbd_itu_cbc = -1;
376 static int hf_mtp3mg_cbd_japan_cbc = -1;
377 static int hf_mtp3mg_eco_ansi_slc = -1;
378 static int hf_mtp3mg_ansi_apc = -1;
379 static int hf_mtp3mg_apc_member = -1;
380 static int hf_mtp3mg_apc_cluster = -1;
381 static int hf_mtp3mg_apc_network = -1;
382 static int hf_mtp3mg_tfc_ansi_status = -1;
383 static int hf_mtp3mg_itu_apc = -1;
384 static int hf_mtp3mg_tfc_itu_status = -1;
385 static int hf_mtp3mg_chinese_apc = -1;
386 static int hf_mtp3mg_tfc_japan_spare = -1;
387 static int hf_mtp3mg_japan_apc = -1;
388 static int hf_mtp3mg_tfc_japan_status = -1;
389 static int hf_mtp3mg_tfc_japan_status_spare = -1;
390 static int hf_mtp3mg_tfm_japan_count = -1;
391 static int hf_mtp3mg_tfm_japan_spare = -1;
392 static int hf_mtp3mg_rsm_japan_count = -1;
393 static int hf_mtp3mg_rsm_japan_spare = -1;
394 static int hf_mtp3mg_mim_ansi_slc = -1;
395 static int hf_mtp3mg_dlc_ansi_slc = -1;
396 static int hf_mtp3mg_dlc_ansi_link = -1;
397 static int hf_mtp3mg_dlc_itu_link = -1;
398 static int hf_mtp3mg_upu_user = -1;
399 static int hf_mtp3mg_upu_cause = -1;
400 static int hf_mtp3test_h0 = -1;
401 static int hf_mtp3mg_test_h1 = -1;
402 static int hf_mtp3mg_test_ansi_slc = -1;
403 static int hf_mtp3mg_test_length = -1;
404 static int hf_mtp3mg_japan_test = -1;
405 static int hf_mtp3mg_japan_test_spare = -1;
406 static int hf_mtp3mg_japan_test_pattern = -1;
407 static int hf_mtp3mg_japan_spare = -1;
408 static int hf_mtp3mg_test_pattern = -1;
409 
410 /* Initialize the subtree pointers */
411 static gint ett_mtp3mg = -1;
412 static gint ett_mtp3mg_fcm_apc = -1;
413 static gint ett_mtp3mg_tfm_apc = -1;
414 static gint ett_mtp3mg_rsm_apc = -1;
415 static gint ett_mtp3mg_upu_apc = -1;
416 
417 static expert_field ei_mtp3mg_unknown_message = EI_INIT;
418 
419 static dissector_handle_t mtp3mg_handle;
420 
421 static void
dissect_mtp3mg_unknown_message(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree)422 dissect_mtp3mg_unknown_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
423 {
424     guint8 message_length;
425 
426     message_length = tvb_captured_length(tvb);
427     proto_tree_add_expert_format(tree, pinfo, &ei_mtp3mg_unknown_message, tvb, 0, message_length,
428                         "Unknown message (%u byte%s)", message_length,
429                         plurality(message_length, "", "s"));
430 }
431 
432 static void
dissect_mtp3mg_chm(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,guint8 h1)433 dissect_mtp3mg_chm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
434                    guint8 h1)
435 {
436     col_add_fstr(pinfo->cinfo, COL_INFO, "%s ",
437                  val_to_str_const(h1, chm_h1_message_type_acro_values, "Unknown"));
438 
439     switch (h1)
440     {
441     case CHM_H1_COO:
442     case CHM_H1_COA:
443         if (mtp3_standard == ANSI_STANDARD)
444         {
445             proto_tree_add_item(tree, hf_mtp3mg_coo_ansi_slc, tvb, 0,
446                                 ANSI_COO_LENGTH, ENC_LITTLE_ENDIAN);
447             proto_tree_add_item(tree, hf_mtp3mg_coo_ansi_fsn, tvb, 0,
448                                 ANSI_COO_LENGTH, ENC_LITTLE_ENDIAN);
449         } else /* ITU_STANDARD, CHINESE_ITU_STANDARD, and JAPAN_STANDARD */ {
450             proto_tree_add_item(tree, hf_mtp3mg_coo_itu_fsn, tvb, 0,
451                                 ITU_COO_LENGTH, ENC_LITTLE_ENDIAN);
452         }
453         break;
454 
455     case CHM_H1_XCO:
456     case CHM_H1_XCA:
457         if (mtp3_standard == ANSI_STANDARD)
458         {
459             proto_tree_add_item(tree, hf_mtp3mg_xco_ansi_slc, tvb, 0,
460                                 ANSI_XCO_LENGTH, ENC_LITTLE_ENDIAN);
461             proto_tree_add_item(tree, hf_mtp3mg_xco_ansi_fsn, tvb, 0,
462                                 ANSI_XCO_LENGTH, ENC_LITTLE_ENDIAN);
463         } else /* ITU_STANDARD, CHINESE_ITU_STANDARD, and JAPAN_STANDARD */ {
464             proto_tree_add_item(tree, hf_mtp3mg_xco_itu_fsn, tvb, 0,
465                                 ITU_XCO_LENGTH, ENC_LITTLE_ENDIAN);
466         }
467         break;
468 
469     case CHM_H1_CBD:
470     case CHM_H1_CBA:
471         if (mtp3_standard == ANSI_STANDARD)
472         {
473             proto_tree_add_item(tree, hf_mtp3mg_cbd_ansi_slc, tvb, 0,
474                                 ANSI_CBD_LENGTH, ENC_LITTLE_ENDIAN);
475             proto_tree_add_item(tree, hf_mtp3mg_cbd_ansi_cbc, tvb, 0,
476                                 ANSI_CBD_LENGTH, ENC_LITTLE_ENDIAN);
477         } else if (mtp3_standard == JAPAN_STANDARD) {
478             proto_tree_add_item(tree, hf_mtp3mg_cbd_japan_cbc, tvb, 0,
479                                 ITU_CBD_LENGTH, ENC_LITTLE_ENDIAN);
480         } else /* ITU_STANDARD and CHINESE_ITU_STANDARD */ {
481             proto_tree_add_item(tree, hf_mtp3mg_cbd_itu_cbc, tvb, 0,
482                                 ITU_CBD_LENGTH, ENC_LITTLE_ENDIAN);
483         }
484         break;
485 
486     default:
487         dissect_mtp3mg_unknown_message(tvb, pinfo, tree);
488   }
489 }
490 
491 static void
dissect_mtp3mg_ecm(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,guint8 h1)492 dissect_mtp3mg_ecm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
493                    guint8 h1)
494 {
495 
496     col_add_fstr(pinfo->cinfo, COL_INFO, "%s ",
497                  val_to_str_const(h1, ecm_h1_message_type_acro_values, "Unknown"));
498 
499     switch (h1)
500     {
501     case ECM_H1_ECO:
502     case ECM_H1_ECA:
503         if (mtp3_standard == ANSI_STANDARD)
504         {
505             proto_tree_add_item(tree, hf_mtp3mg_eco_ansi_slc, tvb, 0,
506                                 ANSI_ECO_LENGTH, ENC_LITTLE_ENDIAN);
507         }
508         /* else: nothing to dissect */
509         break;
510 
511     default:
512         dissect_mtp3mg_unknown_message(tvb, pinfo, tree);
513     }
514 }
515 
516 static void
dissect_mtp3mg_fcm(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,guint8 h1)517 dissect_mtp3mg_fcm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
518                    guint8 h1)
519 {
520     proto_item *apc_item;
521 
522     col_add_fstr(pinfo->cinfo, COL_INFO, "%s ",
523                  val_to_str_const(h1, fcm_h1_message_type_acro_values, "Unknown"));
524 
525     switch (h1)
526     {
527     case FCM_H1_RCT:
528         /* nothing to dissect */
529         break;
530 
531     case FCM_H1_TFC:
532         if (mtp3_standard == ITU_STANDARD)
533         {
534 
535             apc_item = proto_tree_add_item(tree, hf_mtp3mg_itu_apc, tvb, 0,
536                                            ITU_PC_LENGTH, ENC_LITTLE_ENDIAN);
537 
538             if (mtp3_pc_structured()) {
539                 guint32 apc;
540 
541                 apc = tvb_get_letohs(tvb, 0) & ITU_PC_MASK;
542                 proto_item_append_text(apc_item, " (%s)", mtp3_pc_to_str(apc));
543             }
544 
545             /* Congestion level is a national option */
546             proto_tree_add_item(tree, hf_mtp3mg_tfc_itu_status, tvb, 0,
547                                 ITU_TFC_STATUS_LENGTH, ENC_LITTLE_ENDIAN);
548 
549 
550 
551         } else if (mtp3_standard == JAPAN_STANDARD) {
552 
553             proto_tree_add_item(tree, hf_mtp3mg_tfc_japan_spare, tvb,
554                                 JAPAN_TFC_SPARE_OFFSET,
555                                 JAPAN_TFC_SPARE_LENGTH, ENC_LITTLE_ENDIAN);
556 
557             apc_item = proto_tree_add_item(tree, hf_mtp3mg_japan_apc, tvb,
558                                            JAPAN_TFC_APC_OFFSET,
559                                            JAPAN_PC_LENGTH, ENC_LITTLE_ENDIAN);
560             if (mtp3_pc_structured()) {
561                 guint32 apc;
562 
563                 apc = tvb_get_letohs(tvb, JAPAN_TFC_APC_OFFSET);
564                 proto_item_append_text(apc_item, " (%s)", mtp3_pc_to_str(apc));
565             }
566 
567             proto_tree_add_item(tree, hf_mtp3mg_tfc_japan_status, tvb,
568                                 JAPAN_TFC_STATUS_OFFSET,
569                                 JAPAN_TFC_STATUS_LENGTH, ENC_LITTLE_ENDIAN);
570             proto_tree_add_item(tree, hf_mtp3mg_tfc_japan_status_spare, tvb,
571                                 JAPAN_TFC_STATUS_OFFSET,
572                                 JAPAN_TFC_STATUS_LENGTH, ENC_LITTLE_ENDIAN);
573 
574         } else /* ANSI_STANDARD and CHINESE_ITU_STANDARD */ {
575 
576             int hf_apc_string;
577 
578             if (mtp3_standard == ANSI_STANDARD) {
579 
580                 hf_apc_string = hf_mtp3mg_ansi_apc;
581 
582             } else /* CHINESE_ITU_STANDARD */ {
583 
584                 hf_apc_string = hf_mtp3mg_chinese_apc;
585             }
586 
587             dissect_mtp3_3byte_pc(tvb, 0, tree, ett_mtp3mg_fcm_apc,
588                                   hf_apc_string, hf_mtp3mg_apc_network,
589                                   hf_mtp3mg_apc_cluster,
590                                   hf_mtp3mg_apc_member, 0, 0);
591 
592             proto_tree_add_item(tree, hf_mtp3mg_tfc_ansi_status, tvb,
593                                 ANSI_TFC_STATUS_OFFSET, ANSI_TFC_STATUS_LENGTH,
594                                 ENC_LITTLE_ENDIAN);
595 
596         }
597         break;
598 
599     default:
600         dissect_mtp3mg_unknown_message(tvb, pinfo, tree);
601     }
602 }
603 
604 static void
dissect_mtp3mg_tfm(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,guint8 h1)605 dissect_mtp3mg_tfm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
606                    guint8 h1)
607 {
608     proto_item *apc_item;
609 
610     col_add_fstr(pinfo->cinfo, COL_INFO, "%s ",
611                  val_to_str_const(h1, tfm_h1_message_type_acro_values, "Unknown"));
612 
613     switch (h1)
614     {
615     case TFM_H1_TFP:
616     case TFM_H1_TCP:
617     case TFM_H1_TFR:
618     case TFM_H1_TCR:
619     case TFM_H1_TFA:
620     case TFM_H1_TCA:
621         if (mtp3_standard == ANSI_STANDARD) {
622             dissect_mtp3_3byte_pc(tvb, 0, tree, ett_mtp3mg_tfm_apc,
623                                   hf_mtp3mg_ansi_apc,
624                                   hf_mtp3mg_apc_network,
625                                   hf_mtp3mg_apc_cluster,
626                                   hf_mtp3mg_apc_member, 0, 0);
627 
628         } else if (mtp3_standard == JAPAN_STANDARD) {
629             guint8 count, i;
630             guint32 offset;
631 
632             if (h1 == TFM_H1_TCP || h1 == TFM_H1_TCR || h1 == TFM_H1_TCA
633                 || h1 == TFM_H1_TFR)
634                 dissect_mtp3mg_unknown_message(tvb, pinfo, tree);
635 
636             proto_tree_add_item(tree, hf_mtp3mg_tfm_japan_count, tvb,
637                                 JAPAN_TFM_COUNT_OFFSET,
638                                 JAPAN_TFM_COUNT_LENGTH, ENC_LITTLE_ENDIAN);
639 
640             count = tvb_get_guint8(tvb, JAPAN_TFM_COUNT_OFFSET);
641             offset = JAPAN_TFM_COUNT_LENGTH;
642             for (i = 0; i < count; i++)
643             {
644                 apc_item = proto_tree_add_item(tree, hf_mtp3mg_japan_apc, tvb,
645                                     offset, JAPAN_PC_LENGTH, ENC_LITTLE_ENDIAN);
646 
647                 if (mtp3_pc_structured()) {
648                     guint32 apc;
649 
650                     apc = tvb_get_letohs(tvb, offset);
651                     proto_item_append_text(apc_item, " (%s)", mtp3_pc_to_str(apc));
652                 }
653 
654                 offset += JAPAN_PC_LENGTH;
655                 proto_tree_add_item(tree, hf_mtp3mg_tfm_japan_spare, tvb,
656                                     offset, JAPAN_PC_LENGTH, ENC_LITTLE_ENDIAN);
657                 offset += JAPAN_PC_LENGTH;
658             }
659         } else /* ITU_STANDARD and CHINESE_ITU_STANDARD */ {
660 
661             if (h1 == TFM_H1_TCP || h1 == TFM_H1_TCR || h1 == TFM_H1_TCA)
662                 dissect_mtp3mg_unknown_message(tvb, pinfo, tree);
663             else if (mtp3_standard == ITU_STANDARD)
664             {
665                 apc_item = proto_tree_add_item(tree, hf_mtp3mg_itu_apc,
666                                                tvb, 0, ITU_PC_LENGTH, ENC_LITTLE_ENDIAN);
667 
668                 if (mtp3_pc_structured()) {
669                     guint32 apc;
670 
671                     apc = tvb_get_letohs(tvb, 0) & ITU_PC_MASK;
672                     proto_item_append_text(apc_item, " (%s)", mtp3_pc_to_str(apc));
673                 }
674             }
675             else if (mtp3_standard == CHINESE_ITU_STANDARD)
676                 dissect_mtp3_3byte_pc(tvb, 0, tree, ett_mtp3mg_tfm_apc,
677                                       hf_mtp3mg_chinese_apc,
678                                       hf_mtp3mg_apc_network,
679                                       hf_mtp3mg_apc_cluster,
680                                       hf_mtp3mg_apc_member, 0, 0);
681         }
682         break;
683 
684     default:
685         dissect_mtp3mg_unknown_message(tvb, pinfo, tree);
686     }
687 }
688 
689 static void
dissect_mtp3mg_rsm(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,guint8 h1)690 dissect_mtp3mg_rsm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
691                    guint8 h1)
692 {
693     proto_item *apc_item;
694 
695     col_add_fstr(pinfo->cinfo, COL_INFO, "%s ",
696                  val_to_str_const(h1, rsm_h1_message_type_acro_values, "Unknown"));
697 
698     switch (h1)
699     {
700     case RSM_H1_RST:
701     case RSM_H1_RSR:
702     case RSM_H1_RCP:
703     case RSM_H1_RCR:
704         if (mtp3_standard == ANSI_STANDARD) {
705             dissect_mtp3_3byte_pc(tvb, 0, tree, ett_mtp3mg_rsm_apc,
706                                   hf_mtp3mg_ansi_apc,
707                                   hf_mtp3mg_apc_network,
708                                   hf_mtp3mg_apc_cluster,
709                                   hf_mtp3mg_apc_member, 0, 0);
710 
711         } else if (mtp3_standard == JAPAN_STANDARD) {
712             if (h1 == RSM_H1_RST) {
713                 guint32 offset;
714                 guint8 count, i;
715 
716                 proto_tree_add_item(tree, hf_mtp3mg_rsm_japan_count, tvb,
717                                     JAPAN_TFM_COUNT_OFFSET,
718                                     JAPAN_TFM_COUNT_LENGTH, ENC_LITTLE_ENDIAN);
719 
720                 count = tvb_get_guint8(tvb, JAPAN_TFM_COUNT_OFFSET);
721                 offset = JAPAN_TFM_COUNT_LENGTH;
722                 for (i = 0; i < count; i++) {
723                     apc_item = proto_tree_add_item(tree,
724                                                    hf_mtp3mg_japan_apc,
725                                                    tvb, offset,
726                                                    JAPAN_PC_LENGTH,
727                                                    ENC_LITTLE_ENDIAN);
728                     if (mtp3_pc_structured()) {
729                         guint32 apc;
730 
731                         apc = tvb_get_letohs(tvb, 0);
732                         proto_item_append_text(apc_item, " (%s)",
733                                                mtp3_pc_to_str(apc));
734                     }
735                     offset += JAPAN_PC_LENGTH;
736                     proto_tree_add_item(tree, hf_mtp3mg_rsm_japan_spare, tvb,
737                                         offset, JAPAN_PC_LENGTH,
738                                         ENC_LITTLE_ENDIAN);
739                     offset += JAPAN_PC_LENGTH;
740                 }
741             } else
742                 dissect_mtp3mg_unknown_message(tvb, pinfo, tree);
743 
744         } else /* ITU_STANDARD and CHINESE_ITU_STANDARD */ {
745 
746             if (h1 == RSM_H1_RST || h1 == RSM_H1_RSR) {
747                 if (mtp3_standard == ITU_STANDARD) {
748                     apc_item = proto_tree_add_item(tree, hf_mtp3mg_itu_apc,
749                                                    tvb, 0, ITU_PC_LENGTH,
750                                                    ENC_LITTLE_ENDIAN);
751                     if (mtp3_pc_structured()) {
752                         guint32 apc;
753 
754                         apc = tvb_get_letohs(tvb, 0) & ITU_PC_MASK;
755                         proto_item_append_text(apc_item, " (%s)", mtp3_pc_to_str(apc));
756                     }
757                 }
758                 else /* CHINESE_ITU_STANDARD */
759                     dissect_mtp3_3byte_pc(tvb, 0, tree, ett_mtp3mg_rsm_apc,
760                                           hf_mtp3mg_chinese_apc,
761                                           hf_mtp3mg_apc_network,
762                                           hf_mtp3mg_apc_cluster,
763                                           hf_mtp3mg_apc_member, 0, 0);
764             } else
765                 dissect_mtp3mg_unknown_message(tvb, pinfo, tree);
766         }
767         break;
768 
769     default:
770         dissect_mtp3mg_unknown_message(tvb, pinfo, tree);
771     }
772 }
773 
774 static void
dissect_mtp3mg_mim(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,guint8 h1)775 dissect_mtp3mg_mim(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
776                    guint8 h1)
777 {
778     col_add_fstr(pinfo->cinfo, COL_INFO, "%s ",
779                  val_to_str_const(h1, mim_h1_message_type_acro_values, "Unknown"));
780 
781     switch (h1)
782     {
783     case MIM_H1_LIN:
784     case MIM_H1_LUN:
785     case MIM_H1_LIA:
786     case MIM_H1_LUA:
787     case MIM_H1_LID:
788     case MIM_H1_LFU:
789     case MIM_H1_LLT:
790     case MIM_H1_LRT:
791         if (mtp3_standard == ANSI_STANDARD)
792         {
793             proto_tree_add_item(tree, hf_mtp3mg_mim_ansi_slc, tvb, 0,
794                                 ANSI_MIM_LENGTH, ENC_LITTLE_ENDIAN);
795         }
796         /* else: nothing to dissect */
797         break;
798 
799     default:
800         dissect_mtp3mg_unknown_message(tvb, pinfo, tree);
801     }
802 }
803 
804 static void
dissect_mtp3mg_trm(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,guint8 h1)805 dissect_mtp3mg_trm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
806                    guint8 h1)
807 {
808     col_add_fstr(pinfo->cinfo, COL_INFO, "%s ",
809                  val_to_str_const(h1, trm_h1_message_type_acro_values, "Unknown"));
810 
811     switch (h1)
812     {
813     case TRM_H1_TRA:
814         /* nothing to dissect */
815         break;
816     case TRM_H1_TRW:
817         if (mtp3_standard != ANSI_STANDARD)
818             dissect_mtp3mg_unknown_message(tvb, pinfo, tree);
819         /* else: nothing to dissect */
820         break;
821 
822     default:
823         dissect_mtp3mg_unknown_message(tvb, pinfo, tree);
824     }
825 }
826 
827 static void
dissect_mtp3mg_dlm(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,guint8 h1)828 dissect_mtp3mg_dlm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
829                    guint8 h1)
830 {
831     col_add_fstr(pinfo->cinfo, COL_INFO, "%s ",
832                  val_to_str_const(h1, dlm_h1_message_type_acro_values, "Unknown"));
833 
834     switch (h1)
835     {
836     case DLM_H1_DLC:
837         if (mtp3_standard == ANSI_STANDARD)
838         {
839             proto_tree_add_item(tree, hf_mtp3mg_dlc_ansi_slc, tvb, 0,
840                                 ANSI_DLC_LENGTH, ENC_LITTLE_ENDIAN);
841             proto_tree_add_item(tree, hf_mtp3mg_dlc_ansi_link, tvb, 0,
842                                 ANSI_DLC_LENGTH, ENC_LITTLE_ENDIAN);
843         } else /* ITU_STANDARD and CHINESE_ITU_STANDARD */ {
844             proto_tree_add_item(tree, hf_mtp3mg_dlc_itu_link, tvb, 0,
845                                 ITU_DLC_LENGTH, ENC_LITTLE_ENDIAN);
846         }
847         break;
848     case DLM_H1_CSS:
849     case DLM_H1_CNS:
850     case DLM_H1_CNP:
851         /* nothing to dissect */
852         break;
853 
854     default:
855         dissect_mtp3mg_unknown_message(tvb, pinfo, tree);
856     }
857 }
858 
859 static void
dissect_mtp3mg_ufc(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,guint8 h1)860 dissect_mtp3mg_ufc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
861                    guint8 h1)
862 {
863     proto_item *apc_item;
864 
865     col_add_fstr(pinfo->cinfo, COL_INFO, "%s ",
866                  val_to_str_const(h1, ufc_h1_message_type_acro_values, "Unknown"));
867 
868     switch (h1)
869     {
870     case UFC_H1_UPU:
871         if (mtp3_standard == ANSI_STANDARD
872             || mtp3_standard == CHINESE_ITU_STANDARD) {
873             int hf_apc;
874 
875             if (mtp3_standard == ANSI_STANDARD)
876                 hf_apc = hf_mtp3mg_ansi_apc;
877             else /* CHINESE_ITU_STANDARD */
878                 hf_apc = hf_mtp3mg_chinese_apc;
879 
880             dissect_mtp3_3byte_pc(tvb, 0, tree, ett_mtp3mg_upu_apc, hf_apc,
881                                   hf_mtp3mg_apc_network,
882                                   hf_mtp3mg_apc_cluster,
883                                   hf_mtp3mg_apc_member, 0, 0);
884 
885             proto_tree_add_item(tree, hf_mtp3mg_upu_user, tvb,
886                                 ANSI_UPU_USER_OFFSET, UPU_USER_LENGTH, ENC_LITTLE_ENDIAN);
887             proto_tree_add_item(tree, hf_mtp3mg_upu_cause, tvb,
888                                 ANSI_UPU_USER_OFFSET, UPU_USER_LENGTH, ENC_LITTLE_ENDIAN);
889         } else if (mtp3_standard == ITU_STANDARD) {
890 
891             apc_item = proto_tree_add_item(tree, hf_mtp3mg_itu_apc, tvb, 0,
892                                            ITU_PC_LENGTH, ENC_LITTLE_ENDIAN);
893             if (mtp3_pc_structured()) {
894                 guint32 apc;
895 
896                 apc = tvb_get_letohs(tvb, 0) & ITU_PC_MASK;
897                 proto_item_append_text(apc_item, " (%s)", mtp3_pc_to_str(apc));
898             }
899 
900             proto_tree_add_item(tree, hf_mtp3mg_upu_user, tvb,
901                                 ITU_UPU_USER_OFFSET, UPU_USER_LENGTH, ENC_LITTLE_ENDIAN);
902             proto_tree_add_item(tree, hf_mtp3mg_upu_cause, tvb,
903                                 ITU_UPU_USER_OFFSET, UPU_USER_LENGTH, ENC_LITTLE_ENDIAN);
904         } else { /* JAPAN_STANDARD */
905 
906             apc_item = proto_tree_add_item(tree, hf_mtp3mg_japan_apc, tvb,
907                                            0, JAPAN_PC_LENGTH,
908                                            ENC_LITTLE_ENDIAN);
909             if (mtp3_pc_structured()) {
910                 guint32 apc;
911 
912                 apc = tvb_get_letohs(tvb, 0);
913                 proto_item_append_text(apc_item, " (%s)", mtp3_pc_to_str(apc));
914             }
915 
916             proto_tree_add_item(tree, hf_mtp3mg_upu_user, tvb,
917                                 ITU_UPU_USER_OFFSET, UPU_USER_LENGTH, ENC_LITTLE_ENDIAN);
918             proto_tree_add_item(tree, hf_mtp3mg_upu_cause, tvb,
919                                 ITU_UPU_USER_OFFSET, UPU_USER_LENGTH, ENC_LITTLE_ENDIAN);
920         }
921         break;
922 
923     default:
924         dissect_mtp3mg_unknown_message(tvb, pinfo, tree);
925     }
926 }
927 
928 static void
dissect_mtp3mg_test(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,guint8 h1)929 dissect_mtp3mg_test(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
930                    guint8 h1)
931 {
932     guint8 length;
933 
934     col_add_fstr(pinfo->cinfo, COL_INFO, "%s ",
935                  val_to_str_const(h1, test_h1_message_type_acro_values, "Unknown"));
936 
937     switch (h1)
938     {
939     case TEST_H1_SLTM:
940     case TEST_H1_SLTA:
941         if (mtp3_standard == ANSI_STANDARD)
942         {
943             proto_tree_add_item(tree, hf_mtp3mg_test_ansi_slc, tvb, 0,
944                                 TEST_LENGTH, ENC_LITTLE_ENDIAN);
945         }
946 
947         proto_tree_add_item(tree, hf_mtp3mg_test_length, tvb, 0, TEST_LENGTH,
948                             ENC_LITTLE_ENDIAN);
949 
950         length = tvb_get_guint8(tvb, 0) >> TEST_LENGTH_SHIFT;
951         proto_tree_add_item(tree, hf_mtp3mg_test_pattern, tvb, TEST_PATTERN_OFFSET, length, ENC_NA);
952         break;
953 
954     default:
955         dissect_mtp3mg_unknown_message(tvb, pinfo, tree);
956     }
957 }
958 
959 static int
dissect_mtp3mg(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)960 dissect_mtp3mg(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
961 {
962 
963     guint8 h0, h1;
964     tvbuff_t *payload_tvb;
965 
966     /* Set up structures needed to add the protocol subtree and manage it */
967     proto_item *mtp3mg_item;
968     proto_tree *mtp3mg_tree;
969 
970     /* Make entries in Protocol column on summary display */
971     switch(mtp3_standard) {
972     case ITU_STANDARD:
973         col_set_str(pinfo->cinfo, COL_PROTOCOL, "MTP3MG (Int. ITU)");
974         break;
975     case ANSI_STANDARD:
976         col_set_str(pinfo->cinfo, COL_PROTOCOL, "MTP3MG (ANSI)");
977         break;
978     case CHINESE_ITU_STANDARD:
979         col_set_str(pinfo->cinfo, COL_PROTOCOL, "MTP3MG (Chin. ITU)");
980         break;
981     case JAPAN_STANDARD:
982         col_set_str(pinfo->cinfo, COL_PROTOCOL, "MTP3MG (Japan)");
983         break;
984     };
985 
986         /* create display subtree for the protocol */
987         mtp3mg_item = proto_tree_add_item(tree, proto_mtp3mg, tvb, 0, -1, ENC_NA);
988         mtp3mg_tree = proto_item_add_subtree(mtp3mg_item, ett_mtp3mg);
989 
990     /*
991      *  Dissect the message
992      */
993     if(pinfo->match_uint == MTP_SI_MTN || /* ITU */
994        pinfo->match_uint == MTP_SI_MTNS)  /* ANSI */
995     {   /* Test messages */
996 
997         if (mtp3_standard == JAPAN_STANDARD)
998         {
999             guint8 h0h1;
1000             guint16 test_pattern;
1001             proto_item *pattern_item;
1002 
1003             proto_tree_add_item(mtp3mg_tree, hf_mtp3mg_japan_spare, tvb, 0,
1004                                 JAPAN_SPARE_LENGTH, ENC_LITTLE_ENDIAN);
1005 
1006             h0h1 = tvb_get_guint8(tvb, JAPAN_H0H1_OFFSET);
1007 
1008             proto_tree_add_item(mtp3mg_tree, hf_mtp3mg_japan_test, tvb,
1009                                 JAPAN_SPARE_LENGTH, H0H1_LENGTH, ENC_LITTLE_ENDIAN);
1010 
1011             col_add_fstr(pinfo->cinfo, COL_INFO, "%s ",
1012                          val_to_str_const(h0h1, japan_test_message_type_acro_values, "Unknown"));
1013 
1014             switch (h0h1)
1015             {
1016             case JAPAN_TEST_SRT:
1017             case JAPAN_TEST_SRA:
1018                 proto_tree_add_item(mtp3mg_tree, hf_mtp3mg_japan_test_spare,
1019                                     tvb, JAPAN_TEST_SPARE_OFFSET,
1020                                     JAPAN_TEST_SPARE_LENGTH, ENC_LITTLE_ENDIAN);
1021 
1022                 test_pattern = tvb_get_letohs(tvb, JAPAN_TEST_PATTERN_OFFSET);
1023                 pattern_item = proto_tree_add_item(mtp3mg_tree,
1024                                                    hf_mtp3mg_japan_test_pattern,
1025                                                    tvb,
1026                                                    JAPAN_TEST_PATTERN_OFFSET,
1027                                                    JAPAN_TEST_PATTERN_LENGTH,
1028                                                    ENC_LITTLE_ENDIAN);
1029                 proto_item_append_text(pattern_item, " (%s)",
1030                                        test_pattern == JAPAN_TEST_PATTERN
1031                                        ? "correct" : "incorrect");
1032                 break;
1033 
1034             default:
1035                 dissect_mtp3mg_unknown_message(tvb, pinfo, mtp3mg_tree);
1036             }
1037 
1038         } else { /* not JAPAN */
1039             proto_tree_add_item(mtp3mg_tree, hf_mtp3test_h0, tvb, 0, H0H1_LENGTH, ENC_LITTLE_ENDIAN);
1040             /* H1 is added below */
1041 
1042             h0 = tvb_get_guint8(tvb, 0) & H0_MASK;
1043             h1 = (tvb_get_guint8(tvb, 0) & H1_MASK) >> H1_SHIFT;
1044 
1045             payload_tvb = tvb_new_subset_remaining(tvb, H0H1_LENGTH);
1046 
1047             switch (h0)
1048             {
1049             case TEST_H0_SLT:
1050                 proto_tree_add_item(mtp3mg_tree, hf_mtp3mg_test_h1, tvb, 0,
1051                                     H0H1_LENGTH, ENC_LITTLE_ENDIAN);
1052                 dissect_mtp3mg_test(payload_tvb, pinfo, mtp3mg_tree, h1);
1053                 break;
1054 
1055             default:
1056                 col_set_str(pinfo->cinfo, COL_INFO, "Unknown ");
1057 
1058                 dissect_mtp3mg_unknown_message(tvb, pinfo, mtp3mg_tree);
1059             } /* switch */
1060 
1061         }
1062 
1063     } else {    /* Real management messages */
1064 
1065 
1066         if (mtp3_standard == JAPAN_STANDARD)
1067         {
1068             proto_tree_add_item(mtp3mg_tree, hf_mtp3mg_japan_spare, tvb, 0,
1069                                 JAPAN_SPARE_LENGTH, ENC_LITTLE_ENDIAN);
1070 
1071             /*  Get a tvb w/o the spare byte--it makes for less code below */
1072             tvb = tvb_new_subset_remaining(tvb, JAPAN_SPARE_LENGTH);
1073         }
1074 
1075         proto_tree_add_item(mtp3mg_tree, hf_mtp3mg_h0, tvb, 0, H0H1_LENGTH,
1076                             ENC_LITTLE_ENDIAN);
1077         /* H1 is added below */
1078 
1079         h0 = tvb_get_guint8(tvb, 0) & H0_MASK;
1080         h1 = (tvb_get_guint8(tvb, 0) & H1_MASK) >> H1_SHIFT;
1081 
1082         payload_tvb = tvb_new_subset_remaining(tvb, H0H1_LENGTH);
1083 
1084         switch (h0)
1085         {
1086         case H0_CHM:
1087             proto_tree_add_item(mtp3mg_tree, hf_mtp3mg_chm_h1, tvb, 0,
1088                                 H0H1_LENGTH, ENC_LITTLE_ENDIAN);
1089             dissect_mtp3mg_chm(payload_tvb, pinfo, mtp3mg_tree, h1);
1090             break;
1091         case H0_ECM:
1092             proto_tree_add_item(mtp3mg_tree, hf_mtp3mg_ecm_h1, tvb, 0,
1093                                 H0H1_LENGTH, ENC_LITTLE_ENDIAN);
1094             dissect_mtp3mg_ecm(payload_tvb, pinfo, mtp3mg_tree, h1);
1095             break;
1096         case H0_FCM:
1097             proto_tree_add_item(mtp3mg_tree, hf_mtp3mg_fcm_h1, tvb, 0,
1098                                 H0H1_LENGTH, ENC_LITTLE_ENDIAN);
1099             dissect_mtp3mg_fcm(payload_tvb, pinfo, mtp3mg_tree, h1);
1100             break;
1101         case H0_TFM:
1102             proto_tree_add_item(mtp3mg_tree, hf_mtp3mg_tfm_h1, tvb, 0,
1103                                 H0H1_LENGTH, ENC_LITTLE_ENDIAN);
1104             dissect_mtp3mg_tfm(payload_tvb, pinfo, mtp3mg_tree, h1);
1105             break;
1106         case H0_RSM:
1107             proto_tree_add_item(mtp3mg_tree, hf_mtp3mg_rsm_h1, tvb, 0,
1108                                 H0H1_LENGTH, ENC_LITTLE_ENDIAN);
1109             dissect_mtp3mg_rsm(payload_tvb, pinfo, mtp3mg_tree, h1);
1110             break;
1111         case H0_MIM:
1112             if (mtp3_standard != JAPAN_STANDARD)
1113             {
1114                 proto_tree_add_item(mtp3mg_tree, hf_mtp3mg_mim_h1, tvb, 0,
1115                                     H0H1_LENGTH, ENC_LITTLE_ENDIAN);
1116                 dissect_mtp3mg_mim(payload_tvb, pinfo, mtp3mg_tree, h1);
1117             } else
1118                 dissect_mtp3mg_unknown_message(tvb, pinfo, mtp3mg_tree);
1119             break;
1120         case H0_TRM:
1121             if (mtp3_standard != JAPAN_STANDARD)
1122             {
1123                 proto_tree_add_item(mtp3mg_tree, hf_mtp3mg_trm_h1, tvb, 0,
1124                                     H0H1_LENGTH, ENC_LITTLE_ENDIAN);
1125                 dissect_mtp3mg_trm(payload_tvb, pinfo, mtp3mg_tree, h1);
1126             } else
1127                 dissect_mtp3mg_unknown_message(tvb, pinfo, mtp3mg_tree);
1128             break;
1129         case H0_DLM:
1130             if (mtp3_standard != JAPAN_STANDARD)
1131             {
1132                 proto_tree_add_item(mtp3mg_tree, hf_mtp3mg_dlm_h1, tvb, 0,
1133                                     H0H1_LENGTH, ENC_LITTLE_ENDIAN);
1134                 dissect_mtp3mg_dlm(payload_tvb, pinfo, mtp3mg_tree, h1);
1135             } else
1136                 dissect_mtp3mg_unknown_message(tvb, pinfo, mtp3mg_tree);
1137             break;
1138         case H0_UFC:
1139             if (mtp3_standard != JAPAN_STANDARD)
1140             {
1141                 proto_tree_add_item(mtp3mg_tree, hf_mtp3mg_ufc_h1, tvb, 0,
1142                                     H0H1_LENGTH, ENC_LITTLE_ENDIAN);
1143                 dissect_mtp3mg_ufc(payload_tvb, pinfo, mtp3mg_tree, h1);
1144             } else
1145                 dissect_mtp3mg_unknown_message(tvb, pinfo, mtp3mg_tree);
1146             break;
1147 
1148         default:
1149             col_set_str(pinfo->cinfo, COL_INFO, "Unknown ");
1150 
1151             dissect_mtp3mg_unknown_message(tvb, pinfo, mtp3mg_tree);
1152         } /* switch */
1153     } /* else */
1154 
1155     return tvb_captured_length(tvb);
1156 }
1157 
1158 void
proto_register_mtp3mg(void)1159 proto_register_mtp3mg(void)
1160 {
1161 
1162     /* Setup list of header fields  See Section 1.6.1 for details*/
1163     static hf_register_info hf[] = {
1164         { &hf_mtp3mg_h0,
1165             { "H0 (Message Group)", "mtp3mg.h0",
1166               FT_UINT8, BASE_HEX, VALS(h0_message_type_values), H0_MASK,
1167               "Message group identifier", HFILL }},
1168         { &hf_mtp3mg_chm_h1,
1169             { "H1 (Message)", "mtp3mg.h1",
1170               FT_UINT8, BASE_HEX, VALS(chm_h1_message_type_values), H1_MASK,
1171               "Message type", HFILL }},
1172         { &hf_mtp3mg_ecm_h1,
1173             { "H1 (Message)", "mtp3mg.h1",
1174               FT_UINT8, BASE_HEX, VALS(ecm_h1_message_type_values), H1_MASK,
1175               "Message type", HFILL }},
1176         { &hf_mtp3mg_fcm_h1,
1177             { "H1 (Message)", "mtp3mg.h1",
1178               FT_UINT8, BASE_HEX, VALS(fcm_h1_message_type_values), H1_MASK,
1179               "Message type", HFILL }},
1180         { &hf_mtp3mg_tfm_h1,
1181             { "H1 (Message)", "mtp3mg.h1",
1182               FT_UINT8, BASE_HEX, VALS(tfm_h1_message_type_values), H1_MASK,
1183               "Message type", HFILL }},
1184         { &hf_mtp3mg_rsm_h1,
1185             { "H1 (Message)", "mtp3mg.h1",
1186               FT_UINT8, BASE_HEX, VALS(rsm_h1_message_type_values), H1_MASK,
1187               "Message type", HFILL }},
1188         { &hf_mtp3mg_mim_h1,
1189             { "H1 (Message)", "mtp3mg.h1",
1190               FT_UINT8, BASE_HEX, VALS(mim_h1_message_type_values), H1_MASK,
1191               "Message type", HFILL }},
1192         { &hf_mtp3mg_trm_h1,
1193             { "H1 (Message)", "mtp3mg.h1",
1194               FT_UINT8, BASE_HEX, VALS(trm_h1_message_type_values), H1_MASK,
1195               "Message type", HFILL }},
1196         { &hf_mtp3mg_dlm_h1,
1197             { "H1 (Message)", "mtp3mg.h1",
1198               FT_UINT8, BASE_HEX, VALS(dlm_h1_message_type_values), H1_MASK,
1199               "Message type", HFILL }},
1200         { &hf_mtp3mg_ufc_h1,
1201             { "H1 (Message)", "mtp3mg.h1",
1202               FT_UINT8, BASE_HEX, VALS(ufc_h1_message_type_values), H1_MASK,
1203               "Message type", HFILL }},
1204         { &hf_mtp3mg_coo_ansi_slc,
1205             { "Signalling Link Code", "mtp3mg.slc",
1206               FT_UINT8, BASE_DEC, NULL, ANSI_COO_SLC_MASK,
1207               "SLC of affected link", HFILL }},
1208         { &hf_mtp3mg_coo_ansi_fsn,
1209             { "Forward Sequence Number", "mtp3mg.fsn",
1210               FT_UINT8, BASE_DEC, NULL, ANSI_COO_FSN_MASK,
1211               "Forward Sequence Number of last accepted message", HFILL }},
1212         { &hf_mtp3mg_coo_itu_fsn,
1213             { "Forward Sequence Number", "mtp3mg.fsn",
1214               FT_UINT8, BASE_DEC, NULL, ITU_COO_FSN_MASK,
1215               "Forward Sequence Number of last accepted message", HFILL }},
1216         { &hf_mtp3mg_xco_ansi_slc,
1217             { "Signalling Link Code", "mtp3mg.slc",
1218               FT_UINT32, BASE_DEC, NULL, ANSI_XCO_SLC_MASK,
1219               "SLC of affected link", HFILL }},
1220         { &hf_mtp3mg_xco_ansi_fsn,
1221             { "Forward Sequence Number", "mtp3mg.fsn",
1222               FT_UINT32, BASE_DEC, NULL, ANSI_XCO_FSN_MASK,
1223               "Forward Sequence Number of last accepted message", HFILL }},
1224         { &hf_mtp3mg_xco_itu_fsn,
1225             { "Forward Sequence Number", "mtp3mg.fsn",
1226               FT_UINT24, BASE_DEC, NULL, 0x0,
1227               "Forward Sequence Number of last accepted message", HFILL }},
1228         { &hf_mtp3mg_cbd_ansi_slc,
1229             { "Signalling Link Code", "mtp3mg.slc",
1230               FT_UINT16, BASE_DEC, NULL, ANSI_CBD_SLC_MASK,
1231               "SLC of affected link", HFILL }},
1232         { &hf_mtp3mg_cbd_ansi_cbc,
1233             { "Change Back Code", "mtp3mg.cbc",
1234               FT_UINT16, BASE_DEC, NULL, ANSI_CBD_CBC_MASK,
1235               NULL, HFILL }},
1236         { &hf_mtp3mg_cbd_itu_cbc,
1237             { "Change Back Code", "mtp3mg.cbc",
1238               FT_UINT8, BASE_DEC, NULL, 0x0,
1239               NULL, HFILL }},
1240         { &hf_mtp3mg_cbd_japan_cbc,
1241             { "Change Back Code", "mtp3mg.cbc",
1242               FT_UINT8, BASE_DEC, NULL, JAPAN_CBD_CBC_MASK,
1243               NULL, HFILL }},
1244         { &hf_mtp3mg_eco_ansi_slc,
1245             { "Signalling Link Code", "mtp3mg.slc",
1246               FT_UINT8, BASE_DEC, NULL, ANSI_ECO_SLC_MASK,
1247               "SLC of affected link", HFILL }},
1248         { &hf_mtp3mg_ansi_apc,
1249             { "Affected Point Code", "mtp3mg.ansi_apc",
1250               FT_STRING, BASE_NONE, NULL, 0x0,
1251               NULL, HFILL }},
1252         { &hf_mtp3mg_apc_member,
1253             { "Affected Point Code member", "mtp3mg.apc.member",
1254               FT_UINT24, BASE_DEC, NULL, ANSI_MEMBER_MASK,
1255               NULL, HFILL }},
1256         { &hf_mtp3mg_apc_cluster,
1257             { "Affected Point Code cluster", "mtp3mg.apc.cluster",
1258               FT_UINT24, BASE_DEC, NULL, ANSI_CLUSTER_MASK,
1259               NULL, HFILL }},
1260         { &hf_mtp3mg_apc_network,
1261             { "Affected Point Code network", "mtp3mg.apc.network",
1262               FT_UINT24, BASE_DEC, NULL, ANSI_NETWORK_MASK,
1263               NULL, HFILL }},
1264         { &hf_mtp3mg_tfc_ansi_status,
1265             { "Status", "mtp3mg.status",
1266               FT_UINT8, BASE_DEC, NULL, ANSI_TFC_STATUS_MASK,
1267               "Congestion status", HFILL }},
1268         { &hf_mtp3mg_itu_apc,
1269             { "Affected Point Code (ITU)", "mtp3mg.apc",
1270               FT_UINT16, BASE_DEC, NULL, ITU_PC_MASK,
1271               NULL, HFILL }},
1272         { &hf_mtp3mg_tfc_itu_status,
1273             { "Status", "mtp3mg.status",
1274               FT_UINT8, BASE_DEC, NULL, ITU_TFC_STATUS_MASK,
1275               "Congestion status", HFILL }},
1276         { &hf_mtp3mg_chinese_apc,
1277             { "Affected Point Code", "mtp3mg.chinese_apc",
1278               FT_STRING, BASE_NONE, NULL, 0x0,
1279               NULL, HFILL }},
1280         { &hf_mtp3mg_tfc_japan_spare,
1281             { "TFC spare (Japan)", "mtp3mg.japan_spare",
1282               FT_UINT8, BASE_HEX, NULL, 0x0,
1283               NULL, HFILL }},
1284         { &hf_mtp3mg_japan_apc,
1285             { "Affected Point Code", "mtp3mg.japan_apc",
1286               FT_UINT16, BASE_DEC, NULL, 0x0,
1287               NULL, HFILL }},
1288         { &hf_mtp3mg_tfc_japan_status,
1289             { "Status", "mtp3mg.japan_status",
1290               FT_UINT8, BASE_DEC, NULL, JAPAN_TFC_STATUS_MASK,
1291               NULL, HFILL }},
1292         { &hf_mtp3mg_tfc_japan_status_spare,
1293             { "Spare (Japan)", "mtp3mg.japan_spare",
1294               FT_UINT8, BASE_HEX, NULL, JAPAN_TFC_STATUS_SPARE_MASK,
1295               NULL, HFILL }},
1296         { &hf_mtp3mg_tfm_japan_count,
1297             { "Count of Affected Point Codes (Japan)", "mtp3mg.japan_count",
1298               FT_UINT8, BASE_DEC, NULL, 0x0,
1299               NULL, HFILL }},
1300         { &hf_mtp3mg_tfm_japan_spare,
1301             { "Spare (Japan)", "mtp3mg.japan_spare",
1302               FT_UINT16, BASE_DEC, NULL, 0x0,
1303               NULL, HFILL }},
1304         { &hf_mtp3mg_rsm_japan_count,
1305             { "Count of Affected Point Codes (Japan)", "mtp3mg.japan_count",
1306               FT_UINT8, BASE_DEC, NULL, 0x0,
1307               NULL, HFILL }},
1308         { &hf_mtp3mg_rsm_japan_spare,
1309             { "Spare (Japan)", "mtp3mg.japan_spare",
1310               FT_UINT16, BASE_DEC, NULL, 0x0,
1311               NULL, HFILL }},
1312         { &hf_mtp3mg_mim_ansi_slc,
1313             { "Signalling Link Code", "mtp3mg.slc",
1314               FT_UINT8, BASE_DEC, NULL, ANSI_MIM_SLC_MASK,
1315               "SLC of affected link", HFILL }},
1316         { &hf_mtp3mg_dlc_ansi_slc,
1317             { "Signalling Link Code", "mtp3mg.slc",
1318               FT_UINT8, BASE_DEC, NULL, ANSI_DLC_SLC_MASK,
1319               "SLC of affected link", HFILL }},
1320         { &hf_mtp3mg_dlc_ansi_link,
1321             { "Link", "mtp3mg.link",
1322               FT_UINT8, BASE_DEC, NULL, ANSI_DLC_LINK_MASK,
1323               "CIC of BIC used to carry data", HFILL }},
1324         { &hf_mtp3mg_dlc_itu_link,
1325             { "Link", "mtp3mg.link",
1326               FT_UINT8, BASE_DEC, NULL, ITU_DLC_LINK_MASK,
1327               "CIC of BIC used to carry data", HFILL }},
1328         { &hf_mtp3mg_upu_user,
1329             { "User", "mtp3mg.user",
1330               FT_UINT8, BASE_HEX, VALS(service_indicator_code_vals), UPU_USER_MASK,
1331               "Unavailable user part", HFILL }},
1332         { &hf_mtp3mg_upu_cause,
1333             { "Cause", "mtp3mg.cause",
1334               FT_UINT8, BASE_HEX, VALS(upu_cause_values), UPU_CAUSE_MASK,
1335               "Cause of user unavailability", HFILL }},
1336         { &hf_mtp3test_h0,
1337             { "H0 (Message Group)", "mtp3mg.test.h0",
1338               FT_UINT8, BASE_HEX, VALS(test_h0_message_type_values), H0_MASK,
1339               "Message group identifier", HFILL }},
1340         { &hf_mtp3mg_test_h1,
1341             { "H1 (Message)", "mtp3mg.test.h1",
1342               FT_UINT8, BASE_HEX, VALS(test_h1_message_type_values), H1_MASK,
1343               "SLT message type", HFILL }},
1344         { &hf_mtp3mg_test_length,
1345             { "Test length", "mtp3mg.test.length",
1346               FT_UINT8, BASE_DEC, NULL, H1_MASK,
1347               "Signalling link test pattern length", HFILL }},
1348         { &hf_mtp3mg_japan_test,
1349             { "Japan test message", "mtp3mg.test",
1350               FT_UINT8, BASE_HEX, VALS(japan_test_message_type_values), 0x0,
1351               "Japan test message type", HFILL }},
1352         { &hf_mtp3mg_japan_test_spare,
1353             { "Japan test message spare", "mtp3mg.test.spare",
1354               FT_UINT8, BASE_HEX, NULL, 0x0,
1355               NULL, HFILL }},
1356         { &hf_mtp3mg_japan_test_pattern,
1357             { "Japan test message pattern", "mtp3mg.test.pattern",
1358               FT_UINT16, BASE_HEX, NULL, 0x0,
1359               NULL, HFILL }},
1360         { &hf_mtp3mg_japan_spare,
1361             { "Japan management spare", "mtp3mg.spare",
1362               FT_UINT8, BASE_HEX, NULL, 0x0,
1363               NULL, HFILL }},
1364         { &hf_mtp3mg_test_ansi_slc,
1365             { "Signalling Link Code", "mtp3mg.slc",
1366               FT_UINT8, BASE_DEC, NULL, ANSI_TEST_SLC_MASK,
1367               "SLC of affected link", HFILL }},
1368         { &hf_mtp3mg_test_pattern,
1369             { "Test pattern", "mtp3mg.test_pattern",
1370               FT_BYTES, BASE_NONE, NULL, 0x0,
1371               NULL, HFILL }},
1372   };
1373 
1374     /* Setup protocol subtree array */
1375     static gint *ett[] = {
1376         &ett_mtp3mg,
1377         &ett_mtp3mg_fcm_apc,
1378         &ett_mtp3mg_tfm_apc,
1379         &ett_mtp3mg_rsm_apc,
1380         &ett_mtp3mg_upu_apc
1381     };
1382 
1383     static ei_register_info ei[] = {
1384         { &ei_mtp3mg_unknown_message, { "mtp3mg.unknown_message", PI_PROTOCOL, PI_WARN, "Unknown message", EXPFILL }},
1385     };
1386 
1387     expert_module_t* expert_mtp3mg;
1388 
1389     /* Register the protocol name and description */
1390     proto_mtp3mg = proto_register_protocol("Message Transfer Part Level 3 Management",
1391                                            "MTP3MG", "mtp3mg");
1392     mtp3mg_handle = register_dissector("mtp3mg", dissect_mtp3mg, proto_mtp3mg);
1393 
1394     /* Required calls to register the header fields and subtrees used */
1395     proto_register_field_array(proto_mtp3mg, hf, array_length(hf));
1396     proto_register_subtree_array(ett, array_length(ett));
1397     expert_mtp3mg = expert_register_protocol(proto_mtp3mg);
1398     expert_register_field_array(expert_mtp3mg, ei, array_length(ei));
1399 
1400 }
1401 
1402 void
proto_reg_handoff_mtp3mg(void)1403 proto_reg_handoff_mtp3mg(void)
1404 {
1405     dissector_add_uint("mtp3.service_indicator", MTP_SI_SNM, mtp3mg_handle);
1406 
1407     /*  SI 1 is unused in ANSI and SI 2 is unused in ITU, so it's okay for us
1408      *  to grab both (regardless of mtp3.standard setting) here.
1409      */
1410     dissector_add_uint("mtp3.service_indicator", MTP_SI_MTN, mtp3mg_handle);
1411     dissector_add_uint("mtp3.service_indicator", MTP_SI_MTNS, mtp3mg_handle);
1412 }
1413 
1414 /*
1415  * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
1416  *
1417  * Local variables:
1418  * c-basic-offset: 4
1419  * tab-width: 8
1420  * indent-tabs-mode: nil
1421  * End:
1422  *
1423  * vi: set shiftwidth=4 tabstop=8 expandtab:
1424  * :indentSize=4:tabSize=8:noTabs=true:
1425  */
1426