Wireshark-dev: [Wireshark-dev] How to get the PDU length of a 'mutating' protocol?

From: Yaniv Kaul <yaniv.kaul@xxxxxxxxxxxx>
Date: Wed, 4 Dec 2024 10:18:06 +0200
I have a strange protocol[1], which can be optionally compressed and then it may also change its PDU structure, after initial negotiations.
I'm using tcp_dissect_pdus().

I found no better way than fetching the conversation with the _get_len() function and checking, based on the saved conversation (saved when created as part of the negotiation) data, determining what the PDU length is. If it's compressed, I decode the length field in some way. If it is switched to 'streaming mode' , another, etc.

It works. But it looks a bit ugly, fetching the conversation every time.

An alternative which is even a bit more absurd (?) is to create sub-dissectors for them? 

Here's how it looks like (and works!) right now:
static unsigned
get_scylla_pdu_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset, void *data _U_)
{
    unsigned int reported_len;
    conversation_t *conversation;
    scylla_conv_t *scylla_conversation;

    if (looks_like_rpc_negotiation(tvb)) {
        return tvb_get_letohl(tvb, offset + SCYLLA_NEGOTIATION_LEN_OFFSET) + SCYLLA_NEGOTIATION_SIZE;
    }

    conversation = find_conversation(pinfo->num, &pinfo->src, &pinfo->dst,
        conversation_pt_to_conversation_type(pinfo->ptype),
        pinfo->srcport, pinfo->destport, 0);
    if (conversation) {
        scylla_conversation = (scylla_conv_t *)conversation_get_proto_data(conversation, proto_scylla);
        if (scylla_conversation && scylla_conversation->compression) { /* compressed PDU */
            return tvb_get_letohl(tvb, offset);
        }
    } else {
        return 0;
    }

    reported_len = tvb_reported_length(tvb);
    if(pinfo->destport == pinfo->match_uint) { /* request */
        if (reported_len >= SCYLLA_HEADER_SIZE) {
            return tvb_get_letohl(tvb, offset + SCYLLA_HEADER_LEN_OFFSET) + SCYLLA_HEADER_SIZE;
        } else {
            return 0;
        }
    } else { /* response */
        if (reported_len >= SCYLLA_RESPONSE_SIZE) {
            return tvb_get_letohl(tvb, offset + SCYLLA_HEADER_SIZE);
        } else {
            return 0;
        }
    }
}


TIA,
Y.

[1] https://github.com/scylladb/seastar/blob/master/doc/rpc.md