T38: fix a dereference of NULL pointer
[metze/wireshark/wip.git] / epan / dissectors / packet-t38.c
index b0b046a42473cfe3b9f8aff9d48f6bd1f20d1b90..08676f72eff84b00bef8d5df42752700506e0e36 100644 (file)
@@ -12,8 +12,6 @@
  * 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;
@@ -152,7 +145,7 @@ static int hf_t38_fec_data = -1;                  /* T_fec_data */
 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;
@@ -186,12 +179,14 @@ static gint ett_t38_T_fec_info = -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;
 
@@ -256,6 +251,11 @@ static void t38_defragment_init(void)
                               &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,
@@ -272,12 +272,12 @@ 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
@@ -325,7 +325,8 @@ void t38_add_address(packet_info *pinfo,
                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;
@@ -334,10 +335,12 @@ void t38_add_address(packet_info *pinfo,
                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;
@@ -398,13 +401,13 @@ force_reassemble_seq(reassembly_table *table, packet_info *pinfo, guint32 id)
        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;
@@ -472,7 +475,7 @@ dissect_t38_T30_indicator(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U
   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>"));
@@ -511,7 +514,7 @@ dissect_t38_T30_data(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, pr
   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>"));
@@ -544,7 +547,7 @@ dissect_t38_Type_of_msg(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_,
                                  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;
@@ -575,7 +578,7 @@ dissect_t38_T_field_type(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_
   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>"));
@@ -643,15 +646,12 @@ dissect_t38_T_field_type(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_
 
                     /* 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;
             }
@@ -674,26 +674,26 @@ dissect_t38_T_field_type(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_
 
 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));
         }
     }
 
@@ -715,7 +715,7 @@ dissect_t38_T_field_data(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_
                 /* 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;
@@ -772,7 +772,7 @@ dissect_t38_Data_Field_item(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx
   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;
@@ -813,7 +813,7 @@ dissect_t38_T_seq_number(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_
   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;
@@ -827,14 +827,16 @@ dissect_t38_T_seq_number(tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_
 
 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;
@@ -926,14 +928,14 @@ static const per_choice_t T_error_recovery_choice[] = {
 
 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;
@@ -949,7 +951,7 @@ static const per_sequence_t UDPTLPacket_sequence[] = {
 
 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;
 
@@ -980,7 +982,7 @@ static int dissect_UDPTLPacket_PDU(tvbuff_t *tvb _U_, packet_info *pinfo _U_, pr
 
 
 /*--- 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
@@ -1015,7 +1017,7 @@ init_t38_info_conv(packet_info *pinfo)
        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 */
@@ -1032,38 +1034,38 @@ init_t38_info_conv(packet_info *pinfo)
                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);
@@ -1072,10 +1074,10 @@ init_t38_info_conv(packet_info *pinfo)
                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 {
@@ -1130,11 +1132,9 @@ dissect_t38_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
 
        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?]");
        }
 }
@@ -1169,18 +1169,16 @@ dissect_t38_tcp_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
 
        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 {
@@ -1207,19 +1205,6 @@ dissect_t38_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
        }
 }
 
-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)
@@ -1336,7 +1321,7 @@ proto_register_t38(void)
         "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 }},
@@ -1397,21 +1382,29 @@ proto_register_t38(void)
     &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");