1 /* $NetBSD: dnstap.h,v 1.8 2022/09/23 12:15:30 christos Exp $ */ 2 3 /* 4 * Copyright (C) Internet Systems Consortium, Inc. ("ISC") 5 * 6 * SPDX-License-Identifier: MPL-2.0 7 * 8 * This Source Code Form is subject to the terms of the Mozilla Public 9 * License, v. 2.0. If a copy of the MPL was not distributed with this 10 * file, you can obtain one at https://mozilla.org/MPL/2.0/. 11 * 12 * See the COPYRIGHT file distributed with this work for additional 13 * information regarding copyright ownership. 14 */ 15 16 #ifndef _DNSTAP_H 17 #define _DNSTAP_H 18 19 /***** 20 ***** Module Info 21 *****/ 22 23 /*! \file 24 * \brief 25 * The dt (dnstap) module provides fast passive logging of DNS messages. 26 * Protocol Buffers. The protobuf schema for Dnstap messages is in the 27 * file dnstap.proto, which is compiled to dnstap.pb-c.c and dnstap.pb-c.h. 28 */ 29 30 #include <inttypes.h> 31 #include <stdbool.h> 32 33 struct fstrm_iothr_options; 34 35 #include <isc/log.h> 36 #include <isc/refcount.h> 37 #include <isc/region.h> 38 #include <isc/sockaddr.h> 39 #include <isc/time.h> 40 #include <isc/types.h> 41 42 #include <dns/name.h> 43 #include <dns/rdataclass.h> 44 #include <dns/rdatatype.h> 45 #include <dns/types.h> 46 47 /*% 48 * Dnstap message types: 49 * 50 * STUB QUERY: SQ 51 * STUB RESPONSE: SR 52 * CLIENT QUERY: CQ 53 * CLIENT RESPONSE: CR 54 * AUTH QUERY: AQ 55 * AUTH RESPONSE: AR 56 * RESOLVER QUERY: RQ 57 * RESOLVER RESPONSE: RR 58 * FORWARDER QUERY: FQ 59 * FORWARDER RESPONSE: FR 60 */ 61 62 #define DNS_DTTYPE_SQ 0x0001 63 #define DNS_DTTYPE_SR 0x0002 64 #define DNS_DTTYPE_CQ 0x0004 65 #define DNS_DTTYPE_CR 0x0008 66 #define DNS_DTTYPE_AQ 0x0010 67 #define DNS_DTTYPE_AR 0x0020 68 #define DNS_DTTYPE_RQ 0x0040 69 #define DNS_DTTYPE_RR 0x0080 70 #define DNS_DTTYPE_FQ 0x0100 71 #define DNS_DTTYPE_FR 0x0200 72 #define DNS_DTTYPE_TQ 0x0400 73 #define DNS_DTTYPE_TR 0x0800 74 #define DNS_DTTYPE_UQ 0x1000 75 #define DNS_DTTYPE_UR 0x2000 76 77 #define DNS_DTTYPE_QUERY \ 78 (DNS_DTTYPE_SQ | DNS_DTTYPE_CQ | DNS_DTTYPE_AQ | DNS_DTTYPE_RQ | \ 79 DNS_DTTYPE_FQ | DNS_DTTYPE_TQ | DNS_DTTYPE_UQ) 80 #define DNS_DTTYPE_RESPONSE \ 81 (DNS_DTTYPE_SR | DNS_DTTYPE_CR | DNS_DTTYPE_AR | DNS_DTTYPE_RR | \ 82 DNS_DTTYPE_FR | DNS_DTTYPE_TR | DNS_DTTYPE_UR) 83 #define DNS_DTTYPE_ALL (DNS_DTTYPE_QUERY | DNS_DTTYPE_RESPONSE) 84 85 typedef enum { 86 dns_dtmode_none = 0, 87 dns_dtmode_file, 88 dns_dtmode_unix 89 } dns_dtmode_t; 90 91 typedef struct dns_dthandle dns_dthandle_t; 92 93 #ifdef HAVE_DNSTAP 94 struct dns_dtdata { 95 isc_mem_t *mctx; 96 97 void *frame; 98 99 bool query; 100 bool tcp; 101 dns_dtmsgtype_t type; 102 103 isc_time_t qtime; 104 isc_time_t rtime; 105 106 isc_region_t qaddr; 107 isc_region_t raddr; 108 109 uint32_t qport; 110 uint32_t rport; 111 112 isc_region_t msgdata; 113 dns_message_t *msg; 114 115 char namebuf[DNS_NAME_FORMATSIZE]; 116 char typebuf[DNS_RDATATYPE_FORMATSIZE]; 117 char classbuf[DNS_RDATACLASS_FORMATSIZE]; 118 }; 119 #endif /* HAVE_DNSTAP */ 120 121 isc_result_t 122 dns_dt_create(isc_mem_t *mctx, dns_dtmode_t mode, const char *path, 123 struct fstrm_iothr_options **foptp, isc_task_t *reopen_task, 124 dns_dtenv_t **envp); 125 /*%< 126 * Create and initialize the dnstap environment. 127 * 128 * There should be a single global dnstap environment for the server; 129 * copies of it will be attached to each view. 130 * 131 * Notes: 132 * 133 *\li 'path' refers to a UNIX domain socket by default. It may 134 * optionally be prepended with "socket:" or "file:". If prepended 135 * with "file:", then dnstap logs are sent to a file instead of a 136 * socket. 137 * 138 *\li '*foptp' set the options for fstrm_iothr_init(). '*foptp' must have 139 * have had the number of input queues set and this should be set 140 * to the number of worker threads. Additionally the queue model 141 * should also be set. Other options may be set if desired. 142 * If dns_dt_create succeeds the *foptp is set to NULL. 143 * 144 *\li 'reopen_task' needs to be set to the task in the context of which 145 * dns_dt_reopen() will be called. This is not an optional parameter: 146 * using dns_dt_create() (which sets 'reopen_task' to NULL) is only 147 * allowed in unit tests. 148 * 149 * Requires: 150 * 151 *\li 'mctx' is a valid memory context. 152 * 153 *\li 'path' is a valid C string. 154 * 155 *\li 'foptp' is non NULL. 156 * 157 *\li envp != NULL && *envp == NULL 158 * 159 * Returns: 160 * 161 *\li #ISC_R_SUCCESS 162 *\li #ISC_R_NOMEMORY 163 * 164 *\li Other errors are possible. 165 */ 166 167 isc_result_t 168 dns_dt_setupfile(dns_dtenv_t *env, uint64_t max_size, int rolls, 169 isc_log_rollsuffix_t suffix); 170 /*%< 171 * Sets up the dnstap logfile limits. 172 * 173 * 'max_size' is the size a log file may grow before it is rolled 174 * 175 * 'rolls' is the number of rolled files to retain. 176 * 177 * 'suffix' is the logfile suffix setting, increment or timestamp. 178 * 179 * Requires: 180 * 181 *\li 'env' is a valid dnstap environment. 182 * 183 * Returns: 184 *\li #ISC_R_SUCCESS on success 185 *\li #ISC_R_INVALIDFILE if dnstap is set to use a UNIX domain socket 186 */ 187 188 isc_result_t 189 dns_dt_reopen(dns_dtenv_t *env, int roll); 190 /*%< 191 * Reopens files established by dns_dt_create2(). 192 * 193 * If 'roll' is non-negative and 'env->mode' is dns_dtmode_file, 194 * then the file is automatically rolled over before reopening. 195 * The value of 'roll' indicates the number of backup log files to 196 * keep. If 'roll' is negative, or if 'env->mode' is dns_dtmode_unix, 197 * then the channel is simply reopened. 198 * 199 * Note: dns_dt_reopen() uses task-exclusive mode and must be run in the 200 * context of env->reopen_task. 201 * 202 * Requires: 203 *\li 'env' is a valid dnstap environment. 204 */ 205 206 isc_result_t 207 dns_dt_setidentity(dns_dtenv_t *env, const char *identity); 208 isc_result_t 209 dns_dt_setversion(dns_dtenv_t *env, const char *version); 210 /*%< 211 * Set the "identity" and "version" strings to be sent in dnstap messages. 212 * 213 * Requires: 214 * 215 *\li 'env' is a valid dnstap environment. 216 */ 217 218 void 219 dns_dt_attach(dns_dtenv_t *source, dns_dtenv_t **destp); 220 /*%< 221 * Attach '*destp' to 'source', incrementing the reference counter. 222 * 223 * Requires: 224 * 225 *\li 'source' is a valid dnstap environment. 226 * 227 *\li 'destp' is not NULL and '*destp' is NULL. 228 * 229 *\li *destp is attached to source. 230 */ 231 232 void 233 dns_dt_detach(dns_dtenv_t **envp); 234 /*%< 235 * Detach '*envp', decrementing the reference counter. 236 * 237 * Requires: 238 * 239 *\li '*envp' is a valid dnstap environment. 240 * 241 * Ensures: 242 * 243 *\li '*envp' will be destroyed when the number of references reaches zero. 244 * 245 *\li '*envp' is NULL. 246 */ 247 248 isc_result_t 249 dns_dt_getstats(dns_dtenv_t *env, isc_stats_t **statsp); 250 /*%< 251 * Attach to the stats struct if it exists. 252 * 253 * Requires: 254 * 255 *\li 'env' is a valid dnstap environment. 256 * 257 *\li 'statsp' is non NULL and '*statsp' is NULL. 258 * 259 * Returns: 260 * 261 *\li ISC_R_SUCCESS 262 * 263 *\li ISC_R_NOTFOUND 264 */ 265 266 void 267 dns_dt_send(dns_view_t *view, dns_dtmsgtype_t msgtype, isc_sockaddr_t *qaddr, 268 isc_sockaddr_t *dstaddr, bool tcp, isc_region_t *zone, 269 isc_time_t *qtime, isc_time_t *rtime, isc_buffer_t *buf); 270 /*%< 271 * Sends a dnstap message to the log, if 'msgtype' is one of the message 272 * types represented in 'view->dttypes'. 273 * 274 * Parameters are: 'qaddr' (query address, i.e, the address of the 275 * query initiator); 'raddr' (response address, i.e., the address of 276 * the query responder); 'tcp' (boolean indicating whether the transaction 277 * was over TCP); 'zone' (the authoritative zone or bailiwick, in 278 * uncompressed wire format), 'qtime' and 'rtime' (query and response 279 * times; if NULL, they are set to the current time); and 'buf' (the 280 * DNS message being logged, in wire format). 281 * 282 * Requires: 283 * 284 *\li 'view' is a valid view, and 'view->dtenv' is NULL or is a 285 * valid dnstap environment. 286 */ 287 288 isc_result_t 289 dns_dt_parse(isc_mem_t *mctx, isc_region_t *src, dns_dtdata_t **destp); 290 /*%< 291 * Converts a raw dnstap frame in 'src' to a parsed dnstap data structure 292 * in '*destp'. 293 * 294 * Requires: 295 *\li 'src' is not NULL 296 * 297 *\li 'destp' is not NULL and '*destp' points to a valid buffer. 298 * 299 * Returns: 300 *\li #ISC_R_SUCCESS on success 301 * 302 *\li Other errors are possible. 303 */ 304 305 isc_result_t 306 dns_dt_datatotext(dns_dtdata_t *d, isc_buffer_t **dest); 307 /*%< 308 * Converts a parsed dnstap data structure 'd' to text, storing 309 * the result in the buffer 'dest'. If 'dest' points to a dynamically 310 * allocated buffer, then it may be reallocated as needed. 311 * 312 * (XXX: add a 'long_form' option to generate a detailed listing of 313 * dnstap data instead * of a one-line summary.) 314 * 315 * Requires: 316 *\li 'd' is not NULL 317 * 318 *\li 'dest' is not NULL and '*dest' points to a valid buffer. 319 * 320 * Returns: 321 *\li #ISC_R_SUCCESS on success 322 *\li #ISC_R_NOSPACE if buffer is not dynamic and runs out of space 323 *\li #ISC_R_NOMEMORY if buffer is dynamic but memory could not be allocated 324 * 325 *\li Other errors are possible. 326 */ 327 328 void 329 dns_dtdata_free(dns_dtdata_t **dp); 330 /*%< 331 * Frees the specified dns_dtdata structure and all its members, 332 * and sets *dp to NULL. 333 */ 334 335 isc_result_t 336 dns_dt_open(const char *filename, dns_dtmode_t mode, isc_mem_t *mctx, 337 dns_dthandle_t **handlep); 338 /*%< 339 * Opens a dnstap framestream at 'filename' and stores a pointer to the 340 * reader object in a dns_dthandle_t structure. 341 * 342 * The caller is responsible for allocating the handle structure. 343 * 344 * (XXX: Currently only file readers are supported, not unix-domain socket 345 * readers.) 346 * 347 * Requires: 348 * 349 *\li 'filename' is not NULL. 350 * 351 *\li 'handlep' is not NULL and '*handlep' is NULL. 352 * 353 *\li '*mctx' is not a valid memory context. 354 * 355 * Returns: 356 * 357 *\li #ISC_R_SUCCESS on success 358 *\li #ISC_R_NOTIMPLEMENTED if 'mode' is not dns_dtmode_file. (XXX) 359 *\li #ISC_R_NOMEMORY if the fstrm library was unable to allocate a 360 * reader or options structure 361 *\li #ISC_R_FAILURE if 'filename' could not be opened. 362 *\li #DNS_R_BADDNSTAP if 'filename' does not contain a dnstap 363 * framestream. 364 */ 365 366 isc_result_t 367 dns_dt_getframe(dns_dthandle_t *handle, uint8_t **bufp, size_t *sizep); 368 /*%< 369 * Read a dnstap frame from the framstream reader in 'handle', storing 370 * a pointer to it in '*bufp' and its size in '*sizep'. 371 * 372 * Requires: 373 * 374 *\li 'handle' is not NULL 375 *\li 'bufp' is not NULL 376 *\li 'sizep' is not NULL 377 * 378 * Ensures: 379 * \li if returning ISC_R_SUCCESS then '*bufp' is not NULL 380 * 381 * Returns: 382 * 383 *\li #ISC_R_SUCCESS on success 384 *\li #ISC_R_NOMORE at the end of the frame stream 385 *\li #ISC_R_FAILURE for any other failure 386 */ 387 388 void 389 dns_dt_close(dns_dthandle_t **handlep); 390 /*%< 391 * Closes the dnstap file referenced by 'handle'. 392 * 393 * Requires: 394 * 395 *\li '*handlep' is not NULL 396 */ 397 398 #endif /* _DNSTAP_H */ 399