I've been digging into the wslua code, and the wireshark dissection source as well, trying to figure out why perfectly a good header field in wireshark is not getting read by my Lua script's field extractors. Here is what I have figured out so far (some of this will be known to most of you):
First of all, I have concluded that my Lua postdissector code is getting called just fine. However when Field__call looks up my field, it's not found in the "interesting_hfids" hash table.
Futher printfs uncovered the fact that, sometimes it is in the hash table and sometimes it isn't! So I have been investigating how the hash table is created for each packet, and how that might happen differently from one packet dissection to the next.
From what I can tell, as wireshark processes my capture file the dissectors and subdissectors get called three times, via the following three different code paths:
1. Initially each packet in the capture file is dissected starting with a call to add_packet_to_packet_list (in file.c). This leads to a call to dissect_packet and thence to dissect_frame, which then calls any subdissectors that are registered (each of which calls its subdissectors, if any). Finally, call_all_postdissectors runs the postdissectors, including my Lua code.
When this path through the code is traversed, my Lua field extractor gets values just fine!
2. After that first pass, the wireshark GUI code (which I don't understand very deeply) selects the first packet as the "cursor position", and this results in two subsequent calls to cf_select_packet (also in file.c). This calls the dissectors again, both times on frame 1, however this time nothing is added to the "interesting_hfids" hash table because the header field info's "ref_count" field is 0 for each field.
(I don't understand the significance of this, but it doesn't appear to be the real source of my problem. I include it primarily for completeness.)
3. Finally, the packets are dissected again via packet_list_dissect_and_cache_record (in gtk/packet-list_store.c). This time only the packets that are visible in the top pane of the GUI are dissected. The interesting_hfids hash table is created, but the header fields that are added to it are a subset of the original fields that were added in the first pass. In particular, the list does
not include the field that corresponds to my Lua field extractor. So when we get to my postdissector, the hash table lookup fails and Field__call returns nil to Lua.
Of course all this happens very quickly as the wireshark GUI is opening. But by the time I can access the packet display, the data from pass 1 have been overwritten by the nils from pass 3.
I'm continuing to dig through the code, to figure out where the list of "interesting hfids" comes from, and why it changes. But if anybody is familiar with this code and can throw me a hint where to look, I'd appreciate it.
Here's a snippet of my debug output, showing the subset of fields that get added to the hfids hash table in pass 3:
== packet_list_dissect_and_cache_iter ==
== in packet_list_dissect_and_cache_record (fnum=15) ==
::: Calling dissector Frame
Created new hfid table at 0x4715488
Inserted eth in hfid table at 0x4715488 (size=1)
Inserted ip.ttl in hfid table at 0x4715488 (size=2)
Inserted ip.checksum_bad in hfid table at 0x4715488 (size=3)
Inserted ip.dst in hfid table at 0x4715488 (size=4)
Inserted udp in hfid table at 0x4715488 (size=5)
Inserted udp.checksum_bad in hfid table at 0x4715488 (size=6)
::: Calling dissector Data
::: Dissector Data returning 2
** About to call 3 postdissectors for frame#15... "MATE" "PRP" "POST802154"
Field__call: hfid table=0x4715488
Field__call: field info array not found for ieee802.15.4.seq_no
**
::: Dissector Frame returning 90