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