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

Reassembly not working with a chained dissector in Lua

1

I'm writing a Lua chained dissector on top of the standard HTTP dissector to extract information from the HTTP payload. However, when I chain my dissector with the original HTTP dissector, reassembly is failing. I stripped down the Lua dissector to the bare minimum but still have the issue. Here is the stripped down dissector:

do
        local http_wrapper_proto = Proto("http_extra", "Extra analysis of the HTTP protocol");
        local original_http_dissector
        function http_wrapper_proto.dissector(tvbuffer, pinfo, treeitem)
            original_http_dissector:call(tvbuffer, pinfo, treeitem)
        end
    local tcp_dissector_table = DissectorTable.get("tcp.port")
    original_http_dissector = Dissector.get("http")
    tcp_dissector_table:add(80, http_wrapper_proto)
    tcp_dissector_table:add(8888, http_wrapper_proto)

end

Without the dissector, reassembly works fine:

$ tshark -r li.buienradar.nl.pcapng -Y http
5 0.028009000 192.168.0.17 -> 192.168.0.18 HTTP 294 POST http://li.buienradar.nl/api/Publication HTTP/1.1  (application/json)
11 0.463406000 192.168.0.18 -> 192.168.0.17 HTTP 217 HTTP/1.1 200 OK  (application/json)
24 116.487852000 192.168.0.17 -> 192.168.0.18 HTTP 294 POST http://li.buienradar.nl/api/Publication HTTP/1.1  (application/json)
28 116.628794000 192.168.0.18 -> 192.168.0.17 HTTP 217 HTTP/1.1 200 OK  (application/json)
$

But when the Lua dissector is used, reaassembly fails:

$ tshark -r li.buienradar.nl.pcapng -Y http -X lua_script:http3.lua
4 0.028009000 192.168.0.17 -> 192.168.0.18 HTTP 428 POST http://li.buienradar.nl/api/Publication HTTP/1.1
9 0.437610000 192.168.0.18 -> 192.168.0.17 HTTP 523 HTTP/1.1 200 OK
22 116.484815000 192.168.0.17 -> 192.168.0.18 HTTP 428 POST http://li.buienradar.nl/api/Publication HTTP/1.1
26 116.535529000 192.168.0.18 -> 192.168.0.17 HTTP 523 HTTP/1.1 200 OK
$

Am I doing something wrong? Is this a bug? Or is reassembly functionality somehow not implemented yet for chained Lua dissectors?

asked 28 Nov ‘16, 15:02

SYN-bit's gravatar image

SYN-bit ♦♦
17.1k957245
accept rate: 20%


One Answer:

1

So what you're doing is inserting another dissector between TCP and HTTP, right?

The problem, I think, (having not tried anything) comes down to what's explained in this comment in epan/packet.c:

    /*
     * can_desegment is set to 2 by anyone which offers the
     * desegmentation api/service.
     * Then everytime a subdissector is called it is decremented
     * by one.
     * Thus only the subdissector immediately on top of whoever
     * offers this service can use it.
     * We save the current value of "can_desegment" for the
     * benefit of TCP proxying dissectors such as SOCKS, so they
     * can restore it and allow the dissectors they call to use
     * the desegmentation service.
     */

The important part is the Thus only the subdissector immediately on top of whoever offers this service can use it bit.

(pinfo->can_desegment, which is set here, is checked by the req_resp_hdrs.c code which is used by the HTTP dissector.)

You should (if the LUA API allows you) be able to solve this by incrementing can_desegment in your dissector (before calling the HTTP dissector). It appears that's what the SSL dissector does.

answered 04 Dec '16, 07:47

JeffMorriss's gravatar image

JeffMorriss ♦
6.2k572
accept rate: 27%

Thanks Jeff, that did the trick, here is the alteration for future reference:

do
        local http_wrapper_proto = Proto("http_extra", "Extra analysis of the HTTP protocol");
        local original_http_dissector
        function http_wrapper_proto.dissector(tvbuffer, pinfo, treeitem)
            local can_desegment_saved = pinfo.can_desegment
            if pinfo.can_desegment > 0 then
                pinfo.can_desegment = 2
            end
        original_http_dissector:call(tvbuffer, pinfo, treeitem)

        -- my extra diseector code is inserted here

        pinfo.can_desegment = can_desegment_saved
    end

    local tcp_dissector_table = DissectorTable.get("tcp.port")
    original_http_dissector = Dissector.get("http")
    tcp_dissector_table:add(80, http_wrapper_proto)
    tcp_dissector_table:add(8888, http_wrapper_proto)

end

(04 Dec ‘16, 14:33) SYN-bit ♦♦