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