/** Checksums the data. */ static tvbuff_t * checksum_data(tvbuff_t *tvb, proto_tree *tree) { proto_item *hidden_item; int len = tvb_length(tvb) - 2; if (len < 0) return tvb; if (tree) { guint16 actual_fcs = tvb_get_letohs(tvb, len); guint16 calculated_fcs = crc16_ccitt_tvb(tvb, len); if (calculated_fcs == actual_fcs) { proto_tree_add_uint_format(tree, hf_sir_fcs, tvb, len, 2, actual_fcs, "Frame check sequence: 0x%04x (correct)", actual_fcs); } else { hidden_item = proto_tree_add_boolean(tree, hf_sir_fcs_bad, tvb, len, 2, TRUE); PROTO_ITEM_SET_HIDDEN(hidden_item); proto_tree_add_uint_format(tree, hf_sir_fcs, tvb, len, 2, actual_fcs, "Frame check sequence: 0x%04x " "(incorrect, should be 0x%04x)", actual_fcs, calculated_fcs); } } return tvb_new_subset_length(tvb, 0, len); }
static void dissect_srp (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree) { proto_item *srp_item = NULL; proto_tree *srp_tree = NULL; proto_item *hidden_item; guint8 header = tvb_get_guint8(tvb,0); /* add the 'srp' tree to the main tree */ if (tree) { srp_item = proto_tree_add_item (tree, proto_srp, tvb, 0, -1, ENC_NA); srp_tree = proto_item_add_subtree (srp_item, ett_srp); proto_tree_add_uint(srp_tree,hf_srp_header,tvb,0,1,header); } switch( header ) { case SRP_SRP_COMMAND: dissect_srp_command(tvb,pinfo,srp_tree); break; case SRP_SRP_RESPONSE: break; case SRP_NSRP_RESPONSE: if( srp_tree ) proto_tree_add_item(srp_tree,hf_srp_seqno,tvb,1,1,ENC_BIG_ENDIAN); break; default: break; } if( srp_tree ) { guint16 crc, calc_crc; guint crc_offset = tvb_reported_length(tvb)-2; crc = tvb_get_letohs(tvb,-2); /* crc includes the header */ calc_crc = crc16_ccitt_tvb(tvb,crc_offset); if( crc == calc_crc ) { proto_tree_add_uint_format(srp_tree, hf_srp_crc, tvb, crc_offset, 2, crc, "CRC: 0x%04x (correct)", crc); } else { hidden_item = proto_tree_add_boolean(srp_tree, hf_srp_crc_bad, tvb, crc_offset, 2, TRUE); PROTO_ITEM_SET_HIDDEN(hidden_item); proto_tree_add_uint_format(srp_tree, hf_srp_crc, tvb, crc_offset, 2, crc, "CRC: 0x%04x (incorrect, should be 0x%04x)", crc, calc_crc); } } }
/* ******************************************************************************* * DETAILS : Calculate a new FCS-16 given the current FCS-16 and the new data. ******************************************************************************* */ static guint16 mtp2_fcs16(tvbuff_t * tvbuff) { guint len = tvb_captured_length(tvbuff)-2; /* Check for Invalid Length */ if (len == 0) return (0x0000); return crc16_ccitt_tvb(tvbuff, len); }
/** Checksums the data. */ static tvbuff_t * checksum_data(tvbuff_t *tvb, proto_tree *tree) { int len = tvb_reported_length(tvb) - 2; if (len < 0) return tvb; proto_tree_add_checksum(tree, tvb, len, hf_sir_fcs, hf_sir_fcs_status, NULL, NULL, crc16_ccitt_tvb(tvb, len), ENC_LITTLE_ENDIAN, PROTO_CHECKSUM_VERIFY); return tvb_new_subset_length(tvb, 0, len); }
static void dissect_v5dl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_tree *v5dl_tree, *addr_tree; proto_item *v5dl_ti, *addr_ti; int direction; guint v5dl_header_len; guint16 control; #if 0 proto_tree *checksum_tree; proto_item *checksum_ti; guint16 checksum, checksum_calculated; guint checksum_offset; #endif guint16 addr, cr, eah, eal, v5addr; gboolean is_response = 0; #if 0 guint length, reported_length; #endif tvbuff_t *next_tvb; const char *srcname = "?"; const char *dstname = "?"; col_set_str(pinfo->cinfo, COL_PROTOCOL, "V5DL"); col_clear(pinfo->cinfo, COL_INFO); addr = tvb_get_ntohs(tvb, 0); cr = addr & V5DL_CR; eal = (addr & V5DL_EAL) >> V5DL_EAL_SHIFT; eah = (addr & V5DL_EAH) >> V5DL_EAH_SHIFT; v5addr = (eah << 7) + eal; v5dl_header_len = 2; /* addr */ direction = pinfo->p2p_dir; if (pinfo->p2p_dir == P2P_DIR_RECV) { is_response = cr ? FALSE : TRUE; srcname = "Network"; dstname = "User"; } else if (pinfo->p2p_dir == P2P_DIR_SENT) { is_response = cr ? TRUE : FALSE; srcname = "User"; dstname = "Network"; } col_set_str(pinfo->cinfo, COL_RES_DL_SRC, srcname); col_set_str(pinfo->cinfo, COL_RES_DL_DST, dstname); if (tree) { proto_item *direction_ti; v5dl_ti = proto_tree_add_item(tree, proto_v5dl, tvb, 0, -1, ENC_NA); v5dl_tree = proto_item_add_subtree(v5dl_ti, ett_v5dl); /* * Don't show the direction if we don't know it. */ if (direction != P2P_DIR_UNKNOWN) { direction_ti = proto_tree_add_uint(v5dl_tree, hf_v5dl_direction, tvb, 0, 0, pinfo->p2p_dir); PROTO_ITEM_SET_GENERATED(direction_ti); } addr_ti = proto_tree_add_uint(v5dl_tree, hf_v5dl_ef, tvb, 0, 2, v5addr); addr_tree = proto_item_add_subtree(addr_ti, ett_v5dl_address); proto_tree_add_uint(addr_tree, hf_v5dl_eah, tvb, 0, 1, addr); proto_tree_add_uint(addr_tree, hf_v5dl_cr, tvb, 0, 1, addr); proto_tree_add_uint(addr_tree, hf_v5dl_ea1, tvb, 0, 1, addr); proto_tree_add_uint(addr_tree, hf_v5dl_eal, tvb, 1, 1, addr); proto_tree_add_uint(addr_tree, hf_v5dl_ea2, tvb, 1, 1, addr); } else { v5dl_ti = NULL; v5dl_tree = NULL; } control = dissect_xdlc_control(tvb, 2, pinfo, v5dl_tree, hf_v5dl_control, ett_v5dl_control, &v5dl_cf_items, &v5dl_cf_items_ext, NULL, NULL, is_response, TRUE, FALSE); v5dl_header_len += XDLC_CONTROL_LEN(control, TRUE); if (tree) proto_item_set_len(v5dl_ti, v5dl_header_len); /* * XXX - the sample capture supplied with bug 7027 does not * appear to include checksums in the packets. */ #if 0 /* * Check the checksum, if available. * The checksum is a CCITT CRC-16 at the end of the packet, so * if we don't have the entire packet in the capture - i.e., if * tvb_captured_length(tvb) != tvb_reported_length(tvb) we can't check it. */ length = tvb_captured_length(tvb); reported_length = tvb_reported_length(tvb); /* * If the reported length isn't big enough for the V5DL header * and 2 bytes of checksum, the packet is malformed, as the * checksum overlaps the header. */ if (reported_length < v5dl_header_len + 2) THROW(ReportedBoundsError); if (length == reported_length) { /* * There's no snapshot length cutting off any of the * packet. */ checksum_offset = reported_length - 2; checksum = tvb_get_ntohs(tvb, checksum_offset); checksum_calculated = crc16_ccitt_tvb(tvb, checksum_offset); checksum_calculated = g_htons(checksum_calculated); /* Note: g_htons() macro may eval arg multiple times */ if (checksum == checksum_calculated) { checksum_ti = proto_tree_add_uint_format_value(v5dl_tree, hf_v5dl_checksum, tvb, checksum_offset, 2, 0, "0x%04x [correct]", checksum); checksum_tree = proto_item_add_subtree(checksum_ti, ett_v5dl_checksum); proto_tree_add_boolean(checksum_tree, hf_v5dl_checksum_good, tvb, checksum_offset, 2, TRUE); proto_tree_add_boolean(checksum_tree, hf_v5dl_checksum_bad, tvb, checksum_offset, 2, FALSE); } else { checksum_ti = proto_tree_add_uint_format_value(v5dl_tree, hf_v5dl_checksum, tvb, checksum_offset, 2, 0, "0x%04x [incorrect, should be 0x%04x]", checksum, checksum_calculated); checksum_tree = proto_item_add_subtree(checksum_ti, ett_v5dl_checksum); proto_tree_add_boolean(checksum_tree, hf_v5dl_checksum_good, tvb, checksum_offset, 2, FALSE); proto_tree_add_boolean(checksum_tree, hf_v5dl_checksum_bad, tvb, checksum_offset, 2, TRUE); } /* * Remove the V5DL header *and* the checksum. */ next_tvb = tvb_new_subset(tvb, v5dl_header_len, tvb_captured_length_remaining(tvb, v5dl_header_len) - 2, tvb_reported_length_remaining(tvb, v5dl_header_len) - 2); } else { /* * Some or all of the packet is cut off by a snapshot * length. */ if (length == reported_length - 1) { /* * One byte is cut off, so there's only one * byte of checksum in the captured data. * Remove that byte from the captured length * and both bytes from the reported length. */ next_tvb = tvb_new_subset(tvb, v5dl_header_len, tvb_captured_length_remaining(tvb, v5dl_header_len) - 1, tvb_reported_length_remaining(tvb, v5dl_header_len) - 2); } else { /* * Two or more bytes are cut off, so there are * no bytes of checksum in the captured data. * Just remove the checksum from the reported * length. */ next_tvb = tvb_new_subset(tvb, v5dl_header_len, tvb_captured_length_remaining(tvb, v5dl_header_len), tvb_reported_length_remaining(tvb, v5dl_header_len) - 2); } } #else next_tvb = tvb_new_subset_remaining(tvb, v5dl_header_len); #endif if (XDLC_IS_INFORMATION(control)) { /* call V5.2 dissector */ call_dissector(v52_handle, next_tvb, pinfo, tree); } }