1 /* packet-t38.c
2  * Routines for T.38 packet dissection
3  * 2003  Hans Viens
4  * 2004  Alejandro Vaquero, add support Conversations for SDP
5  * 2006  Alejandro Vaquero, add T30 reassemble and dissection
6  *
7  * Wireshark - Network traffic analyzer
8  * By Gerald Combs <gerald@wireshark.org>
9  * Copyright 1998 Gerald Combs
10  *
11  * SPDX-License-Identifier: GPL-2.0-or-later
12  */
13 
14 
15 /* Depending on what ASN.1 specification is used you may have to change
16  * the preference setting regarding Pre-Corrigendum ASN.1 specification:
17  * http://www.itu.int/ITU-T/asn1/database/itu-t/t/t38/1998/T38.html  (Pre-Corrigendum=TRUE)
18  * http://www.itu.int/ITU-T/asn1/database/itu-t/t/t38/2003/T38(1998).html (Pre-Corrigendum=TRUE)
19  *
20  * http://www.itu.int/ITU-T/asn1/database/itu-t/t/t38/2003/T38(2002).html (Pre-Corrigendum=FALSE)
21  * http://www.itu.int/ITU-T/asn1/database/itu-t/t/t38/2002/t38.html  (Pre-Corrigendum=FALSE)
22  * http://www.itu.int/ITU-T/asn1/database/itu-t/t/t38/2002-Amd1/T38.html (Pre-Corrigendum=FALSE)
23  */
24 
25 /* TO DO:
26  * - TCP desegmentation is currently not supported for T.38 IFP directly over TCP.
27  * - H.245 dissectors should be updated to start conversations for T.38 similar to RTP.
28  * - Sometimes the last octet is not high-lighted when selecting something in the tree. Bug in PER dissector?
29  * - Add support for RTP payload audio/t38 (draft-jones-avt-audio-t38-03.txt), i.e. T38 in RTP packets.
30  */
31 
32 
33 #include "config.h"
34 
35 #include <epan/packet.h>
36 #include <epan/reassemble.h>
37 #include <epan/conversation.h>
38 #include <epan/tap.h>
39 #include <epan/expert.h>
40 #include <epan/strutil.h>
41 #include <epan/prefs.h>
42 #include <epan/ipproto.h>
43 #include <epan/asn1.h>
44 #include <epan/proto_data.h>
45 
46 #include "packet-t38.h"
47 #include "packet-per.h"
48 #include "packet-tpkt.h"
49 #include "packet-acdr.h"
50 
51 void proto_register_t38(void);
52 
53 static int t38_tap = -1;
54 
55 /* dissect using the Pre Corrigendum T.38 ASN.1 specification (1998) */
56 static gboolean use_pre_corrigendum_asn1_specification = TRUE;
57 
58 /* dissect packets that looks like RTP version 2 packets as RTP     */
59 /* instead of as T.38. This may result in that some T.38 UPTL       */
60 /* packets with sequence number values higher than 32767 may be     */
61 /* shown as RTP packets.                                            */
62 static gboolean dissect_possible_rtpv2_packets_as_rtp = FALSE;
63 
64 
65 /* Reassembly of T.38 PDUs over TPKT over TCP */
66 static gboolean t38_tpkt_reassembly = TRUE;
67 
68 /* Preference setting whether TPKT header is used when sending T.38 over TCP.
69  * The default setting is Maybe where the dissector will look on the first
70  * bytes to try to determine whether TPKT header is used or not. This may not
71  * work so well in some cases. You may want to change the setting to Always or
72  * Newer.
73  */
74 #define T38_TPKT_NEVER 0   /* Assume that there is never a TPKT header    */
75 #define T38_TPKT_ALWAYS 1  /* Assume that there is always a TPKT header   */
76 #define T38_TPKT_MAYBE 2   /* Assume TPKT if first octets are 03-00-xx-xx */
77 static gint t38_tpkt_usage = T38_TPKT_MAYBE;
78 
79 static const enum_val_t t38_tpkt_options[] = {
80   {"never", "Never", T38_TPKT_NEVER},
81   {"always", "Always", T38_TPKT_ALWAYS},
82   {"maybe", "Maybe", T38_TPKT_MAYBE},
83   {NULL, NULL, -1}
84 };
85 
86 
87 
88 /* T38 */
89 static dissector_handle_t t38_udp_handle;
90 static dissector_handle_t t38_tcp_handle;
91 static dissector_handle_t t38_tcp_pdu_handle;
92 static dissector_handle_t rtp_handle;
93 static dissector_handle_t t30_hdlc_handle;
94 static dissector_handle_t data_handle;
95 
96 static gint32 Type_of_msg_value;
97 static guint32 Data_Field_field_type_value;
98 static guint32 Data_value;
99 static guint32 T30ind_value;
100 static guint32 Data_Field_item_num;
101 
102 static int proto_t38 = -1;
103 static int proto_acdr = -1;
104 #include "packet-t38-hf.c"
105 
106 /* T38 setup fields */
107 static int hf_t38_setup        = -1;
108 static int hf_t38_setup_frame  = -1;
109 static int hf_t38_setup_method = -1;
110 
111 /* T38 Data reassemble fields */
112 static int hf_t38_fragments = -1;
113 static int hf_t38_fragment = -1;
114 static int hf_t38_fragment_overlap = -1;
115 static int hf_t38_fragment_overlap_conflicts = -1;
116 static int hf_t38_fragment_multiple_tails = -1;
117 static int hf_t38_fragment_too_long_fragment = -1;
118 static int hf_t38_fragment_error = -1;
119 static int hf_t38_fragment_count = -1;
120 static int hf_t38_reassembled_in = -1;
121 static int hf_t38_reassembled_length = -1;
122 
123 static gint ett_t38 = -1;
124 #include "packet-t38-ett.c"
125 static gint ett_t38_setup = -1;
126 
127 static gint ett_data_fragment = -1;
128 static gint ett_data_fragments = -1;
129 
130 static expert_field ei_t38_malformed = EI_INIT;
131 
132 static gboolean primary_part = TRUE;
133 static guint32 seq_number = 0;
134 
135 /* Tables for reassembly of Data fragments. */
136 static reassembly_table data_reassembly_table;
137 
138 static const fragment_items data_frag_items = {
139 	/* Fragment subtrees */
140 	&ett_data_fragment,
141 	&ett_data_fragments,
142 	/* Fragment fields */
143 	&hf_t38_fragments,
144 	&hf_t38_fragment,
145 	&hf_t38_fragment_overlap,
146 	&hf_t38_fragment_overlap_conflicts,
147 	&hf_t38_fragment_multiple_tails,
148 	&hf_t38_fragment_too_long_fragment,
149 	&hf_t38_fragment_error,
150 	&hf_t38_fragment_count,
151 	/* Reassembled in field */
152 	&hf_t38_reassembled_in,
153 	/* Reassembled length field */
154 	&hf_t38_reassembled_length,
155 	/* Reassembled data field */
156 	NULL,
157 	/* Tag */
158 	"Data fragments"
159 };
160 
161 typedef struct _fragment_key {
162 	address src;
163 	address dst;
164 	guint32	id;
165 } fragment_key;
166 
167 static conversation_t *p_conv= NULL;
168 static t38_conv *p_t38_conv = NULL;
169 static t38_conv *p_t38_packet_conv = NULL;
170 static t38_conv_info *p_t38_conv_info = NULL;
171 static t38_conv_info *p_t38_packet_conv_info = NULL;
172 
173 /* RTP Version is the first 2 bits of the first octet in the UDP payload*/
174 #define RTP_VERSION(octet)	((octet) >> 6)
175 
176 void proto_reg_handoff_t38(void);
177 
178 static void show_setup_info(tvbuff_t *tvb, proto_tree *tree, t38_conv *p_t38_conv);
179 /* Preferences bool to control whether or not setup info should be shown */
180 static gboolean global_t38_show_setup_info = TRUE;
181 
182 /* Can tap up to 4 T38 packets within same packet */
183 /* We only tap the primary part, not the redundancy */
184 #define MAX_T38_MESSAGES_IN_PACKET 4
185 static t38_packet_info t38_info_arr[MAX_T38_MESSAGES_IN_PACKET];
186 static int t38_info_current=0;
187 static t38_packet_info *t38_info=NULL;
188 
189 
190 /* Set up an T38 conversation */
t38_add_address(packet_info * pinfo,address * addr,int port,int other_port,const gchar * setup_method,guint32 setup_frame_number)191 void t38_add_address(packet_info *pinfo,
192                      address *addr, int port,
193                      int other_port,
194                      const gchar *setup_method, guint32 setup_frame_number)
195 {
196         address null_addr;
197         conversation_t* p_conversation;
198         t38_conv* p_conversation_data = NULL;
199 
200         /*
201          * If this isn't the first time this packet has been processed,
202          * we've already done this work, so we don't need to do it
203          * again.
204          */
205         if ((pinfo->fd->visited) || (t38_udp_handle == NULL))
206         {
207                 return;
208         }
209 
210         clear_address(&null_addr);
211 
212         /*
213          * Check if the ip address and port combination is not
214          * already registered as a conversation.
215          */
216         p_conversation = find_conversation( setup_frame_number, addr, &null_addr, ENDPOINT_UDP, port, other_port,
217                                 NO_ADDR_B | (!other_port ? NO_PORT_B : 0));
218 
219         /*
220          * If not, create a new conversation.
221          */
222         if ( !p_conversation || p_conversation->setup_frame != setup_frame_number) {
223                 p_conversation = conversation_new( setup_frame_number, addr, &null_addr, ENDPOINT_UDP,
224                                            (guint32)port, (guint32)other_port,
225                                                                    NO_ADDR2 | (!other_port ? NO_PORT2 : 0));
226         }
227 
228         /* Set dissector */
229         conversation_set_dissector(p_conversation, t38_udp_handle);
230 
231         /*
232          * Check if the conversation has data associated with it.
233          */
234         p_conversation_data = (t38_conv*)conversation_get_proto_data(p_conversation, proto_t38);
235 
236         /*
237          * If not, add a new data item.
238          */
239         if ( ! p_conversation_data ) {
240                 /* Create conversation data */
241                 p_conversation_data = wmem_new(wmem_file_scope(), t38_conv);
242 
243                 conversation_add_proto_data(p_conversation, proto_t38, p_conversation_data);
244         }
245 
246         /*
247          * Update the conversation data.
248          */
249         (void) g_strlcpy(p_conversation_data->setup_method, setup_method, MAX_T38_SETUP_METHOD_SIZE);
250         p_conversation_data->setup_frame_number = setup_frame_number;
251         p_conversation_data->src_t38_info.reass_ID = 0;
252         p_conversation_data->src_t38_info.reass_start_seqnum = -1;
253         p_conversation_data->src_t38_info.reass_data_type = 0;
254         p_conversation_data->src_t38_info.last_seqnum = -1;
255         p_conversation_data->src_t38_info.packet_lost = 0;
256         p_conversation_data->src_t38_info.burst_lost = 0;
257         p_conversation_data->src_t38_info.time_first_t4_data = 0;
258         p_conversation_data->src_t38_info.additional_hdlc_data_field_counter = 0;
259         p_conversation_data->src_t38_info.seqnum_prev_data_field = -1;
260 
261         p_conversation_data->dst_t38_info.reass_ID = 0;
262         p_conversation_data->dst_t38_info.reass_start_seqnum = -1;
263         p_conversation_data->dst_t38_info.reass_data_type = 0;
264         p_conversation_data->dst_t38_info.last_seqnum = -1;
265         p_conversation_data->dst_t38_info.packet_lost = 0;
266         p_conversation_data->dst_t38_info.burst_lost = 0;
267         p_conversation_data->dst_t38_info.time_first_t4_data = 0;
268         p_conversation_data->dst_t38_info.additional_hdlc_data_field_counter = 0;
269         p_conversation_data->dst_t38_info.seqnum_prev_data_field = -1;
270 }
271 
272 
273 static fragment_head *
force_reassemble_seq(reassembly_table * table,packet_info * pinfo,guint32 id)274 force_reassemble_seq(reassembly_table *table, packet_info *pinfo, guint32 id)
275 {
276 	fragment_head *fd_head;
277 	fragment_item *fd_i;
278 	fragment_item *last_fd;
279 	guint32 dfpos, size, packet_lost, burst_lost, seq_num;
280 	guint8 *data;
281 
282 	fd_head = fragment_get(table, pinfo, id, NULL);
283 
284 	/* have we already seen this frame ?*/
285 	if (pinfo->fd->visited) {
286 		if (fd_head != NULL && fd_head->flags & FD_DEFRAGMENTED) {
287 			return fd_head;
288 		} else {
289 			return NULL;
290 		}
291 	}
292 
293 	if (fd_head==NULL){
294 		/* we must have it to continue */
295 		return NULL;
296 	}
297 
298 	/* check for packet lost and count the burst of packet lost */
299 	packet_lost = 0;
300 	burst_lost = 0;
301 	seq_num = 0;
302 	for(fd_i=fd_head->next;fd_i;fd_i=fd_i->next) {
303 		if (seq_num != fd_i->offset) {
304 			packet_lost += fd_i->offset - seq_num;
305 			if ( (fd_i->offset - seq_num) > burst_lost ) {
306 				burst_lost = fd_i->offset - seq_num;
307 			}
308 		}
309 		seq_num = fd_i->offset + 1;
310 	}
311 
312 	/* we have received an entire packet, defragment it and
313 	 * free all fragments
314 	 */
315 	size=0;
316 	last_fd=NULL;
317 	for(fd_i=fd_head->next;fd_i;fd_i=fd_i->next) {
318 	  if(!last_fd || last_fd->offset!=fd_i->offset){
319 	    size+=fd_i->len;
320 	  }
321 	  last_fd=fd_i;
322 	}
323 
324 	data = (guint8 *) wmem_alloc(pinfo->pool, size);
325 	fd_head->tvb_data = tvb_new_real_data(data, size, size);
326 	fd_head->len = size;		/* record size for caller	*/
327 
328 	/* add all data fragments */
329 	dfpos = 0;
330 	last_fd=NULL;
331 	for (fd_i=fd_head->next;fd_i && fd_i->len + dfpos <= size;fd_i=fd_i->next) {
332 	  if (fd_i->len) {
333 	    if(!last_fd || last_fd->offset!=fd_i->offset){
334 	      tvb_memcpy(fd_i->tvb_data, data+dfpos, 0, fd_i->len);
335 	      dfpos += fd_i->len;
336 	    } else {
337 	      /* duplicate/retransmission/overlap */
338 	      fd_i->flags    |= FD_OVERLAP;
339 	      fd_head->flags |= FD_OVERLAP;
340 	      if( (last_fd->len!=fd_i->len)
341 		  || tvb_memeql(last_fd->tvb_data, 0, tvb_get_ptr(fd_i->tvb_data, 0, last_fd->len), last_fd->len) ){
342 			fd_i->flags    |= FD_OVERLAPCONFLICT;
343 			fd_head->flags |= FD_OVERLAPCONFLICT;
344 	      }
345 	    }
346 	  }
347 	  last_fd=fd_i;
348 	}
349 
350 	/* we have defragmented the pdu, now free all fragments*/
351 	for (fd_i=fd_head->next;fd_i;fd_i=fd_i->next) {
352 	  if(fd_i->tvb_data){
353 	    tvb_free(fd_i->tvb_data);
354 	    fd_i->tvb_data=NULL;
355 	  }
356 	}
357 
358 	/* mark this packet as defragmented */
359 	fd_head->flags |= FD_DEFRAGMENTED;
360 	fd_head->reassembled_in=pinfo->num;
361 
362 	col_append_fstr(pinfo->cinfo, COL_INFO, " (t4-data Reassembled: %d pack lost, %d pack burst lost)", packet_lost, burst_lost);
363 
364 	p_t38_packet_conv_info->packet_lost = packet_lost;
365 	p_t38_packet_conv_info->burst_lost = burst_lost;
366 
367 	return fd_head;
368 }
369 
370 /* T38 Routines */
371 #include "packet-t38-fn.c"
372 
373 /* initialize the tap t38_info and the conversation */
374 static void
init_t38_info_conv(packet_info * pinfo)375 init_t38_info_conv(packet_info *pinfo)
376 {
377 	/* tap info */
378 	t38_info_current++;
379 	if (t38_info_current==MAX_T38_MESSAGES_IN_PACKET) {
380 		t38_info_current=0;
381 	}
382 	t38_info = &t38_info_arr[t38_info_current];
383 
384 	t38_info->seq_num = 0;
385 	t38_info->type_msg = 0;
386 	t38_info->data_value = 0;
387 	t38_info->t30ind_value =0;
388 	t38_info->setup_frame_number = 0;
389 	t38_info->Data_Field_field_type_value = 0;
390 	t38_info->desc[0] = '\0';
391 	t38_info->desc_comment[0] = '\0';
392 	t38_info->time_first_t4_data = 0;
393 	t38_info->frame_num_first_t4_data = 0;
394 
395 
396 	/*
397 		p_t38_packet_conv hold the conversation info in each of the packets.
398 		p_t38_conv hold the conversation info used to reassemble the HDLC packets, and also the Setup info (e.g SDP)
399 		If we already have p_t38_packet_conv in the packet, it means we already reassembled the HDLC packets, so we don't
400 		need to use p_t38_conv
401 	*/
402 	p_t38_packet_conv = NULL;
403 	p_t38_conv = NULL;
404 
405 	/* Use existing packet info if available */
406 	p_t38_packet_conv = (t38_conv *)p_get_proto_data(wmem_file_scope(), pinfo, proto_t38, 0);
407 
408 
409 	/* find the conversation used for Reassemble and Setup Info */
410 	p_conv = find_conversation(pinfo->num, &pinfo->net_dst, &pinfo->net_src,
411                                    conversation_pt_to_endpoint_type(pinfo->ptype),
412                                    pinfo->destport, pinfo->srcport, NO_ADDR_B | NO_PORT_B);
413 
414 	/* create a conv if it doen't exist */
415 	if (!p_conv) {
416 		p_conv = conversation_new(pinfo->num, &pinfo->net_src, &pinfo->net_dst,
417 			      conversation_pt_to_endpoint_type(pinfo->ptype), pinfo->srcport, pinfo->destport, NO_ADDR_B | NO_PORT_B);
418 
419 		/* Set dissector */
420 		conversation_set_dissector(p_conv, t38_udp_handle);
421 	}
422 
423 	p_t38_conv = (t38_conv *)conversation_get_proto_data(p_conv, proto_t38);
424 
425 	/* create the conversation if it doesn't exist */
426 	if (!p_t38_conv) {
427 		p_t38_conv = wmem_new(wmem_file_scope(), t38_conv);
428 		p_t38_conv->setup_method[0] = '\0';
429 		p_t38_conv->setup_frame_number = 0;
430 
431 		p_t38_conv->src_t38_info.reass_ID = 0;
432 		p_t38_conv->src_t38_info.reass_start_seqnum = -1;
433 		p_t38_conv->src_t38_info.reass_data_type = 0;
434 		p_t38_conv->src_t38_info.last_seqnum = -1;
435 		p_t38_conv->src_t38_info.packet_lost = 0;
436 		p_t38_conv->src_t38_info.burst_lost = 0;
437 		p_t38_conv->src_t38_info.time_first_t4_data = 0;
438 		p_t38_conv->src_t38_info.additional_hdlc_data_field_counter = 0;
439 		p_t38_conv->src_t38_info.seqnum_prev_data_field = -1;
440 
441 		p_t38_conv->dst_t38_info.reass_ID = 0;
442 		p_t38_conv->dst_t38_info.reass_start_seqnum = -1;
443 		p_t38_conv->dst_t38_info.reass_data_type = 0;
444 		p_t38_conv->dst_t38_info.last_seqnum = -1;
445 		p_t38_conv->dst_t38_info.packet_lost = 0;
446 		p_t38_conv->dst_t38_info.burst_lost = 0;
447 		p_t38_conv->dst_t38_info.time_first_t4_data = 0;
448 		p_t38_conv->dst_t38_info.additional_hdlc_data_field_counter = 0;
449 		p_t38_conv->dst_t38_info.seqnum_prev_data_field = -1;
450 
451 		conversation_add_proto_data(p_conv, proto_t38, p_t38_conv);
452 	}
453 
454 	if (!p_t38_packet_conv) {
455 		/* copy the t38 conversation info to the packet t38 conversation */
456 		p_t38_packet_conv = wmem_new(wmem_file_scope(), t38_conv);
457 		(void) g_strlcpy(p_t38_packet_conv->setup_method, p_t38_conv->setup_method, MAX_T38_SETUP_METHOD_SIZE);
458 		p_t38_packet_conv->setup_frame_number = p_t38_conv->setup_frame_number;
459 
460 		memcpy(&(p_t38_packet_conv->src_t38_info), &(p_t38_conv->src_t38_info), sizeof(t38_conv_info));
461 		memcpy(&(p_t38_packet_conv->dst_t38_info), &(p_t38_conv->dst_t38_info), sizeof(t38_conv_info));
462 
463 		p_add_proto_data(wmem_file_scope(), pinfo, proto_t38, 0, p_t38_packet_conv);
464 	}
465 
466 	if (addresses_equal(conversation_key_addr1(p_conv->key_ptr), &pinfo->net_src)) {
467 		p_t38_conv_info = &(p_t38_conv->src_t38_info);
468 		p_t38_packet_conv_info = &(p_t38_packet_conv->src_t38_info);
469 	} else {
470 		p_t38_conv_info = &(p_t38_conv->dst_t38_info);
471 		p_t38_packet_conv_info = &(p_t38_packet_conv->dst_t38_info);
472 	}
473 
474 	/* update t38_info */
475 	t38_info->setup_frame_number = p_t38_packet_conv->setup_frame_number;
476 }
477 
478 /* Entry point for dissection */
479 static int
dissect_t38_udp(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)480 dissect_t38_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
481 {
482 	guint8 octet1;
483 	proto_item *it;
484 	proto_tree *tr;
485 	guint32 offset=0;
486 
487 	/*
488 	 * XXX - heuristic to check for misidentified packets.
489 	 */
490 	if (dissect_possible_rtpv2_packets_as_rtp){
491 		octet1 = tvb_get_guint8(tvb, offset);
492 		if (RTP_VERSION(octet1) == 2){
493 			return call_dissector(rtp_handle,tvb,pinfo,tree);
494 		}
495 	}
496 
497 	col_set_str(pinfo->cinfo, COL_PROTOCOL, "T.38");
498 	col_clear(pinfo->cinfo, COL_INFO);
499 
500 	primary_part = TRUE;
501 
502 	/* This indicate the item number in the primary part of the T38 message, it is used for the reassemble of T30 packets */
503 	Data_Field_item_num = 0;
504 
505 	it=proto_tree_add_protocol_format(tree, proto_t38, tvb, 0, -1, "ITU-T Recommendation T.38");
506 	tr=proto_item_add_subtree(it, ett_t38);
507 
508 	/* init tap and conv info */
509 	init_t38_info_conv(pinfo);
510 
511 	/* Show Conversation setup info if exists*/
512 	if (global_t38_show_setup_info) {
513 		show_setup_info(tvb, tr, p_t38_packet_conv);
514 	}
515 
516 	col_append_str(pinfo->cinfo, COL_INFO, "UDP: UDPTLPacket ");
517 
518 	offset = dissect_UDPTLPacket_PDU(tvb, pinfo, tr, NULL);
519 
520 	if (tvb_reported_length_remaining(tvb,offset)>0){
521 		proto_tree_add_expert_format(tr, pinfo, &ei_t38_malformed, tvb, offset, tvb_reported_length_remaining(tvb, offset),
522 				"[MALFORMED PACKET or wrong preference settings]");
523 		col_append_str(pinfo->cinfo, COL_INFO, " [Malformed?]");
524 	}
525 	return tvb_captured_length(tvb);
526 }
527 
528 static int
dissect_t38_tcp_pdu(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)529 dissect_t38_tcp_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
530 {
531 	proto_item *it;
532 	proto_tree *tr;
533 	guint32 offset=0;
534         tvbuff_t *next_tvb;
535 	guint16 ifp_packet_number=1;
536 
537 	col_set_str(pinfo->cinfo, COL_PROTOCOL, "T.38");
538 	col_clear(pinfo->cinfo, COL_INFO);
539 
540 	primary_part = TRUE;
541 
542 	/* This indicate the item number in the primary part of the T38 message, it is used for the reassemble of T30 packets */
543 	Data_Field_item_num = 0;
544 
545 	it=proto_tree_add_protocol_format(tree, proto_t38, tvb, 0, -1, "ITU-T Recommendation T.38");
546 	tr=proto_item_add_subtree(it, ett_t38);
547 
548 	/* init tap and conv info */
549 	init_t38_info_conv(pinfo);
550 
551 	/* Show Conversation setup info if exists*/
552 	if (global_t38_show_setup_info) {
553 		show_setup_info(tvb, tr, p_t38_packet_conv);
554 	}
555 
556 	col_append_str(pinfo->cinfo, COL_INFO, "TCP: IFPPacket");
557 
558 	while(tvb_reported_length_remaining(tvb,offset)>0)
559 	{
560 		next_tvb = tvb_new_subset_remaining(tvb, offset);
561 		offset += dissect_IFPPacket_PDU(next_tvb, pinfo, tr, NULL);
562 		ifp_packet_number++;
563 
564 		if(tvb_reported_length_remaining(tvb,offset)>0){
565 			if(t38_tpkt_usage == T38_TPKT_ALWAYS){
566 				proto_tree_add_expert_format(tr, pinfo, &ei_t38_malformed, tvb, offset, tvb_reported_length_remaining(tvb, offset),
567 						"[MALFORMED PACKET or wrong preference settings]");
568 				col_append_str(pinfo->cinfo, COL_INFO, " [Malformed?]");
569 				break;
570 			}else {
571 				col_append_fstr(pinfo->cinfo, COL_INFO, " IFPPacket#%u",ifp_packet_number);
572 			}
573 		}
574 	}
575 
576 	return tvb_captured_length(tvb);
577 }
578 
579 static int
dissect_t38_tcp(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)580 dissect_t38_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
581 {
582 	primary_part = TRUE;
583 
584 	if(t38_tpkt_usage == T38_TPKT_ALWAYS){
585 		dissect_tpkt_encap(tvb,pinfo,tree,t38_tpkt_reassembly,t38_tcp_pdu_handle);
586 	}
587 	else if((t38_tpkt_usage == T38_TPKT_NEVER) || (is_tpkt(tvb,1) == -1)){
588 		dissect_t38_tcp_pdu(tvb, pinfo, tree, data);
589 	}
590 	else {
591 		dissect_tpkt_encap(tvb,pinfo,tree,t38_tpkt_reassembly,t38_tcp_pdu_handle);
592 	}
593 	return tvb_captured_length(tvb);
594 }
595 
596 /* Look for conversation info and display any setup info found */
597 void
show_setup_info(tvbuff_t * tvb,proto_tree * tree,t38_conv * p_t38_conversation)598 show_setup_info(tvbuff_t *tvb, proto_tree *tree, t38_conv *p_t38_conversation)
599 {
600 	proto_tree *t38_setup_tree;
601 	proto_item *ti;
602 
603 	if (!p_t38_conversation || p_t38_conversation->setup_frame_number == 0) {
604 		/* there is no Setup info */
605 		return;
606 	}
607 
608 	ti =  proto_tree_add_string_format(tree, hf_t38_setup, tvb, 0, 0,
609                       "",
610                       "Stream setup by %s (frame %u)",
611                       p_t38_conversation->setup_method,
612                       p_t38_conversation->setup_frame_number);
613     proto_item_set_generated(ti);
614     t38_setup_tree = proto_item_add_subtree(ti, ett_t38_setup);
615     if (t38_setup_tree)
616     {
617 		/* Add details into subtree */
618 		proto_item* item = proto_tree_add_uint(t38_setup_tree, hf_t38_setup_frame,
619                                                                tvb, 0, 0, p_t38_conversation->setup_frame_number);
620 		proto_item_set_generated(item);
621 		item = proto_tree_add_string(t38_setup_tree, hf_t38_setup_method,
622                                                      tvb, 0, 0, p_t38_conversation->setup_method);
623 		proto_item_set_generated(item);
624     }
625 }
626 
627 /* This function tries to understand if the payload is sitting on top of AC DR */
628 static gboolean
dissect_t38_acdr_heur(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)629 dissect_t38_acdr_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
630 {
631 	guint acdr_prot = GPOINTER_TO_UINT(p_get_proto_data(pinfo->pool, pinfo, proto_acdr, 0));
632 	if (acdr_prot == ACDR_T38)
633 		return dissect_t38_udp(tvb, pinfo, tree, NULL);
634 	return FALSE;
635 }
636 
637 
638 /* Wireshark Protocol Registration */
639 void
proto_register_t38(void)640 proto_register_t38(void)
641 {
642 	static hf_register_info hf[] =
643 	{
644 #include "packet-t38-hfarr.c"
645 		{   &hf_t38_setup,
646 		    { "Stream setup", "t38.setup", FT_STRING, BASE_NONE,
647 		    NULL, 0x0, "Stream setup, method and frame number", HFILL }},
648 		{   &hf_t38_setup_frame,
649             { "Stream frame", "t38.setup-frame", FT_FRAMENUM, BASE_NONE,
650             NULL, 0x0, "Frame that set up this stream", HFILL }},
651         {   &hf_t38_setup_method,
652             { "Stream Method", "t38.setup-method", FT_STRING, BASE_NONE,
653             NULL, 0x0, "Method used to set up this stream", HFILL }},
654 		{&hf_t38_fragments,
655 			{"Message fragments", "t38.fragments",
656 			FT_NONE, BASE_NONE, NULL, 0x00,	NULL, HFILL } },
657 		{&hf_t38_fragment,
658 			{"Message fragment", "t38.fragment",
659 			FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL } },
660 		{&hf_t38_fragment_overlap,
661 			{"Message fragment overlap", "t38.fragment.overlap",
662 			FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL } },
663 		{&hf_t38_fragment_overlap_conflicts,
664 			{"Message fragment overlapping with conflicting data",
665 			"t38.fragment.overlap.conflicts",
666 			FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL } },
667 		{&hf_t38_fragment_multiple_tails,
668 			{"Message has multiple tail fragments",
669 			"t38.fragment.multiple_tails",
670 			FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL } },
671 		{&hf_t38_fragment_too_long_fragment,
672 			{"Message fragment too long", "t38.fragment.too_long_fragment",
673 			FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL } },
674 		{&hf_t38_fragment_error,
675 			{"Message defragmentation error", "t38.fragment.error",
676 			FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL } },
677 		{&hf_t38_fragment_count,
678 			{"Message fragment count", "t38.fragment.count",
679 			FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL } },
680 		{&hf_t38_reassembled_in,
681 			{"Reassembled in", "t38.reassembled.in",
682 			FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL } },
683 		{&hf_t38_reassembled_length,
684 			{"Reassembled T38 length", "t38.reassembled.length",
685 			FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL } },
686 	};
687 
688 	static gint *ett[] =
689 	{
690 		&ett_t38,
691 #include "packet-t38-ettarr.c"
692 		&ett_t38_setup,
693 		&ett_data_fragment,
694 		&ett_data_fragments
695 	};
696 
697 	static ei_register_info ei[] = {
698 		{ &ei_t38_malformed, { "t38.malformed", PI_MALFORMED, PI_ERROR, "Malformed packet", EXPFILL }},
699 	};
700 
701 	module_t *t38_module;
702 	expert_module_t* expert_t38;
703 
704 	proto_t38 = proto_register_protocol("T.38", "T.38", "t38");
705 	proto_register_field_array(proto_t38, hf, array_length(hf));
706 	proto_register_subtree_array(ett, array_length(ett));
707 	expert_t38 = expert_register_protocol(proto_t38);
708 	expert_register_field_array(expert_t38, ei, array_length(ei));
709 	register_dissector("t38_udp", dissect_t38_udp, proto_t38);
710 
711 	/* Register reassemble tables for HDLC */
712 	reassembly_table_register(&data_reassembly_table,
713                               &addresses_reassembly_table_functions);
714 
715 	t38_tap = register_tap("t38");
716 
717 	t38_module = prefs_register_protocol(proto_t38, NULL);
718 	prefs_register_bool_preference(t38_module, "use_pre_corrigendum_asn1_specification",
719 	    "Use the Pre-Corrigendum ASN.1 specification",
720 	    "Whether the T.38 dissector should decode using the Pre-Corrigendum T.38 "
721 		"ASN.1 specification (1998).",
722 	    &use_pre_corrigendum_asn1_specification);
723 	prefs_register_bool_preference(t38_module, "dissect_possible_rtpv2_packets_as_rtp",
724 	    "Dissect possible RTP version 2 packets with RTP dissector",
725 	    "Whether a UDP packet that looks like RTP version 2 packet will "
726 		"be dissected as RTP packet or T.38 packet. If enabled there is a risk that T.38 UDPTL "
727 		"packets with sequence number higher than 32767 may be dissected as RTP.",
728 	    &dissect_possible_rtpv2_packets_as_rtp);
729 	prefs_register_bool_preference(t38_module, "reassembly",
730 		"Reassemble T.38 PDUs over TPKT over TCP",
731 		"Whether the dissector should reassemble T.38 PDUs spanning multiple TCP segments "
732 		"when TPKT is used over TCP. "
733 		"To use this option, you must also enable \"Allow subdissectors to reassemble "
734 		"TCP streams\" in the TCP protocol settings.",
735 		&t38_tpkt_reassembly);
736 	prefs_register_enum_preference(t38_module, "tpkt_usage",
737 		"TPKT used over TCP",
738 		"Whether T.38 is used with TPKT for TCP",
739 		(gint *)&t38_tpkt_usage,t38_tpkt_options,FALSE);
740 
741 	prefs_register_bool_preference(t38_module, "show_setup_info",
742                 "Show stream setup information",
743                 "Where available, show which protocol and frame caused "
744                 "this T.38 stream to be created",
745                 &global_t38_show_setup_info);
746 
747 }
748 
749 void
proto_reg_handoff_t38(void)750 proto_reg_handoff_t38(void)
751 {
752 	t38_udp_handle=create_dissector_handle(dissect_t38_udp, proto_t38);
753 	t38_tcp_handle=create_dissector_handle(dissect_t38_tcp, proto_t38);
754 	t38_tcp_pdu_handle=create_dissector_handle(dissect_t38_tcp_pdu, proto_t38);
755 	rtp_handle = find_dissector_add_dependency("rtp", proto_t38);
756 	t30_hdlc_handle = find_dissector_add_dependency("t30.hdlc", proto_t38);
757 	proto_acdr = proto_get_id_by_filter_name("acdr");
758 	data_handle = find_dissector("data");
759 	dissector_add_for_decode_as("tcp.port", t38_tcp_handle);
760 	dissector_add_for_decode_as("udp.port", t38_udp_handle);
761 	heur_dissector_add("udp", dissect_t38_acdr_heur, "T38 over AC DR", "t38_acdr", proto_t38, HEURISTIC_ENABLE);
762 	dissector_add_uint("acdr.media_type", ACDR_T38, t38_udp_handle);
763 }
764