예제 #1
0
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);
    }
}
예제 #2
0
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);
}