Coverage Report

Created: 2026-11-12 07:01

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wireshark/epan/dissectors/packet-mtp2.c
Line
Count
Source
1
/* packet-mtp2.c
2
 * Routines for MTP2 dissection
3
 * It is hopefully (needs testing) compliant to
4
 * ITU-T Q.703 and Q.703 Annex A.
5
 *
6
 * Copyright 2001, 2004 Michael Tuexen <tuexen [AT] fh-muenster.de>
7
 *
8
 * Wireshark - Network traffic analyzer
9
 * By Gerald Combs <gerald@wireshark.org>
10
 * Copyright 1998 Gerald Combs
11
 *
12
 * Copied from packet-m2pa.c
13
 *
14
 * SPDX-License-Identifier: GPL-2.0-or-later
15
 */
16
17
#include "config.h"
18
0
#define WS_LOG_DOMAIN "packet-mtp2"
19
#include <wireshark.h>
20
21
#include <epan/packet.h>
22
#include <epan/prefs.h>
23
#include <epan/crc16-tvb.h>
24
#include <epan/expert.h>
25
#include <wiretap/wtap.h>
26
#include <epan/conversation.h>
27
#include <epan/proto_data.h>
28
#include <epan/reassemble.h>
29
30
void proto_register_mtp2(void);
31
void proto_reg_handoff_mtp2(void);
32
33
static dissector_handle_t mtp2_handle;
34
static dissector_handle_t mtp2_with_phdr_handle;
35
static dissector_handle_t mtp2_bitstream_handle;
36
static dissector_handle_t mtp3_handle;
37
38
/* possible packet states */
39
enum packet_direction_state_mtp2 {FORWARD, BACKWARD};
40
41
/* structure for telling the bitstream dissector if it shall use a mtp2_flag_search value from the prev. packet */
42
typedef struct mtp2_flag_search {
43
  bool          set;            /* shows if the mtp2_flag_search value is valid, needed to be set in the dissect function */
44
  uint8_t       mtp2_flag_search;    /* mtp2_flag_search value itself */
45
} mtp2_mtp2_flag_search_t;
46
47
/* Possible states of the state machine for decoding the MTP2 bitstream */
48
enum mtp2_bitstream_states {OUT_OF_SYNC, FLAGS, DATA};
49
50
/* data type for chained list of found MTP2 packets in RTP stream */
51
typedef struct mtp2_recognized_packet {
52
  tvbuff_t                *data;              /* data of the actual packet */
53
  uint8_t                 unalignment_offset; /* !=0 signals if this packet was not a multiple of 8 bits in the stream */
54
} mtp2_recognized_packet_t;
55
56
/* structure used in mtp2_dissect_tvb_res
57
   this contains the tvb's before the first and after last header */
58
typedef struct mtp2_remain_data {
59
  tvbuff_t        *before_first_flag;              /* data found before the first flag */
60
  tvbuff_t        *after_last_flag;                /* data found after the last flag */
61
  uint8_t         before_fh_unalignment_offset;    /* !=0 signals if the before_fh data was not a multiple of 8 bits in the stream */
62
  bool            before_fh_frame_reset;           /* signals if there was a frame reset in the data before the 1st flag */
63
} mtp2_remain_data_t;
64
65
66
/* structure to store the result of dissect_mtp2_tvb function */
67
typedef struct mtp2_dissect_tvb_res {
68
  mtp2_remain_data_t              mtp2_remain_data;       /* stores the tvbuffs found before 1st and after last flags in the packet */
69
  mtp2_mtp2_flag_search_t         mtp2_flag_search;       /* this contains the mtp2_flag_search's value at the end of the packet dissection */
70
  wmem_list_t                     *found_packets;         /* contains the packets found in tvbuff */
71
  uint8_t                         data_buff;              /* to store the data_buff value */
72
  uint8_t                         data_buff_offset;       /* to store the data_buff_offset value */
73
  uint8_t                         last_flag_beginning_offset_for_align_check;     /* the offset of the last flag's beginning have to be stored */
74
  bool                            flag_found;             /* boolean value to sign if there was a flag in the RTP packet or not */
75
  enum mtp2_bitstream_states      state;                  /* to store the value of the state of the dissection after finish */
76
} mtp2_dissect_tvb_res_t;
77
78
/* mtp2 per-packet data */
79
typedef struct mtp2_ppd {
80
  mtp2_mtp2_flag_search_t         mtp2_flag_search;                               /* flag search needed to pass to dissect_mtp2_tvb - it was derived from the prev. packet in the same direction */
81
  uint8_t                         data_buff;                                      /* data buff needed to pass to dissect_mtp2_tvb - it was derived from the prev. packet in the same direction */
82
  uint8_t                         data_buff_offset;                               /* data buff offset needed to pass to dissect_mtp2_tvb - it was derived from the prev. packet in the same direction */
83
  uint8_t                         last_flag_beginning_offset_for_align_check;     /* variable for align check, stores the last flag's beginning's offset */
84
  uint32_t                        reass_seq_num_for_reass_check_before_fh;        /* this is the id (reass_seq_num) which should be used for looking up reassembled data found before the first flag */
85
  uint32_t                        reass_seq_num_for_reass_check_after_lh;         /* this is the id (reass_seq_num) which should be used for looking up reassembled data found after the last flag */
86
  enum mtp2_bitstream_states      state;                                          /* state needed to pass to dissect_mtp2_tvb - it was derived from the prev. packet in the same direction */
87
} mtp2_ppd_t;
88
89
/* conversation data about the previous packet in the conversation (in one direction) */
90
typedef struct mtp2_convo_data_prev_packet {
91
  mtp2_mtp2_flag_search_t       mtp2_flag_search;       /* storing the prev. packet's flag search */
92
  uint8_t                       data_buff;              /* storing the prev. packet's data buffer */
93
  uint8_t                       data_buff_offset;       /* storing the prev. packet's data buffer offset */
94
  uint8_t                       last_flag_beginning_offset_for_align_check;     /* storing the prev. packet's last flag's offset */
95
  uint32_t                      reass_seq_num;          /* storing the prev. packet's reassemble seq. num */
96
  enum mtp2_bitstream_states    state;                  /* storing the prev. packet's state in the forward direction */
97
} mtp2_convo_data_prev_packet_t;
98
99
/* conversation data for MTP2 dissection from RTP payload */
100
typedef struct mtp2_convo_data {
101
  address         addr_a;                               /* storing the first packet's originating address */
102
  address         addr_b;                               /* storing the first packet's terminating address */
103
  uint32_t        port_a;                               /* storing the first packet's originating port */
104
  uint32_t        port_b;                               /* storing the first packet's terminating port */
105
  mtp2_convo_data_prev_packet_t   *forward;             /* storing needed info about the prev. packet's in forward direction */
106
  mtp2_convo_data_prev_packet_t   *backward;            /* storing needed info about the prev. packet's in backward direction */
107
} mtp2_convo_data_t;
108
109
/* Initialize the protocol and registered fields */
110
static int proto_mtp2;
111
static int hf_mtp2_bsn;
112
static int hf_mtp2_ext_bsn;
113
static int hf_mtp2_ext_res;
114
static int hf_mtp2_bib;
115
static int hf_mtp2_ext_bib;
116
static int hf_mtp2_fsn;
117
static int hf_mtp2_ext_fsn;
118
static int hf_mtp2_fib;
119
static int hf_mtp2_ext_fib;
120
static int hf_mtp2_li;
121
static int hf_mtp2_ext_li;
122
static int hf_mtp2_spare;
123
static int hf_mtp2_ext_spare;
124
static int hf_mtp2_sf;
125
static int hf_mtp2_sf_extra;
126
static int hf_mtp2_fcs_16;
127
static int hf_mtp2_fcs_16_status;
128
static int hf_mtp2_unexpect_end;
129
static int hf_mtp2_frame_reset;
130
131
/* reassemble variables */
132
static int hf_mtp2_fragments;
133
static int hf_mtp2_fragment;
134
static int hf_mtp2_fragment_overlap;
135
static int hf_mtp2_fragment_overlap_conflicts;
136
static int hf_mtp2_fragment_multiple_tails;
137
static int hf_mtp2_fragment_too_long_fragment;
138
static int hf_mtp2_fragment_error;
139
static int hf_mtp2_fragment_count;
140
static int hf_mtp2_reassembled_in;
141
static int hf_mtp2_reassembled_length;
142
static int ett_mtp2_fragment;
143
static int ett_mtp2_fragments;
144
145
/* local static const needed for reassembly */
146
static const fragment_items mtp2_frag_items = {
147
  &ett_mtp2_fragment,
148
  &ett_mtp2_fragments,
149
  &hf_mtp2_fragments,
150
  &hf_mtp2_fragment,
151
  &hf_mtp2_fragment_overlap,
152
  &hf_mtp2_fragment_overlap_conflicts,
153
  &hf_mtp2_fragment_multiple_tails,
154
  &hf_mtp2_fragment_too_long_fragment,
155
  &hf_mtp2_fragment_error,
156
  &hf_mtp2_fragment_count,
157
  &hf_mtp2_reassembled_in,
158
  &hf_mtp2_reassembled_length,
159
  NULL,
160
  "MTP2 Message fragments"
161
};
162
163
/* needed for packet reassembly */
164
static reassembly_table mtp2_reassembly_table;
165
166
/* variables needed for property registration to wireshark menu */
167
static bool reverse_bit_order_mtp2;
168
169
static expert_field ei_mtp2_checksum_error;
170
static expert_field ei_mtp2_li_bad;
171
172
/* Initialize the subtree pointers */
173
static int ett_mtp2;
174
175
static bool use_extended_sequence_numbers_default;
176
static bool capture_contains_fcs_crc_default;
177
178
/* sequence number of the actual packet to be reassembled
179
 * this is needed because the reassemble handler uses a key based on the
180
 * source and destination IP addresses
181
 * therefore if there are multiple streams between 2 IP end-points
182
 * the reassemble sequence numbers can conflict if they are based on conversations */
183
static uint32_t   mtp2_absolute_reass_seq_num;
184
185
0
#define BSN_BIB_LENGTH          1
186
0
#define FSN_FIB_LENGTH          1
187
0
#define LI_LENGTH               1
188
0
#define HEADER_LENGTH           (BSN_BIB_LENGTH + FSN_FIB_LENGTH + LI_LENGTH)
189
190
0
#define EXTENDED_BSN_BIB_LENGTH 2
191
0
#define EXTENDED_FSN_FIB_LENGTH 2
192
0
#define EXTENDED_LI_LENGTH      2
193
0
#define EXTENDED_HEADER_LENGTH  (EXTENDED_BSN_BIB_LENGTH + EXTENDED_FSN_FIB_LENGTH + EXTENDED_LI_LENGTH)
194
195
0
#define BSN_BIB_OFFSET          0
196
0
#define FSN_FIB_OFFSET          (BSN_BIB_OFFSET + BSN_BIB_LENGTH)
197
0
#define LI_OFFSET               (FSN_FIB_OFFSET + FSN_FIB_LENGTH)
198
0
#define SIO_OFFSET              (LI_OFFSET + LI_LENGTH)
199
200
0
#define EXTENDED_BSN_BIB_OFFSET 0
201
0
#define EXTENDED_FSN_FIB_OFFSET (EXTENDED_BSN_BIB_OFFSET + EXTENDED_BSN_BIB_LENGTH)
202
0
#define EXTENDED_LI_OFFSET      (EXTENDED_FSN_FIB_OFFSET + EXTENDED_FSN_FIB_LENGTH)
203
0
#define EXTENDED_SIO_OFFSET     (EXTENDED_LI_OFFSET + EXTENDED_LI_LENGTH)
204
205
16
#define BSN_MASK                0x7f
206
16
#define BIB_MASK                0x80
207
16
#define FSN_MASK                0x7f
208
16
#define FIB_MASK                0x80
209
16
#define LI_MASK                 0x3f
210
16
#define SPARE_MASK              0xc0
211
212
16
#define EXTENDED_BSN_MASK       0x0fff
213
16
#define EXTENDED_RES_MASK       0x7000
214
16
#define EXTENDED_BIB_MASK       0x8000
215
16
#define EXTENDED_FSN_MASK       0x0fff
216
16
#define EXTENDED_FIB_MASK       0x8000
217
16
#define EXTENDED_LI_MASK        0x01ff
218
16
#define EXTENDED_SPARE_MASK     0xfe00
219
220
/* remove comment to enable debugging of bitstream dissector
221
 * if enabled this produces printout to stderr like this for every packet:
222
223
start_dissect_bitstream_packet: 2120
224
11010010        SKIPPED ZEROS: 3.
225
10000000
226
01100001
227
01101111
228
10011111        SKIPPED ZEROS: 2.
229
10011001        FLAG FOUND
230
11110100        SKIPPED ZEROS: 5.
231
10100000
232
00011000
233
 * under the development it can be very helpful to see RTP packet content like this
234
 * to identify and solve problems regarding bitstream parsing*/
235
/*#define MTP2_BITSTREAM_DEBUG    1*/
236
237
static void
238
dissect_mtp2_header(tvbuff_t *su_tvb, packet_info *pinfo, proto_item *mtp2_tree, bool use_extended_sequence_numbers, bool validate_crc, uint32_t *li)
239
0
{
240
0
  unsigned reported_len;
241
0
  proto_item *li_item;
242
243
0
  if (use_extended_sequence_numbers) {
244
0
    reported_len = tvb_reported_length_remaining(su_tvb, EXTENDED_HEADER_LENGTH);
245
0
    if (validate_crc) {
246
0
      reported_len = reported_len < 2 ? 0 : (reported_len - 2);
247
0
    }
248
0
    proto_tree_add_item(mtp2_tree, hf_mtp2_ext_bsn,   su_tvb, EXTENDED_BSN_BIB_OFFSET, EXTENDED_BSN_BIB_LENGTH, ENC_LITTLE_ENDIAN);
249
0
    proto_tree_add_item(mtp2_tree, hf_mtp2_ext_res,   su_tvb, EXTENDED_BSN_BIB_OFFSET, EXTENDED_BSN_BIB_LENGTH, ENC_LITTLE_ENDIAN);
250
0
    proto_tree_add_item(mtp2_tree, hf_mtp2_ext_bib,   su_tvb, EXTENDED_BSN_BIB_OFFSET, EXTENDED_BSN_BIB_LENGTH, ENC_LITTLE_ENDIAN);
251
0
    proto_tree_add_item(mtp2_tree, hf_mtp2_ext_fsn,   su_tvb, EXTENDED_FSN_FIB_OFFSET, EXTENDED_FSN_FIB_LENGTH, ENC_LITTLE_ENDIAN);
252
0
    proto_tree_add_item(mtp2_tree, hf_mtp2_ext_res,   su_tvb, EXTENDED_FSN_FIB_OFFSET, EXTENDED_FSN_FIB_LENGTH, ENC_LITTLE_ENDIAN);
253
0
    proto_tree_add_item(mtp2_tree, hf_mtp2_ext_fib,   su_tvb, EXTENDED_FSN_FIB_OFFSET, EXTENDED_FSN_FIB_LENGTH, ENC_LITTLE_ENDIAN);
254
0
    li_item = proto_tree_add_item_ret_uint(mtp2_tree, hf_mtp2_ext_li, su_tvb, EXTENDED_LI_OFFSET, EXTENDED_LI_LENGTH, ENC_LITTLE_ENDIAN, li);
255
0
    if (*li != reported_len) {
256
      /* ITU-T Q.703 A.2.3.3 When the extended sequence numbers are used,
257
       * the field is large enough to contain all legal values. 0-273.
258
       * Thus the check in the other case doesn't apply. */
259
0
      proto_item_append_text(li_item, " [expected payload length %u]", reported_len);
260
0
      expert_add_info_format(pinfo, li_item, &ei_mtp2_li_bad, "Bad length value %u != payload length ", *li);
261
0
      col_append_fstr(pinfo->cinfo, COL_INFO, " [BAD MTP2 LI %u != PAYLOAD LENGTH]", *li);
262
0
    }
263
0
    proto_tree_add_item(mtp2_tree, hf_mtp2_ext_spare, su_tvb, EXTENDED_LI_OFFSET,      EXTENDED_LI_LENGTH,      ENC_LITTLE_ENDIAN);
264
0
  } else {
265
0
    reported_len = tvb_reported_length_remaining(su_tvb, HEADER_LENGTH);
266
0
    if (validate_crc) {
267
0
      reported_len = reported_len < 2 ? 0 : (reported_len - 2);
268
0
    }
269
0
    proto_tree_add_item(mtp2_tree, hf_mtp2_bsn,   su_tvb, BSN_BIB_OFFSET, BSN_BIB_LENGTH, ENC_LITTLE_ENDIAN);
270
0
    proto_tree_add_item(mtp2_tree, hf_mtp2_bib,   su_tvb, BSN_BIB_OFFSET, BSN_BIB_LENGTH, ENC_LITTLE_ENDIAN);
271
0
    proto_tree_add_item(mtp2_tree, hf_mtp2_fsn,   su_tvb, FSN_FIB_OFFSET, FSN_FIB_LENGTH, ENC_LITTLE_ENDIAN);
272
0
    proto_tree_add_item(mtp2_tree, hf_mtp2_fib,   su_tvb, FSN_FIB_OFFSET, FSN_FIB_LENGTH, ENC_LITTLE_ENDIAN);
273
0
    li_item = proto_tree_add_item_ret_uint(mtp2_tree, hf_mtp2_li, su_tvb, LI_OFFSET, LI_LENGTH, ENC_LITTLE_ENDIAN, li);
274
    /* ITU-T Q.703 2.3.3: In the case that the payload is more than the
275
     * li field allows, should be set to the max, i.e. the mask 63 */
276
0
    if (reported_len > LI_MASK) {
277
0
      if (*li != LI_MASK) {
278
0
        proto_item_append_text(li_item, " [payload length %u, expected max value %u]", reported_len, LI_MASK);
279
0
        expert_add_info_format(pinfo, li_item, &ei_mtp2_li_bad, "Bad length value %u != max value ", *li);
280
0
        col_append_fstr(pinfo->cinfo, COL_INFO, " [BAD MTP2 LI %u != MAX VALUE]", *li);
281
0
      }
282
0
    } else if (*li != reported_len ) {
283
0
      proto_item_append_text(li_item, " [expected payload length %u]", reported_len);
284
0
      expert_add_info_format(pinfo, li_item, &ei_mtp2_li_bad, "Bad length value %u != payload length ", *li);
285
0
      col_append_fstr(pinfo->cinfo, COL_INFO, " [BAD MTP2 LI %u != PAYLOAD LENGTH]", *li);
286
0
    }
287
0
    proto_tree_add_item(mtp2_tree, hf_mtp2_spare, su_tvb, LI_OFFSET,      LI_LENGTH,      ENC_LITTLE_ENDIAN);
288
0
  }
289
0
}
290
/*
291
*******************************************************************************
292
* DETAILS : Calculate a new FCS-16 given the current FCS-16 and the new data.
293
*******************************************************************************
294
*/
295
static uint16_t
296
mtp2_fcs16(tvbuff_t * tvbuff)
297
0
{
298
0
  unsigned len = tvb_reported_length(tvbuff)-2;
299
300
  /* Check for Invalid Length */
301
0
  if (len == 0)
302
0
    return (0x0000);
303
0
  return crc16_ccitt_tvb(tvbuff, len);
304
0
}
305
306
/*
307
 * This function for CRC16 only is based on the decode_fcs of packet_ppp.c
308
 */
309
static tvbuff_t *
310
mtp2_decode_crc16(tvbuff_t *tvb, proto_tree *fh_tree, packet_info *pinfo)
311
0
{
312
0
  tvbuff_t   *next_tvb;
313
0
  int        len, reported_len;
314
0
  int proto_offset=0;
315
316
  /*
317
   * Do we have the entire packet, and does it include a 2-byte FCS?
318
   */
319
0
  len = tvb_captured_length_remaining(tvb, proto_offset);
320
0
  reported_len = tvb_reported_length_remaining(tvb, proto_offset);
321
0
  if (reported_len < 2 || len < 0) {
322
    /*
323
     * The packet is claimed not to even have enough data for a 2-byte FCS,
324
     * or we're already past the end of the captured data.
325
     * Don't slice anything off.
326
     */
327
0
    next_tvb = tvb_new_subset_remaining(tvb, proto_offset);
328
0
  } else if (len < reported_len) {
329
    /*
330
     * The packet is claimed to have enough data for a 2-byte FCS, but
331
     * we didn't capture all of the packet.
332
     * Slice off the 2-byte FCS from the reported length, and trim the
333
     * captured length so it's no more than the reported length; that
334
     * will slice off what of the FCS, if any, is in the captured
335
     * length.
336
     */
337
0
    reported_len -= 2;
338
0
    next_tvb = tvb_new_subset_length(tvb, proto_offset, reported_len);
339
0
  } else {
340
    /*
341
     * We have the entire packet, and it includes a 2-byte FCS.
342
     * Slice it off.
343
     */
344
0
    len -= 2;
345
0
    reported_len -= 2;
346
0
    next_tvb = tvb_new_subset_length(tvb, proto_offset, reported_len);
347
348
    /*
349
     * Compute the FCS and put it into the tree.
350
     */
351
0
    proto_tree_add_checksum(fh_tree, tvb, proto_offset + len, hf_mtp2_fcs_16, hf_mtp2_fcs_16_status, &ei_mtp2_checksum_error, pinfo, mtp2_fcs16(tvb),
352
0
                            ENC_LITTLE_ENDIAN, PROTO_CHECKSUM_VERIFY);
353
0
  }
354
0
  return next_tvb;
355
0
}
356
357
358
static void
359
dissect_mtp2_fisu(packet_info *pinfo)
360
0
{
361
0
  col_set_str(pinfo->cinfo, COL_INFO, "FISU ");
362
0
}
363
364
static const value_string status_field_vals[] = {
365
  { 0x0, "Status Indication O" },
366
  { 0x1, "Status Indication N" },
367
  { 0x2, "Status Indication E" },
368
  { 0x3, "Status Indication OS" },
369
  { 0x4, "Status Indication PO" },
370
  { 0x5, "Status Indication B" },
371
  { 0,   NULL}
372
};
373
374
/* Same as above but in acronym form (for the Info column) */
375
static const value_string status_field_acro_vals[] = {
376
  { 0x0, "SIO" },
377
  { 0x1, "SIN" },
378
  { 0x2, "SIE" },
379
  { 0x3, "SIOS" },
380
  { 0x4, "SIPO" },
381
  { 0x5, "SIB" },
382
  { 0,   NULL}
383
};
384
385
0
#define SF_OFFSET          (LI_OFFSET + LI_LENGTH)
386
0
#define EXTENDED_SF_OFFSET (EXTENDED_LI_OFFSET + EXTENDED_LI_LENGTH)
387
388
0
#define SF_LENGTH                       1
389
0
#define SF_EXTRA_OFFSET                 (SF_OFFSET + SF_LENGTH)
390
0
#define EXTENDED_SF_EXTRA_OFFSET        (EXTENDED_SF_OFFSET + SF_LENGTH)
391
0
#define SF_EXTRA_LENGTH                 1
392
393
static void
394
dissect_mtp2_lssu(tvbuff_t *su_tvb, packet_info *pinfo, proto_item *mtp2_tree,
395
                  bool use_extended_sequence_numbers, uint32_t li)
396
0
{
397
0
  uint8_t sf = 0xFF;
398
0
  uint8_t sf_offset, sf_extra_offset;
399
400
0
  if (use_extended_sequence_numbers) {
401
0
    sf_offset = EXTENDED_SF_OFFSET;
402
0
    sf_extra_offset = EXTENDED_SF_EXTRA_OFFSET;
403
0
  } else {
404
0
    sf_offset = SF_OFFSET;
405
0
    sf_extra_offset = SF_EXTRA_OFFSET;
406
0
  }
407
408
0
  proto_tree_add_item_ret_uint8(mtp2_tree, hf_mtp2_sf, su_tvb, sf_offset, SF_LENGTH, ENC_LITTLE_ENDIAN, &sf);
409
410
  /*  If the LI is 2 then there is an extra octet following the standard SF
411
   *  field but it is not defined what this octet is.
412
   *  (In any case the first byte of the SF always has the same meaning.)
413
   */
414
0
  if (li == 2)
415
0
    proto_tree_add_item(mtp2_tree, hf_mtp2_sf_extra, su_tvb, sf_extra_offset, SF_EXTRA_LENGTH, ENC_LITTLE_ENDIAN);
416
417
0
  col_set_str(pinfo->cinfo, COL_INFO, val_to_str_const(sf, status_field_acro_vals, "Unknown"));
418
0
}
419
420
static void
421
dissect_mtp2_msu(tvbuff_t *su_tvb, packet_info *pinfo, proto_item *mtp2_item,
422
                 proto_item *tree, bool use_extended_sequence_numbers)
423
0
{
424
0
  int sif_sio_length;
425
0
  tvbuff_t *sif_sio_tvb;
426
427
0
  col_set_str(pinfo->cinfo, COL_INFO, "MSU ");
428
429
0
  if (use_extended_sequence_numbers) {
430
0
    sif_sio_length = tvb_reported_length(su_tvb) - EXTENDED_HEADER_LENGTH;
431
0
    sif_sio_tvb = tvb_new_subset_length(su_tvb, EXTENDED_SIO_OFFSET, sif_sio_length);
432
0
  } else {
433
0
    sif_sio_length = tvb_reported_length(su_tvb) - HEADER_LENGTH;
434
0
    sif_sio_tvb = tvb_new_subset_length(su_tvb, SIO_OFFSET, sif_sio_length);
435
0
  }
436
0
  call_dissector(mtp3_handle, sif_sio_tvb, pinfo, tree);
437
438
0
  if (tree) {
439
0
    if (use_extended_sequence_numbers)
440
0
      proto_item_set_len(mtp2_item, EXTENDED_HEADER_LENGTH);
441
0
    else
442
0
      proto_item_set_len(mtp2_item, HEADER_LENGTH);
443
0
  }
444
0
}
445
446
static void
447
dissect_mtp2_su(tvbuff_t *su_tvb, packet_info *pinfo, proto_item *mtp2_item,
448
                proto_item *mtp2_tree, proto_tree *tree, bool validate_crc,
449
                bool use_extended_sequence_numbers)
450
0
{
451
0
  uint32_t li=0;
452
0
  tvbuff_t  *next_tvb = NULL;
453
454
0
  dissect_mtp2_header(su_tvb, pinfo, mtp2_tree, use_extended_sequence_numbers, validate_crc, &li);
455
  /* In some capture files (like .rf5), CRC are not present */
456
  /* So, to avoid trouble, give the complete buffer if CRC validation is disabled */
457
0
  if (validate_crc)
458
0
    next_tvb = mtp2_decode_crc16(su_tvb, mtp2_tree, pinfo);
459
0
  else
460
0
    next_tvb = su_tvb;
461
462
0
  switch(li) {
463
0
  case 0:
464
0
    dissect_mtp2_fisu(pinfo);
465
0
    break;
466
0
  case 1:
467
0
  case 2:
468
0
    dissect_mtp2_lssu(next_tvb, pinfo, mtp2_tree, use_extended_sequence_numbers, li);
469
0
    break;
470
0
  default:
471
0
    dissect_mtp2_msu(next_tvb, pinfo, mtp2_item, tree, use_extended_sequence_numbers);
472
0
    break;
473
0
  }
474
0
}
475
476
static void
477
dissect_mtp2_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
478
                    bool validate_crc, bool use_extended_sequence_numbers)
479
0
{
480
0
  proto_item *mtp2_item;
481
0
  proto_tree *mtp2_tree;
482
483
0
  col_set_str(pinfo->cinfo, COL_PROTOCOL, "MTP2");
484
485
0
  mtp2_item = proto_tree_add_item(tree, proto_mtp2, tvb, 0, -1, ENC_NA);
486
0
  mtp2_tree = proto_item_add_subtree(mtp2_item, ett_mtp2);
487
488
0
  dissect_mtp2_su(tvb, pinfo, mtp2_item, mtp2_tree, tree, validate_crc,
489
0
                  use_extended_sequence_numbers);
490
0
}
491
492
/* Dissect MTP2 frame without CRC16 and with a pseudo-header */
493
static int
494
dissect_mtp2_with_phdr(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
495
0
{
496
0
  if (pinfo->pseudo_header->mtp2.annex_a_used == MTP2_ANNEX_A_USED_UNKNOWN)
497
0
    dissect_mtp2_common(tvb, pinfo, tree, false, use_extended_sequence_numbers_default);
498
0
  else
499
0
    dissect_mtp2_common(tvb, pinfo, tree, false,
500
0
                        (pinfo->pseudo_header->mtp2.annex_a_used == MTP2_ANNEX_A_USED));
501
502
0
  return tvb_captured_length(tvb);
503
0
}
504
505
/* Dissect MTP2 frame with CRC16 included at end of payload. Used
506
 * if the user has associated "mtp2_with_crc" with a DLT or if the
507
 * packets come from an Endace ERF file.
508
 */
509
static int
510
dissect_mtp2_with_crc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
511
0
{
512
0
  dissect_mtp2_common(tvb, pinfo, tree, true, use_extended_sequence_numbers_default);
513
0
  return tvb_captured_length(tvb);
514
0
}
515
516
/* Dissect MTP2 frame where we don't know if the CRC16 is included at
517
 * end of payload or not.
518
 */
519
static int
520
dissect_mtp2(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
521
0
{
522
0
  dissect_mtp2_common(tvb, pinfo, tree, capture_contains_fcs_crc_default,
523
0
                      use_extended_sequence_numbers_default);
524
0
  return tvb_captured_length(tvb);
525
0
}
526
527
/*  get one bit of a uint8_t byte
528
*   based on the order set in the preferences
529
*   reverse_bit_order_mtp2 = false: as the Q.703 states
530
*   reverse_bit_order_mtp2 = true: just the opposite
531
*/
532
static bool
533
get_bit(uint8_t byte, uint8_t bit)
534
0
{
535
0
  if (reverse_bit_order_mtp2 == false) {
536
0
    return byte & ((0x80 >> (bit-1))) ? true : false;
537
0
  } else {
538
0
    return byte & ((0x01 << (bit-1))) ? true : false;
539
0
  }
540
0
}
541
542
/* store new byte of an MTP2 frame in an array
543
 * after the whole packet is stored the array will be used to construct a new tvb */
544
static void
545
new_byte(wmem_allocator_t* allocator, char full_byte, uint8_t **data, unsigned *data_len)
546
0
{
547
0
  uint8_t *new_data = NULL;
548
0
  unsigned i = 0;
549
550
0
  if ((*data_len) == 0) {
551
    /* if data was never stored in this buffer before */
552
0
    *data = wmem_new(allocator, uint8_t);
553
0
    (**data) = full_byte;
554
0
    (*data_len)++;
555
0
  } else {
556
    /* if this buffer is used -> create a completely new one
557
     * note, that after the dissection of this packet
558
     * the old data will be freed automatically (because of the wmem_alloc) */
559
0
    new_data = (uint8_t *)wmem_alloc(allocator, sizeof(uint8_t)*((*data_len)+1));
560
    /* copy the old one's content */
561
0
    for (i = 0;i<(*data_len);i++) {
562
0
      *(new_data+i) = *((*data)+i);
563
0
    }
564
    /* store the new data */
565
0
    *(new_data+*data_len) = full_byte;
566
    /* re-point the pointer to the new structure's head */
567
0
    *data = new_data;
568
0
    (*data_len)++;
569
0
  }
570
0
}
571
572
/* based on the actual packet's addresses and ports,
573
 * this function determines the packet's direction */
574
static enum packet_direction_state_mtp2
575
get_direction_state(packet_info *pinfo, mtp2_convo_data_t *convo_data)
576
0
{
577
0
  if (convo_data != NULL) {
578
0
    if (addresses_equal(&convo_data->addr_a, &pinfo->src)
579
0
        && addresses_equal(&convo_data->addr_b, &pinfo->dst)
580
0
        && convo_data->port_a == pinfo->srcport
581
0
        && convo_data->port_b == pinfo->destport) {
582
0
      return FORWARD;
583
0
    } else if (addresses_equal(&convo_data->addr_b, &pinfo->src)
584
0
        && addresses_equal(&convo_data->addr_a, &pinfo->dst)
585
0
        && convo_data->port_b == pinfo->srcport
586
0
        && convo_data->port_a == pinfo->destport) {
587
0
      return BACKWARD;
588
0
    }
589
0
  }
590
591
0
  return FORWARD;
592
0
}
593
594
/* prepares the data to be stored as found packet in wmem_list */
595
static mtp2_recognized_packet_t*
596
prepare_data_for_found_packet(tvbuff_t *tvb, wmem_allocator_t* allocator, uint8_t unalignment_offset)
597
0
{
598
0
  mtp2_recognized_packet_t *packet;
599
600
0
  packet = wmem_new(allocator, mtp2_recognized_packet_t);
601
  /* store values */
602
0
  packet->data = tvb;
603
0
  packet->unalignment_offset = unalignment_offset;
604
605
0
  return packet;
606
0
}
607
608
/* this function does the actual dissection of a tvb got from the RTP dissector
609
 * sets the mtp2_flag_search, data_buffer, it's offset and the state to the one which was stored
610
 * at the end of the previous packet's dissection in the same direction */
611
static mtp2_dissect_tvb_res_t*
612
dissect_mtp2_tvb(tvbuff_t* tvb, packet_info* pinfo, mtp2_mtp2_flag_search_t back_mtp2_flag_search, uint8_t back_data_buff, uint8_t back_data_buff_offset,
613
    enum mtp2_bitstream_states back_state, uint8_t back_last_flag_beginning_offset_for_align_check)
614
0
{
615
0
  uint8_t       mtp2_flag_search = 0x00,                        /* this helps to detect the flags in the bitstream */
616
0
                data_buff = 0x00,                               /* buffer to store the found bits without the stuffed zeros */
617
0
                data_buff_offset = 0,                           /* index of the data_buff_offset, where to store the next bit */
618
0
                *found_data_buff_byte = NULL,                   /* buffer to store the found data_buff bytes till they are assembled to a tvb */
619
0
                flag_beginning_offset_for_align_check = 0;      /* this stores the offset of the first bit in a flag */
620
#ifdef MTP2_BITSTREAM_DEBUG
621
  bool          zero_skip0 = 0,                                 /* needed for debug output */
622
                zero_skip1 = 0,                                 /* needed for debug output */
623
                flag = false,                                   /* needed for debug to print flag found message. reset at every new octet read from tvb */
624
                frame_reset = false;                            /* needed for debug, informs about a frame reset */
625
#endif
626
0
  unsigned      available_bytes_in_rtp_payload = 0,             /* stores the tvb's length which need to be analyzed */
627
0
                offset = 0,                                     /* offset of the tvb, needed to get the appropriate byte */
628
0
                data_len = 0;                                   /* the length of the array where the data_buff's are stored */
629
0
  enum mtp2_bitstream_states    state = OUT_OF_SYNC;            /* actual state of the dissection */
630
0
  tvbuff_t                      *new_tvb = NULL;                /* tvbuff which stores the assembled data from the data pointer */
631
0
  mtp2_dissect_tvb_res_t        *result = NULL;                 /* the result structure */
632
633
  /* initialize the result structure, this will be returned at the end */
634
0
  result = wmem_new(pinfo->pool, mtp2_dissect_tvb_res_t);
635
0
  result->mtp2_remain_data.before_first_flag = NULL;
636
0
  result->mtp2_remain_data.before_fh_unalignment_offset = 0;
637
0
  result->mtp2_remain_data.before_fh_frame_reset = false;
638
0
  result->mtp2_remain_data.after_last_flag = NULL;
639
0
  result->found_packets = wmem_list_new(pinfo->pool);
640
0
  result->flag_found = false;
641
0
  result->last_flag_beginning_offset_for_align_check = 0;
642
643
  /* set the mtp2_flag_search if it is set */
644
0
  if (back_mtp2_flag_search.set == true) {
645
0
    mtp2_flag_search = back_mtp2_flag_search.mtp2_flag_search;
646
0
  }
647
  /* set every other variables from the prev. packet's end in the same direction */
648
0
  data_buff = back_data_buff;
649
0
  data_buff_offset = back_data_buff_offset;
650
0
  state = back_state;
651
0
  flag_beginning_offset_for_align_check = back_last_flag_beginning_offset_for_align_check;
652
653
  /* determine how many byte are in the RTP payload */
654
0
  available_bytes_in_rtp_payload = tvb_reported_length_remaining(tvb, offset);
655
656
  /* walk through the tvb in means of octets */
657
0
  while (offset < available_bytes_in_rtp_payload) {
658
    /* get actual packet's byte */
659
0
    uint8_t byte = tvb_get_uint8(tvb,offset);
660
    /* for every bit in the byte */
661
0
    for (uint8_t i=1; i <= 8; i++) {
662
      /* get the bit's boolean value got from byte[i] */
663
0
      bool bit = get_bit(byte, i);
664
665
#ifdef MTP2_BITSTREAM_DEBUG
666
      /* in case of debug, print just the pure RTP payload, not the previous packet's end */
667
      ws_debug("%u",(bit==false?0:1));
668
#endif
669
670
      /* update the mtp2_flag_search */
671
0
      mtp2_flag_search = (mtp2_flag_search << 1) | bit;
672
673
      /* this section contains actions to be taken when the state is not OUT_OF_SYNC like
674
       * skipping zeros after every 5 bits */
675
0
      if (state != OUT_OF_SYNC) {
676
        /* The only values of mtp2_flag_search if we need to drop a zero is 0xBE and 0x3E */
677
0
        if ( (mtp2_flag_search == 0xBE || mtp2_flag_search == 0x3E)) {
678
#ifdef MTP2_BITSTREAM_DEBUG
679
          /* set the debug variables */
680
          if (zero_skip0 == 0)
681
            zero_skip0 = i;
682
          else
683
            zero_skip1 = i;
684
#endif
685
          /* if we need to skip a zero, the next flag offset have to be incremented because the raw data
686
           * between 2 flags is not a multiple of 8 bits now */
687
0
          flag_beginning_offset_for_align_check = (flag_beginning_offset_for_align_check + 1) % 8;
688
0
        } else {
689
          /* No drop -> store the value */
690
0
          data_buff = data_buff | (bit << data_buff_offset);
691
0
          data_buff_offset++;
692
          /* when a new complete byte without zeros was found */
693
0
          if (data_buff_offset == 8) {
694
            /* we don't store flags */
695
0
            if (data_buff != 0x7E) {
696
              /* store the data and change the state */
697
0
              state = DATA;
698
0
              new_byte(pinfo->pool, data_buff, &found_data_buff_byte, &data_len);
699
0
            }
700
            /* clear data_buff and it's offset */
701
0
            data_buff = 0x00;
702
0
            data_buff_offset = 0;
703
0
          }
704
0
        }
705
0
      }
706
      /* we have a flag */
707
0
      if (mtp2_flag_search == 0x7E &&
708
0
          !(offset == 0 && i < 8 && back_mtp2_flag_search.set == false))
709
        /* the second part of the '&&' is not to recognize the 1111110x pattern as flag in the beginning of the 1st packet in every direction
710
         * the 1111110 would be shifted into the mtp2_flag_search variable, this has a 0x00 initial value
711
         * so after shifting 7 bits, the value of mtp2_flag_search would be 01111110 however there was no leading 0*/
712
0
      {
713
        /* set the state */
714
0
        state = FLAGS;
715
        /* if before this flag, we found some real packet related bytes */
716
0
        if (data_len != 0) {
717
0
          uint8_t unaligned_packet_offset = 0; /* !=0 signals if the packet just found was not a multiple of 8 bits in the bitstream */
718
          /* here we check if the just found MTP2 packet is unaligned or not
719
           * 0 is not valid value meaning the flag_beginning_offset_for_align_check was not set at the beginning of the func.
720
           * if flag_beginning_offset_for_align_check != i, we have an unaligned packet */
721
0
          if (flag_beginning_offset_for_align_check != 0 && flag_beginning_offset_for_align_check != i) {
722
            /* set the unaligned offset */
723
0
            unaligned_packet_offset = i;
724
            /* clear the data_buff and offset
725
             * this is needed because at the next flag we would have data_buff offset unaligned
726
             * and we would find a 1 length packet with a part of the flag in it */
727
0
            data_buff = 0x00;
728
0
            data_buff_offset = 0;
729
0
          }
730
          /* fill the temporary buffer with data */
731
0
          uint8_t *buff = (uint8_t *) wmem_memdup(pinfo->pool, found_data_buff_byte, data_len);
732
          /* Allocate new tvb for the proto frame */
733
0
          new_tvb = tvb_new_child_real_data(tvb, buff, data_len, data_len);
734
          /* if there were no flags before, we've found the bytes before the first flag */
735
0
          if (result->flag_found == false) {
736
            /* this tvb is the one we found before the 1st flag */
737
0
            result->mtp2_remain_data.before_first_flag = new_tvb;
738
            /* if the bytes before the first flag was unaligned -> the calling function needs this info */
739
0
            result->mtp2_remain_data.before_fh_unalignment_offset = unaligned_packet_offset;
740
0
          } else {
741
            /* add the packet to the processable packet's list */
742
0
            wmem_list_append(result->found_packets, prepare_data_for_found_packet(new_tvb,pinfo->pool,unaligned_packet_offset));
743
0
          }
744
          /* clear data array (free will be done automatically) */
745
0
          data_len = 0;
746
0
          found_data_buff_byte = NULL;
747
0
        }
748
749
0
        flag_beginning_offset_for_align_check = i;
750
#ifdef MTP2_BITSTREAM_DEBUG
751
        /* for local debug purposes */
752
        flag = true;
753
#endif
754
        /* set the result found in the result to true */
755
0
        result->flag_found = true;
756
        /* 7 consecutive 1s => out of sync */
757
0
      } else if (mtp2_flag_search == 0x7F || mtp2_flag_search == 0xFE || mtp2_flag_search == 0xFF) {
758
        /* set the state and clear everything */
759
0
        state = OUT_OF_SYNC;
760
0
        data_len = 0;
761
0
        found_data_buff_byte = NULL;
762
0
        data_buff = 0x00;
763
0
        data_buff_offset = 0;
764
#ifdef MTP2_BITSTREAM_DEBUG
765
        frame_reset = true;
766
#endif
767
0
        if (result->flag_found == false)
768
0
          result->mtp2_remain_data.before_fh_frame_reset = true;
769
0
      }
770
0
    }
771
772
#ifdef MTP2_BITSTREAM_DEBUG
773
    /* if there were flag, print debug info */
774
    if (flag) {
775
      ws_debug("\tFLAG FOUND");
776
    }
777
    /* if there were zeros skipped, print the debug data */
778
    if (!zero_skip0 == 0) {
779
      ws_debug("\tSKIPPED ZEROS: %u.",zero_skip0);
780
      if (!zero_skip1 == 0)
781
        ws_debug(" %u",zero_skip1);
782
    }
783
    /* if there was frame reset, print debug info */
784
    if (frame_reset) {
785
      ws_debug("\tFRAME RESET");
786
    }
787
    /* print a \n to print the next byte in a different row */
788
    ws_debug("\n");
789
    /* after every byte read from tvb clear debug stuff */
790
    zero_skip0 = 0;
791
    zero_skip1 = 0;
792
    /* set the debug variables as well */
793
    flag = false;
794
    frame_reset = false;
795
#endif
796
    /* increment tvb offset */
797
0
    offset++;
798
0
  }
799
800
0
  if (data_len != 0) {
801
    /* fill the temporary buffer with data */
802
0
    uint8_t * buff = (uint8_t *) wmem_memdup(pinfo->pool, found_data_buff_byte, data_len);
803
    /* Allocate new tvb for the MTP2 frame */
804
0
    new_tvb = tvb_new_child_real_data(tvb, buff, data_len, data_len);
805
    /* this tvb is the one we found after the last flag */
806
0
    result->mtp2_remain_data.after_last_flag = new_tvb;
807
0
  }
808
809
  /* we do not return NULL in before_first_flag because then the reassemble will not work
810
   * we have to add a 0 length tvb with the flag "no more packets" */
811
0
  if (result->mtp2_remain_data.before_first_flag == NULL) {
812
    /* fill the temporary buffer with data */
813
0
    uint8_t *buff = (uint8_t *) wmem_memdup(pinfo->pool, found_data_buff_byte, 0);
814
    /* Allocate new tvb for the MTP2 frame */
815
0
    new_tvb = tvb_new_child_real_data(tvb, buff, 0, 0);
816
    /* this tvb is the one we found after the last flag */
817
0
    result->mtp2_remain_data.before_first_flag = new_tvb;
818
0
  }
819
820
  /* don't set mtp2_flag_search and other stuff if the packet ended in out_of_sync */
821
0
  if (state != OUT_OF_SYNC) {
822
0
    result->mtp2_flag_search.set = true;
823
0
    result->mtp2_flag_search.mtp2_flag_search = mtp2_flag_search;
824
0
    result->data_buff = data_buff;
825
0
    result->data_buff_offset = data_buff_offset;
826
0
  } else {
827
0
    result->mtp2_flag_search.set = false;
828
0
    result->mtp2_flag_search.mtp2_flag_search = result->data_buff = result->data_buff_offset = 0x00;
829
0
  }
830
831
  /* set the state as well, in every case */
832
0
  result->state = state;
833
834
  /* set the last_flag_beginning_offset_for_align_check in the result structure */
835
0
  result->last_flag_beginning_offset_for_align_check = flag_beginning_offset_for_align_check;
836
837
  /* return the result structure */
838
0
  return result;
839
0
}
840
841
/* function to get a new reass. sequence number  */
842
static uint32_t
843
get_new_reass_seq_num(void)
844
0
{
845
  /* fail if it reached the max value */
846
0
  DISSECTOR_ASSERT(mtp2_absolute_reass_seq_num < 0xFFFFFFFE);
847
0
  mtp2_absolute_reass_seq_num++;
848
849
0
  return mtp2_absolute_reass_seq_num;
850
0
}
851
852
853
/* sign if the packet is unaligned in proto tree */
854
static void
855
issue_unaligned_info(proto_tree *tree, tvbuff_t *tvb, uint8_t unalignment_offset)
856
0
{
857
0
  proto_tree_add_none_format(tree, hf_mtp2_unexpect_end, tvb, 0, tvb_reported_length_remaining(tvb,0),
858
0
      "[Packet ended in the middle of an octet. Octet: last, Offset: %u]",
859
0
      unalignment_offset);
860
0
}
861
862
/* sign if the packet is unaligned in proto tree */
863
static void
864
issue_frame_reset_info(proto_tree *tree, tvbuff_t *tvb)
865
0
{
866
0
  proto_tree_add_none_format(tree, hf_mtp2_frame_reset, tvb, 0, 0,
867
0
              "[Frame Reset Occurred, No Reassembly]");
868
0
}
869
870
/* set per packet data based on direction data */
871
static void
872
set_ppd_fields_based_on_convo_directon_data(mtp2_ppd_t *mtp2_ppd, mtp2_convo_data_prev_packet_t *direction_data)
873
0
{
874
0
  mtp2_ppd->mtp2_flag_search = direction_data->mtp2_flag_search;
875
0
  mtp2_ppd->data_buff = direction_data->data_buff;
876
0
  mtp2_ppd->data_buff_offset = direction_data->data_buff_offset;
877
0
  mtp2_ppd->state = direction_data->state;
878
  /* this is because the segment which will be reassembled in this packet
879
   * is stored with the reass_seq_num stored in the convo data
880
   * therefore we have to save this value for dissection in the future */
881
0
  mtp2_ppd->reass_seq_num_for_reass_check_before_fh = direction_data->reass_seq_num;
882
0
  mtp2_ppd->last_flag_beginning_offset_for_align_check = direction_data->last_flag_beginning_offset_for_align_check;
883
0
}
884
885
/* set convo data based on dissection result and reass_seq_num */
886
static void
887
set_direction_fields_based_on_result_and_reass_seq_num(mtp2_convo_data_prev_packet_t *direction_data, mtp2_dissect_tvb_res_t *result, uint32_t reass_seq_num)
888
0
{
889
0
  direction_data->mtp2_flag_search = result->mtp2_flag_search;
890
0
  direction_data->data_buff = result->data_buff;
891
0
  direction_data->data_buff_offset = result->data_buff_offset;
892
0
  direction_data->state = result->state;
893
0
  direction_data->reass_seq_num = reass_seq_num;
894
0
  direction_data->last_flag_beginning_offset_for_align_check = result->last_flag_beginning_offset_for_align_check;
895
0
}
896
897
/* function to dissect bitstream data of MTP2 */
898
static int
899
dissect_mtp2_bitstream(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void * user_data _U_)
900
0
{
901
0
  uint32_t                              reass_seq_num = 0;                      /* reassemble sequence number at the beginning of this packet's dissection */
902
0
  conversation_t                        *conversation = NULL;                   /* conversation of the mtp2 dissection */
903
0
  mtp2_convo_data_t                     *convo_data = NULL;                     /* conversation data of the mtp2 dissection */
904
0
  mtp2_dissect_tvb_res_t                *result = NULL;                         /* variable to store the result of dissect_mtp2_tvb */
905
0
  enum packet_direction_state_mtp2      dir_state = FORWARD;                    /* direction state of this packet in the conversation */
906
0
  mtp2_ppd_t                            *mtp2_ppd = NULL;                       /* per-packet data of this packet */
907
908
#ifdef MTP2_BITSTREAM_DEBUG
909
  ws_debug("start_dissect_bitstream_packet: %u\n",pinfo->fd->num);
910
#endif
911
912
  /* find conversation related to this packet */
913
0
  conversation = find_conversation(pinfo->fd->num,&pinfo->src, &pinfo->dst,conversation_pt_to_conversation_type(pinfo->ptype), pinfo->srcport, pinfo->destport, 0);
914
  /* if there is no conversation or it does not contain the per packet data we need */
915
0
  if (conversation == NULL) {
916
    /* there was no conversation => this packet is the first in a new conversation => let's create it */
917
    /* here we decide about the direction, every following packet with the same direction as this first one will be a forward packet */
918
0
    conversation = conversation_new(pinfo->fd->num,&pinfo->src, &pinfo->dst,conversation_pt_to_conversation_type(pinfo->ptype), pinfo->srcport, pinfo->destport, 0);
919
0
  }
920
921
  /* there is no proto data in the conversation */
922
0
  if (conversation_get_proto_data(conversation, proto_mtp2) == NULL) {
923
    /* create a new convo data and fill it with initial data */
924
0
    convo_data = wmem_new(wmem_file_scope(), mtp2_convo_data_t);
925
0
    copy_address_wmem(wmem_file_scope(), &convo_data->addr_a, &pinfo->src);
926
0
    copy_address_wmem(wmem_file_scope(), &convo_data->addr_b, &pinfo->dst);
927
0
    convo_data->port_a = pinfo->srcport;
928
0
    convo_data->port_b = pinfo->destport;
929
0
    convo_data->forward = wmem_new(wmem_file_scope(), mtp2_convo_data_prev_packet_t);
930
0
    convo_data->backward = wmem_new(wmem_file_scope(), mtp2_convo_data_prev_packet_t);
931
0
    convo_data->forward->mtp2_flag_search.set = convo_data->backward->mtp2_flag_search.set= false;
932
0
    convo_data->forward->mtp2_flag_search.mtp2_flag_search = convo_data->backward->mtp2_flag_search.mtp2_flag_search = 0x00;
933
0
    convo_data->forward->data_buff = convo_data->backward->data_buff = 0x00;
934
0
    convo_data->forward->data_buff_offset = convo_data->backward->data_buff_offset = 0;
935
0
    convo_data->forward->state = convo_data->backward->state = OUT_OF_SYNC;
936
0
    convo_data->forward->reass_seq_num = get_new_reass_seq_num();
937
0
    convo_data->backward->reass_seq_num = get_new_reass_seq_num();
938
0
    convo_data->forward->last_flag_beginning_offset_for_align_check = convo_data->backward->last_flag_beginning_offset_for_align_check = 0;
939
    /* store the convo data */
940
0
    conversation_add_proto_data(conversation, proto_mtp2, convo_data);
941
0
  } else {
942
    /* the packet is part of an existing conversation => get the conversation data */
943
0
    convo_data = (mtp2_convo_data_t*)conversation_get_proto_data(conversation, proto_mtp2);
944
0
  }
945
946
  /* get the packet's state */
947
0
  dir_state = get_direction_state(pinfo, convo_data);
948
949
  /* get the per packet data */
950
0
  mtp2_ppd = (mtp2_ppd_t*)p_get_proto_data(wmem_file_scope(), pinfo, proto_mtp2, pinfo->fd->num);
951
952
  /* if there is no per packet data -> create it */
953
0
  if (mtp2_ppd == NULL) {
954
0
    mtp2_ppd = wmem_new0(wmem_file_scope(), mtp2_ppd_t);
955
    /* set the proto_data_fields
956
     * because these are the values which we would like to see
957
     * if this packet is seen again */
958
0
    if (dir_state == FORWARD) {
959
0
      set_ppd_fields_based_on_convo_directon_data(mtp2_ppd, convo_data->forward);
960
0
    } else {
961
0
      set_ppd_fields_based_on_convo_directon_data(mtp2_ppd, convo_data->backward);
962
0
    }
963
    /* store the ppd to be able to get in the next time we see this packet */
964
0
    p_add_proto_data(wmem_file_scope(), pinfo, proto_mtp2, pinfo->fd->num, mtp2_ppd);
965
0
  }
966
967
  /* get the reass. seq num from the ppd
968
   * this is needed because it is modified and stored in the convo_data */
969
0
  reass_seq_num = mtp2_ppd->reass_seq_num_for_reass_check_before_fh;
970
971
  /* call the function to dissect this actual tvb */
972
0
  result = dissect_mtp2_tvb(tvb, pinfo,
973
0
      mtp2_ppd->mtp2_flag_search,
974
0
      mtp2_ppd->data_buff,
975
0
      mtp2_ppd->data_buff_offset,
976
0
      mtp2_ppd->state,
977
0
      mtp2_ppd->last_flag_beginning_offset_for_align_check);
978
979
  /* if this is the first time, do the reassemble things
980
   * else just check for reassembled data */
981
0
  if (pinfo->fd->visited == false) {
982
    /* if there was a flag in this tvb, the data found before the 1st flag
983
     * have to be treated differently than the data found after the last flag
984
     * this means we need to use different reass_seq_num when adding them to the reass. handler */
985
0
    if (result->flag_found == true) {
986
      /* add the data found before the first flag with the same reass_seq_num as the
987
       * data found after the last flag in the previous packet in this direction */
988
0
      fragment_add_seq_next(&mtp2_reassembly_table, /* bookkeeping table */
989
0
          result->mtp2_remain_data.before_first_flag, /* tvb containing the data which was unidentified before the first flag */
990
0
          0, /* offset is 0 because this tvb contains the unidentified data only */
991
0
          pinfo,
992
0
          mtp2_ppd->reass_seq_num_for_reass_check_before_fh, /* sequence number of the fragment stream */
993
0
          NULL, /* additional data to identify the segment */
994
0
          tvb_reported_length_remaining(result->mtp2_remain_data.before_first_flag, 0), /* length is the whole tvb's length */
995
0
          false); /* there are no more fragments */
996
997
      /* get a new reass seq num for the data found after the last flag */
998
0
      mtp2_ppd->reass_seq_num_for_reass_check_after_lh = reass_seq_num = get_new_reass_seq_num();
999
1000
      /* if there were data found after the last flag, add it to the reass. handler with the new reass_seq_num */
1001
0
      if (result->mtp2_remain_data.after_last_flag != NULL) {
1002
0
        fragment_add_seq_next(&mtp2_reassembly_table, /* bookkeeping table */
1003
0
            result->mtp2_remain_data.after_last_flag, /* tvb containing the data which was unidentified before the first flag */
1004
0
            0, /* offset is 0 because this tvb contains the unidentified data only */
1005
0
            pinfo,
1006
0
            mtp2_ppd->reass_seq_num_for_reass_check_after_lh, /* sequence number of the fragment stream */
1007
0
            NULL, /* additional data to identify the segment */
1008
0
            tvb_reported_length_remaining(result->mtp2_remain_data.after_last_flag, 0), /* length is the whole tvb's length */
1009
0
            true); /* there are more fragments */
1010
0
      }
1011
0
    } else {
1012
      /* here the increment of the reass_seq_num is not needed because this RTP frame was completely part
1013
       * of an MTP2 frame beginning in the previous packet
1014
       * this need to be added with the same reass_seq_num */
1015
0
      if (result->mtp2_remain_data.after_last_flag != NULL) {
1016
0
        fragment_add_seq_next(&mtp2_reassembly_table, /* bookkeeping table */
1017
0
            result->mtp2_remain_data.after_last_flag, /* tvb containing the data which was unidentified before the first flag */
1018
0
            0, /* offset is 0 because this tvb contains the unidentified data only */
1019
0
            pinfo,
1020
0
            mtp2_ppd->reass_seq_num_for_reass_check_before_fh, /* sequence number of the fragment stream */
1021
0
            NULL, /* additional data to identify the segment */
1022
0
            tvb_reported_length_remaining(result->mtp2_remain_data.after_last_flag, 0), /* length is the whole tvb's length */
1023
0
            true); /* there are more fragments */
1024
0
      }
1025
0
    }
1026
    /* store the values in convo_data
1027
     * but just in case if this packet was not seen before
1028
     * if it was
1029
     *   then the convo data shall not be used (contains inappropriate info for us
1030
     *   the actual values needed for reassembly should be get from the mtp2_ppd
1031
     *   therefore no need to set the convo data */
1032
    /* differentiate between forward and backward directions */
1033
0
    if (dir_state == FORWARD) {
1034
0
      set_direction_fields_based_on_result_and_reass_seq_num(convo_data->forward, result, reass_seq_num);
1035
0
    } else {
1036
0
      set_direction_fields_based_on_result_and_reass_seq_num(convo_data->backward, result, reass_seq_num);
1037
0
    }
1038
1039
  /* if the packet was seen before */
1040
0
  } else {
1041
0
    tvbuff_t            *new_tvb = NULL;
1042
0
    fragment_head       *frag_msg_before_fh = NULL;
1043
0
    fragment_head       *frag_msg_after_lh = NULL;
1044
0
    char                *col_info_str = NULL;           /* char array to store temporary string for col info update */
1045
1046
    /* get the fragment data both for before first and after last flags */
1047
    /* before first flag */
1048
0
    frag_msg_before_fh = fragment_get_reassembled_id(&mtp2_reassembly_table,
1049
0
        pinfo,
1050
0
        mtp2_ppd->reass_seq_num_for_reass_check_before_fh);
1051
    /* after last flag */
1052
0
    frag_msg_after_lh = fragment_get_reassembled_id(&mtp2_reassembly_table,
1053
0
        pinfo,
1054
0
        mtp2_ppd->reass_seq_num_for_reass_check_after_lh);
1055
    /* if there is reassembled data before the first flag */
1056
0
    if (frag_msg_before_fh != NULL) {
1057
      /* get the reassembled tvb */
1058
0
      new_tvb = process_reassembled_data(result->mtp2_remain_data.before_first_flag,
1059
0
          0,
1060
0
          pinfo,
1061
0
          (result->mtp2_remain_data.before_fh_unalignment_offset != 0
1062
0
              ?"Reassembled MTP2 Packet [Unaligned]"
1063
0
              :"Reassembled MTP2 Packet"),
1064
0
          frag_msg_before_fh,
1065
0
          &mtp2_frag_items,
1066
0
          NULL,
1067
0
          tree);
1068
      /* there is reassembled data */
1069
0
      if (new_tvb != NULL && tvb_reported_length_remaining(new_tvb, 0) > 0) {
1070
1071
        /* if there was a frame reset before the first flag */
1072
0
        if (result->mtp2_remain_data.before_fh_frame_reset == true) {
1073
          /* issue frame reset */
1074
0
          issue_frame_reset_info(tree, new_tvb);
1075
          /* prepare col_info string */
1076
0
          col_info_str = "[Frame Reset in reassembly]";
1077
0
        } else {
1078
          /* append the reassembled packet to the head of the packet list */
1079
0
          wmem_list_prepend(result->found_packets, prepare_data_for_found_packet(new_tvb,pinfo->pool,result->mtp2_remain_data.before_fh_unalignment_offset));
1080
          /* set the protocol name */
1081
0
          col_set_str(pinfo->cinfo, COL_PROTOCOL, "MTP2");
1082
0
        }
1083
0
      }
1084
0
    }
1085
1086
    /* if there were packets found */
1087
0
    if (wmem_list_count(result->found_packets) != 0) {
1088
      /* boolean variable to help to print proper col_info if unaligned packet is found */
1089
0
      bool was_unaligned_packet = false;
1090
      /* pointer walking through the list of found packets */
1091
0
      wmem_list_frame_t *recognized_packet = wmem_list_head(result->found_packets);
1092
1093
      /* info field pre-set, we can see the MTP2 strings even if there is an error in the dissection */
1094
0
      col_set_str(pinfo->cinfo, COL_PROTOCOL, "MTP2");
1095
0
      col_set_str(pinfo->cinfo, COL_INFO, "MTP2");
1096
      /* while there are available packets */
1097
0
      while (recognized_packet != NULL) {
1098
0
        mtp2_recognized_packet_t *recognized_packet_data = (mtp2_recognized_packet_t *) wmem_list_frame_data(recognized_packet);
1099
0
        if (recognized_packet_data->unalignment_offset == 0) {
1100
          /* pass the data to the mtp2 dissector */
1101
0
          add_new_data_source(pinfo, recognized_packet_data->data, "MTP2 packet");
1102
0
          dissect_mtp2_common(recognized_packet_data->data, pinfo, tree, false, use_extended_sequence_numbers_default);
1103
0
        } else {
1104
0
          add_new_data_source(pinfo, recognized_packet_data->data, "MTP2 packet [Unaligned]");
1105
0
          issue_unaligned_info(tree, recognized_packet_data->data, recognized_packet_data->unalignment_offset);
1106
0
          was_unaligned_packet = true;
1107
0
        }
1108
1109
        /* increment the pointer */
1110
0
        recognized_packet = wmem_list_frame_next(recognized_packet);
1111
0
      }
1112
      /* insert how many packets were found */
1113
0
      col_info_str = wmem_strdup_printf(pinfo->pool, "%s: %u Packet%s%s%s",
1114
0
          "MTP2",
1115
0
          wmem_list_count(result->found_packets),
1116
0
          (wmem_list_count(result->found_packets) > 1
1117
0
              ?"s"
1118
0
              :""
1119
0
          ),
1120
0
          (was_unaligned_packet
1121
0
              ?wmem_strdup_printf(pinfo->pool, " [Unaligned Packet%s]", (wmem_list_count(result->found_packets)>1
1122
0
                  ?"s"
1123
0
                  :""))
1124
0
              :""
1125
0
          ),
1126
0
          (col_info_str == NULL
1127
0
              ?""
1128
0
              :col_info_str
1129
0
          )
1130
0
          );
1131
0
      col_add_str(pinfo->cinfo, COL_INFO, col_info_str);
1132
    /* if there were no packets found */
1133
0
    } else {
1134
0
      if (tvb_reported_length_remaining(result->mtp2_remain_data.before_first_flag,0) == 0
1135
0
          && result->mtp2_remain_data.after_last_flag != NULL
1136
0
          && frag_msg_before_fh)
1137
0
      {
1138
0
        col_set_str(pinfo->cinfo, COL_PROTOCOL, "MTP2");
1139
0
        col_info_str = wmem_strdup_printf(pinfo->pool, "[MTP2 Reassembled in: %u]", frag_msg_before_fh->reassembled_in);
1140
0
        col_add_str(pinfo->cinfo, COL_INFO, col_info_str);
1141
0
      } else {
1142
0
        col_set_str(pinfo->cinfo, COL_PROTOCOL, "MTP2");
1143
0
        col_info_str = "[MTP2 No Packets]";
1144
0
        col_set_str(pinfo->cinfo, COL_INFO, col_info_str);
1145
0
      }
1146
0
    }
1147
    /* this adds the "Reassembled in" text to the proto tree to the packet where there is leftover data at the end */
1148
0
    process_reassembled_data(result->mtp2_remain_data.after_last_flag,
1149
0
        0,
1150
0
        pinfo,
1151
0
        "Reassembled MTP2 Packet",
1152
0
        frag_msg_after_lh,
1153
0
        &mtp2_frag_items,
1154
0
        NULL,
1155
0
        tree);
1156
0
  }
1157
1158
  /* the whole tvb was processed */
1159
0
  return tvb_captured_length(tvb);
1160
0
}
1161
1162
void
1163
proto_register_mtp2(void)
1164
16
{
1165
1166
16
  static hf_register_info hf[] = {
1167
16
    { &hf_mtp2_bsn,       { "Backward sequence number", "mtp2.bsn",      FT_UINT8,  BASE_DEC, NULL,                    BSN_MASK,            NULL, HFILL } },
1168
16
    { &hf_mtp2_ext_bsn,   { "Backward sequence number", "mtp2.bsn",      FT_UINT16, BASE_DEC, NULL,                    EXTENDED_BSN_MASK,   NULL, HFILL } },
1169
16
    { &hf_mtp2_ext_res,   { "Reserved",                 "mtp2.res",      FT_UINT16, BASE_DEC, NULL,                    EXTENDED_RES_MASK,   NULL, HFILL } },
1170
16
    { &hf_mtp2_bib,       { "Backward indicator bit",   "mtp2.bib",      FT_UINT8,  BASE_DEC, NULL,                    BIB_MASK,            NULL, HFILL } },
1171
16
    { &hf_mtp2_ext_bib,   { "Backward indicator bit",   "mtp2.bib",      FT_UINT16, BASE_DEC, NULL,                    EXTENDED_BIB_MASK,   NULL, HFILL } },
1172
16
    { &hf_mtp2_fsn,       { "Forward sequence number",  "mtp2.fsn",      FT_UINT8,  BASE_DEC, NULL,                    FSN_MASK,            NULL, HFILL } },
1173
16
    { &hf_mtp2_ext_fsn,   { "Forward sequence number",  "mtp2.fsn",      FT_UINT16, BASE_DEC, NULL,                    EXTENDED_FSN_MASK,   NULL, HFILL } },
1174
16
    { &hf_mtp2_fib,       { "Forward indicator bit",    "mtp2.fib",      FT_UINT8,  BASE_DEC, NULL,                    FIB_MASK,            NULL, HFILL } },
1175
16
    { &hf_mtp2_ext_fib,   { "Forward indicator bit",    "mtp2.fib",      FT_UINT16, BASE_DEC, NULL,                    EXTENDED_FIB_MASK,   NULL, HFILL } },
1176
16
    { &hf_mtp2_li,        { "Length Indicator",         "mtp2.li",       FT_UINT8,  BASE_DEC, NULL,                    LI_MASK,             NULL, HFILL } },
1177
16
    { &hf_mtp2_ext_li,    { "Length Indicator",         "mtp2.li",       FT_UINT16, BASE_DEC, NULL,                    EXTENDED_LI_MASK,    NULL, HFILL } },
1178
16
    { &hf_mtp2_spare,     { "Spare",                    "mtp2.spare",    FT_UINT8,  BASE_DEC, NULL,                    SPARE_MASK,          NULL, HFILL } },
1179
16
    { &hf_mtp2_ext_spare, { "Spare",                    "mtp2.spare",    FT_UINT16, BASE_DEC, NULL,                    EXTENDED_SPARE_MASK, NULL, HFILL } },
1180
16
    { &hf_mtp2_sf,        { "Status field",             "mtp2.sf",       FT_UINT8,  BASE_DEC, VALS(status_field_vals), 0x0,                 NULL, HFILL } },
1181
16
    { &hf_mtp2_sf_extra,  { "Status field extra octet", "mtp2.sf_extra", FT_UINT8,  BASE_HEX, NULL,                    0x0,                 NULL, HFILL } },
1182
16
    { &hf_mtp2_fcs_16,    { "FCS 16",                   "mtp2.fcs_16",   FT_UINT16, BASE_HEX, NULL,                    0x0,                 NULL, HFILL } },
1183
16
    { &hf_mtp2_fcs_16_status, { "FCS 16",               "mtp2.fcs_16.status", FT_UINT8, BASE_NONE, VALS(proto_checksum_vals), 0x0,          NULL, HFILL } },
1184
16
    { &hf_mtp2_unexpect_end, { "Unexpected packet end","mtp2.unexpected_end", FT_NONE, BASE_NONE, NULL,                0x0,                 NULL, HFILL } },
1185
16
    { &hf_mtp2_frame_reset, { "Frame reset",           "mtp2.frame_reset", FT_NONE, BASE_NONE, NULL,                   0x0,                 NULL, HFILL } },
1186
    /* extend header fields with the reassemble ones */
1187
16
    {&hf_mtp2_fragments,
1188
16
        {"Message fragments", "mtp2.msg.fragments",
1189
16
        FT_NONE, BASE_NONE, NULL, 0x00, NULL, HFILL } },
1190
16
    {&hf_mtp2_fragment,
1191
16
        {"Message fragment", "mtp2.msg.fragment",
1192
16
        FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL } },
1193
16
    {&hf_mtp2_fragment_overlap,
1194
16
        {"Message fragment overlap", "mtp2.msg.fragment.overlap",
1195
16
        FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL } },
1196
16
    {&hf_mtp2_fragment_overlap_conflicts,
1197
16
        {"Message fragment overlapping with conflicting data",
1198
16
        "mtp2.msg.fragment.overlap.conflicts",
1199
16
        FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL } },
1200
16
    {&hf_mtp2_fragment_multiple_tails,
1201
16
        {"Message has multiple tail fragments",
1202
16
        "mtp2.msg.fragment.multiple_tails",
1203
16
        FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL } },
1204
16
    {&hf_mtp2_fragment_too_long_fragment,
1205
16
        {"Message fragment too long", "mtp2.msg.fragment.too_long_fragment",
1206
16
        FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL } },
1207
16
    {&hf_mtp2_fragment_error,
1208
16
        {"Message defragmentation error", "mtp2.msg.fragment.error",
1209
16
        FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL } },
1210
16
    {&hf_mtp2_fragment_count,
1211
16
        {"Message defragmentation count", "mtp2.msg.fragment.count",
1212
16
        FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL } },
1213
16
    {&hf_mtp2_reassembled_in,
1214
16
        {"Reassembled in", "mtp2.msg.reassembled.in",
1215
16
        FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL } },
1216
16
    {&hf_mtp2_reassembled_length,
1217
16
        {"Reassembled length", "mtp2.msg.reassembled.length",
1218
16
        FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL } }
1219
16
  };
1220
1221
16
  static int *ett[] = {
1222
16
    &ett_mtp2,
1223
    /* extend ett with the fragment fields */
1224
16
    &ett_mtp2_fragment,
1225
16
    &ett_mtp2_fragments
1226
16
  };
1227
1228
16
  static ei_register_info ei[] = {
1229
16
     { &ei_mtp2_checksum_error, { "mtp2.checksum.error", PI_CHECKSUM, PI_WARN, "MTP2 Frame CheckFCS 16 Error", EXPFILL }},
1230
16
     { &ei_mtp2_li_bad, { "mtp2.li.bad", PI_PROTOCOL, PI_WARN, "Bad length indicator value", EXPFILL }},
1231
16
  };
1232
1233
16
  module_t *mtp2_module;
1234
16
  expert_module_t* expert_mtp2;
1235
1236
16
  proto_mtp2 = proto_register_protocol("Message Transfer Part Level 2", "MTP2", "mtp2");
1237
16
  mtp2_handle = register_dissector("mtp2", dissect_mtp2, proto_mtp2);
1238
16
  register_dissector("mtp2_with_crc", dissect_mtp2_with_crc, proto_mtp2);
1239
16
  mtp2_with_phdr_handle = register_dissector("mtp2_with_phdr", dissect_mtp2_with_phdr,
1240
16
                                                  proto_mtp2);
1241
16
  mtp2_bitstream_handle = register_dissector("mtp2_bitstream", dissect_mtp2_bitstream, proto_mtp2);
1242
1243
16
  proto_register_field_array(proto_mtp2, hf, array_length(hf));
1244
16
  proto_register_subtree_array(ett, array_length(ett));
1245
16
  expert_mtp2 = expert_register_protocol(proto_mtp2);
1246
16
  expert_register_field_array(expert_mtp2, ei, array_length(ei));
1247
1248
16
  mtp2_module = prefs_register_protocol(proto_mtp2, NULL);
1249
16
  prefs_register_bool_preference(mtp2_module,
1250
16
                                 "use_extended_sequence_numbers",
1251
16
                                 "Use extended sequence numbers",
1252
16
                                 "Whether the MTP2 dissector should use extended sequence numbers as described in Q.703, Annex A as a default.",
1253
16
                                 &use_extended_sequence_numbers_default);
1254
16
  prefs_register_bool_preference(mtp2_module,
1255
16
                                 "capture_contains_frame_check_sequence",
1256
16
                                 "Assume packets have FCS",
1257
16
                                 "Some SS7 capture hardware includes the FCS at the end of the packet, others do not.",
1258
16
                                 &capture_contains_fcs_crc_default);
1259
1260
  /* register bool and range preferences */
1261
16
  prefs_register_bool_preference(mtp2_module,
1262
16
                                 "reverse_bit_order_mtp2",
1263
16
                                 "Reverse bit order inside bytes",
1264
16
                                 "Reverse the bit order inside bytes specified in Q.703.",
1265
16
                                 &reverse_bit_order_mtp2);
1266
16
  prefs_register_obsolete_preference(mtp2_module, "rtp_payload_type");
1267
1268
16
  reassembly_table_register(&mtp2_reassembly_table, &addresses_ports_reassembly_table_functions);
1269
16
}
1270
1271
void
1272
proto_reg_handoff_mtp2(void)
1273
16
{
1274
16
  dissector_add_uint("wtap_encap", WTAP_ENCAP_MTP2, mtp2_handle);
1275
16
  dissector_add_uint("wtap_encap", WTAP_ENCAP_MTP2_WITH_PHDR,
1276
16
                                   mtp2_with_phdr_handle);
1277
1278
16
  mtp3_handle   = find_dissector_add_dependency("mtp3", proto_mtp2);
1279
1280
16
  dissector_add_string("rtp_dyn_payload_type", "MTP2", mtp2_bitstream_handle);
1281
1282
16
  dissector_add_uint_range_with_preference("rtp.pt", "", mtp2_bitstream_handle);
1283
16
}
1284
1285
/*
1286
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
1287
 *
1288
 * Local Variables:
1289
 * c-basic-offset: 2
1290
 * tab-width: 8
1291
 * indent-tabs-mode: nil
1292
 * End:
1293
 *
1294
 * ex: set shiftwidth=2 tabstop=8 expandtab:
1295
 * :indentSize=2:tabSize=8:noTabs=true:
1296
 */