Coverage Report

Created: 2025-12-27 06:52

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wireshark/epan/dissectors/packet-mtp3.c
Line
Count
Source
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
 *   JT-Q704 and NTT-Q704 (Japan)
9
 *
10
 *   Note that the division of the Japan SLS into the SLC and A/B bit (for
11
 *   management messages) is not done.
12
 *
13
 * Copyright 2001, Michael Tuexen <tuexen [AT] fh-muenster.de>
14
 * Updated for ANSI, Chinese ITU, and Japan support by
15
 *  Jeff Morriss <jeff.morriss.ws [AT] gmail.com>
16
 *
17
 * Wireshark - Network traffic analyzer
18
 * By Gerald Combs <gerald@wireshark.org>
19
 * Copyright 1998 Gerald Combs
20
 *
21
 * Copied from README.developer
22
 *
23
 * SPDX-License-Identifier: GPL-2.0-or-later
24
 */
25
26
#include "config.h"
27
28
#include <epan/packet.h>
29
#include <epan/stat_tap_ui.h>
30
#include <epan/tap.h>
31
#include <epan/prefs.h>
32
#include <epan/address_types.h>
33
#include <wiretap/wtap.h>
34
#include <epan/addr_resolv.h>
35
36
#include <wsutil/array.h>
37
38
#include "packet-q708.h"
39
#include "packet-sccp.h"
40
#include "packet-frame.h"
41
42
void proto_register_mtp3(void);
43
void proto_reg_handoff_mtp3(void);
44
45
/* Initialize the protocol and registered fields */
46
static int proto_mtp3;
47
48
static int mtp3_tap;
49
50
static dissector_handle_t mtp3_handle;
51
52
static module_t *mtp3_module;
53
54
static int hf_mtp3_service_indicator;
55
static int hf_mtp3_network_indicator;
56
static int hf_mtp3_itu_spare;
57
static int hf_mtp3_itu_priority;
58
static int hf_mtp3_ansi_priority;
59
static int hf_mtp3_itu_pc;
60
static int hf_mtp3_24bit_pc;
61
static int hf_mtp3_itu_opc;
62
static int hf_mtp3_24bit_opc;
63
static int hf_mtp3_ansi_opc;
64
static int hf_mtp3_chinese_opc;
65
static int hf_mtp3_opc_network;
66
static int hf_mtp3_opc_cluster;
67
static int hf_mtp3_opc_member;
68
static int hf_mtp3_itu_dpc;
69
static int hf_mtp3_24bit_dpc;
70
static int hf_mtp3_ansi_dpc;
71
static int hf_mtp3_chinese_dpc;
72
static int hf_mtp3_dpc_network;
73
static int hf_mtp3_dpc_cluster;
74
static int hf_mtp3_dpc_member;
75
static int hf_mtp3_itu_sls;
76
static int hf_mtp3_ansi_5_bit_sls;
77
static int hf_mtp3_ansi_8_bit_sls;
78
static int hf_mtp3_chinese_itu_sls;
79
static int hf_mtp3_japan_dpc;
80
static int hf_mtp3_japan_opc;
81
static int hf_mtp3_japan_pc;
82
static int hf_mtp3_japan_4_bit_sls;
83
static int hf_mtp3_japan_4_bit_sls_spare;
84
static int hf_mtp3_japan_5_bit_sls;
85
static int hf_mtp3_japan_5_bit_sls_spare;
86
static int hf_mtp3_heuristic_standard;
87
88
/* Initialize the subtree pointers */
89
static int ett_mtp3;
90
static int ett_mtp3_sio;
91
static int ett_mtp3_label;
92
static int ett_mtp3_label_dpc;
93
static int ett_mtp3_label_opc;
94
95
static dissector_table_t mtp3_sio_dissector_table;
96
97
static int mtp3_address_type = -1;
98
99
typedef enum {
100
  ITU_PC_STRUCTURE_NONE    = 1,
101
  ITU_PC_STRUCTURE_3_8_3   = 2,
102
  ITU_PC_STRUCTURE_4_3_4_3 = 3
103
} ITU_PC_Structure_Type;
104
105
typedef enum {
106
  JAPAN_PC_STRUCTURE_NONE    = 1,
107
  JAPAN_PC_STRUCTURE_7_4_5   = 2,
108
  JAPAN_PC_STRUCTURE_3_4_4_5 = 3
109
} JAPAN_PC_Structure_Type;
110
111
static int itu_pc_structure   = ITU_PC_STRUCTURE_NONE;
112
static int japan_pc_structure = JAPAN_PC_STRUCTURE_NONE;
113
114
#include "packet-mtp3.h"
115
116
int mtp3_standard = ITU_STANDARD;
117
bool mtp3_heuristic_standard;
118
119
static int pref_mtp3_standard;
120
121
const value_string mtp3_standard_vals[] = {
122
  { ITU_STANDARD,         "ITU_STANDARD" },
123
  { ANSI_STANDARD,        "ANSI_STANDARD" },
124
  { CHINESE_ITU_STANDARD, "CHINESE_ITU_STANDARD" },
125
  { JAPAN_STANDARD,       "JAPAN_STANDARD" },
126
  { 0,        NULL }
127
};
128
129
static bool mtp3_use_ansi_5_bit_sls;
130
static bool mtp3_use_japan_5_bit_sls;
131
static bool mtp3_show_itu_priority;
132
static int mtp3_addr_fmt = MTP3_ADDR_FMT_DASHED;
133
134
10.2k
#define SIO_LENGTH                1
135
0
#define SLS_LENGTH                1
136
12.4k
#define SIO_OFFSET                0
137
5.81k
#define ROUTING_LABEL_OFFSET      (SIO_OFFSET + SIO_LENGTH)
138
139
6.55k
#define ITU_ROUTING_LABEL_LENGTH  4
140
1.47k
#define ITU_HEADER_LENGTH         (SIO_LENGTH + ITU_ROUTING_LABEL_LENGTH)
141
142
#define ITU_SLS_OFFSET            (SIO_OFFSET + ITU_HEADER_LENGTH - SLS_LENGTH)
143
739
#define ITU_MTP_PAYLOAD_OFFSET    (SIO_OFFSET + ITU_HEADER_LENGTH)
144
145
0
#define ANSI_ROUTING_LABEL_LENGTH (ANSI_PC_LENGTH + ANSI_PC_LENGTH + SLS_LENGTH)
146
0
#define ANSI_HEADER_LENGTH        (SIO_LENGTH + ANSI_ROUTING_LABEL_LENGTH)
147
148
0
#define ANSI_DPC_OFFSET           ROUTING_LABEL_OFFSET
149
0
#define ANSI_OPC_OFFSET           (ANSI_DPC_OFFSET + ANSI_PC_LENGTH)
150
0
#define ANSI_SLS_OFFSET           (ANSI_OPC_OFFSET + ANSI_PC_LENGTH)
151
0
#define ANSI_MTP_PAYLOAD_OFFSET   (SIO_OFFSET + ANSI_HEADER_LENGTH)
152
153
0
#define JAPAN_SLS_SPARE_LENGTH           1
154
0
#define JAPAN_ROUTING_LABEL_LENGTH (JAPAN_PC_LENGTH + JAPAN_PC_LENGTH + JAPAN_SLS_SPARE_LENGTH)
155
0
#define JAPAN_HEADER_LENGTH        (SIO_LENGTH + JAPAN_ROUTING_LABEL_LENGTH)
156
157
0
#define JAPAN_OPC_OFFSET           (ROUTING_LABEL_OFFSET + JAPAN_PC_LENGTH)
158
0
#define JAPAN_SLS_OFFSET           (JAPAN_OPC_OFFSET + JAPAN_PC_LENGTH)
159
#define JAPAN_SPARE_OFFSET         (ROUTING_LABEL_OFFSET + JAPAN_ROUTING_LABEL_LENGTH)
160
0
#define JAPAN_MTP_PAYLOAD_OFFSET   (SIO_OFFSET + JAPAN_HEADER_LENGTH)
161
162
2.23k
#define SERVICE_INDICATOR_MASK     0x0F
163
42
#define SPARE_MASK                 0x30
164
14
#define ANSI_PRIORITY_MASK         SPARE_MASK
165
1.49k
#define NETWORK_INDICATOR_MASK     0xC0
166
753
#define ITU_DPC_MASK               0x00003FFF
167
753
#define ITU_OPC_MASK               0x0FFFC000
168
14
#define ITU_SLS_MASK               0xF0000000
169
170
14
#define ANSI_5BIT_SLS_MASK         0x1F
171
14
#define ANSI_8BIT_SLS_MASK         0x0
172
14
#define CHINESE_ITU_SLS_MASK       0xF
173
14
#define JAPAN_4_BIT_SLS_MASK       0xF
174
14
#define JAPAN_4_BIT_SLS_SPARE_MASK 0xF0
175
14
#define JAPAN_5_BIT_SLS_MASK       0x1F
176
14
#define JAPAN_5_BIT_SLS_SPARE_MASK 0xE0
177
178
/* the higher values are taken from the M3UA RFC */
179
static const value_string mtp3_service_indicator_code_vals[] = {
180
  { MTP_SI_SNM,      "Signalling Network Management Message (SNM)" },
181
  { MTP_SI_MTN,      "Maintenance Regular Message (MTN)" },
182
  { MTP_SI_MTNS,     "Maintenance Special Message (MTNS)" },
183
  { MTP_SI_SCCP,     "SCCP" },
184
  { MTP_SI_TUP,      "TUP" },
185
  { MTP_SI_ISUP,     "ISUP" },
186
  { MTP_SI_DUP_CC,   "DUP (call and circuit related messages)" },
187
  { MTP_SI_DUP_FAC,  "DUP (facility registration and cancellation message)" },
188
  { MTP_SI_MTP_TEST, "MTP testing user part" },
189
  { MTP_SI_ISUP_B,   "Broadband ISUP" },
190
  { MTP_SI_ISUP_S,   "Satellite ISUP" },
191
  { 0xb,             "Spare" },
192
  { MTP_SI_AAL2,     "AAL type2 Signaling" },
193
  { MTP_SI_BICC,     "Bearer Independent Call Control (BICC)" },
194
  { MTP_SI_GCP,      "Gateway Control Protocol" },
195
  { 0xf,             "Spare" },
196
  { 0,        NULL }
197
};
198
199
const value_string mtp3_service_indicator_code_short_vals[] = {
200
  { MTP_SI_SNM,      "SNM" },
201
  { MTP_SI_MTN,      "MTN" },
202
  { MTP_SI_MTNS,     "MTNS" },
203
  { MTP_SI_SCCP,     "SCCP" },
204
  { MTP_SI_TUP,      "TUP" },
205
  { MTP_SI_ISUP,     "ISUP" },
206
  { MTP_SI_DUP_CC,   "DUP (CC)" },
207
  { MTP_SI_DUP_FAC,  "DUP (FAC/CANC)" },
208
  { MTP_SI_MTP_TEST, "MTP Test" },
209
  { MTP_SI_ISUP_B,   "ISUP-b" },
210
  { MTP_SI_ISUP_S,   "ISUP-s" },
211
  { MTP_SI_AAL2,     "AAL type 2" },
212
  { MTP_SI_BICC,     "BICC" },
213
  { MTP_SI_GCP,      "GCP" },
214
  { 0,      NULL }
215
};
216
217
const value_string mtp3_network_indicator_vals[] = {
218
  { MTP3_NI_INT0,  "International network" },
219
  { MTP3_NI_INT1,  "Spare (for international use only)" },
220
  { MTP3_NI_NAT0,  "National network" },
221
  { MTP3_NI_NAT1,  "Reserved for national use" },
222
  { 0,    NULL }
223
};
224
225
226
/*
227
 * helper routine to format a point code in structured form
228
 */
229
230
char*
231
mtp3_pc_to_str(wmem_allocator_t* allocator, const uint32_t pc)
232
0
{
233
0
  switch (mtp3_standard)
234
0
  {
235
0
    case ITU_STANDARD:
236
0
      switch (itu_pc_structure) {
237
0
        case ITU_PC_STRUCTURE_NONE:
238
0
          return wmem_strdup_printf(allocator, "%u", pc);
239
240
0
        case ITU_PC_STRUCTURE_3_8_3:
241
          /* this format is used in international ITU networks */
242
0
          return wmem_strdup_printf(allocator, "%u-%u-%u", (pc & 0x3800)>>11, (pc & 0x7f8) >> 3, (pc & 0x07) >> 0);
243
244
0
        case ITU_PC_STRUCTURE_4_3_4_3:
245
          /* this format is used in some national ITU networks, the German one for example. */
246
0
          return wmem_strdup_printf(allocator, "%u-%u-%u-%u", (pc & 0x3c00) >>10, (pc & 0x0380) >> 7, (pc & 0x0078) >> 3, (pc & 0x0007) >> 0);
247
248
0
        default:
249
0
          DISSECTOR_ASSERT_NOT_REACHED();
250
0
          return wmem_strdup(allocator, "");
251
0
      }
252
0
      break;
253
0
    case ANSI_STANDARD:
254
0
    case CHINESE_ITU_STANDARD:
255
0
      return wmem_strdup_printf(allocator, "%u-%u-%u", (pc & ANSI_NETWORK_MASK) >> 16, (pc & ANSI_CLUSTER_MASK) >> 8, (pc & ANSI_MEMBER_MASK));
256
257
0
    case JAPAN_STANDARD:
258
0
      switch (japan_pc_structure) {
259
0
        case JAPAN_PC_STRUCTURE_NONE:
260
0
          return wmem_strdup_printf(allocator, "%u", pc);
261
262
0
        case JAPAN_PC_STRUCTURE_7_4_5:
263
          /* This format is specified by NTT */
264
0
          return wmem_strdup_printf(allocator, "%u-%u-%u", (pc & 0xfe00)>>9, (pc & 0x1e0)>>5, (pc & 0x1f));
265
266
0
        case JAPAN_PC_STRUCTURE_3_4_4_5:
267
          /* Where does this format come from? */
268
0
          return wmem_strdup_printf(allocator, "%u-%u-%u-%u", (pc & 0xe000)>>13, (pc & 0x1e00)>>9, (pc & 0x1e0)>>5, (pc & 0x1f));
269
270
0
        default:
271
0
          DISSECTOR_ASSERT_NOT_REACHED();
272
0
          return wmem_strdup(allocator, "");
273
0
      }
274
0
      break;
275
0
    default:
276
0
      DISSECTOR_ASSERT_NOT_REACHED();
277
0
      return wmem_strdup(allocator, "");
278
0
  }
279
0
}
280
281
bool
282
mtp3_pc_structured(void)
283
1.48k
{
284
1.48k
  if ((mtp3_standard == ITU_STANDARD) && (itu_pc_structure == ITU_PC_STRUCTURE_NONE))
285
1.48k
    return false;
286
0
  else if ((mtp3_standard == JAPAN_STANDARD) && (japan_pc_structure == JAPAN_PC_STRUCTURE_NONE))
287
0
    return false;
288
0
  else
289
0
    return true;
290
1.48k
}
291
292
/*
293
 * helper routine to format address to string
294
 */
295
296
static char*
297
mtp3_addr_to_str_wmem(wmem_allocator_t* allocator, const mtp3_addr_pc_t  *addr_pc_p)
298
0
{
299
0
  switch (mtp3_addr_fmt)
300
0
  {
301
0
    case MTP3_ADDR_FMT_DEC:
302
0
      switch (addr_pc_p->type)
303
0
      {
304
0
        case ITU_STANDARD:
305
0
          return wmem_strdup_printf(allocator, "%u", addr_pc_p->pc & ITU_PC_MASK);
306
0
        case JAPAN_STANDARD:
307
0
          return wmem_strdup_printf(allocator, "%u", addr_pc_p->pc & JAPAN_PC_MASK);
308
0
        default:
309
          /* assuming 24-bit */
310
0
          return wmem_strdup_printf(allocator, "%u", addr_pc_p->pc & ANSI_PC_MASK);
311
0
      }
312
0
      break;
313
314
0
    case MTP3_ADDR_FMT_HEX:
315
0
      switch (addr_pc_p->type)
316
0
      {
317
0
        case ITU_STANDARD:
318
0
          return wmem_strdup_printf(allocator, "%x", addr_pc_p->pc & ITU_PC_MASK);
319
0
        case JAPAN_STANDARD:
320
0
          return wmem_strdup_printf(allocator, "%x", addr_pc_p->pc & JAPAN_PC_MASK);
321
0
        default:
322
          /* assuming 24-bit */
323
0
          return wmem_strdup_printf(allocator, "%x", addr_pc_p->pc & ANSI_PC_MASK);
324
0
      }
325
0
      break;
326
327
0
    case MTP3_ADDR_FMT_NI_DEC:
328
0
      switch (addr_pc_p->type)
329
0
      {
330
0
        case ITU_STANDARD:
331
0
          return wmem_strdup_printf(allocator, "%u:%u", addr_pc_p->ni, addr_pc_p->pc & ITU_PC_MASK);
332
0
        case JAPAN_STANDARD:
333
0
          return wmem_strdup_printf(allocator, "%u:%u", addr_pc_p->ni, addr_pc_p->pc & JAPAN_PC_MASK);
334
0
        default:
335
          /* assuming 24-bit */
336
0
          return wmem_strdup_printf(allocator, "%u:%u", addr_pc_p->ni, addr_pc_p->pc & ANSI_PC_MASK);
337
0
      }
338
0
      break;
339
340
0
    case MTP3_ADDR_FMT_NI_HEX:
341
0
      switch (addr_pc_p->type)
342
0
      {
343
0
        case ITU_STANDARD:
344
0
          return wmem_strdup_printf(allocator, "%u:%x", addr_pc_p->ni, addr_pc_p->pc & ITU_PC_MASK);
345
0
        case JAPAN_STANDARD:
346
0
          return wmem_strdup_printf(allocator, "%u:%x", addr_pc_p->ni, addr_pc_p->pc & JAPAN_PC_MASK);
347
0
        default:
348
          /* assuming 24-bit */
349
0
          return wmem_strdup_printf(allocator, "%u:%x", addr_pc_p->ni, addr_pc_p->pc & ANSI_PC_MASK);
350
0
      }
351
0
      break;
352
353
0
    default:
354
      /* FALLTHRU */
355
356
0
    case MTP3_ADDR_FMT_DASHED:
357
0
      return mtp3_pc_to_str(allocator, addr_pc_p->pc);
358
0
  }
359
0
}
360
361
uint32_t
362
455
mtp3_pc_hash(const mtp3_addr_pc_t *addr_pc_p) {
363
455
  uint32_t pc;
364
365
455
  switch (addr_pc_p->type)
366
455
  {
367
455
    case ITU_STANDARD:
368
455
      pc = (addr_pc_p->pc & ITU_PC_MASK) | ((addr_pc_p->ni % 4) << 14) ;
369
455
      break;
370
0
    default:
371
      /* assuming 24-bit */
372
0
      pc = (addr_pc_p->pc & ANSI_PC_MASK) | ((addr_pc_p->ni) << 24) ;
373
0
      break;
374
455
  }
375
376
455
  return pc;
377
455
}
378
379
static int mtp3_addr_to_str(const address* addr, char *buf, int buf_len)
380
0
{
381
0
    char* tmp = mtp3_addr_to_str_wmem(NULL, (const mtp3_addr_pc_t*)addr->data);
382
0
    memcpy(buf, tmp, MIN(buf_len, (int)(strlen(tmp)+1)));
383
0
    wmem_free(NULL, tmp);
384
0
    return (int)(strlen(buf)+1);
385
0
}
386
387
static int mtp3_str_addr_len(const address* addr _U_)
388
0
{
389
0
    return 50;
390
0
}
391
392
static const char* mtp3_addr_col_filter_str(const address* addr _U_, bool is_src)
393
0
{
394
0
    if (is_src)
395
0
        return "mtp3.opc";
396
397
0
    return "mtp3.dpc";
398
0
}
399
400
static int mtp3_addr_len(void)
401
1.47k
{
402
1.47k
    return sizeof(mtp3_addr_pc_t);
403
1.47k
}
404
405
static const char* mtp3_addr_name_res_str(const address* addr)
406
0
{
407
0
    const mtp3_addr_pc_t *mtp3_addr = (const mtp3_addr_pc_t *)addr->data;
408
0
    const char *tmp;
409
410
0
    tmp = get_hostname_ss7pc(mtp3_addr->ni, mtp3_addr->pc);
411
412
0
    if (tmp[0] == '\0') {
413
0
        char* str = mtp3_addr_to_str_wmem(NULL, mtp3_addr);
414
0
        fill_unresolved_ss7pc(str, mtp3_addr->ni, mtp3_addr->pc);
415
0
        wmem_free(NULL, str);
416
0
        return get_hostname_ss7pc(mtp3_addr->ni, mtp3_addr->pc);
417
0
    }
418
0
    return tmp;
419
420
0
}
421
422
static int mtp3_addr_name_res_len(void)
423
0
{
424
0
    return MAXNAMELEN;
425
0
}
426
427
428
429
430
/*  Common function for dissecting 3-byte (ANSI or China) PCs. */
431
void
432
dissect_mtp3_3byte_pc(tvbuff_t *tvb, packet_info* pinfo, unsigned offset, proto_tree *tree, int ett_pc, int hf_pc_string, int hf_pc_network,
433
                      int hf_pc_cluster, int hf_pc_member, int hf_dpc, int hf_pc)
434
0
{
435
0
  uint32_t pc;
436
0
  proto_item *pc_item, *hidden_item;
437
0
  proto_tree *pc_tree;
438
0
  char* pc_string;
439
440
0
  pc = tvb_get_letoh24(tvb, offset);
441
0
  pc_string = mtp3_pc_to_str(pinfo->pool, pc);
442
0
  pc_item = proto_tree_add_string(tree, hf_pc_string, tvb, offset, ANSI_PC_LENGTH, pc_string);
443
444
  /* Add alternate formats of the PC
445
   * NOTE: each of these formats is shown to the user,
446
   * so I think that using hidden fields in this case is OK.
447
   */
448
0
  pc_string = wmem_strdup_printf(pinfo->pool, "%u", pc);
449
0
  proto_item_append_text(pc_item, " (%s)", pc_string);
450
0
  hidden_item = proto_tree_add_string(tree, hf_pc_string, tvb, offset, ANSI_PC_LENGTH, pc_string);
451
0
  proto_item_set_hidden(hidden_item);
452
453
0
  pc_string = wmem_strdup_printf(pinfo->pool, "0x%x", pc);
454
0
  proto_item_append_text(pc_item, " (%s)", pc_string);
455
0
  hidden_item = proto_tree_add_string(tree, hf_pc_string, tvb, offset, ANSI_PC_LENGTH, pc_string);
456
0
  proto_item_set_hidden(hidden_item);
457
458
0
  pc_tree = proto_item_add_subtree(pc_item, ett_pc);
459
460
0
  proto_tree_add_uint(pc_tree, hf_pc_network, tvb, offset + ANSI_NETWORK_OFFSET, ANSI_NCM_LENGTH, pc);
461
0
  proto_tree_add_uint(pc_tree, hf_pc_cluster, tvb, offset + ANSI_CLUSTER_OFFSET, ANSI_NCM_LENGTH, pc);
462
0
  proto_tree_add_uint(pc_tree, hf_pc_member,  tvb, offset + ANSI_MEMBER_OFFSET,  ANSI_NCM_LENGTH, pc);
463
464
  /* add full integer values of DPC as hidden for filtering purposes */
465
0
  if (hf_dpc) {
466
0
    hidden_item = proto_tree_add_uint(pc_tree, hf_dpc, tvb, offset, ANSI_PC_LENGTH, pc);
467
0
    proto_item_set_hidden(hidden_item);
468
0
  }
469
0
  if (hf_pc) {
470
0
    hidden_item = proto_tree_add_uint(pc_tree, hf_pc,  tvb, offset, ANSI_PC_LENGTH, pc);
471
0
    proto_item_set_hidden(hidden_item);
472
0
  }
473
0
}
474
475
static void
476
dissect_mtp3_sio(tvbuff_t *tvb, proto_tree *mtp3_tree,
477
                 mtp3_addr_pc_t *mtp3_addr_opc, mtp3_addr_pc_t *mtp3_addr_dpc)
478
739
{
479
739
  uint8_t sio;
480
739
  proto_tree *sio_tree;
481
482
739
  sio_tree = proto_tree_add_subtree(mtp3_tree, tvb, SIO_OFFSET, SIO_LENGTH, ett_mtp3_sio, NULL, "Service information octet");
483
484
739
  sio = tvb_get_uint8(tvb, SIO_OFFSET);
485
739
  proto_tree_add_uint(sio_tree, hf_mtp3_network_indicator, tvb, SIO_OFFSET, SIO_LENGTH, sio);
486
487
739
  mtp3_addr_opc->ni = (sio & NETWORK_INDICATOR_MASK) >> 6;
488
739
  mtp3_addr_dpc->ni = (sio & NETWORK_INDICATOR_MASK) >> 6;
489
490
739
  switch(mtp3_standard){
491
0
    case ANSI_STANDARD:
492
0
      proto_tree_add_uint(sio_tree, hf_mtp3_ansi_priority, tvb, SIO_OFFSET, SIO_LENGTH, sio);
493
0
      break;
494
739
    case ITU_STANDARD:
495
739
    case CHINESE_ITU_STANDARD:
496
739
      if (mtp3_show_itu_priority)
497
0
        proto_tree_add_uint(sio_tree, hf_mtp3_itu_priority, tvb, SIO_OFFSET, SIO_LENGTH, sio);
498
739
      else
499
739
        proto_tree_add_uint(sio_tree, hf_mtp3_itu_spare, tvb, SIO_OFFSET, SIO_LENGTH, sio);
500
739
      break;
501
0
    case JAPAN_STANDARD:
502
      /*  The Japan variant has priority but it's on the LI which belongs to
503
       *  layer 2.  Not sure what we can do about that...
504
       */
505
0
      proto_tree_add_uint(sio_tree, hf_mtp3_itu_spare, tvb, SIO_OFFSET, SIO_LENGTH, sio);
506
0
      break;
507
739
  }
508
509
739
  proto_tree_add_uint(sio_tree, hf_mtp3_service_indicator, tvb, SIO_OFFSET, SIO_LENGTH, sio);
510
739
}
511
512
static void
513
dissect_mtp3_routing_label(tvbuff_t *tvb, packet_info *pinfo, proto_tree *mtp3_tree,
514
                           mtp3_addr_pc_t *mtp3_addr_opc, mtp3_addr_pc_t *mtp3_addr_dpc)
515
739
{
516
739
  uint32_t label, dpc, opc;
517
739
  proto_item *label_dpc_item, *label_opc_item;
518
739
  proto_item *hidden_item;
519
739
  proto_tree *label_tree;
520
739
  proto_tree *pc_subtree;
521
739
  int hf_dpc_string;
522
739
  int hf_opc_string;
523
524
525
739
  switch (mtp3_standard) {
526
739
    case ITU_STANDARD:
527
739
      label_tree = proto_tree_add_subtree(mtp3_tree, tvb, ROUTING_LABEL_OFFSET, ITU_ROUTING_LABEL_LENGTH, ett_mtp3_label, NULL, "Routing label");
528
529
739
      label = tvb_get_letohl(tvb, ROUTING_LABEL_OFFSET);
530
531
739
      opc = (label & ITU_OPC_MASK) >> 14;
532
739
      dpc =  label & ITU_DPC_MASK;
533
534
739
      hidden_item = proto_tree_add_uint(label_tree, hf_mtp3_itu_pc, tvb, ROUTING_LABEL_OFFSET, ITU_ROUTING_LABEL_LENGTH, opc);
535
739
      proto_item_set_hidden(hidden_item);
536
739
      hidden_item = proto_tree_add_uint(label_tree, hf_mtp3_itu_pc, tvb, ROUTING_LABEL_OFFSET, ITU_ROUTING_LABEL_LENGTH, dpc);
537
739
      proto_item_set_hidden(hidden_item);
538
539
739
      label_dpc_item = proto_tree_add_uint(label_tree, hf_mtp3_itu_dpc, tvb, ROUTING_LABEL_OFFSET, ITU_ROUTING_LABEL_LENGTH, label);
540
739
      if (mtp3_pc_structured())
541
0
        proto_item_append_text(label_dpc_item, " (%s)", mtp3_pc_to_str(pinfo->pool, dpc));
542
543
739
      if(mtp3_addr_dpc->ni == MTP3_NI_INT0) {
544
320
        pc_subtree = proto_item_add_subtree(label_dpc_item, ett_mtp3_label_dpc);
545
320
        analyze_q708_ispc(tvb, pc_subtree, ROUTING_LABEL_OFFSET, ITU_ROUTING_LABEL_LENGTH, dpc);
546
320
      }
547
548
549
739
      label_opc_item = proto_tree_add_uint(label_tree, hf_mtp3_itu_opc, tvb, ROUTING_LABEL_OFFSET, ITU_ROUTING_LABEL_LENGTH, label);
550
739
      if (mtp3_pc_structured())
551
0
        proto_item_append_text(label_opc_item, " (%s)", mtp3_pc_to_str(pinfo->pool, opc));
552
553
739
      if(mtp3_addr_opc->ni == MTP3_NI_INT0) {
554
320
        pc_subtree = proto_item_add_subtree(label_opc_item, ett_mtp3_label_opc);
555
320
        analyze_q708_ispc(tvb, pc_subtree, ROUTING_LABEL_OFFSET, ITU_ROUTING_LABEL_LENGTH, opc);
556
320
      }
557
558
739
      proto_tree_add_uint(label_tree, hf_mtp3_itu_sls, tvb, ROUTING_LABEL_OFFSET, ITU_ROUTING_LABEL_LENGTH, label);
559
739
      break;
560
561
0
    case ANSI_STANDARD:
562
0
    case CHINESE_ITU_STANDARD:
563
0
      if (mtp3_standard == ANSI_STANDARD)
564
0
      {
565
0
        hf_dpc_string = hf_mtp3_ansi_dpc;
566
0
        hf_opc_string = hf_mtp3_ansi_opc;
567
0
      } else /* CHINESE_ITU_STANDARD */ {
568
0
        hf_dpc_string = hf_mtp3_chinese_dpc;
569
0
        hf_opc_string = hf_mtp3_chinese_opc;
570
0
      }
571
572
      /* Create the Routing Label Tree */
573
0
      label_tree = proto_tree_add_subtree(mtp3_tree, tvb, ROUTING_LABEL_OFFSET, ANSI_ROUTING_LABEL_LENGTH, ett_mtp3_label, NULL, "Routing label");
574
575
      /* create and fill the DPC tree */
576
0
      dissect_mtp3_3byte_pc(tvb, pinfo, ANSI_DPC_OFFSET, label_tree, ett_mtp3_label_dpc, hf_dpc_string, hf_mtp3_dpc_network,
577
0
                            hf_mtp3_dpc_cluster, hf_mtp3_dpc_member, hf_mtp3_24bit_dpc, hf_mtp3_24bit_pc);
578
      /* Store dpc for mtp3_addr below */
579
0
      dpc = tvb_get_letoh24(tvb, ANSI_DPC_OFFSET);
580
581
      /* create and fill the OPC tree */
582
0
      dissect_mtp3_3byte_pc(tvb, pinfo, ANSI_OPC_OFFSET, label_tree, ett_mtp3_label_opc, hf_opc_string, hf_mtp3_opc_network,
583
0
                            hf_mtp3_opc_cluster, hf_mtp3_opc_member, hf_mtp3_24bit_opc, hf_mtp3_24bit_pc);
584
      /* Store opc for mtp3_addr below */
585
0
      opc = tvb_get_letoh24(tvb, ANSI_OPC_OFFSET);
586
587
      /* SLS */
588
0
      if (mtp3_standard == ANSI_STANDARD) {
589
0
        if (mtp3_use_ansi_5_bit_sls)
590
0
          proto_tree_add_item(label_tree, hf_mtp3_ansi_5_bit_sls, tvb, ANSI_SLS_OFFSET, SLS_LENGTH, ENC_LITTLE_ENDIAN);
591
0
        else
592
0
          proto_tree_add_item(label_tree, hf_mtp3_ansi_8_bit_sls, tvb, ANSI_SLS_OFFSET, SLS_LENGTH, ENC_LITTLE_ENDIAN);
593
0
      } else /* CHINESE_ITU_STANDARD */ {
594
0
        proto_tree_add_item(label_tree, hf_mtp3_chinese_itu_sls, tvb, ANSI_SLS_OFFSET, SLS_LENGTH, ENC_LITTLE_ENDIAN);
595
0
      }
596
0
      break;
597
598
0
    case JAPAN_STANDARD:
599
0
      label_tree = proto_tree_add_subtree(mtp3_tree, tvb, ROUTING_LABEL_OFFSET, JAPAN_ROUTING_LABEL_LENGTH, ett_mtp3_label, NULL, "Routing label");
600
601
0
      label_dpc_item = proto_tree_add_item(label_tree, hf_mtp3_japan_dpc, tvb, ROUTING_LABEL_OFFSET, JAPAN_PC_LENGTH, ENC_LITTLE_ENDIAN);
602
0
      dpc = tvb_get_letohs(tvb, ROUTING_LABEL_OFFSET);
603
0
      if (mtp3_pc_structured()) {
604
0
        proto_item_append_text(label_dpc_item, " (%s)", mtp3_pc_to_str(pinfo->pool, dpc));
605
0
      }
606
607
0
      label_opc_item = proto_tree_add_item(label_tree, hf_mtp3_japan_opc, tvb, JAPAN_OPC_OFFSET, JAPAN_PC_LENGTH, ENC_LITTLE_ENDIAN);
608
0
      opc = tvb_get_letohs(tvb, JAPAN_OPC_OFFSET);
609
0
      if (mtp3_pc_structured()) {
610
0
        proto_item_append_text(label_opc_item, " (%s)", mtp3_pc_to_str(pinfo->pool, opc));
611
0
      }
612
613
0
      hidden_item = proto_tree_add_item(label_tree, hf_mtp3_japan_pc, tvb, ROUTING_LABEL_OFFSET, JAPAN_PC_LENGTH, ENC_LITTLE_ENDIAN);
614
0
      proto_item_set_hidden(hidden_item);
615
0
      hidden_item = proto_tree_add_item(label_tree, hf_mtp3_japan_pc, tvb, JAPAN_OPC_OFFSET, JAPAN_PC_LENGTH, ENC_LITTLE_ENDIAN);
616
0
      proto_item_set_hidden(hidden_item);
617
618
0
      if (mtp3_use_japan_5_bit_sls) {
619
0
        proto_tree_add_item(label_tree, hf_mtp3_japan_5_bit_sls, tvb, JAPAN_SLS_OFFSET, JAPAN_SLS_SPARE_LENGTH, ENC_LITTLE_ENDIAN);
620
0
        proto_tree_add_item(label_tree, hf_mtp3_japan_5_bit_sls_spare, tvb, JAPAN_SLS_OFFSET, JAPAN_SLS_SPARE_LENGTH, ENC_LITTLE_ENDIAN);
621
0
      } else {
622
0
        proto_tree_add_item(label_tree, hf_mtp3_japan_4_bit_sls, tvb, JAPAN_SLS_OFFSET, JAPAN_SLS_SPARE_LENGTH, ENC_LITTLE_ENDIAN);
623
0
        proto_tree_add_item(label_tree, hf_mtp3_japan_4_bit_sls_spare, tvb, JAPAN_SLS_OFFSET, JAPAN_SLS_SPARE_LENGTH, ENC_LITTLE_ENDIAN);
624
0
      }
625
626
0
      break;
627
0
    default:
628
0
      DISSECTOR_ASSERT_NOT_REACHED();
629
739
  }
630
631
739
  mtp3_addr_opc->type = (Standard_Type)mtp3_standard;
632
739
  mtp3_addr_opc->pc = opc;
633
739
  set_address(&pinfo->src, mtp3_address_type, mtp3_addr_len(), (uint8_t *) mtp3_addr_opc);
634
635
739
  mtp3_addr_dpc->type = (Standard_Type)mtp3_standard;
636
739
  mtp3_addr_dpc->pc = dpc;
637
739
  set_address(&pinfo->dst, mtp3_address_type, mtp3_addr_len(), (uint8_t *) mtp3_addr_dpc);
638
739
}
639
640
static void
641
dissect_mtp3_payload(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
642
739
{
643
739
  uint8_t sio;
644
739
  uint8_t service_indicator;
645
739
  tvbuff_t *payload_tvb = NULL;
646
647
739
  sio               = tvb_get_uint8(tvb, SIO_OFFSET);
648
739
  service_indicator = sio & SERVICE_INDICATOR_MASK;
649
650
739
  switch (mtp3_standard) {
651
739
    case ITU_STANDARD:
652
739
      payload_tvb = tvb_new_subset_remaining(tvb, ITU_MTP_PAYLOAD_OFFSET);
653
739
      break;
654
0
    case ANSI_STANDARD:
655
0
    case CHINESE_ITU_STANDARD:
656
0
      payload_tvb = tvb_new_subset_remaining(tvb, ANSI_MTP_PAYLOAD_OFFSET);
657
0
      break;
658
0
    case JAPAN_STANDARD:
659
0
      payload_tvb = tvb_new_subset_remaining(tvb, JAPAN_MTP_PAYLOAD_OFFSET);
660
0
      break;
661
0
    default:
662
0
      DISSECTOR_ASSERT_NOT_REACHED();
663
739
  }
664
665
739
  col_set_str(pinfo->cinfo, COL_INFO, "DATA ");
666
667
739
  if (!dissector_try_uint(mtp3_sio_dissector_table, service_indicator, payload_tvb, pinfo, tree))
668
3
    call_data_dissector(payload_tvb, pinfo, tree);
669
739
}
670
671
static unsigned
672
heur_mtp3_standard(tvbuff_t *tvb, packet_info *pinfo, uint8_t si)
673
0
{
674
0
  tvbuff_t *payload;
675
676
0
  switch (si) {
677
0
    case MTP_SI_SCCP:
678
0
    {
679
0
      payload = tvb_new_subset_remaining(tvb, ITU_HEADER_LENGTH);
680
0
      if (looks_like_valid_sccp(pinfo->num, payload, ITU_STANDARD)) {
681
0
        return ITU_STANDARD;
682
0
      }
683
0
      payload = tvb_new_subset_remaining(tvb, ANSI_HEADER_LENGTH);
684
0
      if (looks_like_valid_sccp(pinfo->num, payload, ANSI_STANDARD)) {
685
0
        return ANSI_STANDARD;
686
0
      }
687
0
      payload = tvb_new_subset_remaining(tvb, ANSI_HEADER_LENGTH);
688
0
      if (looks_like_valid_sccp(pinfo->num, payload, CHINESE_ITU_STANDARD)) {
689
0
        return CHINESE_ITU_STANDARD;
690
0
      }
691
0
      payload = tvb_new_subset_remaining(tvb, JAPAN_HEADER_LENGTH);
692
0
      if (looks_like_valid_sccp(pinfo->num, payload, JAPAN_STANDARD)) {
693
0
        return JAPAN_STANDARD;
694
0
      }
695
696
0
      return HEURISTIC_FAILED_STANDARD;
697
698
0
    }
699
0
    default:
700
0
      return HEURISTIC_FAILED_STANDARD;
701
0
  }
702
703
0
}
704
705
static void
706
reset_mtp3_standard(void)
707
0
{
708
0
    mtp3_standard = pref_mtp3_standard;
709
0
}
710
711
/* Code to actually dissect the packets */
712
static int
713
dissect_mtp3(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
714
739
{
715
739
  mtp3_tap_rec_t* tap_rec = wmem_new0(pinfo->pool, mtp3_tap_rec_t);
716
739
  int heuristic_standard;
717
739
  uint8_t si;
718
739
  mtp3_addr_pc_t* mtp3_addr_dpc;
719
739
  mtp3_addr_pc_t* mtp3_addr_opc;
720
721
  /* Set up structures needed to add the protocol subtree and manage it */
722
739
  proto_item *mtp3_item = NULL, *gen_item;
723
739
  proto_tree *mtp3_tree;
724
725
739
  pref_mtp3_standard = mtp3_standard;
726
727
739
  mtp3_item = proto_tree_add_item(tree, proto_mtp3, tvb, 0, -1, ENC_NA);
728
729
739
  si = tvb_get_uint8(tvb, SIO_OFFSET) & SERVICE_INDICATOR_MASK;
730
739
  if (mtp3_heuristic_standard) {
731
0
    heuristic_standard = heur_mtp3_standard(tvb, pinfo, si);
732
0
    if (heuristic_standard == HEURISTIC_FAILED_STANDARD) {
733
0
      gen_item = proto_tree_add_uint_format(tree, hf_mtp3_heuristic_standard, tvb, 0, 0, mtp3_standard,
734
0
                                            "Could not determine Heuristic using %s", val_to_str_const(mtp3_standard, mtp3_standard_vals, "unknown"));
735
0
    } else {
736
0
      gen_item = proto_tree_add_uint_format(tree, hf_mtp3_heuristic_standard, tvb, 0, 0, heuristic_standard,
737
0
                                            "%s", val_to_str_const(heuristic_standard, mtp3_standard_vals, "unknown"));
738
0
      mtp3_standard = heuristic_standard;
739
740
      /* Register a frame-end routine to ensure mtp3_standard is set
741
       * back even if an exception is thrown.
742
       */
743
0
      register_frame_end_routine(pinfo, reset_mtp3_standard);
744
0
    }
745
0
    proto_item_set_generated(gen_item);
746
0
  }
747
748
  /* Make entries in Protocol column on summary display */
749
739
  switch(mtp3_standard) {
750
739
    case ITU_STANDARD:
751
739
      col_set_str(pinfo->cinfo, COL_PROTOCOL, "MTP3 (Int. ITU)");
752
739
      proto_item_set_len(mtp3_item, ITU_HEADER_LENGTH);
753
739
      break;
754
0
    case ANSI_STANDARD:
755
0
      col_set_str(pinfo->cinfo, COL_PROTOCOL, "MTP3 (ANSI)");
756
0
      proto_item_set_len(mtp3_item, ANSI_HEADER_LENGTH);
757
0
      break;
758
0
    case CHINESE_ITU_STANDARD:
759
0
      col_set_str(pinfo->cinfo, COL_PROTOCOL, "MTP3 (Chin. ITU)");
760
0
      proto_item_set_len(mtp3_item, ANSI_HEADER_LENGTH);
761
0
      break;
762
0
    case JAPAN_STANDARD:
763
0
      col_set_str(pinfo->cinfo, COL_PROTOCOL, "MTP3 (Japan)");
764
0
      proto_item_set_len(mtp3_item, JAPAN_HEADER_LENGTH);
765
0
      break;
766
739
  };
767
768
  /* create display subtree for the protocol */
769
739
  mtp3_tree = proto_item_add_subtree(mtp3_item, ett_mtp3);
770
771
739
  mtp3_addr_opc = wmem_new0(pinfo->pool, mtp3_addr_pc_t);
772
739
  mtp3_addr_dpc = wmem_new0(pinfo->pool, mtp3_addr_pc_t);
773
774
  /* Dissect the packet (even if !tree so can call sub-dissectors and update
775
   * the source and destination address columns) */
776
739
  dissect_mtp3_sio(tvb, mtp3_tree, mtp3_addr_opc, mtp3_addr_dpc);
777
739
  dissect_mtp3_routing_label(tvb, pinfo, mtp3_tree, mtp3_addr_opc, mtp3_addr_dpc);
778
779
739
  memcpy(&(tap_rec->addr_opc), mtp3_addr_opc, sizeof(mtp3_addr_pc_t));
780
739
  memcpy(&(tap_rec->addr_dpc), mtp3_addr_dpc, sizeof(mtp3_addr_pc_t));
781
782
739
  tap_rec->mtp3_si_code = (tvb_get_uint8(tvb, SIO_OFFSET) & SERVICE_INDICATOR_MASK);
783
739
  tap_rec->size = tvb_reported_length(tvb);
784
785
739
  tap_queue_packet(mtp3_tap, pinfo, tap_rec);
786
787
739
  dissect_mtp3_payload(tvb, pinfo, tree);
788
789
739
  mtp3_standard = pref_mtp3_standard;
790
739
  return tvb_captured_length(tvb);
791
739
}
792
793
/* TAP STAT INFO */
794
795
typedef enum
796
{
797
  OPC_COLUMN,
798
  DPC_COLUMN,
799
  SI_COLUMN,
800
  NUM_MSUS_COLUMN,
801
  NUM_BYTES_COLUMN,
802
  AVG_BYTES_COLUMN
803
} mtp3_stat_columns;
804
805
static stat_tap_table_item mtp3_stat_fields[] = {
806
  {TABLE_ITEM_STRING, TAP_ALIGN_LEFT, "OPC", "%-25s"},
807
  {TABLE_ITEM_STRING, TAP_ALIGN_LEFT, "DPC", "%-25s"},
808
  {TABLE_ITEM_STRING, TAP_ALIGN_LEFT, "SI", "%-25s"},
809
  {TABLE_ITEM_UINT, TAP_ALIGN_RIGHT, "MSUs", "%d"},
810
  {TABLE_ITEM_UINT, TAP_ALIGN_RIGHT, "Bytes", "%d"},
811
  {TABLE_ITEM_FLOAT, TAP_ALIGN_RIGHT, "Avg Bytes", "%f"},
812
};
813
814
static void mtp3_stat_init(stat_tap_table_ui* new_stat)
815
0
{
816
0
  const char *table_name = "MTP3 Statistics";
817
0
  int num_fields = array_length(mtp3_stat_fields);
818
0
  stat_tap_table *table;
819
820
0
  table = stat_tap_find_table(new_stat, table_name);
821
0
  if (table) {
822
0
    if (new_stat->stat_tap_reset_table_cb) {
823
0
      new_stat->stat_tap_reset_table_cb(table);
824
0
    }
825
0
    return;
826
0
  }
827
828
0
  table = stat_tap_init_table(table_name, num_fields, 0, NULL);
829
0
  stat_tap_add_table(new_stat, table);
830
0
}
831
832
static tap_packet_status
833
mtp3_stat_packet(void *tapdata, packet_info *pinfo, epan_dissect_t *edt _U_, const void *m3tr_ptr, tap_flags_t flags _U_)
834
0
{
835
0
  stat_data_t* stat_data = (stat_data_t*)tapdata;
836
0
  const mtp3_tap_rec_t  *m3tr = (const mtp3_tap_rec_t *)m3tr_ptr;
837
0
  bool found = false;
838
0
  unsigned element;
839
0
  stat_tap_table* table;
840
0
  stat_tap_table_item_type* item_data;
841
0
  unsigned msu_count;
842
0
  unsigned byte_count;
843
0
  double avg_bytes = 0.0;
844
845
0
  if (m3tr->mtp3_si_code >= MTP3_NUM_SI_CODE)
846
0
  {
847
    /*
848
     * we thought this si_code was not used ?
849
     * is MTP3_NUM_SI_CODE out of date ?
850
     */
851
0
    return TAP_PACKET_DONT_REDRAW;
852
0
  }
853
854
  /*
855
   * look for opc/dpc pair
856
   */
857
0
  table = g_array_index(stat_data->stat_tap_data->tables, stat_tap_table*, 0);
858
0
  for (element = 0; element < table->num_elements; element++)
859
0
  {
860
0
    stat_tap_table_item_type *opc_data, *dpc_data, *si_data;
861
0
    opc_data = stat_tap_get_field_data(table, element, OPC_COLUMN);
862
0
    dpc_data = stat_tap_get_field_data(table, element, DPC_COLUMN);
863
0
    si_data = stat_tap_get_field_data(table, element, SI_COLUMN);
864
865
0
    if (memcmp(&m3tr->addr_opc, opc_data->user_data.ptr_value, sizeof(mtp3_addr_pc_t)) == 0)
866
0
    {
867
0
      if (memcmp(&m3tr->addr_dpc, dpc_data->user_data.ptr_value, sizeof(mtp3_addr_pc_t)) == 0)
868
0
      {
869
0
        if (m3tr->mtp3_si_code == si_data->user_data.uint_value)
870
0
        {
871
0
          found = true;
872
0
          break;
873
0
        }
874
0
      }
875
0
    }
876
0
  }
877
878
0
  if (!found) {
879
    /* Add a new row */
880
    /* XXX The old version added a row per SI. */
881
0
    int num_fields = array_length(mtp3_stat_fields);
882
0
    stat_tap_table_item_type items[array_length(mtp3_stat_fields)];
883
0
    const char *sis;
884
0
    char *col_str;
885
886
0
    memset(items, 0, sizeof(items));
887
888
0
    items[OPC_COLUMN].type = TABLE_ITEM_STRING;
889
0
    items[DPC_COLUMN].type = TABLE_ITEM_STRING;
890
0
    items[SI_COLUMN].type = TABLE_ITEM_STRING;
891
0
    items[NUM_MSUS_COLUMN].type = TABLE_ITEM_UINT;
892
0
    items[NUM_BYTES_COLUMN].type = TABLE_ITEM_UINT;
893
0
    items[AVG_BYTES_COLUMN].type = TABLE_ITEM_FLOAT;
894
895
0
    stat_tap_init_table_row(table, element, num_fields, items);
896
897
0
    item_data = stat_tap_get_field_data(table, element, OPC_COLUMN);
898
0
    item_data->value.string_value = g_strdup(mtp3_addr_to_str_wmem(pinfo->pool, &m3tr->addr_opc));
899
0
    item_data->user_data.ptr_value = g_memdup2(&m3tr->addr_opc, sizeof(mtp3_tap_rec_t));
900
0
    stat_tap_set_field_data(table, element, OPC_COLUMN, item_data);
901
902
0
    item_data = stat_tap_get_field_data(table, element, DPC_COLUMN);
903
0
    item_data->value.string_value = g_strdup(mtp3_addr_to_str_wmem(pinfo->pool, &m3tr->addr_dpc));
904
0
    item_data->user_data.ptr_value = g_memdup2(&m3tr->addr_dpc, sizeof(mtp3_tap_rec_t));
905
0
    stat_tap_set_field_data(table, element, DPC_COLUMN, item_data);
906
907
0
    sis = try_val_to_str(m3tr->mtp3_si_code, mtp3_service_indicator_code_short_vals);
908
0
    if (sis) {
909
0
      col_str = g_strdup(sis);
910
0
    } else {
911
0
      col_str = ws_strdup_printf("Unknown service indicator %d", m3tr->mtp3_si_code);
912
0
    }
913
914
0
    item_data = stat_tap_get_field_data(table, element, SI_COLUMN);
915
0
    item_data->value.string_value = col_str;
916
0
    item_data->user_data.uint_value = m3tr->mtp3_si_code;
917
0
    stat_tap_set_field_data(table, element, SI_COLUMN, item_data);
918
0
  }
919
920
0
  item_data = stat_tap_get_field_data(table, element, NUM_MSUS_COLUMN);
921
0
  item_data->value.uint_value++;
922
0
  msu_count = item_data->value.uint_value;
923
0
  stat_tap_set_field_data(table, element, NUM_MSUS_COLUMN, item_data);
924
925
0
  item_data = stat_tap_get_field_data(table, element, NUM_BYTES_COLUMN);
926
0
  item_data->value.uint_value += m3tr->size;
927
0
  byte_count = item_data->value.uint_value;
928
0
  stat_tap_set_field_data(table, element, NUM_BYTES_COLUMN, item_data);
929
930
0
  if (msu_count > 0) {
931
0
    avg_bytes = (double) byte_count / msu_count;
932
0
  }
933
0
  item_data = stat_tap_get_field_data(table, element, AVG_BYTES_COLUMN);
934
0
  item_data->value.float_value = avg_bytes;
935
0
  stat_tap_set_field_data(table, element, AVG_BYTES_COLUMN, item_data);
936
937
0
  return TAP_PACKET_REDRAW;
938
0
}
939
940
static void
941
mtp3_stat_reset(stat_tap_table* table)
942
0
{
943
0
  unsigned element;
944
0
  stat_tap_table_item_type* item_data;
945
946
0
  for (element = 0; element < table->num_elements; element++)
947
0
  {
948
0
    item_data = stat_tap_get_field_data(table, element, NUM_MSUS_COLUMN);
949
0
    item_data->value.uint_value = 0;
950
0
    stat_tap_set_field_data(table, element, NUM_MSUS_COLUMN, item_data);
951
952
0
    item_data = stat_tap_get_field_data(table, element, NUM_BYTES_COLUMN);
953
0
    item_data->value.uint_value = 0;
954
0
    stat_tap_set_field_data(table, element, NUM_BYTES_COLUMN, item_data);
955
0
  }
956
0
}
957
958
static void
959
mtp3_stat_free_table_item(stat_tap_table* table _U_, unsigned row _U_, unsigned column, stat_tap_table_item_type* field_data)
960
0
{
961
0
  switch(column) {
962
0
    case OPC_COLUMN:
963
0
    case DPC_COLUMN:
964
0
      g_free((char*)field_data->user_data.ptr_value);
965
      /* Fall through */
966
0
    case SI_COLUMN:
967
0
      g_free((char*)field_data->value.string_value);
968
0
      break;
969
0
    default:
970
0
      break;
971
0
  }
972
0
}
973
974
975
void
976
proto_register_mtp3(void)
977
14
{
978
979
  /* Setup list of header fields  See Section 1.6.1 for details*/
980
14
  static hf_register_info hf[] = {
981
14
    { &hf_mtp3_service_indicator,     { "Service indicator",        "mtp3.service_indicator", FT_UINT8,  BASE_HEX,  VALS(mtp3_service_indicator_code_vals), SERVICE_INDICATOR_MASK,     NULL, HFILL }},
982
14
    { &hf_mtp3_network_indicator,     { "Network indicator",        "mtp3.network_indicator", FT_UINT8,  BASE_HEX,  VALS(mtp3_network_indicator_vals),      NETWORK_INDICATOR_MASK,     NULL, HFILL }},
983
14
    { &hf_mtp3_itu_spare,             { "Spare",                    "mtp3.spare",             FT_UINT8,  BASE_HEX,  NULL,                                   SPARE_MASK,                 NULL, HFILL }},
984
14
    { &hf_mtp3_itu_priority,          { "ITU priority",             "mtp3.priority",          FT_UINT8,  BASE_DEC,  NULL,                                   SPARE_MASK,                 NULL, HFILL }},
985
14
    { &hf_mtp3_ansi_priority,         { "ANSI Priority",            "mtp3.priority",          FT_UINT8,  BASE_DEC,  NULL,                                   ANSI_PRIORITY_MASK,         NULL, HFILL }},
986
14
    { &hf_mtp3_itu_opc,               { "OPC",                      "mtp3.opc",               FT_UINT32, BASE_DEC,  NULL,                                   ITU_OPC_MASK,               NULL, HFILL }},
987
14
    { &hf_mtp3_itu_pc,                { "PC",                       "mtp3.pc",                FT_UINT32, BASE_DEC,  NULL,                                   0x0,                        NULL, HFILL }},
988
14
    { &hf_mtp3_24bit_pc,              { "PC",                       "mtp3.pc",                FT_UINT32, BASE_DEC,  NULL,                                   ANSI_PC_MASK,               NULL, HFILL }},
989
14
    { &hf_mtp3_24bit_opc,             { "OPC",                      "mtp3.opc",               FT_UINT32, BASE_DEC,  NULL,                                   ANSI_PC_MASK,               NULL, HFILL }},
990
14
    { &hf_mtp3_ansi_opc,              { "OPC",                      "mtp3.ansi_opc",          FT_STRING, BASE_NONE, NULL,                                   0x0,                        NULL, HFILL }},
991
14
    { &hf_mtp3_chinese_opc,           { "OPC",                      "mtp3.chinese_opc",       FT_STRING, BASE_NONE, NULL,                                   0x0,                        NULL, HFILL }},
992
14
    { &hf_mtp3_opc_network,           { "OPC Network",              "mtp3.opc.network",       FT_UINT24, BASE_DEC,  NULL,                                   ANSI_NETWORK_MASK,          NULL, HFILL }},
993
14
    { &hf_mtp3_opc_cluster,           { "OPC Cluster",              "mtp3.opc.cluster",       FT_UINT24, BASE_DEC,  NULL,                                   ANSI_CLUSTER_MASK,          NULL, HFILL }},
994
14
    { &hf_mtp3_opc_member,            { "OPC Member",               "mtp3.opc.member",        FT_UINT24, BASE_DEC,  NULL,                                   ANSI_MEMBER_MASK,           NULL, HFILL }},
995
14
    { &hf_mtp3_japan_opc,             { "OPC",                      "mtp3.opc",               FT_UINT16, BASE_DEC,  NULL,                                   JAPAN_PC_MASK,              NULL, HFILL }},
996
14
    { &hf_mtp3_japan_pc,              { "PC",                       "mtp3.pc",                FT_UINT16, BASE_DEC,  NULL,                                   JAPAN_PC_MASK,              NULL, HFILL }},
997
14
    { &hf_mtp3_itu_dpc,               { "DPC",                      "mtp3.dpc",               FT_UINT32, BASE_DEC,  NULL,                                   ITU_DPC_MASK,               NULL, HFILL }},
998
14
    { &hf_mtp3_24bit_dpc,             { "DPC",                      "mtp3.dpc",               FT_UINT32, BASE_DEC,  NULL,                                   ANSI_PC_MASK,               NULL, HFILL }},
999
14
    { &hf_mtp3_ansi_dpc,              { "DPC",                      "mtp3.ansi_dpc",          FT_STRING, BASE_NONE, NULL,                                   0x0,                        NULL, HFILL }},
1000
14
    { &hf_mtp3_chinese_dpc,           { "DPC",                      "mtp3.chinese_dpc",       FT_STRING, BASE_NONE, NULL,                                   0x0,                        NULL, HFILL }},
1001
14
    { &hf_mtp3_dpc_network,           { "DPC Network",              "mtp3.dpc.network",       FT_UINT24, BASE_DEC,  NULL,                                   ANSI_NETWORK_MASK,          NULL, HFILL }},
1002
14
    { &hf_mtp3_dpc_cluster,           { "DPC Cluster",              "mtp3.dpc.cluster",       FT_UINT24, BASE_DEC,  NULL,                                   ANSI_CLUSTER_MASK,          NULL, HFILL }},
1003
14
    { &hf_mtp3_dpc_member,            { "DPC Member",               "mtp3.dpc.member",        FT_UINT24, BASE_DEC,  NULL,                                   ANSI_MEMBER_MASK,           NULL, HFILL }},
1004
14
    { &hf_mtp3_japan_dpc,             { "DPC",                      "mtp3.dpc",               FT_UINT16, BASE_DEC,  NULL,                                   JAPAN_PC_MASK,              NULL, HFILL }},
1005
14
    { &hf_mtp3_itu_sls,               { "Signalling Link Selector", "mtp3.sls",               FT_UINT32, BASE_DEC,  NULL,                                   ITU_SLS_MASK,               NULL, HFILL }},
1006
14
    { &hf_mtp3_japan_4_bit_sls,       { "Signalling Link Selector", "mtp3.sls",               FT_UINT8,  BASE_DEC,  NULL,                                   JAPAN_4_BIT_SLS_MASK,       NULL, HFILL }},
1007
14
    { &hf_mtp3_japan_4_bit_sls_spare, { "SLS Spare",                "mtp3.sls_spare",         FT_UINT8,  BASE_HEX,  NULL,                                   JAPAN_4_BIT_SLS_SPARE_MASK, NULL, HFILL }},
1008
14
    { &hf_mtp3_japan_5_bit_sls,       { "Signalling Link Selector", "mtp3.sls",               FT_UINT8,  BASE_DEC,  NULL,                                   JAPAN_5_BIT_SLS_MASK,       NULL, HFILL }},
1009
14
    { &hf_mtp3_japan_5_bit_sls_spare, { "SLS Spare",                "mtp3.sls_spare",         FT_UINT8,  BASE_HEX,  NULL,                                   JAPAN_5_BIT_SLS_SPARE_MASK, NULL, HFILL }},
1010
14
    { &hf_mtp3_ansi_5_bit_sls,        { "Signalling Link Selector", "mtp3.sls",               FT_UINT8,  BASE_DEC,  NULL,                                   ANSI_5BIT_SLS_MASK,         NULL, HFILL }},
1011
14
    { &hf_mtp3_ansi_8_bit_sls,        { "Signalling Link Selector", "mtp3.sls",               FT_UINT8,  BASE_DEC,  NULL,                                   ANSI_8BIT_SLS_MASK,         NULL, HFILL }},
1012
14
    { &hf_mtp3_chinese_itu_sls,       { "Signalling Link Selector", "mtp3.sls",               FT_UINT8,  BASE_DEC,  NULL,                                   CHINESE_ITU_SLS_MASK,       NULL, HFILL }},
1013
14
    { &hf_mtp3_heuristic_standard,    { "Heuristic standard",       "mtp3.heuristic_standard",FT_UINT32, BASE_DEC,  NULL,                                   0x0,                        NULL, HFILL }},
1014
14
  };
1015
1016
  /* Setup protocol subtree array */
1017
14
  static int *ett[] = {
1018
14
    &ett_mtp3,
1019
14
    &ett_mtp3_sio,
1020
14
    &ett_mtp3_label,
1021
14
    &ett_mtp3_label_dpc,
1022
14
    &ett_mtp3_label_opc
1023
14
  };
1024
1025
14
  static const enum_val_t mtp3_options[] = {
1026
14
    { "itu",          "ITU",          ITU_STANDARD },
1027
14
    { "ansi",         "ANSI",         ANSI_STANDARD },
1028
14
    { "chinese-itu",  "Chinese ITU",  CHINESE_ITU_STANDARD },
1029
14
    { "japan",        "Japan",        JAPAN_STANDARD },
1030
14
    { NULL,   NULL,   0 }
1031
14
  };
1032
1033
14
  static const enum_val_t mtp3_addr_fmt_str_e[] = {
1034
14
    { "decimal",        "Decimal",        MTP3_ADDR_FMT_DEC },
1035
14
    { "hexadecimal",    "Hexadecimal",    MTP3_ADDR_FMT_HEX },
1036
14
    { "ni-decimal",     "NI-Decimal",     MTP3_ADDR_FMT_NI_DEC },
1037
14
    { "ni-hexadecimal", "NI-Hexadecimal", MTP3_ADDR_FMT_NI_HEX },
1038
14
    { "dashed",         "Dashed",         MTP3_ADDR_FMT_DASHED },
1039
14
    { NULL,   NULL,     0 }
1040
14
  };
1041
1042
14
  static const enum_val_t itu_pc_structures[] = {
1043
14
    { "unstructured", "Unstructured", ITU_PC_STRUCTURE_NONE},
1044
14
    { "3-8-3",        "3-8-3",        ITU_PC_STRUCTURE_3_8_3 },
1045
14
    { "4-3-4-3",      "4-3-4-3",      ITU_PC_STRUCTURE_4_3_4_3 },
1046
14
    { NULL,   NULL,   0 }
1047
14
  };
1048
1049
14
  static const enum_val_t japan_pc_structures[] = {
1050
14
    { "unstructured", "Unstructured", JAPAN_PC_STRUCTURE_NONE},
1051
14
    { "7-4-5",        "7-4-5",        JAPAN_PC_STRUCTURE_7_4_5 },
1052
14
    { "3-4-4-5",      "3-4-4-5",      JAPAN_PC_STRUCTURE_3_4_4_5 },
1053
14
    { NULL,   NULL,   0 }
1054
14
  };
1055
1056
14
  static tap_param mtp3_stat_params[] = {
1057
14
    { PARAM_FILTER, "filter", "Filter", NULL, true }
1058
14
  };
1059
1060
14
  static stat_tap_table_ui mtp3_stat_table = {
1061
14
    REGISTER_TELEPHONY_GROUP_MTP3,
1062
14
    "MTP3 Statistics",
1063
14
    "mtp3",
1064
14
    "mtp3,msus",
1065
14
    mtp3_stat_init,
1066
14
    mtp3_stat_packet,
1067
14
    mtp3_stat_reset,
1068
14
    mtp3_stat_free_table_item,
1069
14
    NULL,
1070
14
    array_length(mtp3_stat_fields), mtp3_stat_fields,
1071
14
    array_length(mtp3_stat_params), mtp3_stat_params,
1072
14
    NULL,
1073
14
    0
1074
14
  };
1075
1076
 /* Register the protocol name and description */
1077
14
  proto_mtp3 = proto_register_protocol("Message Transfer Part Level 3",
1078
14
               "MTP3", "mtp3");
1079
14
  mtp3_handle = register_dissector("mtp3", dissect_mtp3, proto_mtp3);
1080
1081
  /* Required function calls to register the header fields and subtrees used */
1082
14
  proto_register_field_array(proto_mtp3, hf, array_length(hf));
1083
14
  proto_register_subtree_array(ett, array_length(ett));
1084
1085
14
  mtp3_sio_dissector_table = register_dissector_table("mtp3.service_indicator",
1086
14
                  "MTP3 Service indicator",
1087
14
                  proto_mtp3, FT_UINT8, BASE_HEX);
1088
1089
14
  mtp3_address_type = address_type_dissector_register("AT_SS7PC", "SS7 Point Code", mtp3_addr_to_str, mtp3_str_addr_len, NULL, mtp3_addr_col_filter_str,
1090
14
                                                            mtp3_addr_len, mtp3_addr_name_res_str, mtp3_addr_name_res_len);
1091
1092
1093
14
  mtp3_tap = register_tap("mtp3");
1094
1095
14
  mtp3_module = prefs_register_protocol(proto_mtp3, NULL);
1096
1097
14
  prefs_register_bool_preference(mtp3_module, "heuristic_standard",
1098
14
         "Try to determine the MTP3 standard heuristically",
1099
14
         "This only works for SCCP traffic for now",
1100
14
         &mtp3_heuristic_standard);
1101
1102
14
  prefs_register_enum_preference(mtp3_module, "standard", "MTP3 standard",
1103
14
         "The SS7 standard used in MTP3 packets",
1104
14
         &mtp3_standard, mtp3_options, false);
1105
1106
14
  prefs_register_enum_preference(mtp3_module, "itu_pc_structure", "ITU Pointcode structure",
1107
14
         "The structure of the pointcodes in ITU networks",
1108
14
         &itu_pc_structure, itu_pc_structures, false);
1109
1110
14
  prefs_register_enum_preference(mtp3_module, "japan_pc_structure", "Japan Pointcode structure",
1111
14
         "The structure of the pointcodes in Japan networks",
1112
14
         &japan_pc_structure, japan_pc_structures, false);
1113
1114
14
  prefs_register_bool_preference(mtp3_module, "ansi_5_bit_sls",
1115
14
         "Use 5-bit SLS (ANSI only)",
1116
14
         "Use 5-bit (instead of 8-bit) SLS in ANSI MTP3 packets",
1117
14
         &mtp3_use_ansi_5_bit_sls);
1118
1119
14
  prefs_register_bool_preference(mtp3_module, "japan_5_bit_sls",
1120
14
         "Use 5-bit SLS (Japan only)",
1121
14
         "Use 5-bit (instead of 4-bit) SLS in Japan MTP3 packets",
1122
14
         &mtp3_use_japan_5_bit_sls);
1123
1124
14
  prefs_register_enum_preference(mtp3_module, "addr_format", "Address Format",
1125
14
         "Format for point code in the address columns",
1126
14
         &mtp3_addr_fmt, mtp3_addr_fmt_str_e, false);
1127
1128
14
  prefs_register_bool_preference(mtp3_module, "itu_priority",
1129
14
         "Show MSU priority (national option, ITU and China ITU only)",
1130
14
         "Decode the spare bits of the SIO as the MSU priority (a national option in ITU)",
1131
14
         &mtp3_show_itu_priority);
1132
1133
14
  register_stat_tap_table_ui(&mtp3_stat_table);
1134
1135
14
  register_external_value_string("mtp3_service_indicator_code_short_vals", mtp3_service_indicator_code_short_vals);
1136
14
}
1137
1138
void
1139
proto_reg_handoff_mtp3(void)
1140
14
{
1141
14
  dissector_add_uint("wtap_encap", WTAP_ENCAP_MTP3, mtp3_handle);
1142
14
  dissector_add_string("tali.opcode", "mtp3", mtp3_handle);
1143
14
}
1144
1145
/*
1146
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
1147
 *
1148
 * Local Variables:
1149
 * c-basic-offset: 2
1150
 * tab-width: 8
1151
 * indent-tabs-mode: nil
1152
 * End:
1153
 *
1154
 * ex: set shiftwidth=2 tabstop=8 expandtab:
1155
 * :indentSize=2:tabSize=8:noTabs=true:
1156
 */