This is a static archive of our old Q&A Site. Please post any new questions and answers at ask.wireshark.org.

Wireshark dissector development - Reassembly tcp frames

0

Just before starting, sorry for my english... i'm french.

I'm developing (in C language) a wireshark dissector to dissect a specific protocol to the company (it's owner of it) where I work but I have a problems when messages are several TCP frames ... I can not reassemble the messages when a message is broken into two different frames TCP, I can not reform it in one message...

I read the readme.dissector and try using two methods:

First method:
tcp_dissect_pdus(tvb, pinfo, tree, dns_desegment, 2,
            get_dns_pdu_len, dissect_dns_tcp_pdu, data);
        return tvb_captured_length(tvb);

Second method :

guint offset = 0;
    while(offset < tvb_reported_length(tvb)) {
        gint available = tvb_reported_length_remaining(tvb, offset);
        gint len = tvb_strnlen(tvb, offset, available);

        if( -1 == len ) {
            /* we ran out of data: ask for more */
            pinfo->desegment_offset = offset;
            pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT;
            return (offset + available);
        }

        col_set_str(pinfo->cinfo, COL_INFO, "C String");

        len += 1; /* Add one for the '\0' */

        if (tree) {
            proto_tree_add_item(tree, hf_cstring, tvb, offset, len,
                ENC_ASCII|ENC_NA);
        }
        offset += (guint)len;
    }

    /* if we get here, then the end of the tvb coincided with the end of a
       string. Happy days. */
    return tvb_captured_length(tvb);</code></pre><p>But impossible to reassemble the message, I do not understand why ... can you help me please? I hope you understand my problem ...: /</p></div><div id="question-tags" class="tags-container tags"><span class="post-tag tag-link-reassembly" rel="tag" title="see questions tagged &#39;reassembly&#39;">reassembly</span> <span class="post-tag tag-link-dissector" rel="tag" title="see questions tagged &#39;dissector&#39;">dissector</span> <span class="post-tag tag-link-help" rel="tag" title="see questions tagged &#39;help&#39;">help</span> <span class="post-tag tag-link-tcp" rel="tag" title="see questions tagged &#39;tcp&#39;">tcp</span> <span class="post-tag tag-link-wireshark" rel="tag" title="see questions tagged &#39;wireshark&#39;">wireshark</span></div><div id="question-controls" class="post-controls"></div><div class="post-update-info-container"><div class="post-update-info post-update-info-user"><p>asked <strong>04 Nov '14, 04:47</strong></p><img src="https://secure.gravatar.com/avatar/6e41ef358edbaa0233d30fbd5b41b4d1?s=32&amp;d=identicon&amp;r=g" class="gravatar" width="32" height="32" alt="Guillaume&#39;s gravatar image" /><p><span>Guillaume</span><br />

1112
accept rate: 0%

Nobody can help me please ?

(07 Nov ‘14, 01:53) Guillaume

You’re not really giving anyone a chance to help. You must describe in more detail what happens with the two methods, as they are both used successfully elsewhere in the code.

The first method is definitely the easiest as long as you have correctly created the get_dns_pdu_len() function. Have you tried debugging the code to check that function returns the expected value?

(07 Nov ‘14, 02:48) grahamb ♦

Thank grahamb for your answer!

I will try to explain you… So, my problem is to reassemble the packets between them. To illustrate this, see “picture1.png” (in the end of this message) which shows the packet number 8 should be following the packet number 6. As you can see the number 6 is malformed packet because its sequel is in the number 8 … I can not get them together to make one cut and the entire message …

To reach the result of “picture1.png” I’ll put the code I use. “choixMessageASA” allows according to the header frame of the ASA (the protocol that I have to decode) to know what message travels :

if (tree) {

    col_set_str(pinfo->cinfo, COL_PROTOCOL, "ASA");
col_set_str(pinfo->cinfo, COL_INFO, "Ceci est un test message ASA");
ti = proto_tree_add_item(tree, proto_asa, tvb, 0, -1, ENC_NA);
asa_tree = proto_item_add_subtree(ti, ett_asa);
artrh = wmem_new(wmem_packet_scope(), struct artere_header);
artrh->th_length = tvb_get_ntohs(tvb, offset);
if(artrh->th_length > tvb_length(tvb)){
pinfo->desegment_offset = offset;
pinfo->desegment_len = artrh->th_length - tvb_length(tvb);
choixMessageASA(artrh, tvb, asa_tree, &offset);
} else {
choixMessageASA(artrh, tvb, asa_tree, &offset);
}

}

I hope you can help me :/

picture1.png : alt text

(07 Nov ‘14, 05:14) Guillaume

Why don’t you use tvb_dissect_pdus? It would be much simpler. The code should be something like this:

static int dissect_asa_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
{
tcp_dissect_pdus(tvb, pinfo, tree, TRUE, 2, get_asa_pdu_len, dissect_asa_pdu, data);
return tvb_captured_length(tvb);
}

where get_asa_pdu_len() is:

static guint get_asa_pdu_len(packet_info *pinfo U, tvbuff_t *tvb, int offset)
{
return tvb_get_ntohs(tvb, offset);
}
(07 Nov ‘14, 13:07) Pascal Quantin

Thanks for your answer and sorry for my late reply …

I tried the way you speak with tvb_dissect_pdus but the result is the same, I get the same thing as “picture1.png” I set in my previous message … Do not you know how to meet the frames 6 and 8 (those of “picture1.png”) and dissect the whole frame assembled?

(12 Nov ‘14, 01:08) Guillaume

One small thing reassembly and code adding to columns shouldn’t be under “if (tree) {” as allwas should be executed.

(12 Nov ‘14, 04:10) Anders ♦

Thank you Anders for your answer but I do not know what you mean … is it possible showing me what would be the code please?

You thought that because it gives me the same thing:

col_set_str(pinfo->cinfo, COL_PROTOCOL, "ASA");
col_set_str(pinfo->cinfo, COL_INFO, "Ceci est un test message ASA");

ti = proto_tree_add_item(tree, proto_asa, tvb, 0, -1, ENC_NA); asa_tree = proto_item_add_subtree(ti, ett_asa);

artrh = wmem_new(wmem_packet_scope(), struct artere_header);

artrh->th_length = tvb_get_ntohs(tvb, offset);

if(artrh->th_length > tvb_length(tvb)){ if (tree) { pinfo->desegment_offset = offset; pinfo->desegment_len = artrh->th_length - tvb_length(tvb); choixMessageASA(artrh, tvb, asa_tree, &offset); } else { if (tree) { choixMessageASA(artrh, tvb, asa_tree, &offset); } }

(12 Nov ‘14, 04:45) Guillaume

Higer up in the post before the code box you have

if (tree) { if that’s in your code and the code block is inside it - it’s wrong. e.g the reassembly code must not be inside an if(tree) attement.

(12 Nov ‘14, 05:00) Anders ♦

I’m sorry, I did not understand what you meant! I succeeded to make it work according your advice, thank you!

Quick question, how can I customize the “length” column to display the length of the reassembled message and not the length of the normal message?

(12 Nov ‘14, 05:51) Guillaume

Use something like col_add_fstr(pinfo->cinfo, COL_PACKET_LENGTH, “%i”, new_length);, but be very careful about this, all Wireshark users and code expect the length column to contain the length of that frame, not reassembled length from subsequent frames. You would be better adding the length as a field in the packet tree and possibly in the “Info” column.

(12 Nov ‘14, 06:13) grahamb ♦

The changes made to the hiqnet dissector here show how simple it is to do reassembly when using tcp_dissect_pdus().

(13 Nov ‘14, 01:39) grahamb ♦

I have already tried this method but I have two warnings during compilation :

  • warning C4020: ‘tcp_dissect_pdus’ : too many actuals parameters but if I remove the “data” parameter at the end of tcp_dissect_pdu the warning disappears…

  • warning C4013: ‘tcp_captured_length’ undefined; assuming extern returning int while i imported the correct files…

This is why I have not used this method even if it is faster :/

(13 Nov ‘14, 04:38) Guillaume

Are you using an older version of source code, rather than trunk (or 1.12)?

The dissector_data parameter was added to tcp_dissect_pdus last year:

commit 8081cf1d90397cbbb4404f9720595e1537ed5e14 Author: Michael Mann <[email protected]> Date: Sat Nov 9 17:46:28 2013 +0000 Add data parameter to tcp_dissect_pdus() as well as convert it to using “new” style dissectors.

Did you actually use tcp_captured_length in your code or is that just a typo in your comment? It should be tvb_captured_length and that was added earlier this year:

commit 22149c5523a77e642ec13d12064b2ccef29e51fb Author: Evan Huus <[email protected]> Date: Sat Feb 22 08:39:57 2014 -0500 TVB API deprecations and cleanup - rename tvb_length and similar to tvb_captured_length and similar; leave #defines in place for backwards-compat, but mark them clearly as deprecated in code comments and in checkAPI
(13 Nov ‘14, 04:57) grahamb ♦

I use an an older version is why the tcp_dissect_pdus does not work with the data parameter! You’re right!

For tvb_captured_length is a typo from me in my comment for the tcp .. Maybe the warning is there because I do not have the latest version of Wireshark.

Anyway, thank you all for your answers, it has been of great help!

(13 Nov ‘14, 05:33) Guillaume
showing 5 of 14 show 9 more comments