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