static void dissect_stt_checksum(tvbuff_t *tvb, packet_info *pinfo, proto_tree *stt_tree) { gboolean can_checksum = !pinfo->fragmented && tvb_bytes_exist(tvb, 0, tvb_reported_length(tvb)); if (can_checksum && pref_check_checksum) { vec_t cksum_vec[4]; guint32 phdr[2]; /* Set up the fields of the pseudo-header. */ SET_CKSUM_VEC_PTR(cksum_vec[0], (const guint8 *)pinfo->src.data, pinfo->src.len); SET_CKSUM_VEC_PTR(cksum_vec[1], (const guint8 *)pinfo->dst.data, pinfo->dst.len); switch (pinfo->src.type) { case AT_IPv4: phdr[0] = g_htonl((IP_PROTO_TCP<<16) + tvb_reported_length(tvb)); SET_CKSUM_VEC_PTR(cksum_vec[2], (const guint8 *)phdr, 4); break; case AT_IPv6: phdr[0] = g_htonl(tvb_reported_length(tvb)); phdr[1] = g_htonl(IP_PROTO_TCP); SET_CKSUM_VEC_PTR(cksum_vec[2], (const guint8 *)phdr, 8); break; default: /* STT runs only atop IPv4 and IPv6.... */ DISSECTOR_ASSERT_NOT_REACHED(); break; } SET_CKSUM_VEC_TVB(cksum_vec[3], tvb, 0, tvb_reported_length(tvb)); proto_tree_add_checksum(stt_tree, tvb, 16, hf_stt_checksum, hf_stt_checksum_status, &ei_stt_checksum_bad, pinfo, in_cksum(cksum_vec, 4), ENC_BIG_ENDIAN, PROTO_CHECKSUM_VERIFY); } else { proto_tree_add_checksum(stt_tree, tvb, 16, hf_stt_checksum, hf_stt_checksum_status, &ei_stt_checksum_bad, pinfo, 0, ENC_BIG_ENDIAN, PROTO_CHECKSUM_NO_FLAGS); } }
static void dissect_stt_checksum(tvbuff_t *tvb, packet_info *pinfo, proto_tree *stt_tree) { proto_tree *checksum_tree; proto_item *item; guint16 checksum = tvb_get_ntohs(tvb, 16); gboolean can_checksum; guint16 computed_cksum; gboolean checksum_good = FALSE, checksum_bad = FALSE; item = proto_tree_add_uint_format_value(stt_tree, hf_stt_checksum, tvb, 16, 2, checksum, "0x%04x", checksum); can_checksum = !pinfo->fragmented && tvb_bytes_exist(tvb, 0, tvb_reported_length(tvb)); if (can_checksum && pref_check_checksum) { vec_t cksum_vec[4]; guint32 phdr[2]; /* Set up the fields of the pseudo-header. */ SET_CKSUM_VEC_PTR(cksum_vec[0], (const guint8 *)pinfo->src.data, pinfo->src.len); SET_CKSUM_VEC_PTR(cksum_vec[1], (const guint8 *)pinfo->dst.data, pinfo->dst.len); switch (pinfo->src.type) { case AT_IPv4: phdr[0] = g_htonl((IP_PROTO_TCP<<16) + tvb_reported_length(tvb)); SET_CKSUM_VEC_PTR(cksum_vec[2], (const guint8 *)phdr, 4); break; case AT_IPv6: phdr[0] = g_htonl(tvb_reported_length(tvb)); phdr[1] = g_htonl(IP_PROTO_TCP); SET_CKSUM_VEC_PTR(cksum_vec[2], (const guint8 *)phdr, 8); break; default: /* STT runs only atop IPv4 and IPv6.... */ DISSECTOR_ASSERT_NOT_REACHED(); break; } SET_CKSUM_VEC_TVB(cksum_vec[3], tvb, 0, tvb_reported_length(tvb)); computed_cksum = in_cksum(cksum_vec, 4); checksum_good = (computed_cksum == 0); checksum_bad = !checksum_good; if (checksum_good) { proto_item_append_text(item, " [correct]"); } else if (checksum_bad) { guint16 expected_cksum = in_cksum_shouldbe(checksum, computed_cksum); proto_item_append_text(item, " [incorrect, should be 0x%04x (maybe caused by \"TCP checksum offload\"?)]", expected_cksum); expert_add_info(pinfo, item, &ei_stt_checksum_bad); checksum = expected_cksum; } } else if (pref_check_checksum) { proto_item_append_text(item, " [unchecked, not all data available]"); } else { proto_item_append_text(item, " [validation disabled]"); } checksum_tree = proto_item_add_subtree(item, ett_stt_checksum); if (checksum_good || checksum_bad) { item = proto_tree_add_uint(checksum_tree, hf_stt_checksum_calculated, tvb, 16, 2, checksum); PROTO_ITEM_SET_GENERATED(item); } item = proto_tree_add_boolean(checksum_tree, hf_stt_checksum_good, tvb, 16, 2, checksum_good); PROTO_ITEM_SET_GENERATED(item); item = proto_tree_add_boolean(checksum_tree, hf_stt_checksum_bad, tvb, 16, 2, checksum_bad); PROTO_ITEM_SET_GENERATED(item); }