Skip to content

Instantly share code, notes, and snippets.

@edmonds
Created February 13, 2019 03:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save edmonds/52befc433bb674d41c1631590a6a4afd to your computer and use it in GitHub Desktop.
Save edmonds/52befc433bb674d41c1631590a6a4afd to your computer and use it in GitHub Desktop.
read http://farsightsec.github.io/fstrm/group__fstrm__control.html first!
run fstrm_capture at a high debugging level to dump control frame details, and
send it some data:
$ fstrm_capture -d -d -d -d -d -t protobuf:dnstap.Dnstap -u /tmp/dnstap.sock -w /tmp/dnstap.out
fstrm_capture: opening Unix socket path /tmp/dnstap.sock
fstrm_capture: opened output file /tmp/dnstap.out
fstrm_capture: accepted new connection fd 8
fstrm_capture: connection fd 8: reading control frame (42 bytes): "\x00\x00\x00\x00\x00\x00\x00\"\x00\x00\x00\x04\x00\x00\x00\x01\x00\x00\x00\x16protobuf:dnstap.Dnstap"
fstrm_capture: connection fd 8: received FSTRM_CONTROL_READY (4)
fstrm_capture: connection fd 8: CONTENT_TYPE [1/1] (22 bytes): "protobuf:dnstap.Dnstap"
fstrm_capture: connection fd 8: sending FSTRM_CONTROL_ACCEPT (1)
fstrm_capture: connection fd 8: writing frame (42) bytes: "\x00\x00\x00\x00\x00\x00\x00\"\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x16protobuf:dnstap.Dnstap"
fstrm_capture: connection fd 8: reading control frame (42 bytes): "\x00\x00\x00\x00\x00\x00\x00\"\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x16protobuf:dnstap.Dnstap"
fstrm_capture: connection fd 8: received FSTRM_CONTROL_START (2)
fstrm_capture: connection fd 8: processing data frame (102 bytes)
fstrm_capture: connection fd 8: processing data frame (108 bytes)
fstrm_capture: connection fd 8: processing data frame (978 bytes)
fstrm_capture: connection fd 8: processing data frame (103 bytes)
fstrm_capture: connection fd 8: processing data frame (647 bytes)
fstrm_capture: connection fd 8: processing data frame (118 bytes)
fstrm_capture: connection fd 8: processing data frame (638 bytes)
fstrm_capture: connection fd 8: processing data frame (116 bytes)
fstrm_capture: connection fd 8: processing data frame (116 bytes)
fstrm_capture: connection fd 8: processing data frame (824 bytes)
fstrm_capture: connection fd 8: processing data frame (120 bytes)
fstrm_capture: connection fd 8: incomplete message (have 226 bytes, want 824)
fstrm_capture: connection fd 8: processing data frame (824 bytes)
fstrm_capture: connection fd 8: processing data frame (120 bytes)
fstrm_capture: connection fd 8: processing data frame (878 bytes)
fstrm_capture: connection fd 8: processing data frame (144 bytes)
fstrm_capture: connection fd 8: processing data frame (200 bytes)
fstrm_capture: connection fd 8: processing data frame (878 bytes)
fstrm_capture: connection fd 8: processing data frame (132 bytes)
fstrm_capture: connection fd 8: processing data frame (421 bytes)
fstrm_capture: connection fd 8: processing data frame (110 bytes)
fstrm_capture: connection fd 8: processing data frame (540 bytes)
fstrm_capture: connection fd 8: incomplete message (have 75 bytes, want 521)
fstrm_capture: connection fd 8: processing data frame (521 bytes)
fstrm_capture: connection fd 8: reading control frame (12 bytes): "\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x03"
fstrm_capture: connection fd 8: received FSTRM_CONTROL_STOP (3)
fstrm_capture: connection fd 8: sending FSTRM_CONTROL_FINISH (5)
fstrm_capture: connection fd 8: writing frame (12) bytes: "\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x05"
fstrm_capture: connection fd 8: closing (read 22 frames, 8638 bytes)
^Cfstrm_capture: shutting down
fstrm_capture: closed output file /tmp/dnstap.out (wrote 24 frames, 8692 bytes)
broken down:
1) READY
the first frame on a bi-directional stream is from the data sender and is a
"READY" frame. it needs to specify one (OR MORE) "content type" fields
specifying the types of data it's willing to send. the frame streams "content
type" values are entirely user defined, try not to collide with anyone else's
use! ttbomk the only value in use is "protobuf:dnstap.Dnstap" (no \0 at end)
indicating that the sender wants to send protobufs encoded using the
https://github.com/dnstap/dnstap.pb/blob/master/dnstap.proto schema.
there can be multiple FSTRM_CONTROL_FIELD_CONTENT_TYPE fields inside the
FSTRM_CONTROL_READY control frame, they would just be packed one after the
other as additional TLVs.
fstrm_capture: connection fd 8: reading control frame (42 bytes): "\x00\x00\x00\x00\x00\x00\x00\"\x00\x00\x00\x04\x00\x00\x00\x01\x00\x00\x00\x16protobuf:dnstap.Dnstap"
fstrm_capture: connection fd 8: received FSTRM_CONTROL_READY (4)
fstrm_capture: connection fd 8: CONTENT_TYPE [1/1] (22 bytes): "protobuf:dnstap.Dnstap"
\x00\x00\x00\x00 escape sequence
\x00\x00\x00\" control frame length: 0x22 bytes (34 bytes), not including length field itself
\x00\x00\x00\x04 control frame type: 4 (FSTRM_CONTROL_READY)
(see https://github.com/farsightsec/fstrm/blob/06ddc76ceae2fcdb7496220f266970dcd7d0c1bf/fstrm/control.h#L143-L161 for control frame types)
\x00\x00\x00\x01 control frame field type: 1 (FSTRM_CONTROL_FIELD_CONTENT_TYPE)
(see https://github.com/farsightsec/fstrm/blob/06ddc76ceae2fcdb7496220f266970dcd7d0c1bf/fstrm/control.h#L163-L173 for control frame field types)
\x00\x00\x00\x16 control frame field length: 0x16 bytes (22 bytes), not including length field itself
protobuf:dnstap.Dnstap the 22 bytes of the FSTRM_CONTROL_FIELD_CONTENT_TYPE payload
2) ACCEPT
the second frame on a bi-directional stream is from the data receiver to the
data sender and is an "ACCEPT" frame. the receiver picks among the offered
"content type" values and selects one (OR MORE) "content type" data encodings
that it's willing to accept.
if the receiver actually supports several of the "content types" advertised by
the sender, it can choose to select the exact content type to use on this stream
by only specifying one of the sender's content types in its ACCEPT frame.
otherwise the receiver can specify its set of supported content types (which
must be a subset of the content types advertised by the sender) and let the
sender make the final selection in its START frame.
fstrm_capture: connection fd 8: sending FSTRM_CONTROL_ACCEPT (1)
fstrm_capture: connection fd 8: writing frame (42) bytes: "\x00\x00\x00\x00\x00\x00\x00\"\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x16protobuf:dnstap.Dnstap"
\x00\x00\x00\x00 escape sequence
\x00\x00\x00\" control frame length: 0x22 bytes (34 bytes), not including length field itself
\x00\x00\x00\x01 control frame type: 1 (FSTRM_CONTROL_ACCEPT)
\x00\x00\x00\x01 control frame field type: 1 (FSTRM_CONTROL_FIELD_CONTENT_TYPE)
\x00\x00\x00\x16 control frame field length: 0x16 bytes (22 bytes), not including length field itself
protobuf:dnstap.Dnstap the 22 bytes of the FSTRM_CONTROL_FIELD_CONTENT_TYPE payload
since the sender only sent one "content type" and the receiver is willing to
process it this ACCEPT frame is very similar to the READY frame, only the
control frame type actually differs. the acceptable content types are encoded
the same way as in the READY frame.
3) START
fstrm_capture: connection fd 8: reading control frame (42 bytes): "\x00\x00\x00\x00\x00\x00\x00\"\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x16protobuf:dnstap.Dnstap"
fstrm_capture: connection fd 8: received FSTRM_CONTROL_START (2)
\x00\x00\x00\x00 escape sequence
\x00\x00\x00\" control frame length: 0x22 bytes (34 bytes), not including length field itself
\x00\x00\x00\x02 control frame type: 2 (FSTRM_CONTROL_START)
\x00\x00\x00\x01 control frame field type: 1 (FSTRM_CONTROL_FIELD_CONTENT_TYPE)
\x00\x00\x00\x16 control frame field length: 0x16 bytes (22 bytes), not including length field itself
protobuf:dnstap.Dnstap the 22 bytes of the FSTRM_CONTROL_FIELD_CONTENT_TYPE payload
the third frame is the START frame sent by the data sender. this frame has
EXACTLY ONE "content type" field which specifies the type of data payloads that
will be sent by the sender. all frames in the data stream will be encoded using
this type.
in theory the READY -> ACCEPT -> START handshake lets the sender and receiver
negotiate a mutually acceptable content type from a set of content types
supported by the sender and a set of content types supported by the receiver. in
practice, only one content type ("protobuf:dnstap.Dnstap") has ever been used
and the negotiation is pretty boring and goes like this:
SENDER (READY): i support "protobuf:dnstap.Dnstap"
RECEIVER (ACCEPT): i also support "protobuf.dnstap.Dnstap"
SENDER (START): ok, gonna send you some "protobuf:dnstap.Dnstap"'s
but in theory this capability would e.g., allow a smooth transition from
"original dnstap" to "dnstap V2" or whatever without needing a new protocol.
4) DATA
fstrm_capture: connection fd 8: processing data frame (102 bytes)
[...etc...]
fstrm_capture: connection fd 8: processing data frame (521 bytes)
data frames are sent as length/value...
5) STOP
fstrm_capture: connection fd 8: reading control frame (12 bytes): "\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x03"
fstrm_capture: connection fd 8: received FSTRM_CONTROL_STOP (3)
\x00\x00\x00\x00 escape sequence
\x00\x00\x00\x04 control frame length: 4 bytes, not including length field itself
\x00\x00\x00\x03 control frame type: 3 (FSTRM_CONTROL_STOP)
sender decides to stop sending and sends FSTRM_CONTROL_STOP to indicate end of
data stream.
6) FINISH
fstrm_capture: connection fd 8: sending FSTRM_CONTROL_FINISH (5)
fstrm_capture: connection fd 8: writing frame (12) bytes: "\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x05"
\x00\x00\x00\x00 escape sequence
\x00\x00\x00\x04 control frame length: 4 bytes, not including length field itself
\x00\x00\x00\x05 control frame type: 5 (FSTRM_CONTROL_FINISH)
receiver acknowledges end of stream by sending FSTRM_CONTROL_FINISH.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment