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