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