Add support for Exif decoding (initial framework).
[obnox/wireshark/wip.git] / packet-mtp3.c
1 /* packet-mtp3.c
2  * Routines for Message Transfer Part Level 3 dissection
3  *
4  * It is (hopefully) compliant to:
5  *   ANSI T1.111.4-1996
6  *   ITU-T Q.704 7/1996
7  *   GF 001-9001 (Chinese ITU variant)
8  *
9  * Copyright 2001, Michael Tuexen <tuexen [AT] fh-muenster.de>
10  * Updated for ANSI and Chinese ITU support by Jeff Morriss <jeff.morriss[AT]ulticom.com>
11  *
12  * $Id: packet-mtp3.c,v 1.28 2004/05/24 02:25:19 guy Exp $
13  *
14  * Ethereal - Network traffic analyzer
15  * By Gerald Combs <gerald@ethereal.com>
16  * Copyright 1998 Gerald Combs
17  *
18  * Copied from README.developer
19  *
20  * This program is free software; you can redistribute it and/or
21  * modify it under the terms of the GNU General Public License
22  * as published by the Free Software Foundation; either version 2
23  * of the License, or (at your option) any later version.
24  *
25  * This program is distributed in the hope that it will be useful,
26  * but WITHOUT ANY WARRANTY; without even the implied warranty of
27  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
28  * GNU General Public License for more details.
29  *
30  * You should have received a copy of the GNU General Public License
31  * along with this program; if not, write to the Free Software
32  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
33  */
34
35 #ifdef HAVE_CONFIG_H
36 # include "config.h"
37 #endif
38
39 #include <string.h>
40 #include <glib.h>
41
42 #ifdef NEED_SNPRINTF_H
43 #include "snprintf.h"
44 #endif
45
46 #include <epan/packet.h>
47 #include "tap.h"
48 #include "prefs.h"
49
50 /* Initialize the protocol and registered fields */
51 static int proto_mtp3  = -1;
52
53 static int mtp3_tap = -1;
54
55 static module_t *mtp3_module;
56
57 static int hf_mtp3_service_indicator = -1;
58 static int hf_mtp3_network_indicator = -1;
59 static int hf_mtp3_itu_spare = -1;
60 static int hf_mtp3_ansi_priority = -1;
61 static int hf_mtp3_itu_opc = -1;
62 static int hf_mtp3_24bit_opc = -1;
63 static int hf_mtp3_ansi_opc = -1;
64 static int hf_mtp3_chinese_opc = -1;
65 static int hf_mtp3_opc_network = -1;
66 static int hf_mtp3_opc_cluster = -1;
67 static int hf_mtp3_opc_member = -1;
68 static int hf_mtp3_itu_dpc = -1;
69 static int hf_mtp3_24bit_dpc = -1;
70 static int hf_mtp3_ansi_dpc = -1;
71 static int hf_mtp3_chinese_dpc = -1;
72 static int hf_mtp3_dpc_network = -1;
73 static int hf_mtp3_dpc_cluster = -1;
74 static int hf_mtp3_dpc_member = -1;
75 static int hf_mtp3_itu_sls = -1;
76 static int hf_mtp3_ansi_5_bit_sls = -1;
77 static int hf_mtp3_ansi_8_bit_sls = -1;
78 static int hf_mtp3_chinese_itu_sls = -1;
79
80 /* Initialize the subtree pointers */
81 static gint ett_mtp3 = -1;
82 static gint ett_mtp3_sio = -1;
83 static gint ett_mtp3_label = -1;
84 static gint ett_mtp3_label_dpc = -1;
85 static gint ett_mtp3_label_opc = -1;
86
87 static dissector_table_t mtp3_sio_dissector_table;
88
89 #include <packet-mtp3.h>
90 Standard_Type mtp3_standard = ITU_STANDARD;
91
92 static gboolean mtp3_use_ansi_5_bit_sls = FALSE;
93 static mtp3_net_addr_fmt_e mtp3_net_addr_fmt = MTP3_NET_ADDR_FMT_DASHED;
94 static mtp3_addr_pc_t mtp3_addr_dpc, mtp3_addr_opc;
95
96 #define SIO_LENGTH                1
97
98 #define ITU_ROUTING_LABEL_LENGTH  4
99 #define ITU_HEADER_LENGTH         (SIO_LENGTH + ITU_ROUTING_LABEL_LENGTH)
100 #define ITU_SLS_LENGTH            1
101
102 #define SIO_OFFSET                0
103 #define ITU_SLS_OFFSET            (SIO_OFFSET + ITU_HEADER_LENGTH - ITU_SLS_LENGTH)
104 #define ITU_ROUTING_LABEL_OFFSET  (SIO_OFFSET + SIO_LENGTH)
105 #define ITU_MTP_PAYLOAD_OFFSET    (SIO_OFFSET + ITU_HEADER_LENGTH)
106
107 #define ANSI_SLS_LENGTH           1
108 #define ANSI_ROUTING_LABEL_LENGTH (ANSI_PC_LENGTH + ANSI_PC_LENGTH + ANSI_SLS_LENGTH)
109 #define ANSI_HEADER_LENGTH        (SIO_LENGTH + ANSI_ROUTING_LABEL_LENGTH)
110
111 #define ANSI_ROUTING_LABEL_OFFSET (SIO_OFFSET + SIO_LENGTH)
112 #define ANSI_DPC_OFFSET           ANSI_ROUTING_LABEL_OFFSET
113 #define ANSI_OPC_OFFSET           (ANSI_DPC_OFFSET + ANSI_PC_LENGTH)
114 #define ANSI_SLS_OFFSET           (ANSI_OPC_OFFSET + ANSI_PC_LENGTH)
115 #define ANSI_MTP_PAYLOAD_OFFSET   (SIO_OFFSET + ANSI_HEADER_LENGTH)
116
117 #define SERVICE_INDICATOR_MASK         0x0F
118 #define SPARE_MASK                     0x30
119 #define ANSI_PRIORITY_MASK             SPARE_MASK
120 #define NETWORK_INDICATOR_MASK         0xC0
121 #define ITU_DPC_MASK                   0x00003FFF
122 #define ITU_OPC_MASK                   0x0FFFC000
123 #define ITU_SLS_MASK                   0xF0000000
124
125 #define ANSI_NETWORK_MASK              0x0000FF
126 #define ANSI_CLUSTER_MASK              0x00FF00
127 #define ANSI_MEMBER_MASK               0xFF0000
128 #define ANSI_5BIT_SLS_MASK             0x1F
129 #define ANSI_8BIT_SLS_MASK             0xFF
130 #define CHINESE_ITU_SLS_MASK           0xF
131
132 static const value_string mtp3_service_indicator_code_vals[] = {
133         { 0x0,  "Signalling Network Management Message (SNM)" },
134         { 0x1,  "Maintenance Regular Message (MTN)" },
135         { 0x2,  "Maintenance Special Message (MTNS)" },
136         { 0x3,  "SCCP" },
137         { 0x4,  "TUP" },
138         { 0x5,  "ISUP" },
139         { 0x6,  "DUP (call and circuit related messages)" },
140         { 0x7,  "DUP (facility registration and cancellation message)" },
141         { 0x8,  "MTP testing user part" },
142         { 0x9,  "Spare" },
143         { 0xa,  "Spare" },
144         { 0xb,  "Spare" },
145         { 0xc,  "Spare" },
146         { 0xd,  "Spare" },
147         { 0xe,  "Spare" },
148         { 0xf,  "Spare" },
149         { 0,    NULL }
150 };
151
152 const value_string mtp3_service_indicator_code_short_vals[] = {
153         { 0x0,  "SNM" },
154         { 0x1,  "MTN" },
155         { 0x2,  "MTNS" },
156         { 0x3,  "SCCP" },
157         { 0x4,  "TUP" },
158         { 0x5,  "ISUP" },
159         { 0x6,  "DUP (CC)" },
160         { 0x7,  "DUP (FAC/CANC)" },
161         { 0x8,  "MTP Test" },
162         { 0,    NULL }
163 };
164
165 static const value_string network_indicator_vals[] = {
166         { 0x0,  "International network" },
167         { 0x1,  "Spare (for international use only)" },
168         { 0x2,  "National network" },
169         { 0x3,  "Reserved for national use" },
170         { 0,    NULL }
171 };
172
173 static dissector_handle_t data_handle;
174
175
176 /*
177  * helper routine to format address to string
178  */
179 void
180 mtp3_addr_to_str_buf(
181   const guint8          *data,
182   gchar                 *buf)
183 {
184   mtp3_addr_pc_t        *addr_pc_p = (mtp3_addr_pc_t *) data;
185
186   switch (mtp3_net_addr_fmt)
187   {
188   case MTP3_NET_ADDR_FMT_DEC:
189     switch (addr_pc_p->type)
190     {
191     case ITU_STANDARD:
192       sprintf(buf, "%u", addr_pc_p->pc & ITU_PC_MASK);
193       break;
194     default:
195       /* assuming 24-bit */
196       sprintf(buf, "%u", addr_pc_p->pc & ANSI_PC_MASK);
197       break;
198     }
199     break;
200
201   case MTP3_NET_ADDR_FMT_HEX:
202     switch (addr_pc_p->type)
203     {
204     case ITU_STANDARD:
205       sprintf(buf, "%x", addr_pc_p->pc & ITU_PC_MASK);
206       break;
207     default:
208       /* assuming 24-bit */
209       sprintf(buf, "%x", addr_pc_p->pc & ANSI_PC_MASK);
210       break;
211     }
212     break;
213
214   case MTP3_NET_ADDR_FMT_NI_DEC:
215     switch (addr_pc_p->type)
216     {
217     case ITU_STANDARD:
218       sprintf(buf, "%u:%u", addr_pc_p->ni, addr_pc_p->pc & ITU_PC_MASK);
219       break;
220     default:
221       /* assuming 24-bit */
222       sprintf(buf, "%u:%u", addr_pc_p->ni, addr_pc_p->pc & ANSI_PC_MASK);
223       break;
224     }
225     break;
226
227   case MTP3_NET_ADDR_FMT_NI_HEX:
228     switch (addr_pc_p->type)
229     {
230     case ITU_STANDARD:
231       sprintf(buf, "%u:%x", addr_pc_p->ni, addr_pc_p->pc & ITU_PC_MASK);
232       break;
233     default:
234       /* assuming 24-bit */
235       sprintf(buf, "%u:%x", addr_pc_p->ni, addr_pc_p->pc & ANSI_PC_MASK);
236       break;
237     }
238     break;
239
240   default:
241     /* FALLTHRU */
242
243   case MTP3_NET_ADDR_FMT_DASHED:
244     switch (addr_pc_p->type)
245     {
246     case ITU_STANDARD:
247       sprintf(buf, "%u-%u-%u",
248         (addr_pc_p->pc & 0x3800) >> 11,
249         ((addr_pc_p->pc & 0x7f8) >> 3),
250         (addr_pc_p->pc & 0x07));
251       break;
252     default:
253       /* assuming 24-bit */
254       sprintf(buf, "%u-%u-%u",
255         (addr_pc_p->pc & ANSI_NETWORK_MASK),
256         ((addr_pc_p->pc & ANSI_CLUSTER_MASK) >> 8),
257         ((addr_pc_p->pc & ANSI_MEMBER_MASK) >> 16));
258       break;
259     }
260     break;
261   }
262 }
263
264 static void
265 dissect_mtp3_sio(tvbuff_t *tvb, packet_info *pinfo, proto_tree *mtp3_tree)
266 {
267   guint8 sio;
268   proto_item *sio_item;
269   proto_tree *sio_tree;
270
271   sio_item = proto_tree_add_text(mtp3_tree, tvb, SIO_OFFSET, SIO_LENGTH,
272                                  "Service information octet");
273   sio_tree = proto_item_add_subtree(sio_item, ett_mtp3_sio);
274
275   sio = tvb_get_guint8(tvb, SIO_OFFSET);
276   proto_tree_add_uint(sio_tree, hf_mtp3_network_indicator, tvb, SIO_OFFSET,
277                       SIO_LENGTH, sio);
278
279   mtp3_addr_opc.ni = (sio & NETWORK_INDICATOR_MASK) >> 6;
280   mtp3_addr_dpc.ni = (sio & NETWORK_INDICATOR_MASK) >> 6;
281
282   switch(mtp3_standard){
283   case ANSI_STANDARD:
284     proto_tree_add_uint(sio_tree, hf_mtp3_ansi_priority, tvb, SIO_OFFSET,
285                         SIO_LENGTH, sio);
286     break;
287   case ITU_STANDARD:
288   case CHINESE_ITU_STANDARD:
289     proto_tree_add_uint(sio_tree, hf_mtp3_itu_spare, tvb, SIO_OFFSET,
290                         SIO_LENGTH, sio);
291     break;
292   }
293
294   proto_tree_add_uint(sio_tree, hf_mtp3_service_indicator, tvb, SIO_OFFSET,
295                       SIO_LENGTH, sio);
296
297   /* Store the SI so that subidissectors know what SI this msg is */
298   pinfo->private_data = (void *)(sio & SERVICE_INDICATOR_MASK);
299 }
300
301 static void
302 dissect_mtp3_routing_label(tvbuff_t *tvb, packet_info *pinfo, proto_tree *mtp3_tree)
303 {
304   guint32 label, dpc = 0, opc = 0;
305   guint8 sls;
306   proto_item *label_item, *label_dpc_item, *label_opc_item;
307   proto_tree *label_tree, *label_dpc_tree, *label_opc_tree;
308   char pc[ANSI_PC_STRING_LENGTH];
309   int *hf_dpc_string;
310   int *hf_opc_string;
311
312
313   switch (mtp3_standard) {
314   case ITU_STANDARD:
315     label_item = proto_tree_add_text(mtp3_tree, tvb, ITU_ROUTING_LABEL_OFFSET,
316                                      ITU_ROUTING_LABEL_LENGTH, "Routing label");
317     label_tree = proto_item_add_subtree(label_item, ett_mtp3_label);
318
319     label = tvb_get_letohl(tvb, ITU_ROUTING_LABEL_OFFSET);
320     sls   = tvb_get_guint8(tvb, ITU_SLS_OFFSET);
321
322     opc = (label & ITU_OPC_MASK) >> 14;
323     dpc = label & ITU_DPC_MASK;
324
325     label_dpc_item =
326         proto_tree_add_uint(label_tree, hf_mtp3_itu_dpc, tvb,
327                             ITU_ROUTING_LABEL_OFFSET, ITU_ROUTING_LABEL_LENGTH,
328                             label);
329     proto_item_append_text(label_dpc_item, " (%u-%u-%u)",
330                            (dpc & 0x3800) >> 11,
331                            ((dpc & 0x7f8) >> 3),
332                            (dpc & 0x07));
333
334     label_opc_item =
335         proto_tree_add_uint(label_tree, hf_mtp3_itu_opc, tvb,
336                             ITU_ROUTING_LABEL_OFFSET, ITU_ROUTING_LABEL_LENGTH,
337                             label);
338     proto_item_append_text(label_opc_item, " (%u-%u-%u)",
339                            (opc & 0x3800) >> 11,
340                            ((opc & 0x7f8) >> 3),
341                            (opc & 0x07));
342
343     proto_tree_add_uint(label_tree, hf_mtp3_itu_sls, tvb, ITU_SLS_OFFSET,
344                         ITU_SLS_LENGTH, sls);
345     break;
346
347   case ANSI_STANDARD:
348   case CHINESE_ITU_STANDARD:
349     if (mtp3_standard == ANSI_STANDARD)
350     {
351       hf_dpc_string = &hf_mtp3_ansi_dpc;
352       hf_opc_string = &hf_mtp3_ansi_opc;
353     } else /* CHINESE_ITU_STANDARD */ {
354       hf_dpc_string = &hf_mtp3_chinese_dpc;
355       hf_opc_string = &hf_mtp3_chinese_opc;
356     }
357
358     /* Create the Routing Label Tree */
359     label_item = proto_tree_add_text(mtp3_tree, tvb, ANSI_ROUTING_LABEL_OFFSET,
360                                      ANSI_ROUTING_LABEL_LENGTH,
361                                      "Routing label");
362     label_tree = proto_item_add_subtree(label_item, ett_mtp3_label);
363
364     /* create the DPC tree */
365     dpc = tvb_get_ntoh24(tvb, ANSI_DPC_OFFSET);
366     snprintf(pc, sizeof(pc), "%d-%d-%d", (dpc & ANSI_NETWORK_MASK),
367                                          ((dpc & ANSI_CLUSTER_MASK) >> 8),
368                                          ((dpc & ANSI_MEMBER_MASK) >> 16));
369
370     label_dpc_item = proto_tree_add_string_format(label_tree, *hf_dpc_string,
371                                                   tvb, ANSI_DPC_OFFSET,
372                                                   ANSI_PC_LENGTH, pc,
373                                                   "DPC (%s) (%u)", pc, dpc);
374
375     label_dpc_tree = proto_item_add_subtree(label_dpc_item, ett_mtp3_label_dpc);
376
377     proto_tree_add_uint(label_dpc_tree, hf_mtp3_dpc_member, tvb,
378                         ANSI_DPC_OFFSET + ANSI_MEMBER_OFFSET, ANSI_NCM_LENGTH,
379                         dpc);
380     proto_tree_add_uint(label_dpc_tree, hf_mtp3_dpc_cluster,tvb,
381                         ANSI_DPC_OFFSET + ANSI_CLUSTER_OFFSET, ANSI_NCM_LENGTH,
382                         dpc);
383     proto_tree_add_uint(label_dpc_tree, hf_mtp3_dpc_network,tvb,
384                         ANSI_DPC_OFFSET + ANSI_NETWORK_OFFSET, ANSI_NCM_LENGTH,
385                         dpc);
386
387
388     /* add full integer values of DPC as hidden for filtering purposes */
389     proto_tree_add_uint_hidden(label_dpc_tree, hf_mtp3_24bit_dpc, tvb, ANSI_DPC_OFFSET,
390                                ANSI_PC_LENGTH, dpc);
391
392     /* create the OPC tree */
393     opc = tvb_get_ntoh24(tvb, ANSI_OPC_OFFSET);
394     snprintf(pc, sizeof(pc), "%d-%d-%d", (opc & ANSI_NETWORK_MASK),
395                                          ((opc & ANSI_CLUSTER_MASK) >> 8),
396                                          ((opc & ANSI_MEMBER_MASK) >> 16));
397     label_opc_item = proto_tree_add_string_format(label_tree, *hf_opc_string,
398                                                   tvb, ANSI_OPC_OFFSET,
399                                                   ANSI_PC_LENGTH, pc,
400                                                   "OPC (%s) (%u)", pc, opc);
401
402     label_opc_tree = proto_item_add_subtree(label_opc_item, ett_mtp3_label_opc);
403
404     proto_tree_add_uint(label_opc_tree, hf_mtp3_opc_member, tvb,
405                         ANSI_OPC_OFFSET + ANSI_MEMBER_OFFSET, ANSI_NCM_LENGTH,
406                         opc);
407     proto_tree_add_uint(label_opc_tree, hf_mtp3_opc_cluster, tvb,
408                         ANSI_OPC_OFFSET + ANSI_CLUSTER_OFFSET, ANSI_NCM_LENGTH,
409                         opc);
410     proto_tree_add_uint(label_opc_tree, hf_mtp3_opc_network,tvb,
411                         ANSI_OPC_OFFSET + ANSI_NETWORK_OFFSET, ANSI_NCM_LENGTH,
412                         opc);
413
414     /* add full integer values of OPC as hidden for filtering purposes */
415     proto_tree_add_uint_hidden(label_opc_tree, hf_mtp3_24bit_opc, tvb, ANSI_OPC_OFFSET,
416                                ANSI_PC_LENGTH, opc);
417
418     /* SLS */
419     if (mtp3_standard == ANSI_STANDARD)
420     {
421         if (mtp3_use_ansi_5_bit_sls)
422             proto_tree_add_item(label_tree, hf_mtp3_ansi_5_bit_sls, tvb,
423                                 ANSI_SLS_OFFSET, ANSI_SLS_LENGTH, TRUE);
424         else
425             proto_tree_add_item(label_tree, hf_mtp3_ansi_8_bit_sls, tvb,
426                                 ANSI_SLS_OFFSET, ANSI_SLS_LENGTH, TRUE);
427     } else /* CHINESE_ITU_STANDARD */ {
428         proto_tree_add_item(label_tree, hf_mtp3_chinese_itu_sls, tvb,
429                             ANSI_SLS_OFFSET, ITU_SLS_LENGTH, FALSE);
430     }
431
432     break;
433   }
434
435   mtp3_addr_opc.type = mtp3_standard;
436   mtp3_addr_opc.pc = opc;
437   SET_ADDRESS(&pinfo->net_src, AT_SS7PC, sizeof(mtp3_addr_opc), (guint8 *) &mtp3_addr_opc);
438
439   mtp3_addr_dpc.type = mtp3_standard;
440   mtp3_addr_dpc.pc = dpc;
441   SET_ADDRESS(&pinfo->net_dst, AT_SS7PC, sizeof(mtp3_addr_dpc), (guint8 *) &mtp3_addr_dpc);
442 }
443
444 static void
445 dissect_mtp3_payload(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
446 {
447   guint8 sio;
448   guint8 service_indicator;
449   tvbuff_t *payload_tvb = NULL;
450
451   sio               = tvb_get_guint8(tvb, SIO_OFFSET);
452   service_indicator = sio & SERVICE_INDICATOR_MASK;
453
454   switch (mtp3_standard) {
455   case ITU_STANDARD:
456     payload_tvb = tvb_new_subset(tvb, ITU_MTP_PAYLOAD_OFFSET, -1, -1);
457     break;
458   case ANSI_STANDARD:
459   case CHINESE_ITU_STANDARD:
460     payload_tvb = tvb_new_subset(tvb, ANSI_MTP_PAYLOAD_OFFSET, -1, -1);
461     break;
462   }
463
464   if (check_col(pinfo->cinfo, COL_INFO))
465       col_set_str(pinfo->cinfo, COL_INFO, "DATA ");
466
467   if (!dissector_try_port(mtp3_sio_dissector_table, service_indicator,
468                           payload_tvb, pinfo, tree))
469     call_dissector(data_handle, payload_tvb, pinfo, tree);
470 }
471
472 /* Code to actually dissect the packets */
473 static void
474 dissect_mtp3(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
475 {
476   mtp3_tap_rec_t        tap_rec;
477
478   /* Set up structures needed to add the protocol subtree and manage it */
479   proto_item *mtp3_item = NULL;
480   proto_tree *mtp3_tree = NULL;
481
482   /* Make entries in Protocol column on summary display */
483   if (check_col(pinfo->cinfo, COL_PROTOCOL))
484     switch(mtp3_standard) {
485       case ITU_STANDARD:
486         col_set_str(pinfo->cinfo, COL_PROTOCOL, "MTP3 (Int. ITU)");
487         break;
488       case ANSI_STANDARD:
489         col_set_str(pinfo->cinfo, COL_PROTOCOL, "MTP3 (ANSI)");
490         break;
491       case CHINESE_ITU_STANDARD:
492         col_set_str(pinfo->cinfo, COL_PROTOCOL, "MTP3 (Chin. ITU)");
493         break;
494     };      
495
496   if (tree) {
497     /* create display subtree for the protocol */
498     switch (mtp3_standard) {
499     case ITU_STANDARD:
500       mtp3_item = proto_tree_add_item(tree, proto_mtp3, tvb, 0,
501                                       ITU_HEADER_LENGTH, TRUE);
502       break;
503     case ANSI_STANDARD:
504     case CHINESE_ITU_STANDARD:
505       mtp3_item = proto_tree_add_item(tree, proto_mtp3, tvb, 0,
506                                       ANSI_HEADER_LENGTH, TRUE);
507       break;
508     }
509     mtp3_tree = proto_item_add_subtree(mtp3_item, ett_mtp3);
510
511   }
512
513   memset(&mtp3_addr_opc, 0, sizeof(mtp3_addr_opc));
514   memset(&mtp3_addr_dpc, 0, sizeof(mtp3_addr_dpc));
515
516   /* Dissect the packet (even if !tree so can call sub-dissectors and update
517    * the source and destination address columns) */
518   dissect_mtp3_sio(tvb, pinfo, mtp3_tree);
519   dissect_mtp3_routing_label(tvb, pinfo, mtp3_tree);
520
521   tap_rec.addr_opc = mtp3_addr_opc;
522   tap_rec.addr_dpc = mtp3_addr_dpc;
523   tap_rec.si_code = (tvb_get_guint8(tvb, SIO_OFFSET) & SERVICE_INDICATOR_MASK);
524   tap_rec.size = tvb_length(tvb);
525
526   tap_queue_packet(mtp3_tap, pinfo, &tap_rec);
527
528   dissect_mtp3_payload(tvb, pinfo, tree);
529 }
530
531 void
532 proto_register_mtp3(void)
533 {
534
535   /* Setup list of header fields  See Section 1.6.1 for details*/
536   static hf_register_info hf[] = {
537     { &hf_mtp3_service_indicator,
538       { "Service indicator", "mtp3.service_indicator",
539         FT_UINT8, BASE_HEX, VALS(mtp3_service_indicator_code_vals), SERVICE_INDICATOR_MASK,
540               "", HFILL }},
541     { &hf_mtp3_network_indicator,
542       { "Network indicator", "mtp3.network_indicator",
543               FT_UINT8, BASE_HEX, VALS(network_indicator_vals), NETWORK_INDICATOR_MASK,
544               "", HFILL }},
545     { &hf_mtp3_itu_spare,
546       { "Spare", "mtp3.spare",
547               FT_UINT8, BASE_HEX, NULL, SPARE_MASK,
548               "", HFILL }},
549     { &hf_mtp3_ansi_priority,
550       { "Priority", "mtp3.priority",
551               FT_UINT8, BASE_HEX, NULL, ANSI_PRIORITY_MASK,
552               "", HFILL }},
553     { &hf_mtp3_itu_opc,
554       { "OPC", "mtp3.opc",
555               FT_UINT32, BASE_DEC, NULL, ITU_OPC_MASK,
556               "", HFILL }},
557     { &hf_mtp3_24bit_opc,
558       { "OPC", "mtp3.opc",
559               FT_UINT32, BASE_DEC, NULL, ANSI_PC_MASK,
560               "", HFILL }},
561     { &hf_mtp3_ansi_opc,
562       { "DPC", "mtp3.ansi_opc",
563               FT_STRING, BASE_NONE, NULL, 0x0,
564               "", HFILL }},
565     { &hf_mtp3_chinese_opc,
566       { "DPC", "mtp3.chinese_opc",
567               FT_STRING, BASE_NONE, NULL, 0x0,
568               "", HFILL }},
569     { &hf_mtp3_opc_network,
570      { "OPC Network", "mtp3.opc.network",
571              FT_UINT24, BASE_DEC, NULL, ANSI_NETWORK_MASK,
572              "", HFILL }},
573     { &hf_mtp3_opc_cluster,
574       { "OPC Cluster", "mtp3.opc.cluster",
575               FT_UINT24, BASE_DEC, NULL, ANSI_CLUSTER_MASK,
576               "", HFILL }},
577     { &hf_mtp3_opc_member,
578       { "OPC Member", "mtp3.opc.member",
579               FT_UINT24, BASE_DEC, NULL, ANSI_MEMBER_MASK,
580               "", HFILL }},
581     { &hf_mtp3_itu_dpc,
582       { "DPC", "mtp3.dpc",
583               FT_UINT32, BASE_DEC, NULL, ITU_DPC_MASK,
584               "", HFILL }},
585     { &hf_mtp3_24bit_dpc,
586       { "DPC", "mtp3.dpc",
587               FT_UINT32, BASE_DEC, NULL, ANSI_PC_MASK,
588               "", HFILL }},
589     { &hf_mtp3_ansi_dpc,
590       { "DPC", "mtp3.ansi_dpc",
591               FT_STRING, BASE_NONE, NULL, 0x0,
592               "", HFILL }},
593     { &hf_mtp3_chinese_dpc,
594       { "DPC", "mtp3.chinese_dpc",
595               FT_STRING, BASE_NONE, NULL, 0x0,
596               "", HFILL }},
597     { &hf_mtp3_dpc_network,
598       { "DPC Network", "mtp3.dpc.network",
599               FT_UINT24, BASE_DEC, NULL, ANSI_NETWORK_MASK,
600               "", HFILL }},
601     { &hf_mtp3_dpc_cluster,
602       { "DPC Cluster", "mtp3.dpc.cluster",
603               FT_UINT24, BASE_DEC, NULL, ANSI_CLUSTER_MASK,
604               "", HFILL }},
605     { &hf_mtp3_dpc_member,
606       { "DPC Member", "mtp3.dpc.member",
607               FT_UINT24, BASE_DEC, NULL, ANSI_MEMBER_MASK,
608               "", HFILL }},
609     { &hf_mtp3_itu_sls,
610       { "Signalling Link Selector", "mtp3.sls",
611               FT_UINT32, BASE_DEC, NULL, ITU_SLS_MASK,
612               "", HFILL }},
613     { &hf_mtp3_ansi_5_bit_sls,
614       { "Signalling Link Selector", "mtp3.sls",
615               FT_UINT8, BASE_DEC, NULL, ANSI_5BIT_SLS_MASK,
616               "", HFILL }},
617     { &hf_mtp3_ansi_8_bit_sls,
618       { "Signalling Link Selector", "mtp3.sls",
619               FT_UINT8, BASE_DEC, NULL, ANSI_8BIT_SLS_MASK,
620               "", HFILL }},
621     { &hf_mtp3_chinese_itu_sls,
622       { "Signalling Link Selector", "mtp3.sls",
623               FT_UINT8, BASE_DEC, NULL, CHINESE_ITU_SLS_MASK,
624               "", HFILL }}
625   };
626
627   /* Setup protocol subtree array */
628   static gint *ett[] = {
629     &ett_mtp3,
630     &ett_mtp3_sio,
631     &ett_mtp3_label,
632     &ett_mtp3_label_dpc,
633     &ett_mtp3_label_opc
634   };
635
636   static enum_val_t mtp3_options[] = {
637     { "itu",         "ITU",         ITU_STANDARD },
638     { "ansi",        "ANSI",        ANSI_STANDARD },
639     { "chinese-itu", "Chinese ITU", CHINESE_ITU_STANDARD },
640     { NULL, NULL, 0 }
641   };
642
643   static enum_val_t mtp3_net_addr_fmt_str_e[] = {
644     { "decimal",        "Decimal",              MTP3_NET_ADDR_FMT_DEC },
645     { "hexadecimal",    "Hexadecimal",          MTP3_NET_ADDR_FMT_HEX },
646     { "ni-decimal",     "NI-Decimal",           MTP3_NET_ADDR_FMT_NI_DEC },
647     { "ni-hexadecimal", "NI-Hexadecimal",       MTP3_NET_ADDR_FMT_NI_HEX },
648     { "dashed",         "Dashed",               MTP3_NET_ADDR_FMT_DASHED },
649     { NULL,             NULL,                   0 }
650   };
651
652   /* Register the protocol name and description */
653   proto_mtp3 = proto_register_protocol("Message Transfer Part Level 3",
654                                        "MTP3", "mtp3");
655   register_dissector("mtp3", dissect_mtp3, proto_mtp3);
656
657   /* Required function calls to register the header fields and subtrees used */
658   proto_register_field_array(proto_mtp3, hf, array_length(hf));
659   proto_register_subtree_array(ett, array_length(ett));
660
661   mtp3_sio_dissector_table = register_dissector_table("mtp3.service_indicator",
662                                                       "MTP3 Service indicator",
663                                                       FT_UINT8, BASE_HEX);
664
665   mtp3_tap = register_tap("mtp3");
666
667   mtp3_module = prefs_register_protocol(proto_mtp3, NULL);
668
669   prefs_register_enum_preference(mtp3_module, "standard", "MTP3 standard",
670                                  "The SS7 standard used in MTP3 packets",
671                                  (gint *)&mtp3_standard, mtp3_options, FALSE);
672
673   prefs_register_bool_preference(mtp3_module, "ansi_5_bit_sls",
674                                  "Use 5-bit SLS (ANSI only)",
675                                  "Use 5-bit (instead of 8-bit) SLS in ANSI MTP3 packets",
676                                  &mtp3_use_ansi_5_bit_sls);
677
678   prefs_register_enum_preference(mtp3_module, "net_addr_format", "Network Address Format",
679                                  "Format for point code in the network address columns",
680                                  (gint *)&mtp3_net_addr_fmt, mtp3_net_addr_fmt_str_e, FALSE);
681 }
682
683 void
684 proto_reg_handoff_mtp3(void)
685 {
686   dissector_handle_t mtp3_handle;        
687          
688   mtp3_handle = create_dissector_handle(dissect_mtp3, proto_mtp3);       
689                  
690   dissector_add("wtap_encap", WTAP_ENCAP_MTP3, mtp3_handle);     
691                  
692   data_handle = find_dissector("data");
693 }