1/*
2 * dnstap/dnstap_fstrm.h - Frame Streams protocol for dnstap
3 *
4 * Copyright (c) 2020, NLnet Labs. All rights reserved.
5 *
6 * This software is open source.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * Redistributions of source code must retain the above copyright notice,
13 * this list of conditions and the following disclaimer.
14 *
15 * Redistributions in binary form must reproduce the above copyright notice,
16 * this list of conditions and the following disclaimer in the documentation
17 * and/or other materials provided with the distribution.
18 *
19 * Neither the name of the NLNET LABS nor the names of its contributors may
20 * be used to endorse or promote products derived from this software without
21 * specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
29 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
31 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 *
35 */
36
37/**
38 * \file
39 *
40 * Definitions for the Frame Streams data transport protocol for
41 * dnstap message logs.
42 */
43
44#ifndef DNSTAP_FSTRM_H
45#define DNSTAP_FSTRM_H
46
47/* Frame Streams data transfer protocol encode for DNSTAP messages.
48 * The protocol looks to be specified in the libfstrm library.
49 *
50 * Quick writeup for DNSTAP usage, from reading fstrm/control.h eloquent
51 * comments and fstrm/control.c for some bytesize details (the content type
52 * length).
53 *
54 * The Frame Streams can be unidirectional or bi-directional.
55 * bi-directional streams use control frame types READY, ACCEPT and FINISH.
56 * uni-directional streams use control frame types START and STOP.
57 * unknown control frame types should be ignored by the receiver, they
58 * do not change the data frame encoding.
59 *
60 * bi-directional control frames implement a simple handshake protocol
61 * between sender and receiver.
62 *
63 * The uni-directional control frames have one start and one stop frame,
64 * before and after the data.  The start frame can have a content type.
65 * The start and stop frames are not optional.
66 *
67 * data frames are preceded by 4byte length, bigendian.
68 * zero length data frames are not possible, they are an escape that
69 * signals the presence of a control frame.
70 *
71 * a control frame consists of 0 value in 4byte bigendian, this is really
72 * the data frame length, with 0 the escape sequence that indicates one
73 * control frame follows.
74 * Then, 4byte bigendian, length of the control frame message.
75 * Then, the control frame payload (of that length). with in it:
76 *   4byte bigendian, control type (eg. START, STOP, READY, ACCEPT, FINISH).
77 *   perhaps nothing more (STOP, FINISH), but for other types maybe
78 *   control fields
79 *      4byte bigendian, the control-field-type, currently only content-type.
80 *      4byte bigendian, length of the string for this option.
81 *      .. bytes of that string.
82 *
83 * The START type can have only one field.  Field max len 256.
84 * control frame max frame length 512 (excludes the 0-escape and control
85 * frame length bytes).
86 *
87 * the bidirectional type of transmission is like this:
88 * client sends READY (with content type included),
89 * client waits for ACCEPT (with content type included),
90 * client sends START (with matched content type from ACCEPT)
91 * .. data frames
92 * client sends STOP.
93 * client waits for FINISH frame.
94 *
95 */
96
97/** max length of Frame Streams content type field string */
98#define FSTRM_CONTENT_TYPE_LENGTH_MAX 256
99/** control frame value to denote the control frame ACCEPT */
100#define FSTRM_CONTROL_FRAME_ACCEPT 0x01
101/** control frame value to denote the control frame START */
102#define FSTRM_CONTROL_FRAME_START 0x02
103/** control frame value to denote the control frame STOP */
104#define FSTRM_CONTROL_FRAME_STOP 0x03
105/** control frame value to denote the control frame READY */
106#define FSTRM_CONTROL_FRAME_READY 0x04
107/** control frame value to denote the control frame FINISH */
108#define FSTRM_CONTROL_FRAME_FINISH 0x05
109/** the constant that denotes the control field type that is the
110 * string for the content type of the stream. */
111#define FSTRM_CONTROL_FIELD_TYPE_CONTENT_TYPE 0x01
112/** the content type for DNSTAP frame streams */
113#define DNSTAP_CONTENT_TYPE             "protobuf:dnstap.Dnstap"
114
115/**
116 * This creates an FSTRM control frame of type START.
117 * @param contenttype: a zero delimited string with the content type.
118 * 	eg. use the constant DNSTAP_CONTENT_TYPE, which is defined as
119 * 	"protobuf:dnstap.Dnstap", for a dnstap frame stream.
120 * @param len: if a buffer is returned this is the length of that buffer.
121 * @return NULL on malloc failure.  Returns a malloced buffer with the
122 * protocol message.  The buffer starts with the 4 bytes of 0 that indicate
123 * a control frame.  The buffer should be sent without preceding it with
124 * the 'len' variable (like data frames are), but straight the content of the
125 * buffer, because the lengths are included in the buffer.  This is so that
126 * the zero control indicator can be included before the control frame length.
127 */
128void* fstrm_create_control_frame_start(char* contenttype, size_t* len);
129
130/**
131 * This creates an FSTRM control frame of type READY.
132 * @param contenttype: a zero delimited string with the content type.
133 * 	eg. use the constant DNSTAP_CONTENT_TYPE, which is defined as
134 * 	"protobuf:dnstap.Dnstap", for a dnstap frame stream.
135 * @param len: if a buffer is returned this is the length of that buffer.
136 * @return NULL on malloc failure.  Returns a malloced buffer with the
137 * protocol message.  The buffer starts with the 4 bytes of 0 that indicate
138 * a control frame.  The buffer should be sent without preceding it with
139 * the 'len' variable (like data frames are), but straight the content of the
140 * buffer, because the lengths are included in the buffer.  This is so that
141 * the zero control indicator can be included before the control frame length.
142 */
143void* fstrm_create_control_frame_ready(char* contenttype, size_t* len);
144
145/**
146 * This creates an FSTRM control frame of type STOP.
147 * @param len: if a buffer is returned this is the length of that buffer.
148 * @return NULL on malloc failure.  Returns a malloced buffer with the
149 * protocol message.  The buffer starts with the 4 bytes of 0 that indicate
150 * a control frame.  The buffer should be sent without preceding it with
151 * the 'len' variable (like data frames are), but straight the content of the
152 * buffer, because the lengths are included in the buffer.  This is so that
153 * the zero control indicator can be included before the control frame length.
154 */
155void* fstrm_create_control_frame_stop(size_t* len);
156
157/**
158 * This creates an FSTRM control frame of type ACCEPT.
159 * @param contenttype: a zero delimited string with the content type.
160 * 	for dnstap streams use DNSTAP_CONTENT_TYPE.
161 * @param len: if a buffer is returned this is the length of that buffer.
162 * @return NULL on malloc failure.  Returns a malloced buffer with the
163 * protocol message.  The buffer starts with the 4 bytes of 0 that indicate
164 * a control frame.  The buffer should be sent without preceding it with
165 * the 'len' variable (like data frames are), but straight the content of the
166 * buffer, because the lengths are included in the buffer.  This is so that
167 * the zero control indicator can be included before the control frame length.
168 */
169void* fstrm_create_control_frame_accept(char* contenttype, size_t* len);
170
171/**
172 * This creates an FSTRM control frame of type FINISH.
173 * @param len: if a buffer is returned this is the length of that buffer.
174 * @return NULL on malloc failure.  Returns a malloced buffer with the
175 * protocol message.  The buffer starts with the 4 bytes of 0 that indicate
176 * a control frame.  The buffer should be sent without preceding it with
177 * the 'len' variable (like data frames are), but straight the content of the
178 * buffer, because the lengths are included in the buffer.  This is so that
179 * the zero control indicator can be included before the control frame length.
180 */
181void* fstrm_create_control_frame_finish(size_t* len);
182
183/**
184 * Return string that describes a control packet.  For debug, logs.
185 * Like 'start content-type(protobuf:dnstap.Dnstap)' or 'stop'.
186 * @param pkt: the packet data, that is the data after the 4 zero start
187 * bytes and 4 length bytes.
188 * @param len: the length of the control packet data, in pkt.  This is the
189 * ntohl of the 4 bytes length preceding the data.
190 * @return zero delimited string, malloced.  Or NULL on malloc failure.
191 */
192char* fstrm_describe_control(void* pkt, size_t len);
193
194#endif /* DNSTAP_FSTRM_H */
195