From Matthijs Melchior: check whether the ring buffer timeout has
[obnox/wireshark/wip.git] / packet-mtp3mg.c
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  *
11  * Copyright 2003, Jeff Morriss <jeff.morriss[AT]ulticom.com>
12  *
13  * $Id: packet-mtp3mg.c,v 1.10 2003/09/06 00:05:30 guy Exp $
14  *
15  * Ethereal - Network traffic analyzer
16  * By Gerald Combs <gerald@ethereal.com>
17  * Copyright 1998 Gerald Combs
18  *
19  * Copied from packet-mtp3.c
20  *
21  * This program is free software; you can redistribute it and/or
22  * modify it under the terms of the GNU General Public License
23  * as published by the Free Software Foundation; either version 2
24  * of the License, or (at your option) any later version.
25  *
26  * This program is distributed in the hope that it will be useful,
27  * but WITHOUT ANY WARRANTY; without even the implied warranty of
28  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
29  * GNU General Public License for more details.
30  *
31  * You should have received a copy of the GNU General Public License
32  * along with this program; if not, write to the Free Software
33  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
34  */
35
36 #ifdef HAVE_CONFIG_H
37 # include "config.h"
38 #endif
39
40 #include <glib.h>
41
42 #ifdef NEED_SNPRINTF_H
43 #include "snprintf.h"
44 #endif
45
46 #include <epan/packet.h>
47 #include "prefs.h"
48
49 #include <packet-mtp3.h>
50 extern Standard_Type mtp3_standard;
51
52 /* MTP3 Service Indicators used by this dissector */
53 #define MTP3MG_SI 0
54 #define MTP3MG_ITU_TEST_SI 1
55 #define MTP3MG_ANSI_TEST_SI 2
56
57 #define H0H1_LENGTH 1
58 #define H0_MASK     0x0f
59 #define H1_MASK     0xf0
60 #define H1_SHIFT    4
61
62 #define H0_CHM 0x01
63 #define H0_ECM 0x02
64 #define H0_FCM 0x03
65 #define H0_TFM 0x04
66 #define H0_RSM 0x05
67 #define H0_MIM 0x06
68 #define H0_TRM 0x07
69 #define H0_DLM 0x08
70 #define H0_UFC 0x0a
71 static const value_string h0_message_type_values[] = {
72   { H0_CHM, "Changeover and changeback messages" },
73   { H0_ECM, "Emergency changeover messages" },
74   { H0_FCM, "Transfer-controlled and signalling route set congestion messages" },
75   { H0_TFM, "Transfer prohibited-allowed-restricted messages" },
76   { H0_RSM, "Signalling-route-set-test messages" },
77   { H0_MIM, "Management inhibit messages" },
78   { H0_TRM, "Traffic restart messages" },
79   { H0_DLM, "Signalling-data-link-connection messages" },
80   { H0_UFC, "User part flow control messages" },
81   { 0,      NULL } };
82
83 #define TEST_H0_SLT 0x1
84 static const value_string test_h0_message_type_values[] = {
85   { TEST_H0_SLT, "Test messages" },
86   { 0,           NULL } };
87
88 #define CHM_H1_COO 0x01
89 #define CHM_H1_COA 0x02
90 #define CHM_H1_XCO 0x03
91 #define CHM_H1_XCA 0x04
92 #define CHM_H1_CBD 0x05
93 #define CHM_H1_CBA 0x06
94 static const value_string chm_h1_message_type_values[] = {
95   { CHM_H1_COO, "Changeover-order signal" },
96   { CHM_H1_COA, "Changeover-ack signal" },
97   { CHM_H1_XCO, "Extended changeover-order signal" },
98   { CHM_H1_XCA, "Extended changeover-ack signal" },
99   { CHM_H1_CBD, "Changeback-declaration signal" },
100   { CHM_H1_CBA, "Changeback-ack signal" },
101   { 0,          NULL } };
102
103 /* Same as above but in acronym form (for the Info column) */
104 static const value_string chm_h1_message_type_acro_values[] = {
105   { CHM_H1_COO, "COO" },
106   { CHM_H1_COA, "COA" },
107   { CHM_H1_XCO, "XCO" },
108   { CHM_H1_XCA, "XCA" },
109   { CHM_H1_CBD, "CBD" },
110   { CHM_H1_CBA, "CBA" },
111   { 0,          NULL } };
112
113 #define ECM_H1_ECO 0x01
114 #define ECM_H1_ECA 0x02
115 static const value_string ecm_h1_message_type_values[] = {
116   { ECM_H1_ECO, "Emergency-changeover-order signal" },
117   { ECM_H1_ECA, "Emergency-changeover-ack signal" },
118   { 0,          NULL } };
119
120 /* Same as above but in acronym form (for the Info column) */
121 static const value_string ecm_h1_message_type_acro_values[] = {
122   { ECM_H1_ECO, "ECO" },
123   { ECM_H1_ECA, "ECA" },
124   { 0,          NULL } };
125
126 #define FCM_H1_RCT 0x01
127 #define FCM_H1_TFC 0x02
128 static const value_string fcm_h1_message_type_values[] = {
129   { FCM_H1_RCT, "Signalling-route-set-congestion-test signal" },
130   { FCM_H1_TFC, "Transfer-controlled signal" },
131   { 0,          NULL } };
132
133 /* Same as above but in acronym form (for the Info column) */
134 static const value_string fcm_h1_message_type_acro_values[] = {
135   { FCM_H1_RCT, "RCT" },
136   { FCM_H1_TFC, "TFC" },
137   { 0,          NULL } };
138
139 #define TFM_H1_TFP 0x01
140 #define TFM_H1_TCP 0x02 /* ANSI only */
141 #define TFM_H1_TFR 0x03
142 #define TFM_H1_TCR 0x04 /* ANSI only */
143 #define TFM_H1_TFA 0x05
144 #define TFM_H1_TCA 0x06 /* ANSI only */
145 static const value_string tfm_h1_message_type_values[] = {
146   { TFM_H1_TFP, "Transfer-prohibited signal" },
147   { TFM_H1_TCP, "Transfer-cluster-prohibited signal (ANSI only)" },
148   { TFM_H1_TFR, "Transfer-restricted signal" },
149   { TFM_H1_TCR, "Transfer-cluster-restricted signal (ANSI only)" },
150   { TFM_H1_TFA, "Transfer-allowed signal" },
151   { TFM_H1_TCA, "Transfer-cluster-allowed signal (ANSI only)" },
152   { 0,          NULL } };
153
154 /* Same as above but in acronym form (for the Info column) */
155 static const value_string tfm_h1_message_type_acro_values[] = {
156   { TFM_H1_TFP, "TFP" },
157   { TFM_H1_TCP, "TCP" },
158   { TFM_H1_TFR, "TFR" },
159   { TFM_H1_TCR, "TCR" },
160   { TFM_H1_TFA, "TFA" },
161   { TFM_H1_TCA, "TCA" },
162   { 0,          NULL } };
163
164 #define RSM_H1_RST 0x01
165 #define RSM_H1_RSR 0x02
166 #define RSM_H1_RCP 0x03 /* ANSI only */
167 #define RSM_H1_RCR 0x04 /* ANSI only */
168 static const value_string rsm_h1_message_type_values[] = {
169   { RSM_H1_RST, "Signalling-route-set-test prohibited signal" },
170   { RSM_H1_RSR, "Signalling-route-set-test restricted signal" },
171   { RSM_H1_RCP, "Signalling-route-set-test cluster-prohibited signal (ANSI only)" },
172   { RSM_H1_RCR, "Signalling-route-set-test cluster-restricted signal (ANSI only)" },
173   { 0,          NULL } };
174
175 /* Same as above but in acronym form (for the Info column) */
176 static const value_string rsm_h1_message_type_acro_values[] = {
177   { RSM_H1_RST, "RST" },
178   { RSM_H1_RSR, "RSR" },
179   { RSM_H1_RCP, "RCP" },
180   { RSM_H1_RCR, "RCR" },
181   { 0,          NULL } };
182
183 #define MIM_H1_LIN 0x01
184 #define MIM_H1_LUN 0x02
185 #define MIM_H1_LIA 0x03
186 #define MIM_H1_LUA 0x04
187 #define MIM_H1_LID 0x05
188 #define MIM_H1_LFU 0x06
189 #define MIM_H1_LLT 0x07 /* LLI in ANSI */
190 #define MIM_H1_LRT 0x08 /* LRI in ANSI */
191 static const value_string mim_h1_message_type_values[] = {
192   { MIM_H1_LIN, "Link inhibit signal" },
193   { MIM_H1_LUN, "Link uninhibit signal" },
194   { MIM_H1_LIA, "Link inhibit ack signal" },
195   { MIM_H1_LUA, "Link uninhibit ack signal" },
196   { MIM_H1_LID, "Link inhibit denied signal" },
197   { MIM_H1_LFU, "Link forced uninhibit signal" },
198   { MIM_H1_LLT, "Link local inhibit test signal" },
199   { MIM_H1_LRT, "Link remote inhibit test signal" },
200   { 0,          NULL } };
201
202 /* Same as above but in acronym form (for the Info column) */
203 static const value_string mim_h1_message_type_acro_values[] = {
204   { MIM_H1_LIN, "LIN" },
205   { MIM_H1_LUN, "LUN" },
206   { MIM_H1_LIA, "LIA" },
207   { MIM_H1_LUA, "LUA" },
208   { MIM_H1_LID, "LID" },
209   { MIM_H1_LFU, "LFU" },
210   { MIM_H1_LLT, "LLT (LLI)" },
211   { MIM_H1_LRT, "LRT (LRI)" },
212   { 0,          NULL } };
213
214 #define TRM_H1_TRA 0x01
215 #define TRM_H1_TRW 0x02 /* ANSI only */
216 static const value_string trm_h1_message_type_values[] = {
217   { TRM_H1_TRA, "Traffic-restart-allowed signal" },
218   { TRM_H1_TRW, "Traffic-restart-waiting signal (ANSI only)" },
219   { 0,          NULL } };
220
221 /* Same as above but in acronym form (for the Info column) */
222 static const value_string trm_h1_message_type_acro_values[] = {
223   { TRM_H1_TRA, "TRA" },
224   { TRM_H1_TRW, "TRW" },
225   { 0,          NULL } };
226
227 #define DLM_H1_DLC 0x01
228 #define DLM_H1_CSS 0x02
229 #define DLM_H1_CNS 0x03
230 #define DLM_H1_CNP 0x04
231 static const value_string dlm_h1_message_type_values[] = {
232   { DLM_H1_DLC, "Signalling-data-link-connection-order signal" },
233   { DLM_H1_CSS, "Connection-successful signal" },
234   { DLM_H1_CNS, "Connection-not-successful signal" },
235   { DLM_H1_CNP, "Connection-not-possible signal" },
236   { 0,          NULL } };
237
238 /* Same as above but in acronym form (for the Info column) */
239 static const value_string dlm_h1_message_type_acro_values[] = {
240   { DLM_H1_DLC, "DLC" },
241   { DLM_H1_CSS, "CSS" },
242   { DLM_H1_CNS, "CNS" },
243   { DLM_H1_CNP, "CNP" },
244   { 0,          NULL } };
245
246 #define UFC_H1_UPU 0x01
247 static const value_string ufc_h1_message_type_values[] = {
248   { UFC_H1_UPU, "User part unavailable signal" },
249   { 0,          NULL } };
250
251 /* Same as above but in acronym form (for the Info column) */
252 static const value_string ufc_h1_message_type_acro_values[] = {
253   { UFC_H1_UPU, "UPU" },
254   { 0,          NULL } };
255
256 static const value_string upu_cause_values[] = {
257   { 0x0, "Unknown" },
258   { 0x1, "Unequipped remote user" },
259   { 0x2, "Inaccessible remote user" },
260   { 0,   NULL } };
261
262 #define TEST_H1_SLTM 0x1
263 #define TEST_H1_SLTA 0x2
264 static const value_string test_h1_message_type_values[] = {
265   { TEST_H1_SLTM, "Signalling link test message" },
266   { TEST_H1_SLTA, "Signalling link test acknowledgement message" },
267   { 0,            NULL } };
268
269 /* Same as above but in acronym form (for the Info column) */
270 static const value_string test_h1_message_type_acro_values[] = {
271   { TEST_H1_SLTM, "SLTM" },
272   { TEST_H1_SLTA, "SLTA" },
273   { 0,            NULL } };
274
275
276 #define COO_LENGTH         2
277 #define ANSI_COO_SLC_MASK  0x000f
278 #define ANSI_COO_FSN_MASK  0x07f0
279 #define ITU_COO_FSN_MASK   0x007f
280 #define ANSI_XCO_LENGTH    4
281 #define ANSI_XCO_SLC_MASK  0x0000000f
282 #define ANSI_XCO_FSN_MASK  0x0ffffff0
283 #define ITU_XCO_LENGTH     3
284 #define ANSI_CBD_LENGTH    2
285 #define ANSI_CBD_SLC_MASK  0x000f
286 #define ANSI_CBD_CBC_MASK  0x0ff0
287 #define ITU_CBD_LENGTH     1
288
289 #define ANSI_ECO_LENGTH   1
290 #define ANSI_ECO_SLC_MASK 0x0f
291
292 #define ANSI_TFC_STATUS_LENGTH 1
293 #define ANSI_TFC_STATUS_OFFSET ANSI_PC_LENGTH
294 #define ANSI_TFC_STATUS_MASK   0x03
295 #define ITU_TFC_STATUS_LENGTH  ITU_PC_LENGTH
296 #define ITU_TFC_STATUS_MASK    0xc000
297
298 #define ANSI_MIM_LENGTH   1
299 #define ANSI_MIM_SLC_MASK 0x0f
300
301 #define ANSI_DLC_LENGTH    3
302 #define ANSI_DLC_SLC_MASK  0x0000f
303 #define ANSI_DLC_LINK_MASK 0x3fff0
304 #define ITU_DLC_LENGTH     2
305 #define ITU_DLC_LINK_MASK  0x0fff
306
307 #define ANSI_UPU_USER_OFFSET ANSI_PC_LENGTH
308 #define UPU_USER_LENGTH      1
309 #define UPU_USER_MASK        0x0f
310 #define UPU_CAUSE_MASK       0xf0
311 #define ITU_UPU_USER_OFFSET  ITU_PC_LENGTH
312
313 #define TEST_LENGTH         1
314 #define TEST_LENGTH_MASK    0xf0
315 #define TEST_LENGTH_SHIFT   4
316 #define TEST_PATTERN_OFFSET TEST_LENGTH
317
318 /* This list is slightly different from that in packet-mtp3.c */
319 static const value_string service_indicator_code_vals[] = {
320         { 0x0,  "Spare" },
321         { 0x1,  "Spare"},
322         { 0x2,  "Spare" },
323         { 0x3,  "SCCP" },
324         { 0x4,  "TUP" },
325         { 0x5,  "ISUP" },
326         { 0x6,  "DUP (call and circuit related messages)" },
327         { 0x7,  "DUP (facility registration and cancellation message)" },
328         { 0x8,  "MTP testing user part" },
329         { 0x9,  "Spare" },
330         { 0xa,  "Spare" },
331         { 0xb,  "Spare" },
332         { 0xc,  "Spare" },
333         { 0xd,  "Spare" },
334         { 0xe,  "Spare" },
335         { 0xf,  "Spare" },
336         { 0,    NULL }
337 };
338
339 /* Initialize the protocol and registered fields */
340 static int proto_mtp3mg  = -1;
341 static int hf_mtp3mg_h0 = -1;
342 static int hf_mtp3mg_chm_h1 = -1;
343 static int hf_mtp3mg_ecm_h1 = -1;
344 static int hf_mtp3mg_fcm_h1 = -1;
345 static int hf_mtp3mg_tfm_h1 = -1;
346 static int hf_mtp3mg_rsm_h1 = -1;
347 static int hf_mtp3mg_mim_h1 = -1;
348 static int hf_mtp3mg_trm_h1 = -1;
349 static int hf_mtp3mg_dlm_h1 = -1;
350 static int hf_mtp3mg_ufc_h1 = -1;
351 static int hf_mtp3mg_coo_ansi_slc = -1;
352 static int hf_mtp3mg_coo_ansi_fsn = -1;
353 static int hf_mtp3mg_coo_itu_fsn = -1;
354 static int hf_mtp3mg_xco_ansi_slc = -1;
355 static int hf_mtp3mg_xco_ansi_fsn = -1;
356 static int hf_mtp3mg_xco_itu_fsn = -1;
357 static int hf_mtp3mg_cbd_ansi_slc = -1;
358 static int hf_mtp3mg_cbd_ansi_cbc = -1;
359 static int hf_mtp3mg_cbd_itu_cbc = -1;
360 static int hf_mtp3mg_eco_ansi_slc = -1;
361 static int hf_mtp3mg_tfc_ansi_apc = -1;
362 static int hf_mtp3mg_tfc_apc_member = -1;
363 static int hf_mtp3mg_tfc_apc_cluster = -1;
364 static int hf_mtp3mg_tfc_apc_network = -1;
365 static int hf_mtp3mg_tfc_ansi_status = -1;
366 static int hf_mtp3mg_tfc_itu_apc = -1;
367 static int hf_mtp3mg_tfc_itu_status = -1;
368 static int hf_mtp3mg_tfc_chinese_apc = -1;
369 static int hf_mtp3mg_tfm_ansi_apc = -1;
370 static int hf_mtp3mg_tfm_apc_member = -1;
371 static int hf_mtp3mg_tfm_apc_cluster = -1;
372 static int hf_mtp3mg_tfm_apc_network = -1;
373 static int hf_mtp3mg_tfm_itu_apc = -1;
374 static int hf_mtp3mg_tfm_chinese_apc = -1;
375 static int hf_mtp3mg_rsm_ansi_apc = -1;
376 static int hf_mtp3mg_rsm_apc_member = -1;
377 static int hf_mtp3mg_rsm_apc_cluster = -1;
378 static int hf_mtp3mg_rsm_apc_network = -1;
379 static int hf_mtp3mg_rsm_itu_apc = -1;
380 static int hf_mtp3mg_rsm_chinese_apc = -1;
381 static int hf_mtp3mg_mim_ansi_slc = -1;
382 static int hf_mtp3mg_dlc_ansi_slc = -1;
383 static int hf_mtp3mg_dlc_ansi_link = -1;
384 static int hf_mtp3mg_dlc_itu_link = -1;
385 static int hf_mtp3mg_upu_ansi_apc = -1;
386 static int hf_mtp3mg_upu_apc_member = -1;
387 static int hf_mtp3mg_upu_apc_cluster = -1;
388 static int hf_mtp3mg_upu_apc_network = -1;
389 static int hf_mtp3mg_upu_itu_apc = -1;
390 static int hf_mtp3mg_upu_chinese_apc = -1;
391 static int hf_mtp3mg_upu_user = -1;
392 static int hf_mtp3mg_upu_cause = -1;
393 static int hf_mtp3test_h0 = -1;
394 static int hf_mtp3mg_test_h1 = -1;
395 static int hf_mtp3mg_test_length = -1;
396
397 /* Initialize the subtree pointers */
398 static gint ett_mtp3mg = -1;
399 static gint ett_mtp3mg_fcm_apc = -1;
400 static gint ett_mtp3mg_tfm_apc = -1;
401 static gint ett_mtp3mg_rsm_apc = -1;
402 static gint ett_mtp3mg_upu_apc = -1;
403
404 static void
405 dissect_mtp3mg_unknown_message(tvbuff_t *tvb, proto_tree *tree)
406 {
407     guint8 message_length;
408
409     message_length = tvb_length_remaining(tvb, 0);
410     proto_tree_add_text(tree, tvb, 0, message_length,
411                         "Unknown message (%u byte%s)", message_length,
412                         plurality(message_length, "", "s"));
413 }
414
415 static void
416 dissect_mtp3mg_chm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
417                    guint8 h1)
418 {
419     if (check_col(pinfo->cinfo, COL_INFO))
420         col_add_fstr(pinfo->cinfo, COL_INFO, "%s ",
421                      val_to_str(h1, chm_h1_message_type_acro_values, "Unknown"));
422         
423     switch (h1)
424     {
425     case CHM_H1_COO:
426     case CHM_H1_COA:
427         if (mtp3_standard == ANSI_STANDARD)
428         {
429             proto_tree_add_item(tree, hf_mtp3mg_coo_ansi_slc, tvb, 0,
430                                 COO_LENGTH, TRUE);
431             proto_tree_add_item(tree, hf_mtp3mg_coo_ansi_fsn, tvb, 0,
432                                 COO_LENGTH, TRUE);
433         } else /* ITU_STANDARD and CHINESE_ITU_STANDARD */ {
434             proto_tree_add_item(tree, hf_mtp3mg_coo_itu_fsn, tvb, 0,
435                                 COO_LENGTH, TRUE);
436         }
437         break;
438
439     case CHM_H1_XCO:
440     case CHM_H1_XCA:
441         if (mtp3_standard == ANSI_STANDARD)
442         {
443             proto_tree_add_item(tree, hf_mtp3mg_xco_ansi_slc, tvb, 0,
444                                 ANSI_XCO_LENGTH, TRUE);
445             proto_tree_add_item(tree, hf_mtp3mg_xco_ansi_fsn, tvb, 0,
446                                 ANSI_XCO_LENGTH, TRUE);
447         } else /* ITU_STANDARD and CHINESE_ITU_STANDARD */ {
448             proto_tree_add_item(tree, hf_mtp3mg_xco_itu_fsn, tvb, 0,
449                                 ITU_XCO_LENGTH, TRUE);
450         }
451         break;
452
453     case CHM_H1_CBD:
454     case CHM_H1_CBA:
455         if (mtp3_standard == ANSI_STANDARD)
456         {
457             proto_tree_add_item(tree, hf_mtp3mg_cbd_ansi_slc, tvb, 0,
458                                 ANSI_CBD_LENGTH, TRUE);
459             proto_tree_add_item(tree, hf_mtp3mg_cbd_ansi_cbc, tvb, 0,
460                                 ANSI_CBD_LENGTH, TRUE);
461         } else /* ITU_STANDARD and CHINESE_ITU_STANDARD */ {
462             proto_tree_add_item(tree, hf_mtp3mg_cbd_itu_cbc, tvb, 0,
463                                 ITU_CBD_LENGTH, TRUE);
464         }
465         break;
466
467     default:
468         dissect_mtp3mg_unknown_message(tvb, tree);
469   }
470 }
471
472 static void
473 dissect_mtp3mg_ecm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
474                    guint8 h1)
475 {
476     if (check_col(pinfo->cinfo, COL_INFO))
477         col_add_fstr(pinfo->cinfo, COL_INFO, "%s ",
478                      val_to_str(h1, ecm_h1_message_type_acro_values, "Unknown"));
479
480     switch (h1)
481     {
482     case ECM_H1_ECO:
483     case ECM_H1_ECA:
484         if (mtp3_standard == ANSI_STANDARD)
485         {
486             proto_tree_add_item(tree, hf_mtp3mg_eco_ansi_slc, tvb, 0,
487                                 ANSI_ECO_LENGTH, TRUE);
488         }
489         /* else: nothing to dissect */
490         break;
491
492     default:
493         dissect_mtp3mg_unknown_message(tvb, tree);
494     }
495 }
496
497 static void
498 dissect_mtp3mg_3byte_pc(tvbuff_t *tvb, proto_tree *tree, gint *ett_pc,
499                         int *hf_pc, int *hf_pc_member, int *hf_pc_cluster,
500                         int *hf_pc_network)
501 {
502     guint32 apc;
503     proto_item *apc_item;
504     proto_tree *apc_tree;
505     char pc[ANSI_PC_STRING_LENGTH];
506
507     apc = tvb_get_ntoh24(tvb, 0);
508
509     snprintf(pc, sizeof(pc), "%d-%d-%d",
510              (apc & ANSI_NETWORK_MASK),
511              ((apc & ANSI_CLUSTER_MASK) >> 8),
512              ((apc & ANSI_MEMBER_MASK) >> 16));
513
514     apc_item = proto_tree_add_string_format(tree, *hf_pc, tvb, 0,
515                                             ANSI_PC_LENGTH, pc,
516                                             "Affected PC (%s)", pc);
517
518     apc_tree = proto_item_add_subtree(apc_item, *ett_pc);
519
520     proto_tree_add_uint(apc_tree, *hf_pc_member, tvb,
521                         ANSI_MEMBER_OFFSET, ANSI_NCM_LENGTH, apc);
522     proto_tree_add_uint(apc_tree, *hf_pc_cluster, tvb,
523                         ANSI_CLUSTER_OFFSET, ANSI_NCM_LENGTH, apc);
524     proto_tree_add_uint(apc_tree, *hf_pc_network, tvb,
525                         ANSI_NETWORK_OFFSET, ANSI_NCM_LENGTH, apc);
526
527 }
528
529 static void
530 dissect_mtp3mg_fcm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
531                    guint8 h1)
532 {
533     if (check_col(pinfo->cinfo, COL_INFO))
534         col_add_fstr(pinfo->cinfo, COL_INFO, "%s ",
535                      val_to_str(h1, fcm_h1_message_type_acro_values, "Unknown"));
536
537     switch (h1)
538     {
539     case FCM_H1_RCT:
540         /* nothing to dissect */
541         break;
542
543     case FCM_H1_TFC:
544         if (mtp3_standard == ITU_STANDARD) {
545
546             proto_tree_add_item(tree, hf_mtp3mg_tfc_itu_apc, tvb, 0,
547                                 ITU_PC_LENGTH, TRUE);
548
549             /* Congestion level is a national option */
550             proto_tree_add_item(tree, hf_mtp3mg_tfc_itu_status, tvb, 0,
551                                 ITU_TFC_STATUS_LENGTH, TRUE);
552
553
554
555         } else /* ANSI_STANDARD and CHINESE_ITU_STANDARD */ {
556
557             int *hf_apc_string;
558
559             if (mtp3_standard == ANSI_STANDARD) {
560
561                 hf_apc_string = &hf_mtp3mg_tfc_ansi_apc;
562
563             } else /* CHINESE_ITU_STANDARD */ {
564
565                 hf_apc_string = &hf_mtp3mg_tfc_chinese_apc;
566             }
567
568             dissect_mtp3mg_3byte_pc(tvb, tree, &ett_mtp3mg_fcm_apc,
569                                     hf_apc_string,
570                                     &hf_mtp3mg_tfc_apc_member,
571                                     &hf_mtp3mg_tfc_apc_cluster,
572                                     &hf_mtp3mg_tfc_apc_network);
573
574             proto_tree_add_item(tree, hf_mtp3mg_tfc_ansi_status, tvb,
575                                 ANSI_TFC_STATUS_OFFSET, ANSI_TFC_STATUS_LENGTH,
576                                 TRUE);
577
578         }
579         break;
580
581     default:
582         dissect_mtp3mg_unknown_message(tvb, tree);
583     }
584 }
585
586 static void
587 dissect_mtp3mg_tfm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
588                    guint8 h1)
589 {
590     if (check_col(pinfo->cinfo, COL_INFO))
591         col_add_fstr(pinfo->cinfo, COL_INFO, "%s ",
592                      val_to_str(h1, tfm_h1_message_type_acro_values, "Unknown"));
593
594     switch (h1)
595     {
596     case TFM_H1_TFP:
597     case TFM_H1_TCP:
598     case TFM_H1_TFR:
599     case TFM_H1_TCR:
600     case TFM_H1_TFA:
601     case TFM_H1_TCA:
602         if (mtp3_standard == ANSI_STANDARD)
603         {
604             dissect_mtp3mg_3byte_pc(tvb, tree, &ett_mtp3mg_tfm_apc,
605                                     &hf_mtp3mg_tfm_ansi_apc,
606                                     &hf_mtp3mg_tfm_apc_member,
607                                     &hf_mtp3mg_tfm_apc_cluster,
608                                     &hf_mtp3mg_tfm_apc_network);
609
610         } else /* ITU_STANDARD and CHINESE_ITU_STANDARD */ {
611
612             if (h1 == TFM_H1_TCP || h1 == TFM_H1_TCR || h1 == TFM_H1_TCA)
613                 dissect_mtp3mg_unknown_message(tvb, tree);
614             else if (mtp3_standard == ITU_STANDARD)
615                 proto_tree_add_item(tree, hf_mtp3mg_tfm_itu_apc, tvb, 0,
616                                     ITU_PC_LENGTH, TRUE);
617             else /* CHINESE_ITU_STANDARD */
618                 dissect_mtp3mg_3byte_pc(tvb, tree, &ett_mtp3mg_tfm_apc,
619                                         &hf_mtp3mg_tfm_chinese_apc,
620                                         &hf_mtp3mg_tfm_apc_member,
621                                         &hf_mtp3mg_tfm_apc_cluster,
622                                         &hf_mtp3mg_tfm_apc_network);
623         }
624         break;
625
626     default:
627         dissect_mtp3mg_unknown_message(tvb, tree);
628     }
629 }
630
631 static void
632 dissect_mtp3mg_rsm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
633                    guint8 h1)
634 {
635     if (check_col(pinfo->cinfo, COL_INFO))
636         col_add_fstr(pinfo->cinfo, COL_INFO, "%s ",
637                      val_to_str(h1, rsm_h1_message_type_acro_values, "Unknown"));
638
639     switch (h1)
640     {
641     case RSM_H1_RST:
642     case RSM_H1_RSR:
643     case RSM_H1_RCP:
644     case RSM_H1_RCR:
645         if (mtp3_standard == ANSI_STANDARD)
646         {
647             dissect_mtp3mg_3byte_pc(tvb, tree, &ett_mtp3mg_rsm_apc,
648                                     &hf_mtp3mg_rsm_ansi_apc,
649                                     &hf_mtp3mg_rsm_apc_member,
650                                     &hf_mtp3mg_rsm_apc_cluster,
651                                     &hf_mtp3mg_rsm_apc_network);
652
653         } else /* ITU_STANDARD and CHINESE_ITU_STANDARD */ {
654
655             if (h1 == RSM_H1_RST || h1 == RSM_H1_RSR)
656             {
657                 if (mtp3_standard == ITU_STANDARD)
658                     proto_tree_add_item(tree, hf_mtp3mg_rsm_itu_apc, tvb, 0,
659                                         ITU_PC_LENGTH, TRUE);
660
661                 else /* CHINESE_ITU_STANDARD */
662                     dissect_mtp3mg_3byte_pc(tvb, tree, &ett_mtp3mg_rsm_apc,
663                                             &hf_mtp3mg_rsm_chinese_apc,
664                                             &hf_mtp3mg_rsm_apc_member,
665                                             &hf_mtp3mg_rsm_apc_cluster,
666                                             &hf_mtp3mg_rsm_apc_network);
667             } else
668                 dissect_mtp3mg_unknown_message(tvb, tree);
669         }
670         break;
671
672     default:
673         dissect_mtp3mg_unknown_message(tvb, tree);
674     }
675 }
676
677 static void
678 dissect_mtp3mg_mim(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
679                    guint8 h1)
680 {
681     if (check_col(pinfo->cinfo, COL_INFO))
682         col_add_fstr(pinfo->cinfo, COL_INFO, "%s ",
683                      val_to_str(h1, mim_h1_message_type_acro_values, "Unknown"));
684
685     switch (h1)
686     {
687     case MIM_H1_LIN:
688     case MIM_H1_LUN:
689     case MIM_H1_LIA:
690     case MIM_H1_LUA:
691     case MIM_H1_LID:
692     case MIM_H1_LFU:
693     case MIM_H1_LLT:
694     case MIM_H1_LRT:
695         if (mtp3_standard == ANSI_STANDARD)
696         {
697             proto_tree_add_item(tree, hf_mtp3mg_mim_ansi_slc, tvb, 0,
698                                 ANSI_MIM_LENGTH, TRUE);
699         }
700         /* else: nothing to dissect */
701         break;
702
703     default:
704         dissect_mtp3mg_unknown_message(tvb, tree);
705     }
706 }
707
708 static void
709 dissect_mtp3mg_trm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
710                    guint8 h1)
711 {
712     if (check_col(pinfo->cinfo, COL_INFO))
713         col_add_fstr(pinfo->cinfo, COL_INFO, "%s ",
714                      val_to_str(h1, trm_h1_message_type_acro_values, "Unknown"));
715
716     switch (h1)
717     {
718     case TRM_H1_TRA:
719         /* nothing to dissect */
720         break;
721     case TRM_H1_TRW:
722         if (mtp3_standard != ANSI_STANDARD)
723             dissect_mtp3mg_unknown_message(tvb, tree);
724         /* else: nothing to dissect */
725         break;
726
727     default:
728         dissect_mtp3mg_unknown_message(tvb, tree);
729     }
730 }
731
732 static void
733 dissect_mtp3mg_dlm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
734                    guint8 h1)
735 {
736     if (check_col(pinfo->cinfo, COL_INFO))
737         col_add_fstr(pinfo->cinfo, COL_INFO, "%s ",
738                      val_to_str(h1, dlm_h1_message_type_acro_values, "Unknown"));
739
740     switch (h1)
741     {
742     case DLM_H1_DLC:
743         if (mtp3_standard == ANSI_STANDARD)
744         {
745             proto_tree_add_item(tree, hf_mtp3mg_dlc_ansi_slc, tvb, 0,
746                                 ANSI_DLC_LENGTH, TRUE);
747             proto_tree_add_item(tree, hf_mtp3mg_dlc_ansi_link, tvb, 0,
748                                 ANSI_DLC_LENGTH, TRUE);
749         } else /* ITU_STANDARD and CHINESE_ITU_STANDARD */ {
750             proto_tree_add_item(tree, hf_mtp3mg_dlc_itu_link, tvb, 0,
751                                 ITU_DLC_LENGTH, TRUE);
752         }
753         break;
754     case DLM_H1_CSS:
755     case DLM_H1_CNS:
756     case DLM_H1_CNP:
757         /* nothing to dissect */
758         break;
759
760     default:
761         dissect_mtp3mg_unknown_message(tvb, tree);
762     }
763 }
764
765 static void
766 dissect_mtp3mg_ufc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
767                    guint8 h1)
768 {
769     if (check_col(pinfo->cinfo, COL_INFO))
770         col_add_fstr(pinfo->cinfo, COL_INFO, "%s ",
771                      val_to_str(h1, ufc_h1_message_type_acro_values, "Unknown"));
772
773     switch (h1)
774     {
775     case UFC_H1_UPU:
776         if (mtp3_standard == ANSI_STANDARD
777             || mtp3_standard == CHINESE_ITU_STANDARD)
778         {
779             int *hf_apc;
780
781             if (mtp3_standard == ANSI_STANDARD)
782                 hf_apc = &hf_mtp3mg_upu_ansi_apc;
783             else /* CHINESE_ITU_STANDARD */
784                 hf_apc = &hf_mtp3mg_upu_chinese_apc;
785
786             dissect_mtp3mg_3byte_pc(tvb, tree, &ett_mtp3mg_upu_apc,
787                                     hf_apc,
788                                     &hf_mtp3mg_rsm_apc_member,
789                                     &hf_mtp3mg_rsm_apc_cluster,
790                                     &hf_mtp3mg_rsm_apc_network);
791
792             proto_tree_add_item(tree, hf_mtp3mg_upu_user, tvb,
793                                 ANSI_UPU_USER_OFFSET, UPU_USER_LENGTH, TRUE);
794             proto_tree_add_item(tree, hf_mtp3mg_upu_cause, tvb,
795                                 ANSI_UPU_USER_OFFSET, UPU_USER_LENGTH, TRUE);
796         } else /* ITU_STANDARD */ {
797             proto_tree_add_item(tree, hf_mtp3mg_upu_itu_apc, tvb, 0,
798                                 ITU_PC_LENGTH, TRUE);
799             proto_tree_add_item(tree, hf_mtp3mg_upu_user, tvb,
800                                 ITU_UPU_USER_OFFSET, UPU_USER_LENGTH, TRUE);
801             proto_tree_add_item(tree, hf_mtp3mg_upu_cause, tvb,
802                                 ITU_UPU_USER_OFFSET, UPU_USER_LENGTH, TRUE);
803         }
804         break;
805
806     default:
807         dissect_mtp3mg_unknown_message(tvb, tree);
808     }
809 }
810
811 static void
812 dissect_mtp3mg_test(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
813                    guint8 h1)
814 {
815     guint8 length;
816
817     if (check_col(pinfo->cinfo, COL_INFO))
818         col_add_fstr(pinfo->cinfo, COL_INFO, "%s ",
819                      val_to_str(h1, test_h1_message_type_acro_values, "Unknown"));
820
821     switch (h1)
822     {
823     case TEST_H1_SLTM:
824     case TEST_H1_SLTA:
825         proto_tree_add_item(tree, hf_mtp3mg_test_length, tvb, 0, TEST_LENGTH,
826                             TRUE);
827
828         length = tvb_get_guint8(tvb, 0) >> TEST_LENGTH_SHIFT;
829         proto_tree_add_text(tree, tvb, TEST_PATTERN_OFFSET, length,
830                             "Test pattern (%u byte%s)", length,
831                             plurality(length, "", "s"));
832         break;
833
834     default:
835         dissect_mtp3mg_unknown_message(tvb, tree);
836     }
837 }
838
839 static void
840 dissect_mtp3mg(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
841 {
842
843     guint8 h0, h1;
844     tvbuff_t *payload_tvb;
845
846     /* Set up structures needed to add the protocol subtree and manage it */
847     proto_item *mtp3mg_item = NULL;
848     proto_tree *mtp3mg_tree = NULL;
849
850     /* Make entries in Protocol column on summary display */
851     if (check_col(pinfo->cinfo, COL_PROTOCOL))
852       switch(mtp3_standard) {
853         case ITU_STANDARD:
854           col_set_str(pinfo->cinfo, COL_PROTOCOL, "MTP3MG (Int. ITU)");
855           break;
856         case ANSI_STANDARD:
857           col_set_str(pinfo->cinfo, COL_PROTOCOL, "MTP3MG (ANSI)");
858           break;
859         case CHINESE_ITU_STANDARD:
860           col_set_str(pinfo->cinfo, COL_PROTOCOL, "MTP3MG (Chin. ITU)");
861           break;
862       };      
863
864     if (tree) {
865         /* create display subtree for the protocol */
866         mtp3mg_item = proto_tree_add_item(tree, proto_mtp3mg, tvb, 0, -1,
867                                           TRUE);
868         mtp3mg_tree = proto_item_add_subtree(mtp3mg_item, ett_mtp3mg);
869     }
870
871     /*
872      *  Dissect the message
873      */
874     if(pinfo->private_data == (void *)MTP3MG_ANSI_TEST_SI ||
875        pinfo->private_data == (void *)MTP3MG_ITU_TEST_SI)
876     {   /* Test messages */
877
878         proto_tree_add_item(mtp3mg_tree, hf_mtp3test_h0, tvb, 0, H0H1_LENGTH,
879                             TRUE);
880         /* H1 is added below */
881
882         h0 = tvb_get_guint8(tvb, 0) & H0_MASK;
883         h1 = (tvb_get_guint8(tvb, 0) & H1_MASK) >> H1_SHIFT;
884
885         payload_tvb = tvb_new_subset(tvb, H0H1_LENGTH, -1, -1);
886
887         switch (h0)
888         {
889         case TEST_H0_SLT:
890             proto_tree_add_item(mtp3mg_tree, hf_mtp3mg_test_h1, tvb, 0,
891                                 H0H1_LENGTH, TRUE);
892             dissect_mtp3mg_test(payload_tvb, pinfo, mtp3mg_tree, h1);
893             break;
894
895         default:
896             if (check_col(pinfo->cinfo, COL_INFO))
897                 col_add_fstr(pinfo->cinfo, COL_INFO, "Unknown ");
898
899             dissect_mtp3mg_unknown_message(tvb, mtp3mg_tree);
900         } /* switch */
901
902     } else {    /* Real management messages */
903
904         proto_tree_add_item(mtp3mg_tree, hf_mtp3mg_h0, tvb, 0, H0H1_LENGTH,
905                             TRUE);
906         /* H1 is added below */
907
908         h0 = tvb_get_guint8(tvb, 0) & H0_MASK;
909         h1 = (tvb_get_guint8(tvb, 0) & H1_MASK) >> H1_SHIFT;
910
911         payload_tvb = tvb_new_subset(tvb, H0H1_LENGTH, -1, -1);
912
913         switch (h0)
914         {
915         case H0_CHM:
916             proto_tree_add_item(mtp3mg_tree, hf_mtp3mg_chm_h1, tvb, 0,
917                                 H0H1_LENGTH, TRUE);
918             dissect_mtp3mg_chm(payload_tvb, pinfo, mtp3mg_tree, h1);
919             break;
920         case H0_ECM:
921             proto_tree_add_item(mtp3mg_tree, hf_mtp3mg_ecm_h1, tvb, 0,
922                                 H0H1_LENGTH, TRUE);
923             dissect_mtp3mg_ecm(payload_tvb, pinfo, mtp3mg_tree, h1);
924             break;
925         case H0_FCM:
926             proto_tree_add_item(mtp3mg_tree, hf_mtp3mg_fcm_h1, tvb, 0,
927                                 H0H1_LENGTH, TRUE);
928             dissect_mtp3mg_fcm(payload_tvb, pinfo, mtp3mg_tree, h1);
929             break;
930         case H0_TFM:
931             proto_tree_add_item(mtp3mg_tree, hf_mtp3mg_tfm_h1, tvb, 0,
932                                 H0H1_LENGTH, TRUE);
933             dissect_mtp3mg_tfm(payload_tvb, pinfo, mtp3mg_tree, h1);
934             break;
935         case H0_RSM:
936             proto_tree_add_item(mtp3mg_tree, hf_mtp3mg_rsm_h1, tvb, 0,
937                                 H0H1_LENGTH, TRUE);
938             dissect_mtp3mg_rsm(payload_tvb, pinfo, mtp3mg_tree, h1);
939             break;
940         case H0_MIM:
941             proto_tree_add_item(mtp3mg_tree, hf_mtp3mg_mim_h1, tvb, 0,
942                                 H0H1_LENGTH, TRUE);
943             dissect_mtp3mg_mim(payload_tvb, pinfo, mtp3mg_tree, h1);
944             break;
945         case H0_TRM:
946             proto_tree_add_item(mtp3mg_tree, hf_mtp3mg_trm_h1, tvb, 0,
947                                 H0H1_LENGTH, TRUE);
948             dissect_mtp3mg_trm(payload_tvb, pinfo, mtp3mg_tree, h1);
949             break;
950         case H0_DLM:
951             proto_tree_add_item(mtp3mg_tree, hf_mtp3mg_dlm_h1, tvb, 0,
952                                 H0H1_LENGTH, TRUE);
953             dissect_mtp3mg_dlm(payload_tvb, pinfo, mtp3mg_tree, h1);
954             break;
955         case H0_UFC:
956             proto_tree_add_item(mtp3mg_tree, hf_mtp3mg_ufc_h1, tvb, 0,
957                                 H0H1_LENGTH, TRUE);
958             dissect_mtp3mg_ufc(payload_tvb, pinfo, mtp3mg_tree, h1);
959             break;
960
961         default:
962             if (check_col(pinfo->cinfo, COL_INFO))
963                 col_add_fstr(pinfo->cinfo, COL_INFO, "Unknown ");
964
965             dissect_mtp3mg_unknown_message(tvb, mtp3mg_tree);
966         } /* switch */
967     } /* else */
968
969 }
970
971 void
972 proto_register_mtp3mg(void)
973 {
974
975     /* Setup list of header fields  See Section 1.6.1 for details*/
976     static hf_register_info hf[] = {
977         { &hf_mtp3mg_h0,
978             { "H0 (Message Group)", "mtp3mg.h0",
979               FT_UINT8, BASE_HEX, VALS(h0_message_type_values), H0_MASK,
980               "Message group identifier", HFILL }},
981         { &hf_mtp3mg_chm_h1,
982             { "H1 (Message)", "mtp3mg.h1",
983               FT_UINT8, BASE_HEX, VALS(chm_h1_message_type_values), H1_MASK,
984               "Message type", HFILL }},
985         { &hf_mtp3mg_ecm_h1,
986             { "H1 (Message)", "mtp3mg.h1",
987               FT_UINT8, BASE_HEX, VALS(ecm_h1_message_type_values), H1_MASK,
988               "Message type", HFILL }},
989         { &hf_mtp3mg_fcm_h1,
990             { "H1 (Message)", "mtp3mg.h1",
991               FT_UINT8, BASE_HEX, VALS(fcm_h1_message_type_values), H1_MASK,
992               "Message type", HFILL }},
993         { &hf_mtp3mg_tfm_h1,
994             { "H1 (Message)", "mtp3mg.h1",
995               FT_UINT8, BASE_HEX, VALS(tfm_h1_message_type_values), H1_MASK,
996               "Message type", HFILL }},
997         { &hf_mtp3mg_rsm_h1,
998             { "H1 (Message)", "mtp3mg.h1",
999               FT_UINT8, BASE_HEX, VALS(rsm_h1_message_type_values), H1_MASK,
1000               "Message type", HFILL }},
1001         { &hf_mtp3mg_mim_h1,
1002             { "H1 (Message)", "mtp3mg.h1",
1003               FT_UINT8, BASE_HEX, VALS(mim_h1_message_type_values), H1_MASK,
1004               "Message type", HFILL }},
1005         { &hf_mtp3mg_trm_h1,
1006             { "H1 (Message)", "mtp3mg.h1",
1007               FT_UINT8, BASE_HEX, VALS(trm_h1_message_type_values), H1_MASK,
1008               "Message type", HFILL }},
1009         { &hf_mtp3mg_dlm_h1,
1010             { "H1 (Message)", "mtp3mg.h1",
1011               FT_UINT8, BASE_HEX, VALS(dlm_h1_message_type_values), H1_MASK,
1012               "Message type", HFILL }},
1013         { &hf_mtp3mg_ufc_h1,
1014             { "H1 (Message)", "mtp3mg.h1",
1015               FT_UINT8, BASE_HEX, VALS(ufc_h1_message_type_values), H1_MASK,
1016               "Message type", HFILL }},
1017         { &hf_mtp3mg_coo_ansi_slc,
1018             { "Signalling Link Code", "mtp3mg.slc",
1019               FT_UINT8, BASE_DEC, NULL, ANSI_COO_SLC_MASK,
1020               "SLC of affected link", HFILL }},
1021         { &hf_mtp3mg_coo_ansi_fsn,
1022             { "Forward Sequence Number", "mtp3mg.fsn",
1023               FT_UINT8, BASE_DEC, NULL, ANSI_COO_FSN_MASK,
1024               "Forward Sequence Number of last accepted message", HFILL }},
1025         { &hf_mtp3mg_coo_itu_fsn,
1026             { "Forward Sequence Number", "mtp3mg.fsn",
1027               FT_UINT8, BASE_DEC, NULL, ITU_COO_FSN_MASK,
1028               "Forward Sequence Number of last accepted message", HFILL }},
1029         { &hf_mtp3mg_xco_ansi_slc,
1030             { "Signalling Link Code", "mtp3mg.slc",
1031               FT_UINT32, BASE_DEC, NULL, ANSI_XCO_SLC_MASK,
1032               "SLC of affected link", HFILL }},
1033         { &hf_mtp3mg_xco_ansi_fsn,
1034             { "Forward Sequence Number", "mtp3mg.fsn",
1035               FT_UINT32, BASE_DEC, NULL, ANSI_XCO_FSN_MASK,
1036               "Forward Sequence Number of last accepted message", HFILL }},
1037         { &hf_mtp3mg_xco_itu_fsn,
1038             { "Forward Sequence Number", "mtp3mg.fsn",
1039               FT_UINT24, BASE_DEC, NULL, 0x0,
1040               "Forward Sequence Number of last accepted message", HFILL }},
1041         { &hf_mtp3mg_cbd_ansi_slc,
1042             { "Signalling Link Code", "mtp3mg.slc",
1043               FT_UINT16, BASE_DEC, NULL, ANSI_CBD_SLC_MASK,
1044               "SLC of affected link", HFILL }},
1045         { &hf_mtp3mg_cbd_ansi_cbc,
1046             { "Change Back Code", "mtp3mg.cbc",
1047               FT_UINT16, BASE_DEC, NULL, ANSI_CBD_CBC_MASK,
1048               "", HFILL }},
1049         { &hf_mtp3mg_cbd_itu_cbc,
1050             { "Change Back Code", "mtp3mg.cbc",
1051               FT_UINT8, BASE_DEC, NULL, 0x0,
1052               "", HFILL }},
1053         { &hf_mtp3mg_eco_ansi_slc,
1054             { "Signalling Link Code", "mtp3mg.slc",
1055               FT_UINT8, BASE_DEC, NULL, ANSI_ECO_SLC_MASK,
1056               "SLC of affected link", HFILL }},
1057         { &hf_mtp3mg_tfc_ansi_apc,
1058             { "Affected Point Code", "mtp3mg.ansi_apc",
1059               FT_STRING, BASE_NONE, NULL, 0x0,
1060               "", HFILL }},
1061         { &hf_mtp3mg_tfc_apc_member,
1062             { "Affected Point Code member", "mtp3mg.apc.member",
1063               FT_UINT24, BASE_DEC, NULL, ANSI_MEMBER_MASK,
1064               "", HFILL }},
1065         { &hf_mtp3mg_tfc_apc_cluster,
1066             { "Affected Point Code cluster", "mtp3mg.apc.cluster",
1067               FT_UINT24, BASE_DEC, NULL, ANSI_CLUSTER_MASK,
1068               "", HFILL }},
1069         { &hf_mtp3mg_tfc_apc_network,
1070             { "Affected Point Code network", "mtp3mg.apc.network",
1071               FT_UINT24, BASE_DEC, NULL, ANSI_NETWORK_MASK,
1072               "", HFILL }},
1073         { &hf_mtp3mg_tfc_ansi_status,
1074             { "Status", "mtp3mg.status",
1075               FT_UINT8, BASE_DEC, NULL, ANSI_TFC_STATUS_MASK,
1076               "Congestion status", HFILL }},
1077         { &hf_mtp3mg_tfc_itu_apc,
1078             { "Affected Point Code (ITU)", "mtp3mg.apc",
1079               FT_UINT8, BASE_DEC, NULL, ITU_PC_MASK,
1080               "", HFILL }},
1081         { &hf_mtp3mg_tfc_itu_status,
1082             { "Status", "mtp3mg.status",
1083               FT_UINT8, BASE_DEC, NULL, ITU_TFC_STATUS_MASK,
1084               "Congestion status", HFILL }},
1085         { &hf_mtp3mg_tfc_chinese_apc,
1086             { "Affected Point Code", "mtp3mg.chinese_apc",
1087               FT_STRING, BASE_NONE, NULL, 0x0,
1088               "", HFILL }},
1089         { &hf_mtp3mg_tfm_ansi_apc,
1090             { "Affected Point Code", "mtp3mg.ansi_apc",
1091               FT_STRING, BASE_NONE, NULL, 0x0,
1092               "", HFILL }},
1093         { &hf_mtp3mg_tfm_apc_member,
1094             { "Affected Point Code member", "mtp3mg.apc.member",
1095               FT_UINT24, BASE_DEC, NULL, ANSI_MEMBER_MASK,
1096               "", HFILL }},
1097         { &hf_mtp3mg_tfm_apc_cluster,
1098             { "Affected Point Code cluster", "mtp3mg.apc.cluster",
1099               FT_UINT24, BASE_DEC, NULL, ANSI_CLUSTER_MASK,
1100               "", HFILL }},
1101         { &hf_mtp3mg_tfm_apc_network,
1102             { "Affected Point Code network", "mtp3mg.apc.network",
1103               FT_UINT24, BASE_DEC, NULL, ANSI_NETWORK_MASK,
1104               "", HFILL }},
1105         { &hf_mtp3mg_tfm_itu_apc,
1106             { "Affected Point Code (ITU)", "mtp3mg.apc",
1107               FT_UINT8, BASE_DEC, NULL, ITU_PC_MASK,
1108               "", HFILL }},
1109         { &hf_mtp3mg_tfm_chinese_apc,
1110             { "Affected Point Code", "mtp3mg.chinese_apc",
1111               FT_STRING, BASE_NONE, NULL, 0x0,
1112               "", HFILL }},
1113         { &hf_mtp3mg_rsm_ansi_apc,
1114             { "Affected Point Code", "mtp3mg.ansi_apc",
1115               FT_STRING, BASE_NONE, NULL, 0x0,
1116               "", HFILL }},
1117         { &hf_mtp3mg_rsm_apc_member,
1118             { "Affected Point Code member", "mtp3mg.apc.member",
1119               FT_UINT24, BASE_DEC, NULL, ANSI_MEMBER_MASK,
1120               "", HFILL }},
1121         { &hf_mtp3mg_rsm_apc_cluster,
1122             { "Affected Point Code cluster", "mtp3mg.apc.cluster",
1123               FT_UINT24, BASE_DEC, NULL, ANSI_CLUSTER_MASK,
1124               "", HFILL }},
1125         { &hf_mtp3mg_rsm_apc_network,
1126             { "Affected Point Code network", "mtp3mg.apc.network",
1127               FT_UINT24, BASE_DEC, NULL, ANSI_NETWORK_MASK,
1128               "", HFILL }},
1129         { &hf_mtp3mg_rsm_itu_apc,
1130             { "Affected Point Code (ITU)", "mtp3mg.apc",
1131               FT_UINT8, BASE_DEC, NULL, ITU_PC_MASK,
1132               "", HFILL }},
1133         { &hf_mtp3mg_rsm_chinese_apc,
1134             { "Affected Point Code", "mtp3mg.chinese_apc",
1135               FT_STRING, BASE_NONE, NULL, 0x0,
1136               "", HFILL }},
1137         { &hf_mtp3mg_mim_ansi_slc,
1138             { "Signalling Link Code", "mtp3mg.slc",
1139               FT_UINT8, BASE_DEC, NULL, ANSI_MIM_SLC_MASK,
1140               "SLC of affected link", HFILL }},
1141         { &hf_mtp3mg_dlc_ansi_slc,
1142             { "Signalling Link Code", "mtp3mg.slc",
1143               FT_UINT8, BASE_DEC, NULL, ANSI_DLC_SLC_MASK,
1144               "SLC of affected link", HFILL }},
1145         { &hf_mtp3mg_dlc_ansi_link,
1146             { "Link", "mtp3mg.link",
1147               FT_UINT8, BASE_DEC, NULL, ANSI_DLC_LINK_MASK,
1148               "CIC of BIC used to carry data", HFILL }},
1149         { &hf_mtp3mg_dlc_itu_link,
1150             { "Link", "mtp3mg.link",
1151               FT_UINT8, BASE_DEC, NULL, ITU_DLC_LINK_MASK,
1152               "CIC of BIC used to carry data", HFILL }},
1153         { &hf_mtp3mg_upu_ansi_apc,
1154             { "Affected Point Code", "mtp3mg.ansi_apc",
1155               FT_STRING, BASE_NONE, NULL, 0x0,
1156               "", HFILL }},
1157         { &hf_mtp3mg_upu_apc_member,
1158             { "Affected Point Code member", "mtp3mg.apc.member",
1159               FT_UINT24, BASE_DEC, NULL, ANSI_MEMBER_MASK,
1160               "", HFILL }},
1161         { &hf_mtp3mg_upu_apc_cluster,
1162             { "Affected Point Code cluster", "mtp3mg.apc.cluster",
1163               FT_UINT24, BASE_DEC, NULL, ANSI_CLUSTER_MASK,
1164               "", HFILL }},
1165         { &hf_mtp3mg_upu_apc_network,
1166             { "Affected Point Code network", "mtp3mg.apc.network",
1167               FT_UINT24, BASE_DEC, NULL, ANSI_NETWORK_MASK,
1168               "", HFILL }},
1169         { &hf_mtp3mg_upu_itu_apc,
1170             { "Affected Point Code", "mtp3mg.apc",
1171               FT_UINT8, BASE_DEC, NULL, ITU_PC_MASK,
1172               "", HFILL }},
1173         { &hf_mtp3mg_upu_chinese_apc,
1174             { "Affected Point Code", "mtp3mg.chinese_apc",
1175               FT_STRING, BASE_NONE, NULL, 0x0,
1176               "", HFILL }},
1177         { &hf_mtp3mg_upu_user,
1178             { "User", "mtp3mg.user",
1179               FT_UINT8, BASE_HEX, VALS(service_indicator_code_vals), UPU_USER_MASK,
1180               "Unavailable user part", HFILL }},
1181         { &hf_mtp3mg_upu_cause,
1182             { "Cause", "mtp3mg.cause",
1183               FT_UINT8, BASE_HEX, VALS(upu_cause_values), UPU_CAUSE_MASK,
1184               "Cause of user unavailability", HFILL }},
1185         { &hf_mtp3test_h0,
1186             { "H0 (Message Group)", "mtp3mg.test.h0",
1187               FT_UINT8, BASE_HEX, VALS(test_h0_message_type_values), H0_MASK,
1188               "Message group identifier", HFILL }},
1189         { &hf_mtp3mg_test_h1,
1190             { "H1 (Message)", "mtp3mg.test.h1",
1191               FT_UINT8, BASE_HEX, VALS(test_h1_message_type_values), H1_MASK,
1192               "SLT message type", HFILL }},
1193         { &hf_mtp3mg_test_length,
1194             { "Test length", "mtp3mg.test.length",
1195               FT_UINT8, BASE_DEC, NULL, H1_MASK,
1196               "Signalling link test pattern length", HFILL }}
1197   };
1198
1199     /* Setup protocol subtree array */
1200     static gint *ett[] = {
1201         &ett_mtp3mg,
1202         &ett_mtp3mg_fcm_apc,
1203         &ett_mtp3mg_tfm_apc,
1204         &ett_mtp3mg_rsm_apc,
1205         &ett_mtp3mg_upu_apc
1206     };
1207
1208     /* Register the protocol name and description */
1209     proto_mtp3mg = proto_register_protocol("Message Transfer Part Level 3 Management",
1210                                            "MTP3MG", "mtp3mg");
1211     register_dissector("mtp3mg", dissect_mtp3mg, proto_mtp3mg);
1212
1213     /* Required calls to register the header fields and subtrees used */
1214     proto_register_field_array(proto_mtp3mg, hf, array_length(hf));
1215     proto_register_subtree_array(ett, array_length(ett));
1216
1217 }
1218
1219 void
1220 proto_reg_handoff_mtp3mg(void)
1221 {
1222     dissector_handle_t mtp3mg_handle;
1223
1224     mtp3mg_handle = create_dissector_handle(dissect_mtp3mg, proto_mtp3mg);
1225
1226     dissector_add("mtp3.service_indicator", MTP3MG_SI, mtp3mg_handle);
1227
1228     /*  SI 1 is unused in ANSI and SI 2 is unused in ITU, so it's okay for us
1229      *  to grab both (regardless of mtp3.standard setting) here.
1230      */
1231     dissector_add("mtp3.service_indicator", MTP3MG_ITU_TEST_SI, mtp3mg_handle);
1232     dissector_add("mtp3.service_indicator", MTP3MG_ANSI_TEST_SI, mtp3mg_handle);
1233 }
1234