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