1 /* 2 * dnstap/dnstap_fstrm.c - 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 #include "config.h" 45 #include "dnstap/dnstap_fstrm.h" 46 #include "sldns/sbuffer.h" 47 #include "sldns/wire2str.h" 48 49 void* fstrm_create_control_frame_start(char* contenttype, size_t* len) 50 { 51 uint32_t* control; 52 size_t n; 53 /* start framestream message: 54 * 4byte 0: control indicator. 55 * 4byte bigendian: length of control frame 56 * 4byte bigendian: type START 57 * 4byte bigendian: option: content-type 58 * 4byte bigendian: length of string 59 * string of content type (dnstap) 60 */ 61 n = 4+4+4+4+4+strlen(contenttype); 62 control = malloc(n); 63 if(!control) 64 return NULL; 65 control[0] = 0; 66 control[1] = htonl(4+4+4+strlen(contenttype)); 67 control[2] = htonl(FSTRM_CONTROL_FRAME_START); 68 control[3] = htonl(FSTRM_CONTROL_FIELD_TYPE_CONTENT_TYPE); 69 control[4] = htonl(strlen(contenttype)); 70 memmove(&control[5], contenttype, strlen(contenttype)); 71 *len = n; 72 return control; 73 } 74 75 void* fstrm_create_control_frame_stop(size_t* len) 76 { 77 uint32_t* control; 78 size_t n; 79 /* stop framestream message: 80 * 4byte 0: control indicator. 81 * 4byte bigendian: length of control frame 82 * 4byte bigendian: type STOP 83 */ 84 n = 4+4+4; 85 control = malloc(n); 86 if(!control) 87 return NULL; 88 control[0] = 0; 89 control[1] = htonl(4); 90 control[2] = htonl(FSTRM_CONTROL_FRAME_STOP); 91 *len = n; 92 return control; 93 } 94 95 void* fstrm_create_control_frame_ready(char* contenttype, size_t* len) 96 { 97 uint32_t* control; 98 size_t n; 99 /* start bidirectional stream: 100 * 4 bytes 0 escape 101 * 4 bytes bigendian length of frame 102 * 4 bytes bigendian type READY 103 * 4 bytes bigendian frame option content type 104 * 4 bytes bigendian length of string 105 * string of content type. 106 */ 107 /* len includes the escape and framelength */ 108 n = 4+4+4+4+4+strlen(contenttype); 109 control = malloc(n); 110 if(!control) { 111 return NULL; 112 } 113 control[0] = 0; 114 control[1] = htonl(4+4+4+strlen(contenttype)); 115 control[2] = htonl(FSTRM_CONTROL_FRAME_READY); 116 control[3] = htonl(FSTRM_CONTROL_FIELD_TYPE_CONTENT_TYPE); 117 control[4] = htonl(strlen(contenttype)); 118 memmove(&control[5], contenttype, strlen(contenttype)); 119 *len = n; 120 return control; 121 } 122 123 void* fstrm_create_control_frame_accept(char* contenttype, size_t* len) 124 { 125 uint32_t* control; 126 size_t n; 127 /* control frame on reply: 128 * 4 bytes 0 escape 129 * 4 bytes bigendian length of frame 130 * 4 bytes bigendian type ACCEPT 131 * 4 bytes bigendian frame option content type 132 * 4 bytes bigendian length of string 133 * string of content type. 134 */ 135 /* len includes the escape and framelength */ 136 n = 4+4+4+4+4+strlen(contenttype); 137 control = malloc(n); 138 if(!control) { 139 return NULL; 140 } 141 control[0] = 0; 142 control[1] = htonl(4+4+4+strlen(contenttype)); 143 control[2] = htonl(FSTRM_CONTROL_FRAME_ACCEPT); 144 control[3] = htonl(FSTRM_CONTROL_FIELD_TYPE_CONTENT_TYPE); 145 control[4] = htonl(strlen(contenttype)); 146 memmove(&control[5], contenttype, strlen(contenttype)); 147 *len = n; 148 return control; 149 } 150 151 void* fstrm_create_control_frame_finish(size_t* len) 152 { 153 uint32_t* control; 154 size_t n; 155 /* control frame on reply: 156 * 4 bytes 0 escape 157 * 4 bytes bigendian length of frame 158 * 4 bytes bigendian type FINISH 159 */ 160 /* len includes the escape and framelength */ 161 n = 4+4+4; 162 control = malloc(n); 163 if(!control) { 164 return NULL; 165 } 166 control[0] = 0; 167 control[1] = htonl(4); 168 control[2] = htonl(FSTRM_CONTROL_FRAME_FINISH); 169 *len = n; 170 return control; 171 } 172 173 char* fstrm_describe_control(void* pkt, size_t len) 174 { 175 uint32_t frametype = 0; 176 char buf[512]; 177 char* str = buf; 178 size_t remain, slen = sizeof(buf); 179 uint8_t* pos; 180 181 buf[0]=0; 182 if(len < 4) { 183 snprintf(buf, sizeof(buf), "malformed control frame, " 184 "too short, len=%u", (unsigned int)len); 185 return strdup(buf); 186 } 187 frametype = sldns_read_uint32(pkt); 188 if(frametype == FSTRM_CONTROL_FRAME_ACCEPT) { 189 (void)sldns_str_print(&str, &slen, "accept"); 190 } else if(frametype == FSTRM_CONTROL_FRAME_START) { 191 (void)sldns_str_print(&str, &slen, "start"); 192 } else if(frametype == FSTRM_CONTROL_FRAME_STOP) { 193 (void)sldns_str_print(&str, &slen, "stop"); 194 } else if(frametype == FSTRM_CONTROL_FRAME_READY) { 195 (void)sldns_str_print(&str, &slen, "ready"); 196 } else if(frametype == FSTRM_CONTROL_FRAME_FINISH) { 197 (void)sldns_str_print(&str, &slen, "finish"); 198 } else { 199 (void)sldns_str_print(&str, &slen, "type%d", (int)frametype); 200 } 201 202 /* show the content type options */ 203 pos = pkt + 4; 204 remain = len - 4; 205 while(remain >= 8) { 206 uint32_t field_type = sldns_read_uint32(pos); 207 uint32_t field_len = sldns_read_uint32(pos+4); 208 if(remain < field_len) { 209 (void)sldns_str_print(&str, &slen, "malformed_field"); 210 break; 211 } 212 if(field_type == FSTRM_CONTROL_FIELD_TYPE_CONTENT_TYPE) { 213 char tempf[512]; 214 (void)sldns_str_print(&str, &slen, " content-type("); 215 if(field_len < sizeof(tempf)-1) { 216 memmove(tempf, pos+8, field_len); 217 tempf[field_len] = 0; 218 (void)sldns_str_print(&str, &slen, "%s", tempf); 219 } else { 220 (void)sldns_str_print(&str, &slen, "<error-too-long>"); 221 } 222 (void)sldns_str_print(&str, &slen, ")"); 223 } else { 224 (void)sldns_str_print(&str, &slen, 225 " field(type %u, length %u)", 226 (unsigned int)field_type, 227 (unsigned int)field_len); 228 } 229 pos += 8 + field_len; 230 remain -= (8 + field_len); 231 } 232 if(remain > 0) 233 (void)sldns_str_print(&str, &slen, " trailing-bytes" 234 "(length %u)", (unsigned int)remain); 235 return strdup(buf); 236 } 237