static gboolean IsDFP_Frame(tvbuff_t *tvb) { guint16 u16SFCRC16; guint8 u8SFPosition; guint8 u8SFDataLength = 255; int offset = 0; guint32 u32SubStart; guint16 crc; gint tvb_len =0; offset += 2; /*Skip first crc because data is no more available */ tvb_len = tvb_length(tvb); if(offset + 4 > tvb_len) return FALSE; while(1) { u32SubStart = offset; u8SFPosition = tvb_get_guint8(tvb, offset); offset += 1; u8SFDataLength = tvb_get_guint8(tvb, offset); offset += 1; if(u8SFDataLength == 0) { break; } offset += 1; offset += 1; offset += u8SFDataLength; if(offset > tvb_len) return /*TRUE; */FALSE; u16SFCRC16 = tvb_get_letohs(tvb, offset); if(u16SFCRC16 != 0){ if(u8SFPosition & 0x80) { crc = crc16_plain_tvb_offset(tvb, u32SubStart, offset-u32SubStart); if(crc != u16SFCRC16) { return FALSE; } else { } } else { } } offset += 2; } return TRUE; }
/* possibly dissect a CSF_SDU related PN-RT packet */ static gboolean dissect_CSF_SDU_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { guint16 u16FrameID; guint16 u16SFCRC16; guint8 u8SFPosition; guint8 u8SFDataLength = 255; guint8 u8SFCycleCounter; guint8 u8SFDataStatus; int offset = 0; guint32 u32SubStart; proto_item *sub_item; proto_tree *sub_tree; proto_item *item; guint16 crc; /* the sub tvb will NOT contain the frame_id here! */ u16FrameID = GPOINTER_TO_UINT(pinfo->private_data); /* possible FrameID ranges for DFP */ if ((u16FrameID >= 0x0500 && u16FrameID < 0x05ff) || (u16FrameID >= 0x0600 && u16FrameID < 0x07ff) || (u16FrameID >= 0x4800 && u16FrameID < 0x4fff) || (u16FrameID >= 0x5800 && u16FrameID < 0x5fff) || (u16FrameID >= 0x6800 && u16FrameID < 0x6fff) || (u16FrameID >= 0x7800 && u16FrameID < 0x7fff)) { /* can't check this CRC, as the checked data bytes are not available */ u16SFCRC16 = tvb_get_letohs(tvb, offset); proto_tree_add_uint(tree, hf_pn_rt_sf_crc16, tvb, offset, 2, u16SFCRC16); offset += 2; while(1) { sub_item = proto_tree_add_item(tree, hf_pn_rt_sf, tvb, offset, 0, FALSE); sub_tree = proto_item_add_subtree(sub_item, ett_pn_rt_sf); u32SubStart = offset; u8SFPosition = tvb_get_guint8(tvb, offset); proto_tree_add_uint(sub_tree, hf_pn_rt_sf_position_control, tvb, offset, 1, u8SFPosition); proto_tree_add_uint(sub_tree, hf_pn_rt_sf_position, tvb, offset, 1, u8SFPosition); offset += 1; u8SFDataLength = tvb_get_guint8(tvb, offset); proto_tree_add_uint(sub_tree, hf_pn_rt_sf_data_length, tvb, offset, 1, u8SFDataLength); offset += 1; if(u8SFDataLength == 0) { proto_item_append_text(sub_item, ": Pos:%u, Length:%u", u8SFPosition, u8SFDataLength); proto_item_set_len(sub_item, offset - u32SubStart); break; } u8SFCycleCounter = tvb_get_guint8(tvb, offset); proto_tree_add_uint(sub_tree, hf_pn_rt_sf_cycle_counter, tvb, offset, 1, u8SFCycleCounter); offset += 1; u8SFDataStatus = tvb_get_guint8(tvb, offset); dissect_DataStatus(tvb, offset, sub_tree, u8SFDataStatus); offset += 1; offset = dissect_pn_user_data(tvb, offset, pinfo, sub_tree, u8SFDataLength, "DataItem"); u16SFCRC16 = tvb_get_letohs(tvb, offset); item = proto_tree_add_uint(sub_tree, hf_pn_rt_sf_crc16, tvb, offset, 2, u16SFCRC16); if(u8SFPosition & 0x80) { crc = crc16_plain_tvb_offset(tvb, u32SubStart, offset-u32SubStart); if(crc != u16SFCRC16) { proto_item_append_text(item, " [Preliminary check: incorrect, should be: %u]", crc); expert_add_info_format(pinfo, item, PI_CHECKSUM, PI_ERROR, "Bad checksum"); } else { proto_item_append_text(item, " [Preliminary check: Correct]"); } } else { proto_item_append_text(item, " [No preliminary check, Control bit not set]"); } offset += 2; proto_item_append_text(sub_item, ": Pos:%u, Length:%u, Cycle:%u, Status: 0x%02x (%s,%s,%s,%s)", u8SFPosition, u8SFDataLength, u8SFCycleCounter, u8SFDataStatus, (u8SFDataStatus & 0x04) ? "Valid" : "Invalid", (u8SFDataStatus & 0x01) ? "Primary" : "Backup", (u8SFDataStatus & 0x20) ? "Ok" : "Problem", (u8SFDataStatus & 0x10) ? "Run" : "Stop"); proto_item_set_len(sub_item, offset - u32SubStart); } return TRUE; } return FALSE; }