/* * Dissect TPKT-encapsulated data in a TCP stream. */ void dissect_tpkt_encap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gboolean desegment, dissector_handle_t subdissector_handle) { proto_item *ti = NULL; proto_tree *tpkt_tree = NULL; volatile int offset = 0; int length_remaining; int data_len; volatile int length; tvbuff_t *volatile next_tvb; const char *saved_proto; /* * If we're reassembling segmented TPKT PDUs, empty the COL_INFO * column, so subdissectors can append information * without having to worry about emptying the column. * * We use "col_add_str()" because the subdissector * might be appending information to the column, in * which case we'd have to zero the buffer out explicitly * anyway. */ if (desegment && check_col(pinfo->cinfo, COL_INFO)) col_set_str(pinfo->cinfo, COL_INFO, ""); while (tvb_reported_length_remaining(tvb, offset) != 0) { /* * Is the first byte of this putative TPKT header * a valid TPKT version number, i.e. 3? */ if (tvb_get_guint8(tvb, offset) != 3) { /* * No, so don't assume this is a TPKT header; * we might be in the middle of TPKT data, * so don't get the length and don't try to * do reassembly. */ col_set_str(pinfo->cinfo, COL_PROTOCOL, "TPKT"); col_set_str(pinfo->cinfo, COL_INFO, "Continuation"); if (tree) { ti = proto_tree_add_item(tree, proto_tpkt, tvb, offset, -1, FALSE); tpkt_tree = proto_item_add_subtree(ti, ett_tpkt); proto_item_set_text(ti, "TPKT"); proto_tree_add_text(tpkt_tree, tvb, offset, -1, "Continuation data"); } return; } length_remaining = tvb_length_remaining(tvb, offset); /* * Can we do reassembly? */ if (desegment && pinfo->can_desegment) { /* * Yes - is the TPKT header split across segment * boundaries? */ if (length_remaining < 4) { /* * Yes. Tell the TCP dissector where * the data for this message starts in * the data it handed us, and how many * more bytes we need, and return. */ pinfo->desegment_offset = offset; pinfo->desegment_len = 4 - length_remaining; return; } } /* * Get the length from the TPKT header. */ data_len = tvb_get_ntohs(tvb, offset + 2); /* * Can we do reassembly? */ if (desegment && pinfo->can_desegment) { /* * Yes - is the payload split across segment * boundaries? */ if (length_remaining < data_len) { /* * Yes. Tell the TCP dissector where * the data for this message starts in * the data it handed us, and how many * more bytes we need, and return. */ pinfo->desegment_offset = offset; pinfo->desegment_len = data_len - length_remaining; return; } } /* * Dissect the TPKT header. * Save and restore "pinfo->current_proto". */ saved_proto = pinfo->current_proto; pinfo->current_proto = "TPKT"; col_set_str(pinfo->cinfo, COL_PROTOCOL, "TPKT"); /* * Don't add the TPKT header information if we're * reassembling segmented TPKT PDUs or if this * PDU isn't reassembled. * * XXX - the first is so that subdissectors can append * information without getting TPKT stuff in the middle; * why the second? */ if (!desegment && !pinfo->fragmented && check_col(pinfo->cinfo, COL_INFO)) { col_add_fstr(pinfo->cinfo, COL_INFO, "TPKT Data length = %u", data_len); } if (tree) { ti = proto_tree_add_item(tree, proto_tpkt, tvb, offset, 4, FALSE); tpkt_tree = proto_item_add_subtree(ti, ett_tpkt); proto_item_set_text(ti, "TPKT"); /* Version */ proto_tree_add_item(tpkt_tree, hf_tpkt_version, tvb, offset, 1, FALSE); proto_item_append_text(ti, ", Version: 3"); /* Reserved octet*/ proto_tree_add_item(tpkt_tree, hf_tpkt_reserved, tvb, offset + 1, 1, FALSE); /* Length */ proto_tree_add_uint(tpkt_tree, hf_tpkt_length, tvb, offset + 2, 2, data_len); proto_item_append_text(ti, ", Length: %u", data_len); } pinfo->current_proto = saved_proto; /* Skip the TPKT header. */ offset += 4; data_len -= 4; /* * Construct a tvbuff containing the amount of the payload * we have available. Make its reported length the * amount of data in this TPKT packet. * * XXX - if reassembly isn't enabled. the subdissector * will throw a BoundsError exception, rather than a * ReportedBoundsError exception. We really want * a tvbuff where the length is "length", the reported * length is "plen + 2", and the "if the snapshot length * were infinite" length were the minimum of the * reported length of the tvbuff handed to us and "plen+2", * with a new type of exception thrown if the offset is * within the reported length but beyond that third length, * with that exception getting the "Unreassembled Packet" * error. */ length = length_remaining - 4; if (length > data_len) length = data_len; next_tvb = tvb_new_subset(tvb, offset, length, data_len); /* * Call the subdissector. * * Catch the ReportedBoundsError exception; if this * particular message happens to get a ReportedBoundsError * exception, that doesn't mean that we should stop * dissecting TPKT messages within this frame or chunk * of reassembled data. * * If it gets a BoundsError, we can stop, as there's nothing * more to see, so we just re-throw it. */ TRY { call_dissector(subdissector_handle, next_tvb, pinfo, tree); } CATCH(BoundsError) { RETHROW; } CATCH(ReportedBoundsError) { show_reported_bounds_error(tvb, pinfo, tree); } ENDTRY; /* * Skip the payload. */ offset += length; } }
void show_exception(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned long exception, const char *exception_message) { static const char dissector_error_nomsg[] = "Dissector writer didn't bother saying what the error was"; proto_item *item; if (exception == ReportedBoundsError && pinfo->fragmented) exception = FragmentBoundsError; switch (exception) { case ScsiBoundsError: col_append_str(pinfo->cinfo, COL_INFO, "[SCSI transfer limited due to allocation_length too small]"); /*item =*/ proto_tree_add_protocol_format(tree, proto_short, tvb, 0, 0, "SCSI transfer limited due to allocation_length too small: %s truncated]", pinfo->current_proto); /* Don't record ScsiBoundsError exceptions as expert events - they merely * reflect a normal SCSI condition. * (any case where it's caused by something else is a bug). */ /* expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR, "Packet size limited");*/ break; case BoundsError: col_append_str(pinfo->cinfo, COL_INFO, "[Packet size limited during capture]"); /*item =*/ proto_tree_add_protocol_format(tree, proto_short, tvb, 0, 0, "[Packet size limited during capture: %s truncated]", pinfo->current_proto); /* Don't record BoundsError exceptions as expert events - they merely * reflect a capture done with a snapshot length too short to capture * all of the packet * (any case where it's caused by something else is a bug). */ /* expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR, "Packet size limited");*/ break; case FragmentBoundsError: col_append_fstr(pinfo->cinfo, COL_INFO, "[Unreassembled Packet%s]", pinfo->noreassembly_reason); /*item =*/ proto_tree_add_protocol_format(tree, proto_unreassembled, tvb, 0, 0, "[Unreassembled Packet%s: %s]", pinfo->noreassembly_reason, pinfo->current_proto); /* Don't record FragmentBoundsError exceptions as expert events - they merely * reflect dissection done with reassembly turned off * (any case where it's caused by something else is a bug). */ /* expert_add_info_format(pinfo, item, PI_REASSEMBLE, PI_WARN, "Unreassembled Packet (Exception occured)");*/ break; case ReportedBoundsError: show_reported_bounds_error(tvb, pinfo, tree); break; case DissectorError: col_append_fstr(pinfo->cinfo, COL_INFO, "[Dissector bug, protocol %s: %s]", pinfo->current_proto, exception_message == NULL ? dissector_error_nomsg : exception_message); item = proto_tree_add_protocol_format(tree, proto_malformed, tvb, 0, 0, "[Dissector bug, protocol %s: %s]", pinfo->current_proto, exception_message == NULL ? dissector_error_nomsg : exception_message); g_warning("Dissector bug, protocol %s, in packet %u: %s", pinfo->current_proto, pinfo->fd->num, exception_message == NULL ? dissector_error_nomsg : exception_message); expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR, "%s", exception_message == NULL ? dissector_error_nomsg : exception_message); break; case ReassemblyError: col_append_fstr(pinfo->cinfo, COL_INFO, "[Reassembly error, protocol %s: %s]", pinfo->current_proto, exception_message == NULL ? dissector_error_nomsg : exception_message); item = proto_tree_add_protocol_format(tree, proto_malformed, tvb, 0, 0, "[Reassembly error, protocol %s: %s]", pinfo->current_proto, exception_message == NULL ? dissector_error_nomsg : exception_message); expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR, "%s", exception_message == NULL ? dissector_error_nomsg : exception_message); break; default: /* XXX - we want to know, if an unknown exception passed until here, don't we? */ g_assert_not_reached(); } }
/* * Dissect ASCII TPKT-encapsulated data in a TCP stream. */ void dissect_asciitpkt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, dissector_handle_t subdissector_handle) { proto_item *ti = NULL; proto_tree *tpkt_tree = NULL; volatile int offset = 0; int length_remaining; int data_len; int mgcp_packet_len = 0; int mgcp_version = 0; int mgcp_reserved = 0; volatile int length; tvbuff_t *volatile next_tvb; const char *saved_proto; guint8 string[4]; /* * If we're reassembling segmented TPKT PDUs, empty the COL_INFO * column, so subdissectors can append information * without having to worry about emptying the column. * * We use "col_add_str()" because the subdissector * might be appending information to the column, in * which case we'd have to zero the buffer out explicitly * anyway. */ if (tpkt_desegment && check_col(pinfo->cinfo, COL_INFO)) col_add_str(pinfo->cinfo, COL_INFO, ""); while (tvb_reported_length_remaining(tvb, offset) != 0) { /* * Is the first byte of this putative TPKT header * a valid TPKT version number, i.e. 3? */ if (tvb_get_guint8(tvb, offset) != 48) { /* * No, so don't assume this is a TPKT header; * we might be in the middle of TPKT data, * so don't get the length and don't try to * do reassembly. */ col_set_str(pinfo->cinfo, COL_PROTOCOL, "TPKT"); col_set_str(pinfo->cinfo, COL_INFO, "Continuation"); if (tree) { ti = proto_tree_add_item(tree, proto_tpkt, tvb, offset, -1, FALSE); tpkt_tree = proto_item_add_subtree(ti, ett_tpkt); proto_item_set_text(ti, "TPKT"); proto_tree_add_text(tpkt_tree, tvb, offset, -1, "Continuation data"); } return; } length_remaining = tvb_length_remaining(tvb, offset); /* * Get the length from the TPKT header. */ tvb_memcpy(tvb, (guint8 *)string, offset, 2); mgcp_version = parseVersionText(string); tvb_memcpy(tvb, (guint8 *)string, offset +2, 2); mgcp_reserved = parseReservedText(string); tvb_memcpy(tvb, (guint8 *)string, offset + 4, 4); mgcp_packet_len = parseLengthText(string); data_len = mgcp_packet_len; /* * Dissect the TPKT header. * Save and restore "pinfo->current_proto". */ saved_proto = pinfo->current_proto; pinfo->current_proto = "TPKT"; col_set_str(pinfo->cinfo, COL_PROTOCOL, "TPKT"); /* * Don't add the TPKT header information if we're * reassembling segmented TPKT PDUs or if this * PDU isn't reassembled. * * XXX - the first is so that subdissectors can append * information without getting TPKT stuff in the middle; * why the second? */ if (!tpkt_desegment && !pinfo->fragmented && check_col(pinfo->cinfo, COL_INFO)) { col_add_fstr(pinfo->cinfo, COL_INFO, "TPKT Data length = %u", data_len); } if (tree) { ti = proto_tree_add_item(tree, proto_tpkt, tvb, offset, 8, FALSE); tpkt_tree = proto_item_add_subtree(ti, ett_tpkt); proto_item_set_text(ti, "TPKT"); /* Version */ proto_tree_add_uint(tpkt_tree, hf_tpkt_version, tvb, offset, 2, mgcp_version); /* Reserved octet*/ proto_tree_add_uint(tpkt_tree, hf_tpkt_reserved, tvb, offset + 2, 2, mgcp_reserved); /* Length */ proto_tree_add_uint(tpkt_tree, hf_tpkt_length, tvb, offset + 4, 4, mgcp_packet_len); } pinfo->current_proto = saved_proto; /* Skip the TPKT header. */ offset += TEXT_LAYER_LENGTH; length = length_remaining - TEXT_LAYER_LENGTH; if (length > data_len) length = data_len; next_tvb = tvb_new_subset(tvb, offset,length, data_len); /* * Call the subdissector. * * Catch the ReportedBoundsError exception; if this * particular message happens to get a ReportedBoundsError * exception, that doesn't mean that we should stop * dissecting TPKT messages within this frame or chunk * of reassembled data. * * If it gets a BoundsError, we can stop, as there's nothing * more to see, so we just re-throw it. */ TRY { call_dissector(subdissector_handle, next_tvb, pinfo, tree); } CATCH(BoundsError) { RETHROW; } CATCH(ReportedBoundsError) { show_reported_bounds_error(tvb, pinfo, tree); } ENDTRY; /* * Skip the payload. */ offset += data_len; } }