Help with binpac 'cannot handle incremental input'

I’m looking to develop a new TCP-based protocol parser using binpac. Getting the ‘cannot handle incremental input’ error from binpac. But I don’t understand exactly why I’m seeing it. It happens whenever I use "flowunit = " instead of "datagram = ". I’m literally changing one line from the skeleton produced by the binpac quickstarter.

Here’s what I’m doing. Creating this as a plugin, so I start with init-plugin:

bro-aux/plugin-support/init-plugin $SRC/analyzer/fob Bro_Fob fob

Next I run the binpac quickstart:

cd ~/src/binpac_quickstart
./start.py fob “FOB Protocol” $SRC/analyzer/fob --tcp --plugin --buffered

If I now configure and make, everything works fine:

cd $SRC/analyzer/fob
./configure --bro-dist=$BRO_SRC
make

But if I edit src/fob.pac to uncomment the “flowunit =” line (and comment out the datagram line), I get this error from binpac:

src/fob-protocol.pac:18: error : cannot handle incremental input

Thinking it had something to do with the definition of FOB_PDU there (“data: bytestring &restofdata;”), I removed that line so that my PDU definition is nothing but:

type FOB_PDU(is_orig: bool) = record {
foo: uint32;
} &byteorder=bigendian;

But I still get the error. I’ve tried the same thing with current master branch, and with v2.4.1 and an older version I’m using and I get the same result in each case.

If I remove all fields from the PDU, it compiles, but that’s not very useful. :wink:

I know the flowunit feature works. I see it in other analyzers in the source tree. Seems like I must be missing something simple in the .pac files. But I can’t figure it out from inspection.

Anybody know what’s the trick?

Thanks!

Jeff

I finally figured out what’s happening by looking at the binpac source. Documenting for posterity:

Apparently if you use “flowunit”, you must place the &length= on the record (or somewhere in the derived hierarchy of types under the record). I was under the impression that binpac could figure that out implicitly by measuring the size of the types in the record, and that you only needed to use &length when the field length was determined by a previous field value in the record.

So, anyway this works:

type FOB_PDU(is_orig: bool) = record {
foo: uint32;
} &byteorder=bigendian &length=4;

My real analyzer will of course do this more dynamically. But at least I have a starting point that builds now.

Cheers