Ask Your Question
0

Looking for strategies when Lua dissectors are getting too big

asked 2025-01-08 00:04:35 +0000

tasty_sprout gravatar image

updated 2025-01-08 00:05:04 +0000

Hey there!

While working on my first dissector I hit Wireshark's and Lua's ressource constraints. I used up all the 200 local variables at ProtoFields, and from the looks I still have use for at least 200+ variables. At the moment the dissector has about 2000 lines of code, and I covered roughly 20% of the protocol.

I get error messages like these:

  • [..] too many local variables (limit is 200) ..
  • [..] function or expression too complex near ..

The second error is apparently from the Lua VM. According to this SO comment the Lua VM has (only) 255 registers: https://stackoverflow.com/q/54609218

There is potential to reduce the number of local variables within functions that get referenced by proto.dissector() - but the readability of the code will suffer, and I'm not sure if these non-ProtoField local variables are contributing to the exhaustion after all. Nevertheless such an optimization won't free nearly enough variables to cover the remaining 80% of the protocol.

I found this posting in which cmaynard suggested putting the variables in a Lua table but the example wasn't verbose enough for me to successfully apply. I tried putting ProtoFields in a table but I failed unpacking the content in proto.fields = {}. :(

https://osqa-ask.wireshark.org/questi...

So what are the/my options to successfully implement such a variable-heavy protocol in Wireshark?

  • Break up the dissector and write a dissector for each component of the protocol?
  • Use global variables instead of local vars?
  • [Your brilliant suggestions here :) ]

Thank you and have a nice day!

edit retag flag offensive close merge delete

1 Answer

Sort by ยป oldest newest most voted
0

answered 2025-01-08 15:22:00 +0000

cmaynard gravatar image

Regarding " I used up all the 200 local variables at ProtoFields, and from the looks I still have use for at least 200+ variables." ...

You can use a table to group them all into a single variable, for example, a snippet from the Guacamole dissector I wrote and published on the Wireshark wiki:

-- Fields
local pf = {
    length = ProtoField.uint32("guacp.len", "Length", base.DEC, nil, 0, "The length of the message"),
    instructions = ProtoField.uint32("guacp.instructions", "Instructions", base.DEC, nil, 0, "The number of instructions"),
    instruction = ProtoField.bytes("guacp.instruction", "Instruction", base.NONE),
    ...
}

-- Register protocol fields
p_guacp.fields = pf

And an example usage:

local function dissect_instruction(tvbuf, pinfo, tree, offset, count)
    local instr_tree

    ...
    instr_tree = tree:add(pf.instruction, tvbuf(offset, (off + 1) - offset)):set_text("Instruction " .. count .. ": ")
    ...

end -- dissect_instruction()

Maybe see how far you get with this idea and reply again if you're still hitting resource limits?

edit flag offensive delete link more

Comments

Thank you so much! Your verbose example really got me going again!

The only hick-up I experienced was with a couple of global ProtoFields variables that couldn't be placed inside the local pf table. But once I defined them outside the table and added each of them with

table.insert(p_guacp.fields, global_proto_fields_var_name)
-- I'm using p_guacp here to relate to the example code above.

everything went smooth again. I would have loved to put the global vars also inside a table (like the local vars in your example) and then concatenated this table to the p_guacp.field table but I couldn't find an elegant way to do that, so I sticked with table.insert() although it is a little tedious.

I'll leave the question open for now because I'm still interested if someone wants to share strategies on how to deal (best) with protocols that ...(more)

tasty_sprout gravatar imagetasty_sprout ( 2025-01-10 22:24:25 +0000 )edit

If I understand you correctly, you could add a table concatenation function, such as the one given in the top answer at https://stackoverflow.com/questions/1..., pasted here for convenience:

function TableConcat(t1,t2)
    for i=1,#t2 do
        t1[#t1+1] = t2[i]
    end
    return t1
end

Once you have that, then just call it to combine both the local protocol fields table and the global protocol fields table into a single table, e.g.:

p_guacp.fields = TableConcat(pf, global_pf)
cmaynard gravatar imagecmaynard ( 2025-01-13 16:56:48 +0000 )edit

I suppose I'm a little spoiled from using Python so much in the past ;D Having to write a custom function for smushing two tables needs some adjusting to :D Thank you so much, again!

tasty_sprout gravatar imagetasty_sprout ( 2025-01-14 05:10:44 +0000 )edit

Your Answer

Please start posting anonymously - your entry will be published after you log in or create a new account.

Add Answer

Question Tools

1 follower

Stats

Asked: 2025-01-08 00:04:35 +0000

Seen: 109 times

Last updated: Jan 08