Huge thanks to our Platinum Members Endace and LiveAction,
and our Silver Member Veeam, for supporting the Wireshark Foundation and project.

Wireshark-dev: [Wireshark-dev] wslua tcp reconstruct behaves strange when multiple messages spa

From: Sjoerd van Doorn <sjoerd.van.doorn@xxxxxxxxxxxx>
Date: Tue, 5 Nov 2013 12:40:45 +0000

I have been working on various Lua based dissectors.

I found something that I would entitle as undesirable, however I'm not sure if it is a actual bug.

For example if I have a TCP connection with packets over it and the packets contain messages including a header.

it would be very well possible that there are two TCP packets.

            One including the first message and the first part of the second message

            The second with the second part of the second message and the third message

In order to instruct the Lua dissector to combine multiple packets, TCP reconstruction is (ab)used.

            when dissecting the first packet, there is not enough data for the second message therefore a negative value of the second part of the second message is returned

                        and the pinfo.desegment_len and pinfo.desegment_offset are set

            when the second packet is received, it takes the number of bytes as specified in pinfo.desegment_len and adds it to the buffer of the previous dissect.

                        It than reruns the dissector.

                        next it calls the dissector again with the remaining part of the second packet.

To me this appears to be strange since in the GUI, the frame tab is not fully included in the Reassembled TCP tab.

The third message is not in the reassembled data and I don't know how to handle it as a big block ( since I am not aware of the third message while handling the first packet)

 

Please see http://www.cloudshark.org/captures/2a86e8fd2c69 for a demo pcap including the scenarion above and one with 4 messages over 3 packets.

the dissector used :

 

            do

           local p_nuffproto     = Proto("nuff_protocol", "Nuff Protocol")

          

           local f_tag     = ProtoField.string ("nuff_protocol.starttag" , "Start Tag " )

           local f_length  = ProtoField.uint16 ("nuff_protocol.length"   , "Length    ", base.DEC)

           local f_data    = ProtoField.bytes  ("nuff_protocol.data"     , "Data      ", base.HEX)

           p_nuffproto.fields = {f_tag,f_length,f_data}

          

           local STARTTAGLENGTH = 8

           local LENGTHLENGTH   = 2

           local HEADERLENGTH   = STARTTAGLENGTH + LENGTHLENGTH

          

           function p_nuffproto.dissector(buf,pinfo,root)

             local offset = 0

             local remaining = buf:len() - offset

             while ( remaining > 0 ) do

                 -- make sure we have enough data to read the header

                 if ( remaining < HEADERLENGTH) then

                    pinfo.desegment_len    = (HEADERLENGTH - remaining) -- how much more do we need

                    pinfo.desegment_offset = 0 -- start with disector from 0 next run

                    return (remaining - HEADERLENGTH)

                 end

                 local len = buf(offset+STARTTAGLENGTH,LENGTHLENGTH):uint()

                 if ( len > remaining ) then

                    pinfo.desegment_len    = (len - remaining) -- how much more do we need

                    pinfo.desegment_offset = 0 -- start with disector from 0 next run

                    return (remaining - len)

                  end

                 local subtree = root:add(p_nuffproto,buf(offset,len))

                 subtree:add(f_tag   , buf(offset ,STARTTAGLENGTH))

                 subtree:add(f_length, buf(offset + STARTTAGLENGTH,LENGTHLENGTH))

                 subtree:add(f_data  , buf(offset + HEADERLENGTH,(len - HEADERLENGTH)))

                 pinfo.cols.protocol = "NUFF"

                 offset = offset + len

                 remaining = buf:len() - offset

             end

           end

           -- register to the UDP port

           local tcp_encap_table = DissectorTable.get("tcp.port")

           tcp_encap_table:add(33445, p_nuffproto)

       end

 

Please note that both the data and the dissector are "created" to demo the effect.

I would like to know if:

            * The effect is intended to behave this way

            * Is there a way to keep rerunning the dissector until it no longer returns a negative value ?

            * Is there another way of combining the data from various packets with the wslua api ?

           

Thanks and all the best,

 

Sjoerd van doorn