/* void ethertype(guint16 etype, tvbuff_t *tvb, int offset_after_etype, packet_info *pinfo, proto_tree *tree, proto_tree *fh_tree, int etype_id, int trailer_id, int fcs_len) */ static int dissect_ethertype(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) { const char *description; tvbuff_t *volatile next_tvb; guint length_before; gint captured_length, reported_length; volatile int dissector_found = 0; const char *volatile saved_proto; ethertype_data_t *ethertype_data; /* Reject the packet if data is NULL */ if (data == NULL) return 0; ethertype_data = (ethertype_data_t*)data; /* Add the Ethernet type to the protocol tree */ proto_tree_add_uint(ethertype_data->fh_tree, ethertype_data->etype_id, tvb, ethertype_data->offset_after_ethertype - 2, 2, ethertype_data->etype); /* Get the captured length and reported length of the data after the Ethernet type. */ captured_length = tvb_captured_length_remaining(tvb, ethertype_data->offset_after_ethertype); reported_length = tvb_reported_length_remaining(tvb, ethertype_data->offset_after_ethertype); /* Remember how much data there is after the Ethernet type, including any trailer and FCS. */ length_before = reported_length; /* Construct a tvbuff for the payload after the Ethernet type. If the FCS length is positive, remove the FCS. (If it's zero, there's no FCS; if it's negative, we don't know whether there's an FCS, so we'll guess based on the length of the trailer.) */ if (ethertype_data->fcs_len > 0) { if (captured_length >= 0 && reported_length >= 0) { if (reported_length >= ethertype_data->fcs_len) reported_length -= ethertype_data->fcs_len; if (captured_length > reported_length) captured_length = reported_length; } } next_tvb = tvb_new_subset(tvb, ethertype_data->offset_after_ethertype, captured_length, reported_length); p_add_proto_data(pinfo->pool, pinfo, proto_ethertype, 0, GUINT_TO_POINTER((guint)ethertype_data->etype)); /* Look for sub-dissector, and call it if found. Catch exceptions, so that if the reported length of "next_tvb" was reduced by some dissector before an exception was thrown, we can still put in an item for the trailer. */ saved_proto = pinfo->current_proto; TRY { dissector_found = dissector_try_uint(ethertype_dissector_table, ethertype_data->etype, next_tvb, pinfo, tree); } CATCH_NONFATAL_ERRORS { /* Somebody threw an exception that means that there was a problem dissecting the payload; that means that a dissector was found, so we don't need to dissect the payload as data or update the protocol or info columns. Just show the exception and then drive on to show the trailer, after noting that a dissector was found and restoring the protocol value that was in effect before we called the subdissector. */ show_exception(next_tvb, pinfo, tree, EXCEPT_CODE, GET_MESSAGE); dissector_found = 1; pinfo->current_proto = saved_proto; } ENDTRY; if (!dissector_found) { /* No sub-dissector found. Label rest of packet as "Data" */ call_data_dissector(next_tvb, pinfo, tree); /* Label protocol */ col_add_fstr(pinfo->cinfo, COL_PROTOCOL, "0x%04x", ethertype_data->etype); description = try_val_to_str(ethertype_data->etype, etype_vals); if (description) { col_add_str(pinfo->cinfo, COL_INFO, description); } } add_dix_trailer(pinfo, tree, ethertype_data->fh_tree, ethertype_data->trailer_id, tvb, next_tvb, ethertype_data->offset_after_ethertype, length_before, ethertype_data->fcs_len); return tvb_captured_length(tvb); }
void ethertype(guint16 etype, tvbuff_t *tvb, int offset_after_etype, packet_info *pinfo, proto_tree *tree, proto_tree *fh_tree, int etype_id, int trailer_id, int fcs_len) { const char *description; tvbuff_t *volatile next_tvb; guint length_before; gint captured_length, reported_length; volatile gboolean dissector_found = FALSE; const char *volatile saved_proto; void *pd_save; /* Add the Ethernet type to the protocol tree */ if (tree) { proto_tree_add_uint(fh_tree, etype_id, tvb, offset_after_etype - 2, 2, etype); } /* Get the captured length and reported length of the data after the Ethernet type. */ captured_length = tvb_length_remaining(tvb, offset_after_etype); reported_length = tvb_reported_length_remaining(tvb, offset_after_etype); /* Remember how much data there is after the Ethernet type, including any trailer and FCS. */ length_before = reported_length; /* Construct a tvbuff for the payload after the Ethernet type. If the FCS length is positive, remove the FCS. (If it's zero, there's no FCS; if it's negative, we don't know whether there's an FCS, so we'll guess based on the length of the trailer.) */ if (fcs_len > 0) { if (captured_length >= 0 && reported_length >= 0) { if (reported_length >= fcs_len) reported_length -= fcs_len; if (captured_length > reported_length) captured_length = reported_length; } } next_tvb = tvb_new_subset(tvb, offset_after_etype, captured_length, reported_length); pinfo->ethertype = etype; /* Look for sub-dissector, and call it if found. Catch exceptions, so that if the reported length of "next_tvb" was reduced by some dissector before an exception was thrown, we can still put in an item for the trailer. */ saved_proto = pinfo->current_proto; pd_save = pinfo->private_data; TRY { dissector_found = dissector_try_uint(ethertype_dissector_table, etype, next_tvb, pinfo, tree); } CATCH(BoundsError) { /* Somebody threw BoundsError, which means that: 1) a dissector was found, so we don't need to dissect the payload as data or update the protocol or info columns; 2) dissecting the payload found that the packet was cut off by a snapshot length before the end of the payload. The trailer comes after the payload, so *all* of the trailer is cut off, and we'll just get another BoundsError if we add the trailer. Therefore, we just rethrow the exception so it gets reported; we don't dissect the trailer or do anything else. */ RETHROW; } CATCH(OutOfMemoryError) { RETHROW; } CATCH_ALL { /* Somebody threw an exception other than BoundsError, which means that a dissector was found, so we don't need to dissect the payload as data or update the protocol or info columns. We just show the exception and then drive on to show the trailer, after noting that a dissector was found and restoring the protocol value that was in effect before we called the subdissector. */ show_exception(next_tvb, pinfo, tree, EXCEPT_CODE, GET_MESSAGE); /* Restore the private_data structure in case one of the * called dissectors modified it (and, due to the exception, * was unable to restore it). */ pinfo->private_data = pd_save; dissector_found = TRUE; pinfo->current_proto = saved_proto; } ENDTRY; if (!dissector_found) { /* No sub-dissector found. Label rest of packet as "Data" */ call_dissector(data_handle,next_tvb, pinfo, tree); /* Label protocol */ col_add_fstr(pinfo->cinfo, COL_PROTOCOL, "0x%04x", etype); description = match_strval(etype, etype_vals); if (description) { col_add_str(pinfo->cinfo, COL_INFO, description); } } add_dix_trailer(pinfo, tree, fh_tree, trailer_id, tvb, next_tvb, offset_after_etype, length_before, fcs_len); }