static void dissect_t38_tcp_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_item *it; proto_tree *tr; guint32 offset=0; tvbuff_t *next_tvb; guint16 ifp_packet_number=1; col_set_str(pinfo->cinfo, COL_PROTOCOL, "T.38"); col_clear(pinfo->cinfo, COL_INFO); primary_part = TRUE; /* This indicate the item number in the primary part of the T38 message, it is used for the reassemble of T30 packets */ Data_Field_item_num = 0; it=proto_tree_add_protocol_format(tree, proto_t38, tvb, 0, -1, "ITU-T Recommendation T.38"); tr=proto_item_add_subtree(it, ett_t38); /* init tap and conv info */ init_t38_info_conv(pinfo); /* Show Conversation setup info if exists*/ if (global_t38_show_setup_info) { show_setup_info(tvb, tr, p_t38_packet_conv); } if (check_col(pinfo->cinfo, COL_INFO)){ col_append_str(pinfo->cinfo, COL_INFO, "TCP: IFPPacket"); } while(tvb_length_remaining(tvb,offset)>0) { next_tvb = tvb_new_subset_remaining(tvb, offset); offset += dissect_IFPPacket_PDU(next_tvb, pinfo, tr); ifp_packet_number++; if(tvb_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), "[MALFORMED PACKET or wrong preference settings]"); } if (check_col(pinfo->cinfo, COL_INFO)){ col_append_str(pinfo->cinfo, COL_INFO, " [Malformed?]"); } break; } else { if (check_col(pinfo->cinfo, COL_INFO)){ col_append_fstr(pinfo->cinfo, COL_INFO, " IFPPacket#%u",ifp_packet_number); } } } } }
/* Entry point for dissection */ static void dissect_t38_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { guint8 octet1; proto_item *it; proto_tree *tr; guint32 offset=0; /* * XXX - heuristic to check for misidentified packets. */ if (dissect_possible_rtpv2_packets_as_rtp){ octet1 = tvb_get_guint8(tvb, offset); if (RTP_VERSION(octet1) == 2){ call_dissector(rtp_handle,tvb,pinfo,tree); return; } } col_set_str(pinfo->cinfo, COL_PROTOCOL, "T.38"); col_clear(pinfo->cinfo, COL_INFO); primary_part = TRUE; /* This indicate the item number in the primary part of the T38 message, it is used for the reassemble of T30 packets */ Data_Field_item_num = 0; it=proto_tree_add_protocol_format(tree, proto_t38, tvb, 0, -1, "ITU-T Recommendation T.38"); tr=proto_item_add_subtree(it, ett_t38); /* init tap and conv info */ init_t38_info_conv(pinfo); /* Show Conversation setup info if exists*/ if (global_t38_show_setup_info) { show_setup_info(tvb, tr, p_t38_packet_conv); } if (check_col(pinfo->cinfo, COL_INFO)){ col_append_str(pinfo->cinfo, COL_INFO, "UDP: UDPTLPacket "); } offset = dissect_UDPTLPacket_PDU(tvb, pinfo, tr); if (tvb_length_remaining(tvb,offset)>0){ if (tr){ proto_tree_add_text(tr, tvb, offset, tvb_reported_length_remaining(tvb, offset), "[MALFORMED PACKET or wrong preference settings]"); } if (check_col(pinfo->cinfo, COL_INFO)){ col_append_str(pinfo->cinfo, COL_INFO, " [Malformed?]"); } } }
/* Code to actually dissect the packets */ static int dissect_msrp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { gint offset = 0; gint next_offset = 0; proto_item *ti, *th, *msrp_headers_item, *msrp_element_item; proto_tree *msrp_tree, *reqresp_tree, *raw_tree, *msrp_hdr_tree, *msrp_end_tree; proto_tree *msrp_element_tree, *msrp_data_tree; gint linelen; gint space_offset; gint token_2_start; guint token_2_len; gint token_3_start; guint token_3_len; gint token_4_start = 0; guint token_4_len = 0; gboolean is_msrp_response; gint end_line_offset; gint end_line_len; gint line_end_offset; gint message_end_offset; gint colon_offset; char *transaction_id_str = NULL; gint header_len; gint hf_index; gint value_offset; guchar c; gint value_len; char *value; gboolean have_body = FALSE; gboolean found_match = FALSE; gint content_type_len, content_type_parameter_str_len; gchar *media_type_str_lower_case = NULL; char *content_type_parameter_str = NULL; tvbuff_t *next_tvb; gint parameter_offset; gint semi_colon_offset; if ( !check_msrp_header(tvb)){ return 0; } /* We have a MSRP header with at least three tokens * * Note that "tvb_find_line_end()" will return a value that * is not longer than what's in the buffer, so the * "tvb_get_ptr()" calls below won't throw exceptions. * */ offset = 0; linelen = tvb_find_line_end(tvb, 0, -1, &next_offset, FALSE); /* Find the first SP and skip the first token */ token_2_start = tvb_find_guint8(tvb, 0, linelen, ' ') + 1; /* Work out 2nd token's length by finding next space */ space_offset = tvb_find_guint8(tvb, token_2_start, linelen-token_2_start, ' '); token_2_len = space_offset - token_2_start; /* Transaction ID found store it for later use */ transaction_id_str = tvb_get_ephemeral_string(tvb, token_2_start, token_2_len); /* Look for another space in this line to indicate a 4th token */ token_3_start = space_offset + 1; space_offset = tvb_find_guint8(tvb, token_3_start,linelen-token_3_start, ' '); if ( space_offset == -1){ /* 3rd token runs to the end of the line */ token_3_len = linelen - token_3_start; }else{ /* We have a fourth token */ token_3_len = space_offset - token_3_start; token_4_start = space_offset + 1; token_4_len = linelen - token_4_start; } /* * Yes, so this is either a msrp-request or msrp-response. * To be a msrp-response, the second token must be * a 3-digit number. */ is_msrp_response = FALSE; if (token_3_len == 3) { if (isdigit(tvb_get_guint8(tvb, token_3_start)) && isdigit(tvb_get_guint8(tvb, token_3_start + 1)) && isdigit(tvb_get_guint8(tvb, token_3_start + 2))) { is_msrp_response = TRUE; } } /* Make entries in Protocol column and Info column on summary display */ col_set_str(pinfo->cinfo, COL_PROTOCOL, "MSRP"); if (is_msrp_response){ if (check_col(pinfo->cinfo, COL_INFO)) { col_add_fstr(pinfo->cinfo, COL_INFO, "Response: %s ", tvb_format_text(tvb, token_3_start, token_3_len)); if (token_4_len ) col_append_fstr(pinfo->cinfo, COL_INFO, "%s ", tvb_format_text(tvb, token_4_start, token_4_len)); col_append_fstr(pinfo->cinfo, COL_INFO, "Transaction ID: %s", tvb_format_text(tvb, token_2_start, token_2_len)); } }else{ if (check_col(pinfo->cinfo, COL_INFO)) { proto_tree_add_text(tree, tvb, token_3_start, token_3_len, "Col %s L=%u", tvb_format_text(tvb, token_3_start, token_3_len),token_3_len); col_add_fstr(pinfo->cinfo, COL_INFO, "Request: %s ", tvb_format_text(tvb, token_3_start, token_3_len)); col_append_fstr(pinfo->cinfo, COL_INFO, "Transaction ID: %s", tvb_format_text(tvb, token_2_start, token_2_len)); } } /* Find the end line to be able to process the headers * Note that in case of [content-stuff] headers and [content-stuff] is separated by CRLF */ offset = next_offset; end_line_offset = find_end_line(tvb,offset); /* TODO if -1 (No end line found, is returned do something) */ end_line_len = tvb_find_line_end(tvb, end_line_offset, -1, &next_offset, FALSE); message_end_offset = end_line_offset + end_line_len + 2; if (tree) { ti = proto_tree_add_item(tree, proto_msrp, tvb, 0, message_end_offset, FALSE); msrp_tree = proto_item_add_subtree(ti, ett_msrp); if (is_msrp_response){ th = proto_tree_add_item(msrp_tree,hf_msrp_response_line,tvb,0,linelen,FALSE); reqresp_tree = proto_item_add_subtree(th, ett_msrp_reqresp); proto_tree_add_item(reqresp_tree,hf_msrp_transactionID,tvb,token_2_start,token_2_len,FALSE); proto_tree_add_uint(reqresp_tree,hf_msrp_status_code,tvb,token_3_start,token_3_len, atoi(tvb_get_ephemeral_string(tvb, token_3_start, token_3_len))); }else{ th = proto_tree_add_item(msrp_tree,hf_msrp_request_line,tvb,0,linelen,FALSE); reqresp_tree = proto_item_add_subtree(th, ett_msrp_reqresp); proto_tree_add_item(reqresp_tree,hf_msrp_transactionID,tvb,token_2_start,token_2_len,FALSE); proto_tree_add_item(reqresp_tree,hf_msrp_method,tvb,token_3_start,token_3_len,FALSE); } /* Conversation setup info */ if (global_msrp_show_setup_info) { show_setup_info(tvb, pinfo, msrp_tree); } /* Headers */ msrp_headers_item = proto_tree_add_item(msrp_tree, hf_msrp_msg_hdr, tvb, offset,(end_line_offset - offset), FALSE); msrp_hdr_tree = proto_item_add_subtree(msrp_headers_item, ett_msrp_hdr); /* * Process the headers */ while (tvb_reported_length_remaining(tvb, offset) > 0 && offset < end_line_offset ) { /* 'desegment' is FALSE so will set next_offset to beyond the end of the buffer if no line ending is found */ linelen = tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE); if (linelen == 0) { /* * This is a blank line separating the * message header from the message body. */ have_body = TRUE; break; } line_end_offset = offset + linelen; colon_offset = tvb_find_guint8(tvb, offset, linelen, ':'); if (colon_offset == -1) { /* * Malformed header - no colon after the name. */ proto_tree_add_text(msrp_hdr_tree, tvb, offset, next_offset - offset, "%s", tvb_format_text(tvb, offset, linelen)); } else { header_len = colon_offset - offset; hf_index = msrp_is_known_msrp_header(tvb, offset, header_len); if (hf_index == -1) { proto_tree_add_text(msrp_hdr_tree, tvb, offset, next_offset - offset, "%s", tvb_format_text(tvb, offset, linelen)); } else { /* * Skip whitespace after the colon. */ value_offset = colon_offset + 1; while (value_offset < line_end_offset && ((c = tvb_get_guint8(tvb, value_offset)) == ' ' || c == '\t')) value_offset++; /* * Fetch the value. */ value_len = line_end_offset - value_offset; value = tvb_get_ephemeral_string(tvb, value_offset, value_len); /* * Add it to the protocol tree, * but display the line as is. */ msrp_element_item = proto_tree_add_string_format(msrp_hdr_tree, hf_header_array[hf_index], tvb, offset, next_offset - offset, value, "%s", tvb_format_text(tvb, offset, linelen)); msrp_element_tree = proto_item_add_subtree( msrp_element_item, ett_msrp_element); switch ( hf_index ) { case MSRP_CONTENT_TYPE : content_type_len = value_len; semi_colon_offset = tvb_find_guint8(tvb, value_offset,linelen, ';'); if ( semi_colon_offset != -1) { parameter_offset = semi_colon_offset +1; /* * Skip whitespace after the semicolon. */ while (parameter_offset < line_end_offset && ((c = tvb_get_guint8(tvb, parameter_offset)) == ' ' || c == '\t')) parameter_offset++; content_type_len = semi_colon_offset - value_offset; content_type_parameter_str_len = line_end_offset - parameter_offset; content_type_parameter_str = tvb_get_ephemeral_string(tvb, parameter_offset, content_type_parameter_str_len); } media_type_str_lower_case = ascii_strdown_inplace( (gchar *)tvb_get_ephemeral_string(tvb, value_offset, content_type_len)); break; default: break; } } } offset = next_offset; }/* End while */ if ( have_body ){ /* * There's a message body starting at "next_offset". * Set the length of the header item. */ proto_item_set_end(msrp_headers_item, tvb, next_offset); /* Create new tree & tvb for data */ next_tvb = tvb_new_subset_remaining(tvb, next_offset); ti = proto_tree_add_item(msrp_tree, hf_msrp_data, tvb, next_offset, -1, FALSE); msrp_data_tree = proto_item_add_subtree(ti, ett_msrp_data); /* give the content type parameters to sub dissectors */ if ( media_type_str_lower_case != NULL ) { void *save_private_data = pinfo->private_data; pinfo->private_data = content_type_parameter_str; found_match = dissector_try_string(media_type_dissector_table, media_type_str_lower_case, next_tvb, pinfo, msrp_data_tree); pinfo->private_data = save_private_data; /* If no match dump as text */ } if ( found_match != TRUE ) { offset = 0; while (tvb_offset_exists(next_tvb, offset)) { tvb_find_line_end(next_tvb, offset, -1, &next_offset, FALSE); linelen = next_offset - offset; proto_tree_add_text(msrp_data_tree, next_tvb, offset, linelen, "%s", tvb_format_text(next_tvb, offset, linelen)); offset = next_offset; }/* end while */ } } /* End line */ ti = proto_tree_add_item(msrp_tree,hf_msrp_end_line,tvb,end_line_offset,end_line_len,FALSE); msrp_end_tree = proto_item_add_subtree(ti, ett_msrp_end_line); proto_tree_add_item(msrp_end_tree,hf_msrp_transactionID,tvb,end_line_offset + 7,token_2_len,FALSE); /* continuation-flag */ proto_tree_add_item(msrp_end_tree,hf_msrp_cnt_flg,tvb,end_line_offset+end_line_len-1,1,FALSE); if (global_msrp_raw_text){ ti = proto_tree_add_text(tree, tvb, 0, -1,"Message Session Relay Protocol(as raw text)"); raw_tree = proto_item_add_subtree(ti, ett_msrp); tvb_raw_text_add(tvb,raw_tree); } }/* if tree */ return message_end_offset; /* return tvb_length(tvb); */ /* If this protocol has a sub-dissector call it here, see section 1.8 */ }