* 2004 Alejandro Vaquero, add support Conversations for SDP
* 2006 Alejandro Vaquero, add T30 reassemble and dissection
*
- * $Id$
- *
* Wireshark - Network traffic analyzer
* By Gerald Combs <gerald@wireshark.org>
* Copyright 1998 Gerald Combs
#include "config.h"
-#include <glib.h>
#include <epan/packet.h>
#include <epan/reassemble.h>
#include <epan/conversation.h>
#include <epan/tap.h>
#include <epan/expert.h>
-
-#include <string.h>
-
-#include "packet-t38.h"
+#include <epan/strutil.h>
#include <epan/prefs.h>
#include <epan/ipproto.h>
#include <epan/asn1.h>
+
+#include "packet-t38.h"
#include "packet-per.h"
#include "packet-tpkt.h"
-#include <epan/wmem/wmem.h>
-#include <epan/strutil.h>
void proto_register_t38(void);
-void proto_reg_handoff_t38(void);
#define PORT_T38 6004
static guint global_t38_tcp_port = PORT_T38;
static int hf_t38_fec_data_item = -1; /* OCTET_STRING */
/*--- End of included file: packet-t38-hf.c ---*/
-#line 125 "../../asn1/t38/packet-t38-template.c"
+#line 118 "../../asn1/t38/packet-t38-template.c"
/* T38 setup fields */
static int hf_t38_setup = -1;
static gint ett_t38_T_fec_data = -1;
/*--- End of included file: packet-t38-ett.c ---*/
-#line 145 "../../asn1/t38/packet-t38-template.c"
+#line 138 "../../asn1/t38/packet-t38-template.c"
static gint ett_t38_setup = -1;
static gint ett_data_fragment = -1;
static gint ett_data_fragments = -1;
+static expert_field ei_t38_malformed = EI_INIT;
+
static gboolean primary_part = TRUE;
static guint32 seq_number = 0;
&addresses_reassembly_table_functions);
}
+static void t38_defragment_cleanup(void)
+{
+ reassembly_table_destroy(&data_reassembly_table);
+}
+
/* Set up an T38 conversation */
void t38_add_address(packet_info *pinfo,
* we've already done this work, so we don't need to do it
* again.
*/
- if (pinfo->fd->flags.visited)
+ if ((pinfo->fd->flags.visited) || (t38_udp_handle == NULL))
{
return;
}
- SET_ADDRESS(&null_addr, AT_NONE, 0, NULL);
+ set_address(&null_addr, AT_NONE, 0, NULL);
/*
* Check if the ip address and port combination is not
p_conversation_data->src_t38_info.packet_lost = 0;
p_conversation_data->src_t38_info.burst_lost = 0;
p_conversation_data->src_t38_info.time_first_t4_data = 0;
-
+ p_conversation_data->src_t38_info.additional_hdlc_data_field_counter = 0;
+ p_conversation_data->src_t38_info.seqnum_prev_data_field = -1;
p_conversation_data->dst_t38_info.reass_ID = 0;
p_conversation_data->dst_t38_info.reass_start_seqnum = -1;
p_conversation_data->dst_t38_info.packet_lost = 0;
p_conversation_data->dst_t38_info.burst_lost = 0;
p_conversation_data->dst_t38_info.time_first_t4_data = 0;
+ p_conversation_data->dst_t38_info.additional_hdlc_data_field_counter = 0;
+ p_conversation_data->dst_t38_info.seqnum_prev_data_field = -1;
}
-fragment_head *
+static fragment_head *
force_reassemble_seq(reassembly_table *table, packet_info *pinfo, guint32 id)
{
fragment_head *fd_head;
for (fd_i=fd_head->next;fd_i && fd_i->len + dfpos <= size;fd_i=fd_i->next) {
if (fd_i->len) {
if(!last_fd || last_fd->offset!=fd_i->offset){
- memcpy(data+dfpos,tvb_get_ptr(fd_i->tvb_data,0,fd_i->len),fd_i->len);
+ tvb_memcpy(fd_i->tvb_data, data+dfpos, 0, fd_i->len);
dfpos += fd_i->len;
} else {
/* duplicate/retransmission/overlap */
fd_i->flags |= FD_OVERLAP;
fd_head->flags |= FD_OVERLAP;
- if( (last_fd->len!=fd_i->datalen)
+ if( (last_fd->len!=fd_i->len)
|| tvb_memeql(last_fd->tvb_data, 0, tvb_get_ptr(fd_i->tvb_data, 0, last_fd->len), last_fd->len) ){
fd_i->flags |= FD_OVERLAPCONFLICT;
fd_head->flags |= FD_OVERLAPCONFLICT;
offset = dissect_per_enumerated(tvb, offset, actx, tree, hf_index,
16, &T30ind_value, TRUE, 7, NULL);
-#line 31 "../../asn1/t38/t38.cnf"
+#line 29 "../../asn1/t38/t38.cnf"
if (primary_part){
col_append_fstr(actx->pinfo->cinfo, COL_INFO, " t30ind: %s",
val_to_str(T30ind_value,t38_T30_indicator_vals,"<unknown>"));
offset = dissect_per_enumerated(tvb, offset, actx, tree, hf_index,
9, &Data_value, TRUE, 6, NULL);
-#line 43 "../../asn1/t38/t38.cnf"
+#line 41 "../../asn1/t38/t38.cnf"
if (primary_part){
col_append_fstr(actx->pinfo->cinfo, COL_INFO, " data:%s:",
val_to_str(Data_value,t38_T30_data_vals,"<unknown>"));
ett_t38_Type_of_msg, Type_of_msg_choice,
&Type_of_msg_value);
-#line 24 "../../asn1/t38/t38.cnf"
+#line 22 "../../asn1/t38/t38.cnf"
/* info for tap */
if (primary_part)
t38_info->type_msg = Type_of_msg_value;
offset = dissect_per_enumerated(tvb, offset, actx, tree, hf_index,
8, &Data_Field_field_type_value, (use_pre_corrigendum_asn1_specification)?FALSE:TRUE, (use_pre_corrigendum_asn1_specification)?0:4, NULL);
-#line 63 "../../asn1/t38/t38.cnf"
+#line 61 "../../asn1/t38/t38.cnf"
if (primary_part){
col_append_fstr(actx->pinfo->cinfo, COL_INFO, " %s",
val_to_str(Data_Field_field_type_value,t38_T_field_type_vals,"<unknown>"));
/* Now reset fragmentation information in pinfo */
actx->pinfo->fragmented = save_fragmented;
- actx->pinfo->private_data = t38_info;
- if (new_tvb) call_dissector((t30_hdlc_handle) ? t30_hdlc_handle : data_handle, new_tvb, actx->pinfo, tree);
+ if (new_tvb) call_dissector_with_data((t30_hdlc_handle) ? t30_hdlc_handle : data_handle, new_tvb, actx->pinfo, tree, t38_info);
}
} else {
- if(tree){
- proto_tree_add_text(tree, tvb, offset, tvb_reported_length_remaining(tvb, offset),
+ proto_tree_add_expert_format(tree, actx->pinfo, &ei_t38_malformed, tvb, offset, tvb_reported_length_remaining(tvb, offset),
"[RECEIVED END OF FRAGMENT W/OUT ANY FRAGMENT DATA]");
- }
col_append_str(actx->pinfo->cinfo, COL_INFO, " [Malformed?]");
actx->pinfo->fragmented = save_fragmented;
}
static int
dissect_t38_T_field_data(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
-#line 156 "../../asn1/t38/t38.cnf"
+#line 151 "../../asn1/t38/t38.cnf"
tvbuff_t *value_tvb = NULL;
guint32 value_len;
offset = dissect_per_octet_string(tvb, offset, actx, tree, hf_index,
1, 65535, FALSE, &value_tvb);
- value_len = tvb_length(value_tvb);
+ value_len = tvb_reported_length(value_tvb);
-#line 163 "../../asn1/t38/t38.cnf"
+#line 158 "../../asn1/t38/t38.cnf"
if (primary_part){
if(value_len < 8){
col_append_fstr(actx->pinfo->cinfo, COL_INFO, "[%s]",
- tvb_bytes_to_str(value_tvb,0,value_len));
+ tvb_bytes_to_str(wmem_packet_scope(), value_tvb,0,value_len));
}
else {
col_append_fstr(actx->pinfo->cinfo, COL_INFO, "[%s...]",
- tvb_bytes_to_str(value_tvb,0,7));
+ tvb_bytes_to_str(wmem_packet_scope(), value_tvb,0,7));
}
}
/* we use the first fragment's frame_number as fragment ID because the protocol doesn't provide it */
p_t38_conv_info->reass_ID = actx->pinfo->fd->num;
p_t38_conv_info->reass_start_seqnum = seq_number;
- p_t38_conv_info->time_first_t4_data = nstime_to_sec(&actx->pinfo->fd->rel_ts);
+ p_t38_conv_info->time_first_t4_data = nstime_to_sec(&actx->pinfo->rel_ts);
p_t38_conv_info->additional_hdlc_data_field_counter = 0;
p_t38_packet_conv_info->reass_ID = p_t38_conv_info->reass_ID;
p_t38_packet_conv_info->reass_start_seqnum = p_t38_conv_info->reass_start_seqnum;
offset = dissect_per_sequence(tvb, offset, actx, tree, hf_index,
ett_t38_Data_Field_item, Data_Field_item_sequence);
-#line 55 "../../asn1/t38/t38.cnf"
+#line 53 "../../asn1/t38/t38.cnf"
if (primary_part) Data_Field_item_num++;
return offset;
offset = dissect_per_constrained_integer(tvb, offset, actx, tree, hf_index,
0U, 65535U, &seq_number, FALSE);
-#line 243 "../../asn1/t38/t38.cnf"
+#line 238 "../../asn1/t38/t38.cnf"
/* info for tap */
if (primary_part)
t38_info->seq_num = seq_number;
static int
dissect_t38_T_primary_ifp_packet(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
-#line 251 "../../asn1/t38/t38.cnf"
+#line 246 "../../asn1/t38/t38.cnf"
primary_part = TRUE;
offset = dissect_per_open_type(tvb, offset, actx, tree, hf_index, dissect_t38_IFPPacket);
-#line 253 "../../asn1/t38/t38.cnf"
+#line 248 "../../asn1/t38/t38.cnf"
/* if is a valid t38 packet, add to tap */
- if (p_t38_packet_conv && (!actx->pinfo->flags.in_error_pkt) && ((gint32) seq_number != p_t38_packet_conv_info->last_seqnum))
+ /* Note that t4-non-ecm-sig-end without first_t4_data is not valid */
+ if (p_t38_packet_conv && (!actx->pinfo->flags.in_error_pkt) && ((gint32) seq_number != p_t38_packet_conv_info->last_seqnum) &&
+ !(t38_info->type_msg == 1 && t38_info->Data_Field_field_type_value == 7 && t38_info->frame_num_first_t4_data == 0))
tap_queue_packet(t38_tap, actx->pinfo, t38_info);
if (p_t38_conv) p_t38_conv_info->last_seqnum = (gint32) seq_number;
static int
dissect_t38_T_error_recovery(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
-#line 261 "../../asn1/t38/t38.cnf"
+#line 258 "../../asn1/t38/t38.cnf"
primary_part = FALSE;
offset = dissect_per_choice(tvb, offset, actx, tree, hf_index,
ett_t38_T_error_recovery, T_error_recovery_choice,
NULL);
-#line 263 "../../asn1/t38/t38.cnf"
+#line 260 "../../asn1/t38/t38.cnf"
primary_part = TRUE;
return offset;
static int
dissect_t38_UDPTLPacket(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
-#line 237 "../../asn1/t38/t38.cnf"
+#line 232 "../../asn1/t38/t38.cnf"
/* Initialize to something else than data type */
Data_Field_field_type_value = 1;
/*--- End of included file: packet-t38-fn.c ---*/
-#line 394 "../../asn1/t38/packet-t38-template.c"
+#line 397 "../../asn1/t38/packet-t38-template.c"
/* initialize the tap t38_info and the conversation */
static void
p_t38_conv = NULL;
/* Use existing packet info if available */
- p_t38_packet_conv = (t38_conv *)p_get_proto_data(pinfo->fd, proto_t38, 0);
+ p_t38_packet_conv = (t38_conv *)p_get_proto_data(wmem_file_scope(), pinfo, proto_t38, 0);
/* find the conversation used for Reassemble and Setup Info */
conversation_set_dissector(p_conv, t38_udp_handle);
}
- if (!p_t38_packet_conv) {
- p_t38_conv = (t38_conv *)conversation_get_proto_data(p_conv, proto_t38);
-
- /* create the conversation if it doen't exist */
- if (!p_t38_conv) {
- p_t38_conv = wmem_new(wmem_file_scope(), t38_conv);
- p_t38_conv->setup_method[0] = '\0';
- p_t38_conv->setup_frame_number = 0;
-
- p_t38_conv->src_t38_info.reass_ID = 0;
- p_t38_conv->src_t38_info.reass_start_seqnum = -1;
- p_t38_conv->src_t38_info.reass_data_type = 0;
- p_t38_conv->src_t38_info.last_seqnum = -1;
- p_t38_conv->src_t38_info.packet_lost = 0;
- p_t38_conv->src_t38_info.burst_lost = 0;
- p_t38_conv->src_t38_info.time_first_t4_data = 0;
- p_t38_conv->src_t38_info.additional_hdlc_data_field_counter = 0;
- p_t38_conv->src_t38_info.seqnum_prev_data_field = -1;
-
- p_t38_conv->dst_t38_info.reass_ID = 0;
- p_t38_conv->dst_t38_info.reass_start_seqnum = -1;
- p_t38_conv->dst_t38_info.reass_data_type = 0;
- p_t38_conv->dst_t38_info.last_seqnum = -1;
- p_t38_conv->dst_t38_info.packet_lost = 0;
- p_t38_conv->dst_t38_info.burst_lost = 0;
- p_t38_conv->dst_t38_info.time_first_t4_data = 0;
- p_t38_conv->dst_t38_info.additional_hdlc_data_field_counter = 0;
- p_t38_conv->dst_t38_info.seqnum_prev_data_field = -1;
-
- conversation_add_proto_data(p_conv, proto_t38, p_t38_conv);
- }
+ p_t38_conv = (t38_conv *)conversation_get_proto_data(p_conv, proto_t38);
+
+ /* create the conversation if it doesn't exist */
+ if (!p_t38_conv) {
+ p_t38_conv = wmem_new(wmem_file_scope(), t38_conv);
+ p_t38_conv->setup_method[0] = '\0';
+ p_t38_conv->setup_frame_number = 0;
+
+ p_t38_conv->src_t38_info.reass_ID = 0;
+ p_t38_conv->src_t38_info.reass_start_seqnum = -1;
+ p_t38_conv->src_t38_info.reass_data_type = 0;
+ p_t38_conv->src_t38_info.last_seqnum = -1;
+ p_t38_conv->src_t38_info.packet_lost = 0;
+ p_t38_conv->src_t38_info.burst_lost = 0;
+ p_t38_conv->src_t38_info.time_first_t4_data = 0;
+ p_t38_conv->src_t38_info.additional_hdlc_data_field_counter = 0;
+ p_t38_conv->src_t38_info.seqnum_prev_data_field = -1;
+
+ p_t38_conv->dst_t38_info.reass_ID = 0;
+ p_t38_conv->dst_t38_info.reass_start_seqnum = -1;
+ p_t38_conv->dst_t38_info.reass_data_type = 0;
+ p_t38_conv->dst_t38_info.last_seqnum = -1;
+ p_t38_conv->dst_t38_info.packet_lost = 0;
+ p_t38_conv->dst_t38_info.burst_lost = 0;
+ p_t38_conv->dst_t38_info.time_first_t4_data = 0;
+ p_t38_conv->dst_t38_info.additional_hdlc_data_field_counter = 0;
+ p_t38_conv->dst_t38_info.seqnum_prev_data_field = -1;
+
+ conversation_add_proto_data(p_conv, proto_t38, p_t38_conv);
+ }
+ if (!p_t38_packet_conv) {
/* copy the t38 conversation info to the packet t38 conversation */
p_t38_packet_conv = wmem_new(wmem_file_scope(), t38_conv);
g_strlcpy(p_t38_packet_conv->setup_method, p_t38_conv->setup_method, MAX_T38_SETUP_METHOD_SIZE);
memcpy(&(p_t38_packet_conv->src_t38_info), &(p_t38_conv->src_t38_info), sizeof(t38_conv_info));
memcpy(&(p_t38_packet_conv->dst_t38_info), &(p_t38_conv->dst_t38_info), sizeof(t38_conv_info));
- p_add_proto_data(pinfo->fd, proto_t38, 0, p_t38_packet_conv);
+ p_add_proto_data(wmem_file_scope(), pinfo, proto_t38, 0, p_t38_packet_conv);
}
- if (ADDRESSES_EQUAL(&p_conv->key_ptr->addr1, &pinfo->net_src)) {
+ if (addresses_equal(&p_conv->key_ptr->addr1, &pinfo->net_src)) {
p_t38_conv_info = &(p_t38_conv->src_t38_info);
p_t38_packet_conv_info = &(p_t38_packet_conv->src_t38_info);
} else {
offset = dissect_UDPTLPacket_PDU(tvb, pinfo, tr, NULL);
- if (tvb_length_remaining(tvb,offset)>0){
- if (tr){
- proto_tree_add_text(tr, tvb, offset, tvb_reported_length_remaining(tvb, offset),
+ if (tvb_reported_length_remaining(tvb,offset)>0){
+ proto_tree_add_expert_format(tr, pinfo, &ei_t38_malformed, tvb, offset, tvb_reported_length_remaining(tvb, offset),
"[MALFORMED PACKET or wrong preference settings]");
- }
col_append_str(pinfo->cinfo, COL_INFO, " [Malformed?]");
}
}
col_append_str(pinfo->cinfo, COL_INFO, "TCP: IFPPacket");
- while(tvb_length_remaining(tvb,offset)>0)
+ while(tvb_reported_length_remaining(tvb,offset)>0)
{
next_tvb = tvb_new_subset_remaining(tvb, offset);
offset += dissect_IFPPacket_PDU(next_tvb, pinfo, tr, NULL);
ifp_packet_number++;
- if(tvb_length_remaining(tvb,offset)>0){
+ if(tvb_reported_length_remaining(tvb,offset)>0){
if(t38_tpkt_usage == T38_TPKT_ALWAYS){
- if(tr){
- proto_tree_add_text(tr, tvb, offset, tvb_reported_length_remaining(tvb, offset),
+ proto_tree_add_expert_format(tr, pinfo, &ei_t38_malformed, tvb, offset, tvb_reported_length_remaining(tvb, offset),
"[MALFORMED PACKET or wrong preference settings]");
- }
col_append_str(pinfo->cinfo, COL_INFO, " [Malformed?]");
break;
}else {
}
}
-static void
-dissect_t38(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
-{
- if(pinfo->ipproto == IP_PROTO_TCP)
- {
- dissect_t38_tcp(tvb, pinfo, tree);
- }
- else if(pinfo->ipproto == IP_PROTO_UDP)
- {
- dissect_t38_udp(tvb, pinfo, tree);
- }
-}
-
/* Look for conversation info and display any setup info found */
void
show_setup_info(tvbuff_t *tvb, proto_tree *tree, t38_conv *p_t38_conversation)
"OCTET_STRING", HFILL }},
/*--- End of included file: packet-t38-hfarr.c ---*/
-#line 673 "../../asn1/t38/packet-t38-template.c"
+#line 659 "../../asn1/t38/packet-t38-template.c"
{ &hf_t38_setup,
{ "Stream setup", "t38.setup", FT_STRING, BASE_NONE,
NULL, 0x0, "Stream setup, method and frame number", HFILL }},
&ett_t38_T_fec_data,
/*--- End of included file: packet-t38-ettarr.c ---*/
-#line 720 "../../asn1/t38/packet-t38-template.c"
+#line 706 "../../asn1/t38/packet-t38-template.c"
&ett_t38_setup,
&ett_data_fragment,
&ett_data_fragments
};
+ static ei_register_info ei[] = {
+ { &ei_t38_malformed, { "t38.malformed", PI_MALFORMED, PI_ERROR, "Malformed packet", EXPFILL }},
+ };
+
module_t *t38_module;
+ expert_module_t* expert_t38;
proto_t38 = proto_register_protocol("T.38", "T.38", "t38");
proto_register_field_array(proto_t38, hf, array_length(hf));
proto_register_subtree_array(ett, array_length(ett));
- register_dissector("t38", dissect_t38, proto_t38);
+ expert_t38 = expert_register_protocol(proto_t38);
+ expert_register_field_array(expert_t38, ei, array_length(ei));
+ register_dissector("t38_udp", dissect_t38_udp, proto_t38);
/* Init reassemble tables for HDLC */
register_init_routine(t38_defragment_init);
+ register_cleanup_routine(t38_defragment_cleanup);
t38_tap = register_tap("t38");