├── contrib └── .placeholder ├── debian ├── compat ├── pdns-logger.conffiles ├── pdns-logger.docs ├── pdns-logger.dirs ├── pdns-logger.install ├── copyright ├── changelog ├── control ├── pdns-logger.postinst ├── rules └── pdns-logger.init ├── cmake ├── TestInline.c ├── FindSystemd.cmake ├── TestInline.cmake ├── DefineCMakeDefaults.cmake ├── FindProtobufC.cmake ├── ProjectFunctions.cmake ├── ProjectDefaults.cmake ├── DefineCompilerFlags.cmake ├── VersionString.cmake ├── FindSqlite3.cmake ├── ModuleHelpers.cmake ├── TDDHelpers.cmake ├── DefineInstallationPaths.cmake └── HeadersChecks.cmake ├── .gitignore ├── config ├── CMakeLists.txt └── pdns-logger.ini.in ├── src ├── CMakeLists.txt ├── inih │ ├── LICENSE.txt │ ├── ini.h │ ├── README.md │ └── ini.c ├── pdns-logger-ini.c ├── pdns-logger.h.in ├── dnsmessage.proto ├── pdns-logger-dns.c ├── pdns-logger-queue.c ├── pdns-logger-dns.h ├── pdns-logger.c ├── pdns-logger-protobuf.c ├── dnsmessage.pb-c.h ├── pdns-logger-syslog.c ├── pdns-logger-file.c ├── pdns-logger-sqlite.c └── dnsmessage.pb-c.c ├── do_indent.sh ├── .gitlab-ci.yml ├── CMakeLists.txt ├── README.md └── COPYING /contrib/.placeholder: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /debian/compat: -------------------------------------------------------------------------------- 1 | 9 2 | -------------------------------------------------------------------------------- /debian/pdns-logger.conffiles: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /debian/pdns-logger.docs: -------------------------------------------------------------------------------- 1 | README.md 2 | COPYING 3 | -------------------------------------------------------------------------------- /debian/pdns-logger.dirs: -------------------------------------------------------------------------------- 1 | etc/pdns-logger 2 | usr/sbin 3 | var/lib/pdns-logger 4 | var/log/pdns-logger 5 | -------------------------------------------------------------------------------- /debian/pdns-logger.install: -------------------------------------------------------------------------------- 1 | debian/tmp/etc/pdns-logger/pdns-logger.ini 2 | debian/tmp/usr/sbin/pdns-logger 3 | -------------------------------------------------------------------------------- /cmake/TestInline.c: -------------------------------------------------------------------------------- 1 | typedef int foo_t; 2 | static inline foo_t static_foo(){return 0;} 3 | foo_t foo(){return 0;} 4 | int main(int argc, char *argv[]){return 0;} 5 | 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | 3 | debian/tmp/ 4 | debian/pdns-logger/ 5 | 6 | debian/files 7 | debian/*.debhelper.log 8 | debian/*.debhelper 9 | debian/*.substvars 10 | 11 | -------------------------------------------------------------------------------- /config/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | CONFIGURE_FILE( 3 | ${CMAKE_CURRENT_SOURCE_DIR}/pdns-logger.ini.in 4 | ${CMAKE_CURRENT_BINARY_DIR}/pdns-logger.ini 5 | ) 6 | 7 | INSTALL_IF_NOT_EXISTS(${CMAKE_CURRENT_BINARY_DIR}/pdns-logger.ini ${PROJECT_SYSCONF_DIR}) 8 | -------------------------------------------------------------------------------- /debian/copyright: -------------------------------------------------------------------------------- 1 | This package was debianized by Massimo Cetra 2 | Thu Oct 12 11:22:31 UTC 2017 3 | 4 | Upstream Author: Massimo Cetra 5 | 6 | Copyright: 7 | Copyright (C) 2017 Spamhaus Tecnology 8 | Copyright (C) 2017 Massimo Cetra 9 | 10 | License: 11 | MPL 2 12 | 13 | -------------------------------------------------------------------------------- /debian/changelog: -------------------------------------------------------------------------------- 1 | pdns-logger (1.0-2) unstable; urgency=low 2 | 3 | * Modified the default config options 4 | * documentation improvements. 5 | * autocommit feature for sqlite added, defaulting to 1 6 | 7 | -- MC Thu, 02 Nov 2017 11:22:31 +0000 8 | 9 | pdns-logger (1.0-1) unstable; urgency=low 10 | 11 | * First version 12 | 13 | -- MC Thu, 12 Oct 2017 11:22:31 +0000 14 | -------------------------------------------------------------------------------- /debian/control: -------------------------------------------------------------------------------- 1 | Source: pdns-logger 2 | Section: net 3 | Priority: extra 4 | Maintainer: MC 5 | Build-Depends: cdbs (>= 0.4.23-1.1), debhelper (>= 5), devscripts, cmake, build-essential, pkg-config, 6 | libprotobuf-c-dev, libsqlite3-dev 7 | Standards-Version: 3.9.8 8 | #, libsystemd-dev 9 | 10 | Package: pdns-logger 11 | Architecture: any 12 | Depends: lsb-base, ${shlibs:Depends}, ${misc:Depends} 13 | Suggests: pdns-recursor (>= 4.0.4) 14 | Description: SpamTeq Powernd-recursor Logger 15 | Basic logger for the PowerDNS recursor protobuf socket 16 | 17 | -------------------------------------------------------------------------------- /debian/pdns-logger.postinst: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | case "$1" in 5 | configure) 6 | addgroup --system pdns 7 | adduser --system --home /var/spool/powerdns --shell /bin/false --ingroup pdns --disabled-password --disabled-login --gecos "PowerDNS" pdns 8 | mkdir -p -m0755 /var/lib/pdns-logger 9 | mkdir -p -m0755 /var/log/pdns-logger 10 | chown pdns:pdns /var/log/pdns-logger /var/lib/pdns-logger 11 | ;; 12 | 13 | *) 14 | echo "postinst called with unknown argument \`$1'" >&2 15 | exit 1 16 | ;; 17 | esac 18 | 19 | # Startup errors should never cause dpkg to fail. 20 | initscript_error() { 21 | return 0 22 | } 23 | 24 | #DEBHELPER# 25 | 26 | exit 0 27 | -------------------------------------------------------------------------------- /cmake/FindSystemd.cmake: -------------------------------------------------------------------------------- 1 | 2 | FIND_PATH(SYSTEMD_INCLUDE_DIR 3 | NAMES sd-daemon.h 4 | PATH_SUFFIXES include/ systemd/ 5 | PATHS "${PROJECT_SOURCE_DIR}/../systemd/" 6 | ${SYSTEMD_ROOT} 7 | $ENV{SYSTEMD_ROOT} 8 | /usr/include/ 9 | /usr/local/ 10 | /usr/ 11 | ) 12 | 13 | IF(SYSTEMD_INCLUDE_DIR) 14 | SET(SYSTEMD_FOUND TRUE) 15 | ELSE(SYSTEMD_INCLUDE_DIR) 16 | SET(SYSTEMD_FOUND FALSE) 17 | ENDIF(SYSTEMD_INCLUDE_DIR) 18 | 19 | IF(SYSTEMD_FOUND) 20 | MESSAGE(STATUS "Found Systemd in ${SYSTEMD_INCLUDE_DIR}") 21 | ELSE(SYSTEMD_FOUND) 22 | IF(SYSTEMD_FIND_REQUIRED) 23 | MESSAGE(FATAL_ERROR "Could not find Systemd library") 24 | ENDIF(SYSTEMD_FIND_REQUIRED) 25 | ENDIF(SYSTEMD_FOUND) 26 | 27 | MARK_AS_ADVANCED( 28 | SYSTEMD_INCLUDE_DIR 29 | ) 30 | 31 | -------------------------------------------------------------------------------- /cmake/TestInline.cmake: -------------------------------------------------------------------------------- 1 | 2 | FOREACH(KEYWORD "inline" "__inline__" "__inline") 3 | IF(NOT DEFINED C_INLINE) 4 | TRY_COMPILE(C_HAS_${KEYWORD} "${CMAKE_CURRENT_BINARY_DIR}" 5 | "${CMAKE_CURRENT_SOURCE_DIR}/cmake/TestInline.c" 6 | COMPILE_DEFINITIONS "-Dinline=${KEYWORD}" 7 | OUTPUT_VARIABLE ASD 8 | ) 9 | 10 | IF(C_HAS_${KEYWORD}) 11 | SET(C_INLINE TRUE) 12 | SET(C_INLINE_VAL ${KEYWORD}) 13 | #ADD_DEFINITIONS("-Dinline=${KEYWORD}") 14 | ENDIF(C_HAS_${KEYWORD}) 15 | 16 | ENDIF(NOT DEFINED C_INLINE) 17 | ENDFOREACH(KEYWORD) 18 | 19 | IF(NOT DEFINED C_INLINE) 20 | MESSAGE(STATUS "Inline support not found") 21 | ELSE(NOT DEFINED C_INLINE) 22 | MESSAGE(STATUS "Inline support found: ${C_INLINE_VAL}") 23 | ENDIF(NOT DEFINED C_INLINE) 24 | 25 | -------------------------------------------------------------------------------- /cmake/DefineCMakeDefaults.cmake: -------------------------------------------------------------------------------- 1 | # Always include srcdir and builddir in include path 2 | # This saves typing ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY} in 3 | # about every subdir 4 | # since cmake 2.4.0 5 | 6 | set(CMAKE_INCLUDE_CURRENT_DIR ON) 7 | 8 | # Put the include dirs which are in the source or build tree 9 | # before all other include dirs, so the headers in the sources 10 | # are prefered over the already installed ones 11 | # since cmake 2.4.1 12 | 13 | set(CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE ON) 14 | 15 | # Use colored output 16 | # since cmake 2.4.0 17 | 18 | set(CMAKE_COLOR_MAKEFILE ON) 19 | 20 | # Define the generic version of the libraries here 21 | 22 | set(GENERIC_LIB_VERSION "0.1.0") 23 | set(GENERIC_LIB_SOVERSION "0") 24 | 25 | # Set the default build type to release with debug info 26 | if (NOT CMAKE_BUILD_TYPE) 27 | set(CMAKE_BUILD_TYPE Debug 28 | CACHE STRING 29 | "Choose the type of build, options are: Debug, Release" 30 | FORCE 31 | ) 32 | endif (NOT CMAKE_BUILD_TYPE) 33 | -------------------------------------------------------------------------------- /cmake/FindProtobufC.cmake: -------------------------------------------------------------------------------- 1 | 2 | INCLUDE(FindPkgConfig) 3 | 4 | IF(NOT PKG_CONFIG_FOUND) 5 | MESSAGE(STATUS "Cannot find PKG-CONFIG cmake extensions. Protobuf modules will not be built.") 6 | ELSE(NOT PKG_CONFIG_FOUND) 7 | 8 | PKG_CHECK_MODULES(PROTOBUFC QUIET libprotobuf-c) 9 | 10 | IF(NOT ${PROTOBUFC_VERSION}) 11 | IF(NOT ${PROTOBUFC_FIND_QUIETLY}) 12 | MESSAGE(STATUS "PROTOBUF-C support not found ${PROTOBUFC_VERSION}") 13 | ENDIF(NOT ${PROTOBUFC_FIND_QUIETLY}) 14 | ELSE(NOT ${PROTOBUFC_VERSION}) 15 | IF(NOT ${PROTOBUFC_FIND_QUIETLY}) 16 | MESSAGE(STATUS "PROTOBUF-C support found") 17 | ENDIF(NOT ${PROTOBUFC_FIND_QUIETLY}) 18 | SET(PROTOBUFC_FOUND TRUE) 19 | ENDIF(NOT ${PROTOBUFC_VERSION}) 20 | 21 | ENDIF(NOT PKG_CONFIG_FOUND) 22 | 23 | IF(PROTOBUFC_FIND_REQUIRED) 24 | IF (NOT ${PROTOBUFC_FOUND}) 25 | MESSAGE(FATAL_ERROR "Could not find protobuf-c library which is a required prerequisite for pdns-logger") 26 | ENDIF (NOT ${PROTOBUFC_FOUND}) 27 | ENDIF(PROTOBUFC_FIND_REQUIRED) 28 | -------------------------------------------------------------------------------- /cmake/ProjectFunctions.cmake: -------------------------------------------------------------------------------- 1 | # 2 | # Usage: 3 | # install_if_not_exists(source_file destination_directory) 4 | # 5 | 6 | FUNCTION(install_if_not_exists src dest) 7 | IF(NOT IS_ABSOLUTE "${src}") 8 | SET(src "${CMAKE_CURRENT_SOURCE_DIR}/${src}") 9 | ENDIF() 10 | 11 | GET_FILENAME_COMPONENT(src_name "${src}" NAME) 12 | 13 | IF(NOT IS_ABSOLUTE "${dest}") 14 | SET(dest "${CMAKE_INSTALL_PREFIX}/${dest}") 15 | ENDIF() 16 | 17 | INSTALL(CODE " 18 | IF(NOT EXISTS \"\$ENV{DESTDIR}${dest}/${src_name}\") 19 | #file(INSTALL \"${src}\" DESTINATION \"${dest}\") 20 | MESSAGE(STATUS \"Installing: \$ENV{DESTDIR}${dest}/${src_name}\") 21 | EXECUTE_PROCESS(COMMAND \${CMAKE_COMMAND} -E copy \"${src}\" 22 | \"\$ENV{DESTDIR}${dest}/${src_name}\" 23 | RESULT_VARIABLE copy_result 24 | ERROR_VARIABLE error_output) 25 | IF(copy_result) 26 | MESSAGE(FATAL_ERROR \${error_output}) 27 | ENDIF() 28 | ELSE() 29 | message(STATUS \"Skipping : \$ENV{DESTDIR}${dest}/${src_name}\") 30 | ENDIF() 31 | ") 32 | ENDFUNCTION(install_if_not_exists) 33 | -------------------------------------------------------------------------------- /cmake/ProjectDefaults.cmake: -------------------------------------------------------------------------------- 1 | 2 | MARK_AS_ADVANCED( PROJECT_DEFAULT_USER ) 3 | IF(NOT PROJECT_DEFAULT_USER) 4 | SET(PROJECT_DEFAULT_USER "nobody") 5 | ENDIF(NOT PROJECT_DEFAULT_USER) 6 | 7 | MARK_AS_ADVANCED( PROJECT_DEFAULT_GROUP ) 8 | IF(NOT PROJECT_DEFAULT_GROUP) 9 | SET(PROJECT_DEFAULT_GROUP "nogroup") 10 | ENDIF(NOT PROJECT_DEFAULT_GROUP) 11 | 12 | MARK_AS_ADVANCED( PROJECT_SYSCONF_DIR ) 13 | IF(NOT PROJECT_SYSCONF_DIR) 14 | SET(PROJECT_SYSCONF_DIR ${SYSCONF_INSTALL_DIR}/pdns-logger/) 15 | ENDIF(NOT PROJECT_SYSCONF_DIR) 16 | 17 | MARK_AS_ADVANCED( PROJECT_STATE_DIR ) 18 | IF(NOT PROJECT_STATE_DIR) 19 | SET(PROJECT_STATE_DIR ${CMAKE_INSTALL_PREFIX}/run/) 20 | ENDIF(NOT PROJECT_STATE_DIR) 21 | 22 | MARK_AS_ADVANCED( PROJECT_LOG_DIR ) 23 | IF(NOT PROJECT_LOG_DIR) 24 | SET(PROJECT_LOG_DIR ${CMAKE_INSTALL_PREFIX}/var/log/pdns-logger) 25 | ENDIF(NOT PROJECT_LOG_DIR) 26 | 27 | MARK_AS_ADVANCED( PROJECT_MODULES_DIR ) 28 | IF(NOT PROJECT_MODULES_DIR) 29 | SET(PROJECT_MODULES_DIR ${LIB_INSTALL_DIR}/pdns-logger/modules) 30 | ENDIF(NOT PROJECT_MODULES_DIR) 31 | 32 | #MARK_AS_ADVANCED( PROJECT_LANG_DIR ) 33 | # IF(NOT PROJECT_LANG_DIR) 34 | # SET(PROJECT_LANG_DIR ${CMAKE_INSTALL_PREFIX}/lib/name/lang) 35 | # ENDIF(NOT PROJECT_LANG_DIR) 36 | -------------------------------------------------------------------------------- /src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | CONFIGURE_FILE( 3 | ${CMAKE_CURRENT_SOURCE_DIR}/pdns-logger.h.in 4 | ${CMAKE_CURRENT_BINARY_DIR}/pdns-logger.h 5 | ) 6 | 7 | SET (INCLUDES "${PROTOBUFC_INCLUDEDIR}") 8 | 9 | IF(SYSTEMD_FOUND) 10 | SET (INCLUDES "${INCLUDES} ${SYSTEMD_INCLUDE_DIR}") 11 | ENDIF(SYSTEMD_FOUND) 12 | 13 | INCLUDE_DIRECTORIES( 14 | ${INCLUDES} 15 | ) 16 | 17 | SET(SOURCES 18 | dnsmessage.pb-c.c 19 | inih/ini.c 20 | 21 | pdns-logger-syslog.c 22 | pdns-logger-file.c 23 | pdns-logger-protobuf.c 24 | pdns-logger-queue.c 25 | pdns-logger-dns.c 26 | pdns-logger-ini.c 27 | pdns-logger.c 28 | ) 29 | 30 | 31 | SET (LINKLIBS 32 | ${PROTOBUFC_LIBRARIES} 33 | pthread 34 | ) 35 | 36 | IF(SQLITE3_FOUND) 37 | ADD_DEFINITIONS(-DSQLITE3_FOUND) 38 | SET (SOURCES 39 | ${SOURCES} 40 | pdns-logger-sqlite.c 41 | ) 42 | SET (LINKLIBS 43 | ${LINKLIBS} 44 | ${SQLITE3_LIBRARIES} 45 | ) 46 | ENDIF(SQLITE3_FOUND) 47 | 48 | ADD_EXECUTABLE ( 49 | pdns-logger 50 | ${SOURCES} 51 | ) 52 | 53 | TARGET_LINK_LIBRARIES ( 54 | pdns-logger 55 | ${LINKLIBS} 56 | ) 57 | 58 | SET_TARGET_PROPERTIES( 59 | pdns-logger 60 | PROPERTIES 61 | PROJECT_LABEL "pdns-logger" 62 | OUTPUT_NAME pdns-logger 63 | ) 64 | 65 | INSTALL( 66 | TARGETS 67 | pdns-logger 68 | RUNTIME DESTINATION "${SBIN_INSTALL_DIR}" 69 | LIBRARY DESTINATION "${BIN_INSTALL_DIR}" 70 | ARCHIVE DESTINATION "${BIN_INSTALL_DIR}" 71 | ) 72 | 73 | INSTALL(DIRECTORY DESTINATION ${PROJECT_STATE_DIR}) 74 | -------------------------------------------------------------------------------- /src/inih/LICENSE.txt: -------------------------------------------------------------------------------- 1 | 2 | The "inih" library is distributed under the New BSD license: 3 | 4 | Copyright (c) 2009, Ben Hoyt 5 | All rights reserved. 6 | 7 | Redistribution and use in source and binary forms, with or without 8 | modification, are permitted provided that the following conditions are met: 9 | * Redistributions of source code must retain the above copyright 10 | notice, this list of conditions and the following disclaimer. 11 | * Redistributions in binary form must reproduce the above copyright 12 | notice, this list of conditions and the following disclaimer in the 13 | documentation and/or other materials provided with the distribution. 14 | * Neither the name of Ben Hoyt nor the names of its contributors 15 | may be used to endorse or promote products derived from this software 16 | without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY BEN HOYT ''AS IS'' AND ANY 19 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL BEN HOYT BE LIABLE FOR ANY 22 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 25 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /debian/rules: -------------------------------------------------------------------------------- 1 | #!/usr/bin/make -f 2 | 3 | #include /usr/share/cdbs/1/rules/debhelper.mk 4 | #include /usr/share/cdbs/1/class/makefile.mk 5 | #Added simple-patchsys for Kubuntu 6 | #include /usr/share/cdbs/1/rules/simple-patchsys.mk 7 | 8 | DEB_DESTDIR=DESTDIR=$(CURDIR)/debian/tmp/ 9 | DEB_BUILD_OPTIONS=nostrip 10 | 11 | #DEB_MAKE_ENVVARS += INSTALL_ROOT=debian/tmp/ 12 | DEB_MAKE_INSTALL_TARGET = install $(DEB_DESTDIR) 13 | 14 | configure: 15 | mkdir -p build 16 | cd build && \ 17 | $(DEB_DESTDIR) \ 18 | cmake ../ \ 19 | -DCMAKE_BUILD_TYPE=Release \ 20 | -DCMAKE_INSTALL_PREFIX="/usr/" \ 21 | -DSYSCONF_INSTALL_DIR="/etc" \ 22 | -DPROJECT_STATE_DIR="/var/run/" 23 | 24 | build: configure 25 | dh_testdir 26 | cd build && $(MAKE) 27 | 28 | install: build 29 | dh_testdir 30 | dh_testroot 31 | cd build && $(MAKE) $(DEB_MAKE_INSTALL_TARGET) 32 | 33 | binary-indep: 34 | dh_testdir 35 | dh_testroot 36 | dh_installdirs -a 37 | dh_installdocs -a 38 | dh_installdebconf -a 39 | dh_installman -a 40 | dh_compress -a 41 | dh_fixperms -a 42 | dh_installdeb -a 43 | dh_gencontrol -a 44 | 45 | binary-arch: build install 46 | dh_testdir 47 | dh_testroot 48 | 49 | dh_installdebconf 50 | dh_installlogrotate 51 | dh_installdirs -a 52 | dh_installinit -R --init-script=pdns-logger 53 | dh_install 54 | #dh_installchangelogs -a ChangeLog 55 | dh_link 56 | dh_compress 57 | dh_fixperms 58 | dh_installdeb 59 | dh_makeshlibs 60 | dh_shlibdeps 61 | dh_gencontrol 62 | 63 | 64 | binary: binary-arch binary-indep 65 | dh_md5sums 66 | dh_builddeb 67 | 68 | clean: 69 | rm -f debian/stamp-patched 70 | rm -rf build 71 | dh_clean 72 | -------------------------------------------------------------------------------- /config/pdns-logger.ini.in: -------------------------------------------------------------------------------- 1 | ; Please add something like this: 2 | ; protobufServer("127.0.0.1:4242", 2, 100, 1, 32, 128, false, true) 3 | ; to the LUA configuration file of the recursor. 4 | ; Note that the last parameter is supported only in 4.1.0 or later. 5 | ; Remove it if you're using a previous version of the recursor 6 | 7 | [globals] 8 | allow-root=0 9 | bind-ip=127.0.0.1 10 | bind-port=4242 11 | ;foreground=0 ; If set, this will override the CLI -f option 12 | 13 | 14 | [logfile] 15 | disabled = 0 ; should we disable the log-to-file backend ? 16 | only-rewrites=1 ; log only RPZ rewrites 17 | ; what is the path of our log file ? 18 | logfile=/var/log/pdns-logger/pdns.log 19 | force-flush=1 ; flush buffers to disk at each query 20 | 21 | 22 | [syslog] 23 | disabled = 1 ; Should we disable the syslog backend ? 24 | only-rewrites=1 ; log only RPZ rewrites 25 | ident=pdns-logger ; the syslog ident 26 | facility=syslog ; the log facility 27 | 28 | 29 | [sqlite3] 30 | disabled = 1; ; should we disable the sqlite3 backend ? 31 | only-rewrites=1 ; log only RPZ rewrites 32 | ; what is the path to our sqlite3 database ? 33 | dbfile=/var/lib/pdns-logger/queries.db 34 | autocommit=1 ; should the backend commit to file for every record ? 35 | 36 | ; NOTES: 37 | ; 38 | ; When configuring the recursor with the protobufServer() function, the taggedOnly parameter 39 | ; works only for 4.1.0 and later versions. This will affect the logger setting 'only-rewrites' 40 | ; which will become basically useless. 41 | -------------------------------------------------------------------------------- /debian/pdns-logger.init: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Start or stop PDNS-LOGGER 4 | 5 | ### BEGIN INIT INFO 6 | # Provides: pdns-logger 7 | # Required-Start: $local_fs $remote_fs $syslog $network 8 | # Required-Stop: $local_fs $remote_fs $syslog $network 9 | # Default-Start: 2 3 4 5 10 | # Default-Stop: 0 1 6 11 | # Short-Description: Start and Stop the pdns-logger daemon. 12 | ### END INIT INFO 13 | 14 | PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin 15 | 16 | NAME=pdns-logger 17 | DESC="PowerDNS Logger" 18 | PIDFILE="/var/run/$NAME.pid" 19 | DAEMON="/usr/sbin/pdns-logger" 20 | 21 | # by default: no params 22 | PDNS_LOGGER_USER=pdns 23 | PDNS_LOGGER_PARAMETERS="" 24 | PDNS_LOGGER_START="yes" 25 | 26 | if [ -r /etc/default/$NAME ]; then . /etc/default/$NAME; fi 27 | 28 | if [ "$PDNS_LOGGER_START" != "yes" ];then 29 | echo "$DESC not yet configured. Edit /etc/default/$NAME first." 30 | exit 0 31 | fi 32 | 33 | test -x $DAEMON || exit 0 34 | 35 | set -e 36 | 37 | case "$1" in 38 | start) 39 | echo -n "Starting $DESC: " 40 | start-stop-daemon --chuid $PDNS_LOGGER_USER --start --pidfile "$PIDFILE" --exec $DAEMON -- $PDNS_LOGGER_PARAMETERS 41 | echo "$NAME." 42 | ;; 43 | stop) 44 | echo -n "Stopping $DESC: " 45 | start-stop-daemon --stop --quiet --oknodo --signal=TERM --exec $DAEMON 46 | sleep 3 47 | start-stop-daemon --stop --quiet --oknodo --retry=0/2/2/KILL/5 --exec $DAEMON 48 | echo -n "$NAME" 49 | echo "." 50 | ;; 51 | rotate) 52 | start-stop-daemon --stop --quiet --oknodo --signal=HUP --exec $DAEMON 53 | ;; 54 | reload) 55 | start-stop-daemon --stop --quiet --oknodo --signal=HUP --exec $DAEMON 56 | ;; 57 | force-reload) 58 | $0 stop 59 | $0 start 60 | ;; 61 | restart) 62 | $0 stop 63 | $0 start 64 | ;; 65 | *) 66 | N=/etc/init.d/$NAME 67 | echo "Usage: $N {start|stop|restart|force-reload|reload|rotate}" >&2 68 | exit 1 69 | ;; 70 | esac 71 | 72 | exit 0 73 | -------------------------------------------------------------------------------- /do_indent.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # 4 | # This file is used to conform all code to the same style. 5 | # Please use indent, if you need to submit patches or contribute 6 | # your code. 7 | # 8 | 9 | function do_indent() { 10 | local FROM=$1 11 | local TO=$2 12 | 13 | 14 | /usr/bin/indent \ 15 | --braces-on-func-def-line \ 16 | \ 17 | --no-blank-lines-after-declarations \ 18 | --no-blank-lines-after-procedures \ 19 | --no-blank-lines-after-commas \ 20 | --break-before-boolean-operator \ 21 | --braces-on-struct-decl-line \ 22 | --honour-newlines \ 23 | --braces-on-if-line \ 24 | --comment-indentation33 \ 25 | --declaration-comment-column33 \ 26 | --no-comment-delimiters-on-blank-lines \ 27 | --cuddle-else \ 28 | --continuation-indentation4 \ 29 | --case-indentation0 \ 30 | --line-comments-indentation0 \ 31 | --declaration-indentation1 \ 32 | --dont-format-first-column-comments \ 33 | --parameter-indentation0 \ 34 | --continue-at-parentheses \ 35 | --no-space-after-function-call-names \ 36 | --dont-break-procedure-type \ 37 | --space-after-if \ 38 | --space-after-for \ 39 | --space-after-while \ 40 | --no-space-after-parentheses \ 41 | --dont-star-comments \ 42 | --swallow-optional-blank-lines \ 43 | --dont-format-comments \ 44 | --else-endif-column33 \ 45 | --space-special-semicolon \ 46 | --indent-label1 \ 47 | --case-indentation4 \ 48 | \ 49 | --tab-size4 \ 50 | -i4 \ 51 | -l200 \ 52 | --no-tabs \ 53 | $FROM \ 54 | -o $TO 55 | } 56 | 57 | 58 | SOURCES=`find src/ -name *.[c,h] -print;` 59 | 60 | for SOURCE in $SOURCES; do 61 | if $( echo $SOURCE | grep -v --quiet 'foobar' ) 62 | then 63 | echo $SOURCE 64 | do_indent $SOURCE $SOURCE 65 | fi 66 | done; 67 | 68 | -------------------------------------------------------------------------------- /cmake/DefineCompilerFlags.cmake: -------------------------------------------------------------------------------- 1 | # define system dependent compiler flags 2 | 3 | INCLUDE(CheckCCompilerFlag) 4 | 5 | IF (UNIX AND NOT WIN32) 6 | 7 | ADD_DEFINITIONS(-D_GNU_SOURCE) 8 | 9 | CHECK_C_COMPILER_FLAG("-fstack-protector" WITH_STACK_PROTECTOR) 10 | IF (WITH_STACK_PROTECTOR) 11 | ADD_DEFINITIONS(-fstack-protector) 12 | ENDIF (WITH_STACK_PROTECTOR) 13 | 14 | CHECK_C_COMPILER_FLAG("-D_FORTIFY_SOURCE=2" WITH_FORTIFY_SOURCE) 15 | IF (WITH_FORTIFY_SOURCE) 16 | ADD_DEFINITIONS(-D_FORTIFY_SOURCE=2) 17 | ENDIF (WITH_FORTIFY_SOURCE) 18 | 19 | 20 | SET(CMAKE_INCLUDE_PATH "/usr/include/ /usr/local/include" ) 21 | 22 | SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -W -Wreturn-type -Wstrict-prototypes") 23 | SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -W -Wmissing-prototypes -Wmissing-declarations -Wpointer-arith -Wchar-subscripts -Wformat=2 -Wbad-function-cast -Wno-strict-aliasing -Wshadow") 24 | SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wdeclaration-after-statement -Wuninitialized -Wno-format-nonliteral" ) 25 | #SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-omit-frame-pointer -Wstrict-aliasing=2") 26 | #SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-unused -Wno-unused-parameter" ) 27 | #SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fvisibility=hidden") 28 | #SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fstack-protector-all") 29 | SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fstack-protector-strong") 30 | #SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=undefined -fno-sanitize-recover") 31 | 32 | # Mandatory for loadable modules 33 | SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC" ) 34 | 35 | IF ("${CMAKE_BUILD_TYPE}" STREQUAL "Release") 36 | SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O3 -Wno-strict-aliasing") 37 | ENDIF ("${CMAKE_BUILD_TYPE}" STREQUAL "Release") 38 | 39 | IF ("${CMAKE_BUILD_TYPE}" STREQUAL "Debug") 40 | SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -O0 -Wstrict-aliasing=2 -fno-omit-frame-pointer") 41 | ENDIF ("${CMAKE_BUILD_TYPE}" STREQUAL "Debug") 42 | 43 | 44 | ENDIF (UNIX AND NOT WIN32) 45 | -------------------------------------------------------------------------------- /src/pdns-logger-ini.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Powerdns logger daemon 3 | * ---------------------- 4 | * 5 | * This Source Code Form is subject to the terms of the 6 | * Mozilla Public License, v. 2.0. 7 | * If a copy of the MPL was not distributed with this 8 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 9 | * 10 | * Copyright (C) 2017, Spamhaus Technology Ltd, London 11 | * 12 | * The Initial developer of the Original code is: 13 | * Massimo Cetra 14 | * 15 | */ 16 | 17 | #include "pdns-logger.h" 18 | #include "inih/ini.h" 19 | 20 | static int opt_handler(void *user, const char *section, const char *name, const char *value, int lineno) { 21 | globals_t *globals = user; 22 | 23 | if (zstr(section) || zstr(name) || zstr(value)) { 24 | return 1; 25 | } 26 | 27 | if (!strncmp(section, "globals", sizeof("globals"))) { 28 | if (!strncmp(name, "bind-ip", sizeof("bind-ip"))) { 29 | globals->bind_ip = strdup(value); 30 | } else if (!strncmp(name, "bind-port", sizeof("bind-port"))) { 31 | globals->bind_port = atoi(value); 32 | } else if (!strncmp(name, "allow-root", sizeof("allow-root"))) { 33 | globals->allow_root = atoi(value) ? 1 : 0; 34 | } else if (!strncmp(name, "foreground", sizeof("foreground"))) { 35 | globals->foreground = atoi(value) ? 1 : 0; 36 | /* 37 | } else if (!strncmp(name, "user", sizeof("user"))) { 38 | globals->user = strdup(value); 39 | } else if (!strncmp(name, "group", sizeof("group"))) { 40 | globals->group = strdup(value); 41 | */ 42 | } else { 43 | fprintf(stderr, "Unmanaged INI option '%s' at line %d\n", name, lineno); 44 | } 45 | 46 | return 1; 47 | } 48 | 49 | return 1; 50 | } 51 | 52 | pdns_status_t parse_config_file(const char *cf, globals_t * globals) { 53 | 54 | if (zstr(cf)) { 55 | return PDNS_NO; 56 | } 57 | 58 | if (ini_parse(cf, opt_handler, globals) != 0) { 59 | fprintf(stderr, "Can't read options file: '%s'\n", cf); 60 | return PDNS_NO; 61 | } 62 | 63 | return PDNS_OK; 64 | } 65 | -------------------------------------------------------------------------------- /cmake/VersionString.cmake: -------------------------------------------------------------------------------- 1 | # 2 | # Create a tag with 'git tag ' and 'git push --tags' 3 | # 4 | 5 | FIND_PACKAGE(Git) 6 | 7 | IF(NOT GIT_FOUND) 8 | # cmake 2.8.1 (in Lucid) does not have a git Cmake interface 9 | # cmake 2.8.5 (in Oneiric) does have it 10 | MESSAGE(STATUS "Couldn't find CMAKE interface to git, old version of Cmake? looking by hand...") 11 | EXECUTE_PROCESS( 12 | COMMAND git --version 13 | RESULT_VARIABLE RC 14 | ) 15 | IF(${RC} EQUAL 0) 16 | SET(GIT_FOUND 1) 17 | SET(GIT_EXECUTABLE "git") 18 | ELSE() 19 | MESSAGE(ERROR "couldn't run git executable!") 20 | ENDIF() 21 | ENDIF() 22 | 23 | IF(GIT_FOUND) 24 | EXECUTE_PROCESS( 25 | COMMAND ${GIT_EXECUTABLE} describe --tags 26 | RESULT_VARIABLE res_var 27 | OUTPUT_VARIABLE GIT_COM_ID 28 | OUTPUT_STRIP_TRAILING_WHITESPACE 29 | ) 30 | IF( NOT ${res_var} EQUAL 0 ) 31 | MESSAGE(WARNING "Git failed (not a repo, or no tags)." ) 32 | FILE(READ "git-tag.txt" GIT_COMMIT_ID) 33 | MESSAGE(STATUS "GIT_COMMIT_ID: " ${GIT_COMMIT_ID} " (from file)") 34 | ELSE() 35 | STRING(REPLACE "\n" "" GIT_COMMIT_ID ${GIT_COM_ID} ) 36 | MESSAGE(STATUS "GIT_COMMIT_ID: " ${GIT_COMMIT_ID}) 37 | ENDIF() 38 | ELSE() 39 | # if we don't have git, try to read git-tag from file instead 40 | FILE(READ "git-tag.txt" GIT_COMMIT_ID) 41 | MESSAGE(WARNING "Git not found. Reading tag from git-tag.txt instead: " ${GIT_COMMIT_ID}) 42 | #MESSAGE(STATUS "GIT_COMMIT_ID: " ${GIT_COMMIT_ID} " (from file)") 43 | ENDIF() 44 | 45 | SET( vstring "//version_string.hpp - written by cmake. changes will be lost!\n" 46 | "#ifndef VERSION_STRING\n" 47 | "#define VERSION_STRING \"${GIT_COMMIT_ID}\"\n" 48 | "#endif\n" 49 | ) 50 | 51 | FILE(WRITE ${CMAKE_CURRENT_BINARY_DIR}/version_string.hpp ${vstring} ) 52 | SET_SOURCE_FILES_PROPERTIES( 53 | ${CMAKE_CURRENT_BINARY_DIR}/version_string.hpp 54 | PROPERTIES GENERATED TRUE 55 | HEADER_FILE_ONLY TRUE 56 | ) 57 | 58 | # copy the file to the final header only if the version changes 59 | # reduces needless rebuilds 60 | #EXECUTE_PROCESS(COMMAND ${CMAKE_COMMAND} -E copy_if_different 61 | # version_string.hpp.txt /version_string.hpp) 62 | 63 | -------------------------------------------------------------------------------- /src/pdns-logger.h.in: -------------------------------------------------------------------------------- 1 | /* 2 | * Powerdns logger daemon 3 | * ---------------------- 4 | * 5 | * This Source Code Form is subject to the terms of the 6 | * Mozilla Public License, v. 2.0. 7 | * If a copy of the MPL was not distributed with this 8 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 9 | * 10 | * Copyright (C) 2017, Spamhaus Technology Ltd, London 11 | * 12 | * The Initial developer of the Original code is: 13 | * Massimo Cetra 14 | * 15 | */ 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | #include "pdns-logger-dns.h" 28 | 29 | #define PDNS_LOGGER_VERSION 171001 30 | #define DEFAULT_CONFIG_FILE "@PROJECT_SYSCONF_DIR@" "pdns-logger.ini" 31 | 32 | typedef enum pdns_status_e { 33 | PDNS_NO, 34 | PDNS_OK, 35 | PDNS_FORK, 36 | PDNS_RETRY 37 | } pdns_status_t; 38 | 39 | #define zstr(x) ( ((x==NULL) || (*x == '\0')) ? 1 : 0) 40 | #define safe_free(x) if(x != NULL) { free( (void*) x); x = NULL; } 41 | 42 | typedef struct globals_s globals_t; 43 | struct globals_s { 44 | char *user; 45 | char *group; 46 | 47 | char *config_file; 48 | char *bind_ip; 49 | int bind_port; 50 | 51 | char allow_root; 52 | char foreground; 53 | 54 | char running; 55 | char verbose; 56 | 57 | int socket; 58 | }; 59 | 60 | typedef struct fifo_s fifo_t; 61 | fifo_t *fifo_init(void); 62 | pdns_status_t fifo_push_item(fifo_t *fifo, void *data); 63 | void *fifo_pop_item(fifo_t *fifo); 64 | void fifo_lock(fifo_t *fifo); 65 | void fifo_unlock(fifo_t *fifo); 66 | 67 | 68 | typedef pdns_status_t(*init_function_f)(const char *inifile); 69 | typedef pdns_status_t(*rotate_function_f)(void); 70 | typedef pdns_status_t(*stop_function_f)(void); 71 | typedef pdns_status_t(*log_function_f)(void *rawpb); 72 | 73 | typedef struct pdns_logger_s pdns_logger_t; 74 | struct pdns_logger_s { 75 | init_function_f start; 76 | rotate_function_f rotate; 77 | stop_function_f stop; 78 | log_function_f log; 79 | }; 80 | 81 | extern pdns_logger_t logfile_engine; 82 | extern pdns_logger_t syslog_engine; 83 | extern pdns_logger_t sqlite_engine; 84 | 85 | pdns_status_t parse_config_file(const char *cf, globals_t *globals); 86 | pdns_status_t pdns_socket_run(globals_t *globals); 87 | pdns_status_t pdns_loggers_log(void *pbm); 88 | -------------------------------------------------------------------------------- /.gitlab-ci.yml: -------------------------------------------------------------------------------- 1 | stages: 2 | - build 3 | - deploy 4 | 5 | build:debian:stretch: 6 | stage: build 7 | before_script: 8 | - sudo apt-get update 9 | - sudo apt-get -y install cdbs debhelper devscripts sed cmake build-essential pkg-config libprotobuf-c-dev libsqlite3-dev libsystemd-dev 10 | script: 11 | - dpkg-buildpackage -uc -us -b 12 | - rm -rf artifacts && mkdir -p artifacts 13 | - mv ../pdns-logger*.deb artifacts/ 14 | - mv ../pdns-logger*.changes artifacts/ 15 | artifacts: 16 | expire_in: 1 month 17 | paths: 18 | - artifacts/* 19 | tags: 20 | - debian-stretch 21 | 22 | deploy:debian:stretch: 23 | stage: deploy 24 | tags: 25 | - debian-stretch 26 | dependencies: 27 | - build:ubuntu:xenial 28 | script: 29 | - echo "Deploying to repository" 30 | - pushd artifacts 31 | - sed -i.bak "s|unstable|stretch|" *.changes 32 | - grep Distribution *.changes && /usr/bin/dput glab *.changes 33 | - popd 34 | only: 35 | - web # Pipelines run from the "Run Pipeline" button in Gitlab UI 36 | 37 | # **************************************************************************** 38 | # **************************************************************************** 39 | # **************************************************************************** 40 | 41 | build:ubuntu:xenial: 42 | stage: build 43 | before_script: 44 | - sudo apt-get update 45 | - sudo apt-get -y install cdbs debhelper devscripts sed cmake build-essential pkg-config libprotobuf-c-dev libsqlite3-dev libsystemd-dev 46 | script: 47 | - dpkg-buildpackage -uc -us -b 48 | - rm -rf artifacts && mkdir -p artifacts 49 | - mv ../pdns-logger*.deb artifacts/ 50 | - mv ../pdns-logger*.changes artifacts/ 51 | artifacts: 52 | expire_in: 1 month 53 | paths: 54 | - artifacts/* 55 | tags: 56 | - ubuntu-16.04 57 | 58 | deploy:ubuntu:xenial: 59 | stage: deploy 60 | tags: 61 | - ubuntu-16.04 62 | dependencies: 63 | - build:ubuntu:xenial 64 | script: 65 | - echo "Deploying to repository" 66 | - pushd artifacts 67 | - sed -i.bak "s|unstable|xenial|" *.changes 68 | - grep Distribution *.changes && /usr/bin/dput glab *.changes 69 | - popd 70 | only: 71 | - web # Pipelines run from the "Run Pipeline" button in Gitlab UI 72 | -------------------------------------------------------------------------------- /cmake/FindSqlite3.cmake: -------------------------------------------------------------------------------- 1 | # - find Sqlite 3 2 | # SQLITE3_INCLUDE_DIR - Where to find Sqlite 3 header files (directory) 3 | # SQLITE3_LIBRARIES - Sqlite 3 libraries 4 | # SQLITE3_LIBRARY_RELEASE - Where the release library is 5 | # SQLITE3_LIBRARY_DEBUG - Where the debug library is 6 | # SQLITE3_FOUND - Set to TRUE if we found everything (library, includes and executable) 7 | 8 | # Copyright (c) 2010 Pau Garcia i Quiles, 9 | # 10 | # Redistribution and use is allowed according to the terms of the BSD license. 11 | # For details see the accompanying COPYING-CMAKE-SCRIPTS file. 12 | # 13 | # Generated by CModuler, a CMake Module Generator - http://gitorious.org/cmoduler 14 | 15 | IF( SQLITE3_INCLUDE_DIR AND SQLITE3_LIBRARY_RELEASE AND SQLITE3_LIBRARY_DEBUG ) 16 | SET(SQLITE3_FIND_QUIETLY TRUE) 17 | ENDIF( SQLITE3_INCLUDE_DIR AND SQLITE3_LIBRARY_RELEASE AND SQLITE3_LIBRARY_DEBUG ) 18 | 19 | FIND_PATH( SQLITE3_INCLUDE_DIR sqlite3.h ) 20 | 21 | FIND_LIBRARY(SQLITE3_LIBRARY_RELEASE NAMES sqlite3 ) 22 | 23 | FIND_LIBRARY(SQLITE3_LIBRARY_DEBUG NAMES sqlite3 sqlite3d HINTS /usr/lib/debug/usr/lib/ ) 24 | 25 | IF( SQLITE3_LIBRARY_RELEASE OR SQLITE3_LIBRARY_DEBUG AND SQLITE3_INCLUDE_DIR ) 26 | SET( SQLITE3_FOUND TRUE ) 27 | ENDIF( SQLITE3_LIBRARY_RELEASE OR SQLITE3_LIBRARY_DEBUG AND SQLITE3_INCLUDE_DIR ) 28 | 29 | IF( SQLITE3_LIBRARY_DEBUG AND SQLITE3_LIBRARY_RELEASE ) 30 | # if the generator supports configuration types then set 31 | # optimized and debug libraries, or if the CMAKE_BUILD_TYPE has a value 32 | IF( CMAKE_CONFIGURATION_TYPES OR CMAKE_BUILD_TYPE ) 33 | SET( SQLITE3_LIBRARIES optimized ${SQLITE3_LIBRARY_RELEASE} debug ${SQLITE3_LIBRARY_DEBUG} ) 34 | ELSE( CMAKE_CONFIGURATION_TYPES OR CMAKE_BUILD_TYPE ) 35 | # if there are no configuration types and CMAKE_BUILD_TYPE has no value 36 | # then just use the release libraries 37 | SET( SQLITE3_LIBRARIES ${SQLITE3_LIBRARY_RELEASE} ) 38 | ENDIF( CMAKE_CONFIGURATION_TYPES OR CMAKE_BUILD_TYPE ) 39 | ELSEIF( SQLITE3_LIBRARY_RELEASE ) 40 | SET( SQLITE3_LIBRARIES ${SQLITE3_LIBRARY_RELEASE} ) 41 | ELSE( SQLITE3_LIBRARY_DEBUG AND SQLITE3_LIBRARY_RELEASE ) 42 | SET( SQLITE3_LIBRARIES ${SQLITE3_LIBRARY_DEBUG} ) 43 | ENDIF( SQLITE3_LIBRARY_DEBUG AND SQLITE3_LIBRARY_RELEASE ) 44 | 45 | IF( SQLITE3_FOUND ) 46 | IF( NOT SQLITE3_FIND_QUIETLY ) 47 | MESSAGE( STATUS "Found Sqlite3 header file in ${SQLITE3_INCLUDE_DIR}") 48 | MESSAGE( STATUS "Found Sqlite3 libraries: ${SQLITE3_LIBRARIES}") 49 | ENDIF( NOT SQLITE3_FIND_QUIETLY ) 50 | ELSE(SQLITE3_FOUND) 51 | IF( SQLITE3_FIND_REQUIRED) 52 | MESSAGE( FATAL_ERROR "Could not find Sqlite3" ) 53 | ELSE( SQLITE3_FIND_REQUIRED) 54 | MESSAGE( STATUS "Optional package Sqlite3 was not found" ) 55 | ENDIF( SQLITE3_FIND_REQUIRED) 56 | ENDIF(SQLITE3_FOUND) 57 | -------------------------------------------------------------------------------- /cmake/ModuleHelpers.cmake: -------------------------------------------------------------------------------- 1 | 2 | MACRO(CAR var) 3 | SET(${var} ${ARGV1}) 4 | ENDMACRO(CAR) 5 | 6 | MACRO(CDR var junk) 7 | SET(${var} ${ARGN}) 8 | ENDMACRO(CDR) 9 | 10 | MACRO(PARSE_ARGUMENTS prefix arg_names option_names) 11 | SET(DEFAULT_ARGS) 12 | FOREACH(arg_name ${arg_names}) 13 | SET(${prefix}_${arg_name}) 14 | ENDFOREACH(arg_name) 15 | FOREACH(option ${option_names}) 16 | SET(${prefix}_${option} FALSE) 17 | ENDFOREACH(option) 18 | 19 | SET(current_arg_name DEFAULT_ARGS) 20 | SET(current_arg_list) 21 | 22 | FOREACH(arg ${ARGN}) 23 | SET(larg_names ${arg_names}) 24 | LIST(FIND larg_names "${arg}" is_arg_name) 25 | IF (is_arg_name GREATER -1) 26 | SET(${prefix}_${current_arg_name} ${current_arg_list}) 27 | SET(current_arg_name ${arg}) 28 | SET(current_arg_list) 29 | ELSE (is_arg_name GREATER -1) 30 | SET(loption_names ${option_names}) 31 | LIST(FIND loption_names "${arg}" is_option) 32 | IF (is_option GREATER -1) 33 | SET(${prefix}_${arg} TRUE) 34 | ELSE (is_option GREATER -1) 35 | SET(current_arg_list ${current_arg_list} ${arg}) 36 | ENDIF (is_option GREATER -1) 37 | ENDIF (is_arg_name GREATER -1) 38 | ENDFOREACH(arg) 39 | SET(${prefix}_${current_arg_name} ${current_arg_list}) 40 | ENDMACRO(PARSE_ARGUMENTS) 41 | 42 | MACRO(PROJECT_ADD_MODULE) 43 | PARSE_ARGUMENTS( 44 | PLUGIN 45 | "SOURCE;LIBS" 46 | "" 47 | ${ARGN} 48 | ) 49 | CAR(PLUGIN_NAME ${PLUGIN_DEFAULT_ARGS}) 50 | CDR(PLUGIN_SOURCES ${PLUGIN_DEFAULT_ARGS}) 51 | 52 | #MESSAGE("*** Arguments for : ${PLUGIN_NAME}") 53 | #MESSAGE(" Sources : ${PLUGIN_SOURCE}") 54 | #MESSAGE(" Link libraries : ${PLUGIN_LIBS}") 55 | 56 | IF ("${PLUGIN_SOURCE}" STREQUAL "") 57 | MESSAGE(FATAL_ERROR "No source files for module ${PLUGIN_NAME}") 58 | ENDIF("${PLUGIN_SOURCE}" STREQUAL "") 59 | 60 | SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fvisibility=hidden") 61 | 62 | ADD_LIBRARY( 63 | ${PLUGIN_NAME} MODULE 64 | ${PLUGIN_SOURCE} 65 | ) 66 | 67 | TARGET_LINK_LIBRARIES( 68 | ${PLUGIN_NAME} 69 | ${PLUGIN_LIBS} 70 | ) 71 | 72 | SET_TARGET_PROPERTIES( 73 | ${PLUGIN_NAME} 74 | PROPERTIES 75 | PREFIX "" 76 | PROJECT_LABEL "Module ${PLUGIN_NAME}" 77 | ) 78 | 79 | IF (NOT APPLE AND NOT WIN32) 80 | SET_TARGET_PROPERTIES( 81 | ${PLUGIN_NAME} 82 | PROPERTIES 83 | LINK_FLAGS "${MODULES_LINKER_OPTIONS}" 84 | ) 85 | ENDIF(NOT APPLE AND NOT WIN32) 86 | 87 | INSTALL( 88 | TARGETS 89 | ${PLUGIN_NAME} 90 | LIBRARY DESTINATION ${PROJECT_MODULES_DIR} 91 | ARCHIVE DESTINATION ${PROJECT_MODULES_DIR} 92 | ) 93 | ENDMACRO(PROJECT_ADD_MODULE) 94 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | PROJECT (PDNS-LOGGER) 2 | 3 | SET(APPLICATION_NAME "pdns-logger") 4 | 5 | CMAKE_MINIMUM_REQUIRED(VERSION 2.8.0) 6 | 7 | SET(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake) 8 | 9 | IF(${CMAKE_SOURCE_DIR} STREQUAL ${CMAKE_BINARY_DIR}) 10 | MESSAGE(FATAL_ERROR "Prevented in-tree built. This is not a good practice. Please read README.md to find a suitable example.") 11 | ENDIF() 12 | 13 | IF (WIN32) 14 | MESSAGE(FATAL_ERROR "This software does not work on Windows, sorry!") 15 | ENDIF (WIN32) 16 | 17 | INCLUDE(DefineCMakeDefaults) 18 | INCLUDE(DefineCompilerFlags) 19 | INCLUDE(HeadersChecks) 20 | INCLUDE(TestInline) 21 | 22 | INCLUDE(DefineInstallationPaths) 23 | INCLUDE(ProjectDefaults) 24 | INCLUDE(ProjectFunctions) 25 | 26 | INCLUDE(TDDHelpers) 27 | INCLUDE(ModuleHelpers) 28 | 29 | # ********************************************************** 30 | 31 | SET(SYSTEMD_FIND_REQUIRED OFF) 32 | SET(SYSTEMD_FIND_QUIETLY OFF) 33 | INCLUDE(FindSystemd) 34 | IF(SYSTEMD_FOUND) 35 | ADD_DEFINITIONS(-DSYSTEMD_FOUND) 36 | ENDIF(SYSTEMD_FOUND) 37 | 38 | SET(PROTOBUFC_FIND_REQUIRED ON) 39 | SET(PROTOBUFC_FIND_QUIETLY ON) 40 | INCLUDE(FindProtobufC) 41 | 42 | SET(THREADS_PREFER_PTHREAD_FLAG ON) 43 | FIND_PACKAGE(Threads REQUIRED) 44 | IF(NOT CMAKE_USE_PTHREADS_INIT) 45 | MESSAGE(ERROR "Cannot find PTHREAD library") 46 | ENDIF(NOT CMAKE_USE_PTHREADS_INIT) 47 | 48 | SET(SQLITE3_FIND_REQUIRED OFF) 49 | SET(SQLITE3_FIND_QUIETLY ON) 50 | INCLUDE(FindSqlite3) 51 | 52 | # ******************************************************************************* 53 | 54 | ADD_SUBDIRECTORY(config) 55 | ADD_SUBDIRECTORY(src) 56 | 57 | # ******************************************************************************* 58 | # *** TESTS 59 | # ******************************************************************************* 60 | 61 | SET(_USE_TESTS false CACHE BOOL "Compile the tests") 62 | 63 | IF ( ${_USE_TESTS} ) 64 | ENABLE_TESTING() 65 | MESSAGE(STATUS "ENABLING TESTS") 66 | ADD_SUBDIRECTORY(tests) 67 | ELSE( ${NMAIL_USE_TESTS} ) 68 | MESSAGE(STATUS "TESTS NOT ENABLED") 69 | ENDIF( ${_USE_TESTS} ) 70 | 71 | # ******************************************************************************* 72 | # ******************************************************************************* 73 | # ******************************************************************************* 74 | 75 | IF(SYSTEMD_FOUND) 76 | MESSAGE(STATUS "SYSTEMD SUPPORT: Enabled") 77 | ELSE(SYSTEMD_FOUND) 78 | MESSAGE(STATUS "SYSTEMD SUPPORT: NOT Enabled") 79 | ENDIF(SYSTEMD_FOUND) 80 | 81 | IF(PROTOBUFC_FOUND) 82 | MESSAGE(STATUS "PROTOBUFC SUPPORT: Enabled") 83 | ELSE(PROTOBUFC_FOUND) 84 | MESSAGE(STATUS "PROTOBUFC SUPPORT: NOT Enabled") 85 | ENDIF(PROTOBUFC_FOUND) 86 | 87 | IF(SQLITE3_FOUND) 88 | MESSAGE(STATUS "SQLITE3 SUPPORT: Enabled") 89 | ELSE(SQLITE3_FOUND) 90 | MESSAGE(STATUS "SQLITE3 SUPPORT: NOT Enabled") 91 | ENDIF(SQLITE3_FOUND) 92 | -------------------------------------------------------------------------------- /cmake/TDDHelpers.cmake: -------------------------------------------------------------------------------- 1 | 2 | MACRO(TDD_CAR var) 3 | SET(${var} ${ARGV1}) 4 | ENDMACRO(TDD_CAR) 5 | 6 | 7 | MACRO(TDD_CDR var junk) 8 | SET(${var} ${ARGN}) 9 | ENDMACRO(TDD_CDR) 10 | 11 | 12 | MACRO(TDD_PARSE_ARGUMENTS prefix arg_names option_names) 13 | SET(DEFAULT_ARGS) 14 | FOREACH(arg_name ${arg_names}) 15 | SET(${prefix}_${arg_name}) 16 | ENDFOREACH(arg_name) 17 | FOREACH(option ${option_names}) 18 | SET(${prefix}_${option} FALSE) 19 | ENDFOREACH(option) 20 | 21 | SET(current_arg_name DEFAULT_ARGS) 22 | SET(current_arg_list) 23 | 24 | FOREACH(arg ${ARGN}) 25 | SET(larg_names ${arg_names}) 26 | LIST(FIND larg_names "${arg}" is_arg_name) 27 | IF (is_arg_name GREATER -1) 28 | SET(${prefix}_${current_arg_name} ${current_arg_list}) 29 | SET(current_arg_name ${arg}) 30 | SET(current_arg_list) 31 | ELSE (is_arg_name GREATER -1) 32 | SET(loption_names ${option_names}) 33 | LIST(FIND loption_names "${arg}" is_option) 34 | IF (is_option GREATER -1) 35 | SET(${prefix}_${arg} TRUE) 36 | ELSE (is_option GREATER -1) 37 | SET(current_arg_list ${current_arg_list} ${arg}) 38 | ENDIF (is_option GREATER -1) 39 | ENDIF (is_arg_name GREATER -1) 40 | ENDFOREACH(arg) 41 | SET(${prefix}_${current_arg_name} ${current_arg_list}) 42 | ENDMACRO(TDD_PARSE_ARGUMENTS) 43 | 44 | 45 | MACRO(PROJECT_ADD_TEST) 46 | 47 | TDD_PARSE_ARGUMENTS( 48 | TESTUNIT 49 | "SOURCE;LIBS;VALGRIND" 50 | "" 51 | ${ARGN} 52 | ) 53 | TDD_CAR(TESTUNIT_NAME ${TESTUNIT_DEFAULT_ARGS}) 54 | TDD_CDR(TESTUNIT_SOURCES ${TESTUNIT_DEFAULT_ARGS}) 55 | 56 | #MESSAGE("*** Arguments for : ${TESTUNIT_NAME}") 57 | #MESSAGE(" Sources : ${TESTUNIT_SOURCE}") 58 | #MESSAGE(" Link libraries : ${TESTUNIT_LIBS}") 59 | #MESSAGE(" Use Valgrind : ${TESTUNIT_VALGRIND}") 60 | 61 | IF ("${TESTUNIT_SOURCE}" STREQUAL "") 62 | MESSAGE(FATAL_ERROR "No source files for unit ${TESTUNIT_NAME}") 63 | ENDIF("${TESTUNIT_SOURCE}" STREQUAL "") 64 | 65 | ADD_EXECUTABLE( 66 | ${TESTUNIT_NAME} ${TESTUNIT_SOURCE} 67 | ) 68 | 69 | TARGET_LINK_LIBRARIES( 70 | ${TESTUNIT_NAME} 71 | ${TESTUNIT_LIBS} 72 | ) 73 | 74 | SET_TARGET_PROPERTIES( 75 | ${TESTUNIT_NAME} 76 | PROPERTIES 77 | PREFIX "" 78 | PROJECT_LABEL "Module ${TESTUNIT_NAME}" 79 | ) 80 | 81 | IF (NOT APPLE AND NOT WIN32) 82 | SET_TARGET_PROPERTIES( 83 | ${TESTUNIT_NAME} 84 | PROPERTIES 85 | LINK_FLAGS "${MODULES_LINKER_OPTIONS}" 86 | ) 87 | ENDIF(NOT APPLE AND NOT WIN32) 88 | 89 | IF( ${TESTUNIT_VALGRIND} STREQUAL "1") 90 | ADD_TEST(${TESTUNIT_NAME}_vg 91 | valgrind 92 | --error-exitcode=1 93 | --read-var-info=yes 94 | --leak-check=full 95 | --show-leak-kinds=all 96 | ./${TESTUNIT_NAME} 97 | ) 98 | ELSE( ${TESTUNIT_VALGRIND} STREQUAL "1") 99 | ADD_TEST(${TESTUNIT_NAME} ${TESTUNIT_NAME} ) 100 | ENDIF( ${TESTUNIT_VALGRIND} STREQUAL "1") 101 | 102 | ENDMACRO(PROJECT_ADD_TEST) 103 | -------------------------------------------------------------------------------- /src/dnsmessage.proto: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of PowerDNS or dnsdist. 3 | * Copyright -- PowerDNS.COM B.V. and its contributors 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of version 2 of the GNU General Public License as 7 | * published by the Free Software Foundation. 8 | * 9 | * In addition, for the avoidance of any doubt, permission is granted to 10 | * link this program with OpenSSL and to (re)distribute the binaries 11 | * produced as the result of such linking. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program; if not, write to the Free Software 20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 21 | */ 22 | syntax = "proto2"; 23 | 24 | message PBDNSMessage { 25 | enum Type { 26 | DNSQueryType = 1; 27 | DNSResponseType = 2; 28 | DNSOutgoingQueryType = 3; 29 | DNSIncomingResponseType = 4; 30 | } 31 | enum SocketFamily { 32 | INET = 1; // IPv4 (RFC 791) 33 | INET6 = 2; // IPv6 (RFC 2460) 34 | } 35 | enum SocketProtocol { 36 | UDP = 1; // User Datagram Protocol (RFC 768) 37 | TCP = 2; // Transmission Control Protocol (RFC 793) 38 | } 39 | required Type type = 1; 40 | optional bytes messageId = 2; // UUID, shared by the query and the response 41 | optional bytes serverIdentity = 3; // UUID of the server emitting the protobuf message 42 | optional SocketFamily socketFamily = 4; 43 | optional SocketProtocol socketProtocol = 5; 44 | optional bytes from = 6; // DNS requestor (client) 45 | optional bytes to = 7; // DNS responder (server) 46 | optional uint64 inBytes = 8; // Size of the query or response on the wire 47 | optional uint32 timeSec = 9; // Time of message reception (seconds since epoch) 48 | optional uint32 timeUsec = 10; // Time of message reception (additional micro-seconds) 49 | optional uint32 id = 11; // ID of the query/response as found in the DNS header 50 | 51 | message DNSQuestion { 52 | optional string qName = 1; 53 | optional uint32 qType = 2; 54 | optional uint32 qClass = 3; 55 | } 56 | optional DNSQuestion question = 12; 57 | 58 | message DNSResponse { 59 | 60 | message DNSRR { 61 | optional string name = 1; 62 | optional uint32 type = 2; 63 | optional uint32 class = 3; 64 | optional uint32 ttl = 4; 65 | optional bytes rdata = 5; 66 | } 67 | repeated DNSRR rrs = 2; 68 | 69 | repeated string tags = 4; // Additional tags 70 | optional uint32 rcode = 1; 71 | optional string appliedPolicy = 3; // Filtering policy (RPZ or Lua) applied 72 | optional uint32 queryTimeSec = 5; // Time of the corresponding query reception (seconds since epoch) 73 | optional uint32 queryTimeUsec = 6; // Time of the corresponding query reception (additional micro-seconds) 74 | } 75 | optional DNSResponse response = 13; 76 | 77 | optional bytes originalRequestorSubnet = 14; // EDNS Client Subnet value 78 | optional string requestorId = 15; // Username of the requestor 79 | optional bytes initialRequestId = 16; // UUID of the incoming query that initiated this outgoing query or incoming response 80 | } 81 | -------------------------------------------------------------------------------- /cmake/DefineInstallationPaths.cmake: -------------------------------------------------------------------------------- 1 | if (UNIX) 2 | IF (NOT APPLICATION_NAME) 3 | MESSAGE(STATUS "${PROJECT_NAME} is used as APPLICATION_NAME") 4 | SET(APPLICATION_NAME ${PROJECT_NAME}) 5 | ENDIF (NOT APPLICATION_NAME) 6 | 7 | # Suffix for Linux 8 | SET(LIB_SUFFIX 9 | CACHE STRING "Define suffix of directory name (32/64)" 10 | ) 11 | SET(EXEC_INSTALL_PREFIX 12 | "${CMAKE_INSTALL_PREFIX}" 13 | CACHE PATH "Base directory for executables and libraries" 14 | FORCE 15 | ) 16 | SET(SHARE_INSTALL_PREFIX 17 | "${CMAKE_INSTALL_PREFIX}/share" 18 | CACHE PATH "Base directory for files which go to share/" 19 | FORCE 20 | ) 21 | SET(DATA_INSTALL_PREFIX 22 | "${SHARE_INSTALL_PREFIX}/${APPLICATION_NAME}" 23 | CACHE PATH "The parent directory where applications can install their data" 24 | FORCE 25 | ) 26 | # The following are directories where stuff will be installed to 27 | SET(BIN_INSTALL_DIR 28 | "${EXEC_INSTALL_PREFIX}/bin" 29 | CACHE PATH "The ${APPLICATION_NAME} binary install dir (default prefix/bin)" 30 | FORCE 31 | ) 32 | SET(SBIN_INSTALL_DIR 33 | "${EXEC_INSTALL_PREFIX}/sbin" 34 | CACHE PATH "The ${APPLICATION_NAME} sbin install dir (default prefix/sbin)" 35 | FORCE 36 | ) 37 | SET(LIB_INSTALL_DIR 38 | "${EXEC_INSTALL_PREFIX}/lib${LIB_SUFFIX}" 39 | CACHE PATH "The subdirectory relative to the install prefix where libraries will be installed (default is prefix/lib)" 40 | FORCE 41 | ) 42 | SET(LIBEXEC_INSTALL_DIR 43 | "${EXEC_INSTALL_PREFIX}/libexec" 44 | CACHE PATH "The subdirectory relative to the install prefix where libraries will be installed (default is prefix/libexec)" 45 | FORCE 46 | ) 47 | SET(INCLUDE_INSTALL_DIR 48 | "${CMAKE_INSTALL_PREFIX}/include" 49 | CACHE PATH "The subdirectory to the header prefix (default prefix/include)" 50 | FORCE 51 | ) 52 | SET(DATA_INSTALL_DIR 53 | "${DATA_INSTALL_PREFIX}" 54 | CACHE PATH "The parent directory where applications can install their data (default prefix/share/${APPLICATION_NAME})" 55 | FORCE 56 | ) 57 | SET(HTML_INSTALL_DIR 58 | "${DATA_INSTALL_PREFIX}/doc/HTML" 59 | CACHE PATH "The HTML install dir for documentation (default data/doc/html)" 60 | FORCE 61 | ) 62 | SET(ICON_INSTALL_DIR 63 | "${DATA_INSTALL_PREFIX}/icons" 64 | CACHE PATH "The icon install dir (default data/icons/)" 65 | FORCE 66 | ) 67 | SET(SOUND_INSTALL_DIR 68 | "${DATA_INSTALL_PREFIX}/sounds" 69 | CACHE PATH "The install dir for sound files (default data/sounds)" 70 | FORCE 71 | ) 72 | SET(LOCALE_INSTALL_DIR 73 | "${SHARE_INSTALL_PREFIX}/locale" 74 | CACHE PATH "The install dir for translations (default prefix/share/locale)" 75 | FORCE 76 | ) 77 | 78 | MARK_AS_ADVANCED(SYSCONF_INSTALL_DIR) 79 | IF ( NOT SYSCONF_INSTALL_DIR ) 80 | SET(SYSCONF_INSTALL_DIR 81 | "${EXEC_INSTALL_PREFIX}/etc" 82 | CACHE PATH "The ${APPLICATION_NAME} sysconfig install dir (default prefix/etc)" 83 | FORCE 84 | ) 85 | ENDIF ( NOT SYSCONF_INSTALL_DIR ) 86 | 87 | SET(MAN_INSTALL_DIR 88 | "${SHARE_INSTALL_PREFIX}/man" 89 | CACHE PATH "The ${APPLICATION_NAME} man install dir (default prefix/man)" 90 | FORCE 91 | ) 92 | SET(INFO_INSTALL_DIR 93 | "${SHARE_INSTALL_PREFIX}/info" 94 | CACHE PATH "The ${APPLICATION_NAME} info install dir (default prefix/info)" 95 | FORCE 96 | ) 97 | endif (UNIX) 98 | 99 | 100 | if (WIN32) 101 | # Same same 102 | SET(BIN_INSTALL_DIR .) 103 | SET(SBIN_INSTALL_DIR .) 104 | SET(LIB_INSTALL_DIR .) 105 | SET(PLUGIN_INSTALL_DIR plugins) 106 | SET(HTML_INSTALL_DIR doc/HTML) 107 | SET(ICON_INSTALL_DIR .) 108 | SET(SOUND_INSTALL_DIR .) 109 | SET(SYSCONF_INSTALL_DIR .) 110 | SET(LOCALE_INSTALL_DIR lang) 111 | endif (WIN32) 112 | 113 | -------------------------------------------------------------------------------- /src/pdns-logger-dns.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Powerdns logger daemon 3 | * ---------------------- 4 | * 5 | * This Source Code Form is subject to the terms of the 6 | * Mozilla Public License, v. 2.0. 7 | * If a copy of the MPL was not distributed with this 8 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 9 | * 10 | * Copyright (C) 2017, Spamhaus Technology Ltd, London 11 | * 12 | * The Initial developer of the Original code is: 13 | * Massimo Cetra 14 | * 15 | */ 16 | 17 | #include "pdns-logger.h" 18 | 19 | /* *INDENT-OFF* */ 20 | struct dns_nameval { 21 | int val; 22 | const char *name; 23 | }; 24 | 25 | const struct dns_nameval dns_classtab[] = { 26 | {DNS_C_INVALID, "INVALID"}, 27 | {DNS_C_IN, "IN"}, 28 | {DNS_C_CH, "CH"}, 29 | {DNS_C_HS, "HS"}, 30 | {DNS_C_ANY, "ANY"}, 31 | {0,0} 32 | }; 33 | 34 | const struct dns_nameval dns_typetab[] = { 35 | {DNS_T_INVALID, "INVALID"}, 36 | {DNS_T_A, "A"}, 37 | {DNS_T_NS, "NS"}, 38 | {DNS_T_MD, "MD"}, 39 | {DNS_T_MF, "MF"}, 40 | {DNS_T_CNAME, "CNAME"}, 41 | {DNS_T_SOA, "SOA"}, 42 | {DNS_T_MB, "MB"}, 43 | {DNS_T_MG, "MG"}, 44 | {DNS_T_MR, "MR"}, 45 | {DNS_T_NULL, "NULL"}, 46 | {DNS_T_WKS, "WKS"}, 47 | {DNS_T_PTR, "PTR"}, 48 | {DNS_T_HINFO, "HINFO"}, 49 | {DNS_T_MINFO, "MINFO"}, 50 | {DNS_T_MX, "MX"}, 51 | {DNS_T_TXT, "TXT"}, 52 | {DNS_T_RP, "RP"}, 53 | {DNS_T_AFSDB, "AFSDB"}, 54 | {DNS_T_X25, "X25"}, 55 | {DNS_T_ISDN, "ISDN"}, 56 | {DNS_T_RT, "RT"}, 57 | {DNS_T_NSAP, "NSAP"}, 58 | {DNS_T_NSAP_PTR, "NSAP_PTR"}, 59 | {DNS_T_SIG, "SIG"}, 60 | {DNS_T_KEY, "KEY"}, 61 | {DNS_T_PX, "PX"}, 62 | {DNS_T_GPOS, "GPOS"}, 63 | {DNS_T_AAAA, "AAAA"}, 64 | {DNS_T_LOC, "LOC"}, 65 | {DNS_T_NXT, "NXT"}, 66 | {DNS_T_EID, "EID"}, 67 | {DNS_T_NIMLOC, "NIMLOC"}, 68 | {DNS_T_SRV, "SRV"}, 69 | {DNS_T_ATMA, "ATMA"}, 70 | {DNS_T_NAPTR, "NAPTR"}, 71 | {DNS_T_KX, "KX"}, 72 | {DNS_T_CERT, "CERT"}, 73 | {DNS_T_A6, "A6"}, 74 | {DNS_T_DNAME, "DNAME"}, 75 | {DNS_T_SINK, "SINK"}, 76 | {DNS_T_OPT, "OPT"}, 77 | {DNS_T_TSIG, "TSIG"}, 78 | {DNS_T_IXFR, "IXFR"}, 79 | {DNS_T_AXFR, "AXFR"}, 80 | {DNS_T_MAILB, "MAILB"}, 81 | {DNS_T_MAILA, "MAILA"}, 82 | {DNS_T_ANY, "ANY"}, 83 | {DNS_T_ZXFR, "ZXFR"}, 84 | {DNS_T_MAX, "MAX"}, 85 | {0,0} 86 | }; 87 | 88 | const struct dns_nameval dns_rcodetab[] = { 89 | {DNS_R_NOERROR, "NOERROR"}, 90 | {DNS_R_FORMERR, "FORMERR"}, 91 | {DNS_R_SERVFAIL, "SERVFAIL"}, 92 | {DNS_R_NXDOMAIN, "NXDOMAIN"}, 93 | {DNS_R_NOTIMPL, "NOTIMPL"}, 94 | {DNS_R_REFUSED, "REFUSED"}, 95 | {DNS_R_YXDOMAIN, "YXDOMAIN"}, 96 | {DNS_R_YXRRSET, "YXRRSET"}, 97 | {DNS_R_NXRRSET, "NXRRSET"}, 98 | {DNS_R_NOTAUTH, "NOTAUTH"}, 99 | {DNS_R_NOTZONE, "NOTZONE"}, 100 | {DNS_R_BADSIG, "BADSIG"}, 101 | {DNS_R_BADKEY, "BADKEY"}, 102 | {DNS_R_BADTIME, "BADTIME"}, 103 | {0,0} 104 | }; 105 | /* *INDENT-ON* */ 106 | 107 | const char *pdns_logger_rcode2p(enum dns_rcode_e i) { 108 | if (i < sizeof(dns_rcodetab) / sizeof(dns_rcodetab[0])) { 109 | return dns_rcodetab[i].name; 110 | } 111 | return NULL; 112 | } 113 | 114 | const char *pdns_logger_type2p(enum dns_type_e i) { 115 | if (i < sizeof(dns_typetab) / sizeof(dns_typetab[0])) { 116 | return dns_typetab[i].name; 117 | } 118 | return NULL; 119 | } 120 | 121 | const char *pdns_logger_class2p(enum dns_class_e i) { 122 | if (i < sizeof(dns_classtab) / sizeof(dns_classtab[0])) { 123 | return dns_classtab[i].name; 124 | } 125 | return NULL; 126 | } 127 | -------------------------------------------------------------------------------- /src/inih/ini.h: -------------------------------------------------------------------------------- 1 | /* inih -- simple .INI file parser 2 | 3 | inih is released under the New BSD license (see LICENSE.txt). Go to the project 4 | home page for more info: 5 | 6 | https://github.com/benhoyt/inih 7 | 8 | */ 9 | 10 | #ifndef __INI_H__ 11 | #define __INI_H__ 12 | 13 | /* Make this header file easier to include in C++ code */ 14 | #ifdef __cplusplus 15 | extern "C" { 16 | #endif 17 | 18 | #include 19 | #include 20 | 21 | /* Nonzero if ini_handler callback should accept lineno parameter. */ 22 | #ifndef INI_HANDLER_LINENO 23 | #define INI_HANDLER_LINENO 1 24 | #endif 25 | 26 | /* Typedef for prototype of handler function. */ 27 | #if INI_HANDLER_LINENO 28 | typedef int (*ini_handler) (void *user, const char *section, const char *name, const char *value, int lineno); 29 | #else 30 | typedef int (*ini_handler) (void *user, const char *section, const char *name, const char *value); 31 | #endif 32 | 33 | /* Typedef for prototype of fgets-style reader function. */ 34 | typedef char *(*ini_reader) (char *str, int num, void *stream); 35 | 36 | /* Parse given INI-style file. May have [section]s, name=value pairs 37 | (whitespace stripped), and comments starting with ';' (semicolon). Section 38 | is "" if name=value pair parsed before any section heading. name:value 39 | pairs are also supported as a concession to Python's configparser. 40 | 41 | For each name=value pair parsed, call handler function with given user 42 | pointer as well as section, name, and value (data only valid for duration 43 | of handler call). Handler should return nonzero on success, zero on error. 44 | 45 | Returns 0 on success, line number of first error on parse error (doesn't 46 | stop on first error), -1 on file open error, or -2 on memory allocation 47 | error (only when INI_USE_STACK is zero). 48 | */ 49 | int ini_parse(const char *filename, ini_handler handler, void *user); 50 | 51 | /* Same as ini_parse(), but takes a FILE* instead of filename. This doesn't 52 | close the file when it's finished -- the caller must do that. */ 53 | int ini_parse_file(FILE * file, ini_handler handler, void *user); 54 | 55 | /* Same as ini_parse(), but takes an ini_reader function pointer instead of 56 | filename. Used for implementing custom or string-based I/O (see also 57 | ini_parse_string). */ 58 | int ini_parse_stream(ini_reader reader, void *stream, ini_handler handler, void *user); 59 | 60 | /* Same as ini_parse(), but takes a zero-terminated string with the INI data 61 | instead of a file. Useful for parsing INI data from a network socket or 62 | already in memory. */ 63 | int ini_parse_string(const char *string, ini_handler handler, void *user); 64 | 65 | /* Nonzero to allow multi-line value parsing, in the style of Python's 66 | configparser. If allowed, ini_parse() will call the handler with the same 67 | name for each subsequent line parsed. */ 68 | #ifndef INI_ALLOW_MULTILINE 69 | #define INI_ALLOW_MULTILINE 1 70 | #endif 71 | 72 | /* Nonzero to allow a UTF-8 BOM sequence (0xEF 0xBB 0xBF) at the start of 73 | the file. See http://code.google.com/p/inih/issues/detail?id=21 */ 74 | #ifndef INI_ALLOW_BOM 75 | #define INI_ALLOW_BOM 1 76 | #endif 77 | 78 | /* Nonzero to allow inline comments (with valid inline comment characters 79 | specified by INI_INLINE_COMMENT_PREFIXES). Set to 0 to turn off and match 80 | Python 3.2+ configparser behaviour. */ 81 | #ifndef INI_ALLOW_INLINE_COMMENTS 82 | #define INI_ALLOW_INLINE_COMMENTS 1 83 | #endif 84 | #ifndef INI_INLINE_COMMENT_PREFIXES 85 | #define INI_INLINE_COMMENT_PREFIXES ";" 86 | #endif 87 | 88 | /* Nonzero to use stack, zero to use heap (malloc/free). */ 89 | #ifndef INI_USE_STACK 90 | #define INI_USE_STACK 1 91 | #endif 92 | 93 | /* Stop parsing on first error (default is to keep parsing). */ 94 | #ifndef INI_STOP_ON_FIRST_ERROR 95 | #define INI_STOP_ON_FIRST_ERROR 0 96 | #endif 97 | 98 | /* Maximum line length for any line in INI file. */ 99 | #ifndef INI_MAX_LINE 100 | #define INI_MAX_LINE 200 101 | #endif 102 | 103 | #ifdef __cplusplus 104 | } 105 | #endif 106 | #endif /* __INI_H__ */ 107 | -------------------------------------------------------------------------------- /src/pdns-logger-queue.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Powerdns logger daemon 3 | * ---------------------- 4 | * 5 | * This Source Code Form is subject to the terms of the 6 | * Mozilla Public License, v. 2.0. 7 | * If a copy of the MPL was not distributed with this 8 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 9 | * 10 | * Copyright (C) 2017, Spamhaus Technology Ltd, London 11 | * 12 | * The Initial developer of the Original code is: 13 | * Massimo Cetra 14 | * 15 | */ 16 | 17 | #include 18 | #include 19 | #include "pdns-logger.h" 20 | 21 | typedef struct fifo_item_s fifo_item_t; 22 | struct fifo_item_s { 23 | void *data; 24 | fifo_item_t *next; 25 | }; 26 | 27 | struct fifo_s { 28 | pthread_mutex_t lock; 29 | 30 | pthread_mutex_t sync_mutex; 31 | pthread_cond_t sync_cond; 32 | 33 | fifo_item_t *head; 34 | fifo_item_t *tail; 35 | }; 36 | 37 | static void fifo_wait_signal(fifo_t * fifo) { 38 | int msw = 1000; 39 | struct timeval tv; 40 | struct timespec ts; 41 | 42 | gettimeofday(&tv, NULL); 43 | ts.tv_sec = time(NULL) + msw / 1000; 44 | ts.tv_nsec = tv.tv_usec * 1000 + 1000 * 1000 * (msw % 1000); 45 | ts.tv_sec += ts.tv_nsec / (1000 * 1000 * 1000); 46 | ts.tv_nsec %= (1000 * 1000 * 1000); 47 | 48 | pthread_mutex_lock(&fifo->sync_mutex); 49 | pthread_cond_timedwait(&fifo->sync_cond, &fifo->sync_mutex, &ts); 50 | pthread_mutex_unlock(&fifo->sync_mutex); 51 | 52 | return; 53 | } 54 | 55 | static void fifo_send_signal(fifo_t * fifo) { 56 | pthread_mutex_lock(&fifo->sync_mutex); 57 | pthread_cond_signal(&fifo->sync_cond); 58 | pthread_mutex_unlock(&fifo->sync_mutex); 59 | return; 60 | } 61 | 62 | fifo_t *fifo_init(void) { 63 | fifo_t *fifo = NULL; 64 | pthread_mutexattr_t attr; 65 | 66 | fifo = malloc(sizeof(fifo_t)); 67 | if (fifo != NULL) { 68 | memset(fifo, 0, sizeof(fifo_t)); 69 | pthread_mutexattr_init(&attr); 70 | pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); 71 | pthread_mutex_init(&fifo->lock, &attr); 72 | 73 | pthread_mutex_init(&fifo->sync_mutex, NULL); 74 | pthread_cond_init(&fifo->sync_cond, NULL); 75 | 76 | } 77 | 78 | return fifo; 79 | } 80 | 81 | static pdns_status_t fifo_push(fifo_t * fifo, void *value) { 82 | fifo_item_t *item; 83 | if (fifo == NULL || value == NULL) { 84 | return PDNS_NO; 85 | } 86 | 87 | item = malloc(sizeof(fifo_item_t)); 88 | if (item != NULL) { 89 | item->data = value; 90 | 91 | pthread_mutex_lock(&fifo->lock); 92 | if (fifo->tail == NULL && fifo->head == NULL) { 93 | fifo->head = fifo->tail = item; 94 | } else if (fifo->tail != NULL || fifo->head != NULL) { 95 | /* Should not happen */ 96 | assert(0); 97 | } else { 98 | item->next = fifo->head; 99 | fifo->head = item; 100 | } 101 | pthread_mutex_unlock(&fifo->lock); 102 | 103 | return PDNS_OK; 104 | } 105 | 106 | safe_free(item); 107 | 108 | return PDNS_NO; 109 | } 110 | 111 | static void *fifo_pop(fifo_t * fifo) { 112 | void *ret; 113 | fifo_item_t *item = NULL; 114 | 115 | if (fifo == NULL) { 116 | return NULL; 117 | } 118 | 119 | pthread_mutex_lock(&fifo->lock); 120 | if (fifo->head == NULL && fifo->tail == NULL) { 121 | /* Empty */ 122 | } else if (fifo->head != NULL && fifo->tail == fifo->head) { 123 | item = fifo->head; 124 | fifo->head = fifo->tail = NULL; 125 | } else { 126 | item = fifo->head; 127 | fifo->head = item->next; 128 | } 129 | pthread_mutex_unlock(&fifo->lock); 130 | 131 | if (item != NULL) { 132 | ret = item->data; 133 | safe_free(item); 134 | return ret; 135 | } 136 | 137 | return NULL; 138 | } 139 | 140 | pdns_status_t fifo_push_item(fifo_t * fifo, void *data) { 141 | 142 | if (fifo == NULL || data == NULL) { 143 | return PDNS_NO; 144 | } 145 | 146 | if (fifo_push(fifo, data) == PDNS_OK) { 147 | fifo_send_signal(fifo); 148 | return PDNS_OK; 149 | } 150 | 151 | return PDNS_NO; 152 | } 153 | 154 | void *fifo_pop_item(fifo_t * fifo) { 155 | if (fifo == NULL) { 156 | return NULL; 157 | } 158 | 159 | fifo_wait_signal(fifo); 160 | return fifo_pop(fifo); 161 | } 162 | 163 | void fifo_lock(fifo_t * fifo) { 164 | if (fifo != NULL) { 165 | pthread_mutex_lock(&fifo->lock); 166 | } 167 | } 168 | 169 | void fifo_unlock(fifo_t * fifo) { 170 | if (fifo != NULL) { 171 | pthread_mutex_unlock(&fifo->lock); 172 | } 173 | } 174 | -------------------------------------------------------------------------------- /src/pdns-logger-dns.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Powerdns logger daemon 3 | * ---------------------- 4 | * 5 | * This Source Code Form is subject to the terms of the 6 | * Mozilla Public License, v. 2.0. 7 | * If a copy of the MPL was not distributed with this 8 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 9 | * 10 | * Copyright (C) 2017, Spamhaus Technology Ltd, London 11 | * 12 | * The Initial developer of the Original code is: 13 | * Massimo Cetra 14 | * 15 | */ 16 | 17 | /* *INDENT-OFF* */ 18 | enum dns_section_e{ 19 | DNS_S_NONE = 0, 20 | DNS_S_ANSWERS, 21 | DNS_S_AUTHORITY, 22 | DNS_S_ADDITIONAL 23 | }; 24 | 25 | enum dns_class_e { 26 | DNS_C_INVALID = 0, /* invalid class */ 27 | DNS_C_IN = 1, /* Internet */ 28 | DNS_C_CH = 3, /* CHAOS */ 29 | DNS_C_HS = 4, /* HESIOD */ 30 | DNS_C_ANY = 255 /* wildcard */ 31 | }; 32 | 33 | enum dns_type_e { 34 | DNS_T_INVALID = 0, /* Cookie. */ 35 | DNS_T_A = 1, /* Host address. */ 36 | DNS_T_NS = 2, /* Authoritative server. */ 37 | DNS_T_MD = 3, /* Mail destination. */ 38 | DNS_T_MF = 4, /* Mail forwarder. */ 39 | DNS_T_CNAME = 5, /* Canonical name. */ 40 | DNS_T_SOA = 6, /* Start of authority zone. */ 41 | DNS_T_MB = 7, /* Mailbox domain name. */ 42 | DNS_T_MG = 8, /* Mail group member. */ 43 | DNS_T_MR = 9, /* Mail rename name. */ 44 | DNS_T_NULL = 10, /* Null resource record. */ 45 | DNS_T_WKS = 11, /* Well known service. */ 46 | DNS_T_PTR = 12, /* Domain name pointer. */ 47 | DNS_T_HINFO = 13, /* Host information. */ 48 | DNS_T_MINFO = 14, /* Mailbox information. */ 49 | DNS_T_MX = 15, /* Mail routing information. */ 50 | DNS_T_TXT = 16, /* Text strings. */ 51 | DNS_T_RP = 17, /* Responsible person. */ 52 | DNS_T_AFSDB = 18, /* AFS cell database. */ 53 | DNS_T_X25 = 19, /* X_25 calling address. */ 54 | DNS_T_ISDN = 20, /* ISDN calling address. */ 55 | DNS_T_RT = 21, /* Router. */ 56 | DNS_T_NSAP = 22, /* NSAP address. */ 57 | DNS_T_NSAP_PTR = 23, /* Reverse NSAP lookup (deprecated). */ 58 | DNS_T_SIG = 24, /* Security signature. */ 59 | DNS_T_KEY = 25, /* Security key. */ 60 | DNS_T_PX = 26, /* X.400 mail mapping. */ 61 | DNS_T_GPOS = 27, /* Geographical position (withdrawn). */ 62 | DNS_T_AAAA = 28, /* Ip6 Address. */ 63 | DNS_T_LOC = 29, /* Location Information. */ 64 | DNS_T_NXT = 30, /* Next domain (security). */ 65 | DNS_T_EID = 31, /* Endpoint identifier. */ 66 | DNS_T_NIMLOC = 32, /* Nimrod Locator. */ 67 | DNS_T_SRV = 33, /* Server Selection. */ 68 | DNS_T_ATMA = 34, /* ATM Address */ 69 | DNS_T_NAPTR = 35, /* Naming Authority PoinTeR */ 70 | DNS_T_KX = 36, /* Key Exchange */ 71 | DNS_T_CERT = 37, /* Certification record */ 72 | DNS_T_A6 = 38, /* IPv6 address (deprecates AAAA) */ 73 | DNS_T_DNAME = 39, /* Non-terminal DNAME (for IPv6) */ 74 | DNS_T_SINK = 40, /* Kitchen sink (experimentatl) */ 75 | DNS_T_OPT = 41, /* EDNS0 option (meta-RR) */ 76 | DNS_T_TSIG = 250, /* Transaction signature. */ 77 | DNS_T_IXFR = 251, /* Incremental zone transfer. */ 78 | DNS_T_AXFR = 252, /* Transfer zone of authority. */ 79 | DNS_T_MAILB = 253, /* Transfer mailbox records. */ 80 | DNS_T_MAILA = 254, /* Transfer mail agent records. */ 81 | DNS_T_ANY = 255, /* Wildcard match. */ 82 | DNS_T_ZXFR = 256, /* BIND-specific, nonstandard. */ 83 | DNS_T_MAX = 65536 84 | }; 85 | 86 | enum dns_rcode_e { /* reply code */ 87 | DNS_R_NOERROR = 0, /* ok, no error */ 88 | DNS_R_FORMERR = 1, /* format error */ 89 | DNS_R_SERVFAIL = 2, /* server failed */ 90 | DNS_R_NXDOMAIN = 3, /* domain does not exists */ 91 | DNS_R_NOTIMPL = 4, /* not implemented */ 92 | DNS_R_REFUSED = 5, /* query refused */ 93 | /* these are for BIND_UPDATE */ 94 | DNS_R_YXDOMAIN = 6, /* Name exists */ 95 | DNS_R_YXRRSET = 7, /* RRset exists */ 96 | DNS_R_NXRRSET = 8, /* RRset does not exist */ 97 | DNS_R_NOTAUTH = 9, /* Not authoritative for zone */ 98 | DNS_R_NOTZONE = 10, /* Zone of record different from zone section */ 99 | /*ns_r_max = 11,*/ 100 | /* The following are TSIG extended errors */ 101 | DNS_R_BADSIG = 16, 102 | DNS_R_BADKEY = 17, 103 | DNS_R_BADTIME = 18 104 | }; 105 | /* *INDENT-ON* */ 106 | 107 | const char *pdns_logger_rcode2p(enum dns_rcode_e); 108 | const char *pdns_logger_type2p(enum dns_type_e); 109 | const char *pdns_logger_class2p(enum dns_class_e); 110 | -------------------------------------------------------------------------------- /src/inih/README.md: -------------------------------------------------------------------------------- 1 | ----------------------------------------------- 2 | DOWNLOADED FROM https://github.com/benhoyt/inih 3 | ----------------------------------------------- 4 | 5 | **inih (INI Not Invented Here)** is a simple [.INI file](http://en.wikipedia.org/wiki/INI_file) parser written in C. It's only a couple of pages of code, and it was designed to be _small and simple_, so it's good for embedded systems. It's also more or less compatible with Python's [ConfigParser](http://docs.python.org/library/configparser.html) style of .INI files, including RFC 822-style multi-line syntax and `name: value` entries. 6 | 7 | To use it, just give `ini_parse()` an INI file, and it will call a callback for every `name=value` pair parsed, giving you strings for the section, name, and value. It's done this way ("SAX style") because it works well on low-memory embedded systems, but also because it makes for a KISS implementation. 8 | 9 | You can also call `ini_parse_file()` to parse directly from a `FILE*` object, `ini_parse_string()` to parse data from a string, or `ini_parse_stream()` to parse using a custom fgets-style reader function for custom I/O. 10 | 11 | Download a release, browse the source, or read about [how to use inih in a DRY style](http://blog.brush.co.nz/2009/08/xmacros/) with X-Macros. 12 | 13 | 14 | ## Compile-time options ## 15 | 16 | * **Multi-line entries:** By default, inih supports multi-line entries in the style of Python's ConfigParser. To disable, add `-DINI_ALLOW_MULTILINE=0`. 17 | * **UTF-8 BOM:** By default, inih allows a UTF-8 BOM sequence (0xEF 0xBB 0xBF) at the start of INI files. To disable, add `-DINI_ALLOW_BOM=0`. 18 | * **Inline comments:** By default, inih allows inline comments with the `;` character. To disable, add `-DINI_ALLOW_INLINE_COMMENTS=0`. You can also specify which character(s) start an inline comment using `INI_INLINE_COMMENT_PREFIXES`. 19 | * **Stack vs heap:** By default, inih allocates its line buffer on the stack. To allocate on the heap using `malloc` instead, specify `-DINI_USE_STACK=0`. 20 | * **Stop on first error:** By default, inih keeps parsing the rest of the file after an error. To stop parsing on the first error, add `-DINI_STOP_ON_FIRST_ERROR=1`. 21 | * **Maximum line length:** The default maximum line length is 200 bytes. To override this, add something like `-DINI_MAX_LINE=1000`. 22 | * **Report line numbers:** By default, the `ini_handler` callback doesn't receive the line number as a parameter. If you need that, add `-DINI_HANDLER_LINENO=1`. 23 | 24 | 25 | ## Simple example in C ## 26 | 27 | ```c 28 | #include 29 | #include 30 | #include 31 | #include "../ini.h" 32 | 33 | typedef struct 34 | { 35 | int version; 36 | const char* name; 37 | const char* email; 38 | } configuration; 39 | 40 | static int handler(void* user, const char* section, const char* name, 41 | const char* value) 42 | { 43 | configuration* pconfig = (configuration*)user; 44 | 45 | #define MATCH(s, n) strcmp(section, s) == 0 && strcmp(name, n) == 0 46 | if (MATCH("protocol", "version")) { 47 | pconfig->version = atoi(value); 48 | } else if (MATCH("user", "name")) { 49 | pconfig->name = strdup(value); 50 | } else if (MATCH("user", "email")) { 51 | pconfig->email = strdup(value); 52 | } else { 53 | return 0; /* unknown section/name, error */ 54 | } 55 | return 1; 56 | } 57 | 58 | int main(int argc, char* argv[]) 59 | { 60 | configuration config; 61 | 62 | if (ini_parse("test.ini", handler, &config) < 0) { 63 | printf("Can't load 'test.ini'\n"); 64 | return 1; 65 | } 66 | printf("Config loaded from 'test.ini': version=%d, name=%s, email=%s\n", 67 | config.version, config.name, config.email); 68 | return 0; 69 | } 70 | ``` 71 | 72 | 73 | ## C++ example ## 74 | 75 | If you're into C++ and the STL, there is also an easy-to-use [INIReader class](https://github.com/benhoyt/inih/blob/master/cpp/INIReader.h) that stores values in a `map` and lets you `Get()` them: 76 | 77 | ```cpp 78 | #include 79 | #include "INIReader.h" 80 | 81 | int main() 82 | { 83 | INIReader reader("../examples/test.ini"); 84 | 85 | if (reader.ParseError() < 0) { 86 | std::cout << "Can't load 'test.ini'\n"; 87 | return 1; 88 | } 89 | std::cout << "Config loaded from 'test.ini': version=" 90 | << reader.GetInteger("protocol", "version", -1) << ", name=" 91 | << reader.Get("user", "name", "UNKNOWN") << ", email=" 92 | << reader.Get("user", "email", "UNKNOWN") << ", pi=" 93 | << reader.GetReal("user", "pi", -1) << ", active=" 94 | << reader.GetBoolean("user", "active", true) << "\n"; 95 | return 0; 96 | } 97 | ``` 98 | 99 | This simple C++ API works fine, but it's not very fully-fledged. I'm not planning to work more on the C++ API at the moment, so if you want a bit more power (for example `GetSections()` and `GetFields()` functions), see these forks: 100 | 101 | * https://github.com/Blandinium/inih 102 | * https://github.com/OSSystems/inih 103 | 104 | 105 | ## Differences from ConfigParser ## 106 | 107 | Some differences between inih and Python's [ConfigParser](http://docs.python.org/library/configparser.html) standard library module: 108 | 109 | * INI name=value pairs given above any section headers are treated as valid items with no section (section name is an empty string). In ConfigParser having no section is an error. 110 | * Line continuations are handled with leading whitespace on continued lines (like ConfigParser). However, instead of concatenating continued lines together, they are treated as separate values for the same key (unlike ConfigParser). 111 | 112 | 113 | ## Platform-specific notes ## 114 | 115 | * Windows/Win32 uses UTF-16 filenames natively, so to handle Unicode paths you need to call `_wfopen()` to open a file and then `ini_parse_file()` to parse it; inih does not include `wchar_t` or Unicode handling. 116 | -------------------------------------------------------------------------------- /src/inih/ini.c: -------------------------------------------------------------------------------- 1 | /* 2 | inih -- simple .INI file parser 3 | 4 | inih is released under the New BSD license (see LICENSE.txt). Go to the project 5 | home page for more info: 6 | 7 | https://github.com/benhoyt/inih 8 | */ 9 | 10 | #if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS) 11 | #define _CRT_SECURE_NO_WARNINGS 12 | #endif 13 | 14 | #include 15 | #include 16 | #include 17 | 18 | #include "ini.h" 19 | 20 | #if !INI_USE_STACK 21 | #include 22 | #endif 23 | 24 | #define MAX_SECTION 50 25 | #define MAX_NAME 50 26 | 27 | /* Used by ini_parse_string() to keep track of string parsing state. */ 28 | typedef struct { 29 | const char *ptr; 30 | size_t num_left; 31 | } ini_parse_string_ctx; 32 | 33 | /* Strip whitespace chars off end of given string, in place. Return s. */ 34 | static char *rstrip(char *s) { 35 | char *p = s + strlen(s); 36 | while (p > s && isspace((unsigned char) (*--p))) 37 | *p = '\0'; 38 | return s; 39 | } 40 | 41 | /* Return pointer to first non-whitespace char in given string. */ 42 | static char *lskip(const char *s) { 43 | while (*s && isspace((unsigned char) (*s))) 44 | s++; 45 | return (char *) s; 46 | } 47 | 48 | /* Return pointer to first char (of chars) or inline comment in given string, 49 | or pointer to null at end of string if neither found. Inline comment must 50 | be prefixed by a whitespace character to register as a comment. */ 51 | static char *find_chars_or_comment(const char *s, const char *chars) { 52 | #if INI_ALLOW_INLINE_COMMENTS 53 | int was_space = 0; 54 | while (*s && (!chars || !strchr(chars, *s)) && !(was_space && strchr(INI_INLINE_COMMENT_PREFIXES, *s))) { 55 | was_space = isspace((unsigned char) (*s)); 56 | s++; 57 | } 58 | #else 59 | while (*s && (!chars || !strchr(chars, *s))) { 60 | s++; 61 | } 62 | #endif 63 | return (char *) s; 64 | } 65 | 66 | /* Version of strncpy that ensures dest (size bytes) is null-terminated. */ 67 | static char *strncpy0(char *dest, const char *src, size_t size) { 68 | strncpy(dest, src, size); 69 | dest[size - 1] = '\0'; 70 | return dest; 71 | } 72 | 73 | /* See documentation in header file. */ 74 | int ini_parse_stream(ini_reader reader, void *stream, ini_handler handler, void *user) { 75 | /* Uses a fair bit of stack (use heap instead if you need to) */ 76 | #if INI_USE_STACK 77 | char line[INI_MAX_LINE]; 78 | #else 79 | char *line; 80 | #endif 81 | char section[MAX_SECTION] = ""; 82 | char prev_name[MAX_NAME] = ""; 83 | 84 | char *start; 85 | char *end; 86 | char *name; 87 | char *value; 88 | int lineno = 0; 89 | int error = 0; 90 | 91 | #if !INI_USE_STACK 92 | line = (char *) malloc(INI_MAX_LINE); 93 | if (!line) { 94 | return -2; 95 | } 96 | #endif 97 | 98 | #if INI_HANDLER_LINENO 99 | #define HANDLER(u, s, n, v) handler(u, s, n, v, lineno) 100 | #else 101 | #define HANDLER(u, s, n, v) handler(u, s, n, v) 102 | #endif 103 | 104 | /* Scan through stream line by line */ 105 | while (reader(line, INI_MAX_LINE, stream) != NULL) { 106 | lineno++; 107 | 108 | start = line; 109 | #if INI_ALLOW_BOM 110 | if (lineno == 1 && (unsigned char) start[0] == 0xEF && (unsigned char) start[1] == 0xBB && (unsigned char) start[2] == 0xBF) { 111 | start += 3; 112 | } 113 | #endif 114 | start = lskip(rstrip(start)); 115 | 116 | if (*start == ';' || *start == '#') { 117 | /* Per Python configparser, allow both ; and # comments at the 118 | start of a line */ 119 | } 120 | #if INI_ALLOW_MULTILINE 121 | else if (*prev_name && *start && start > line) { 122 | /* Non-blank line with leading whitespace, treat as continuation 123 | of previous name's value (as per Python configparser). */ 124 | if (!HANDLER(user, section, prev_name, start) && !error) 125 | error = lineno; 126 | } 127 | #endif 128 | else if (*start == '[') { 129 | /* A "[section]" line */ 130 | end = find_chars_or_comment(start + 1, "]"); 131 | if (*end == ']') { 132 | *end = '\0'; 133 | strncpy0(section, start + 1, sizeof(section)); 134 | *prev_name = '\0'; 135 | } else if (!error) { 136 | /* No ']' found on section line */ 137 | error = lineno; 138 | } 139 | } else if (*start) { 140 | /* Not a comment, must be a name[=:]value pair */ 141 | end = find_chars_or_comment(start, "=:"); 142 | if (*end == '=' || *end == ':') { 143 | *end = '\0'; 144 | name = rstrip(start); 145 | value = end + 1; 146 | #if INI_ALLOW_INLINE_COMMENTS 147 | end = find_chars_or_comment(value, NULL); 148 | if (*end) 149 | *end = '\0'; 150 | #endif 151 | value = lskip(value); 152 | rstrip(value); 153 | 154 | /* Valid name[=:]value pair found, call handler */ 155 | strncpy0(prev_name, name, sizeof(prev_name)); 156 | if (!HANDLER(user, section, name, value) && !error) 157 | error = lineno; 158 | } else if (!error) { 159 | /* No '=' or ':' found on name[=:]value line */ 160 | error = lineno; 161 | } 162 | } 163 | #if INI_STOP_ON_FIRST_ERROR 164 | if (error) 165 | break; 166 | #endif 167 | } 168 | 169 | #if !INI_USE_STACK 170 | free(line); 171 | #endif 172 | 173 | return error; 174 | } 175 | 176 | /* See documentation in header file. */ 177 | int ini_parse_file(FILE * file, ini_handler handler, void *user) { 178 | return ini_parse_stream((ini_reader) fgets, file, handler, user); 179 | } 180 | 181 | /* See documentation in header file. */ 182 | int ini_parse(const char *filename, ini_handler handler, void *user) { 183 | FILE *file; 184 | int error; 185 | 186 | file = fopen(filename, "r"); 187 | if (!file) 188 | return -1; 189 | error = ini_parse_file(file, handler, user); 190 | fclose(file); 191 | return error; 192 | } 193 | 194 | /* An ini_reader function to read the next line from a string buffer. This 195 | is the fgets() equivalent used by ini_parse_string(). */ 196 | static char *ini_reader_string(char *str, int num, void *stream) { 197 | ini_parse_string_ctx *ctx = (ini_parse_string_ctx *) stream; 198 | const char *ctx_ptr = ctx->ptr; 199 | size_t ctx_num_left = ctx->num_left; 200 | char *strp = str; 201 | char c; 202 | 203 | if (ctx_num_left == 0 || num < 2) 204 | return NULL; 205 | 206 | while (num > 1 && ctx_num_left != 0) { 207 | c = *ctx_ptr++; 208 | ctx_num_left--; 209 | *strp++ = c; 210 | if (c == '\n') 211 | break; 212 | num--; 213 | } 214 | 215 | *strp = '\0'; 216 | ctx->ptr = ctx_ptr; 217 | ctx->num_left = ctx_num_left; 218 | return str; 219 | } 220 | 221 | /* See documentation in header file. */ 222 | int ini_parse_string(const char *string, ini_handler handler, void *user) { 223 | ini_parse_string_ctx ctx; 224 | 225 | ctx.ptr = string; 226 | ctx.num_left = strlen(string); 227 | return ini_parse_stream((ini_reader) ini_reader_string, &ctx, handler, user); 228 | } 229 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | PDNS-LOGGER 2 | =========== 3 | 4 | ** pdns-logger ** is a small daemon that leverages the protobufServer feature of Powerdns Recursor 5 | to log the queries to syslog, to a file and to an sqlite3 database. 6 | 7 | Use cases 8 | --------- 9 | 10 | The program was written to debug RPZ rewrites in an easy way because unfortunately, debugging RPZ when used together with powerdns-recursor 11 | is an ugly task. 12 | 13 | The initial version of this program was logging to file, only. 14 | Syslog and sqlite3 came later to add more features and increase the use cases. 15 | 16 | In particular, the sqlite3 database can be easily used to log queries and show them on a nice web interface. 17 | 18 | DEBIAN OR UBUNTU PACKAGE 19 | ------------------------ 20 | 21 | If you need a debian or an ubuntu package, the repository includes everything you need. 22 | 23 | First, you need to install the build environment and the required developent libraries. 24 | ```bash 25 | apt-get install cdbs debhelper devscripts cmake build-essential pkg-config libprotobuf-c-dev libsqlite3-dev 26 | ``` 27 | 28 | Then you need to start the configuration, compilation and the build of the packages. Don't worry, it's a single command: 29 | ```bash 30 | dpkg-buildpackage -uc -us -b 31 | ``` 32 | 33 | After the process, you will have a nice debian/ubuntu package ready to be installed: 34 | 35 | ```bash 36 | dpkg -i ../pdns-logger*.deb 37 | ``` 38 | 39 | MANUAL INSTALLATION 40 | ------------------- 41 | 42 | To compile pdns-logger, you need [cmake](https://cmake.org/). 43 | 44 | Other required libraries are: 45 | - [protobuf-c](https://github.com/protobuf-c/protobuf-c) 46 | - [sqlite3](https://www.sqlite.org/) 47 | 48 | Checkout the code from Git and then 49 | ```bash 50 | mkdir -p build 51 | cd build 52 | cmake ../ \ 53 | -DCMAKE_BUILD_TYPE=Release \ 54 | -DCMAKE_INSTALL_PREFIX="/usr/" \ 55 | -DSYSCONF_INSTALL_DIR="/etc" 56 | 57 | make 58 | make install 59 | ``` 60 | 61 | After installation, you will have 62 | * /etc/pdns-logger/pdns-logger.ini - The configuration file 63 | * /usr/sbin/pdns-logger - the daemon 64 | 65 | Command line options are: 66 | ```bash 67 | Usage: pdns-collector [options] 68 | Options: 69 | -c configfile Location of the config file (default: /etc/pdns-logger/pdns-logger.ini) 70 | -f Do not fork and stay in foreground 71 | -h Print this message and exit. 72 | 73 | ``` 74 | 75 | In the debian/ directory there is an init script (`pdns-logger.init`) that you can adapt and use for your purposes. 76 | 77 | POWERDNS CONFIGURATION 78 | ---------------------- 79 | 80 | To effectively use the daemon, you need to configure powerdns. 81 | If you're using RPZ, you already know that you need to add the following configuration to recursor.conf: 82 | ``` 83 | lua-config-file=/etc/powerdns/recursor.conf.lua 84 | ``` 85 | 86 | What you're probably missing is that in the recursor.conf.lua you need to add: 87 | ```lua 88 | protobufServer("127.0.0.1:4242") 89 | ``` 90 | 91 | This will instruct powerdns-recursor to send the logs to our daemon. 92 | If you're using pdns-recursor 4.1.0 or higher, you may want to use this command instead. With this, you will be able to log only the RPZ rewrites and not all the queries sent to the logger.: 93 | ```lua 94 | protobufServer("127.0.0.1:4242", 2, 100, 1, 32, 128, false, true) 95 | ``` 96 | 97 | Please notice that the IP address and the port must match what is configured in the .ini file of the daemon. 98 | 99 | Restart the recursor. If you're on debian or ubuntu, then 100 | 101 | ```bash 102 | service pdns-resolver restart 103 | ``` 104 | 105 | will be enough. 106 | 107 | PDNS-LOGGER CONFIGURATION 108 | ------------------------- 109 | Don't forget to have a look and eventually modify the configuration of the logger. 110 | The configuration INI file is usually in "/etc/pdns-logger/pdns-logger.ini" and contains very few directives. 111 | 112 | ```ini 113 | [globals] 114 | allow-root=0 115 | bind-ip=127.0.0.1 116 | bind-port=4242 117 | ;foreground=0 ; If set, this will override the CLI -f option 118 | 119 | 120 | [logfile] 121 | disabled = 0 ; should we disable the log-to-file backend ? 122 | only-rewrites=1 ; log only RPZ rewrites 123 | ; what is the path of our log file ? 124 | logfile=/var/log/pdns-logger/pdns.log 125 | force-flush=1 ; flush buffers to disk at each query 126 | 127 | 128 | [syslog] 129 | disabled = 1 ; Should we disable the syslog backend ? 130 | only-rewrites=1 ; log only RPZ rewrites 131 | ident=pdns-logger ; the syslog ident 132 | facility=syslog ; the log facility 133 | 134 | 135 | [sqlite3] 136 | disabled = 1; ; should we disable the sqlite3 backend ? 137 | only-rewrites=1 ; log only RPZ rewrites 138 | ; what is the path to our sqlite3 database ? 139 | dbfile=/var/lib/pdns-logger/queries.db 140 | autocommit=1 ; should the backend commit to file for every record ? 141 | ``` 142 | 143 | LOG FORMAT 144 | ---------- 145 | 146 | The logfile and the syslog backends share the same format. 147 | Each line will have the following format: 148 | ``` 149 | Nov 2 18:01:19 NS0 pdns-logger[12718]: QID: 20542 from: 127.0.0.1 qtype: A qclass: IN qname: dbltest.com. rcode: NXDOMAIN rrcount: 0 policy: 'DBL' 150 | ``` 151 | 152 | The sinble bits in the line are: 153 | * QID: the query ID, as sent from the client to the DNS server 154 | * FROM: the querier IP address 155 | * QTYPE: the query type (A, NS, MX, ...) 156 | * QCLASS: the query class. Usually it's always 'IN' 157 | * QNAME: the query name, that is the main thing that you need to know. 158 | * RCODE: the response code sent back to the client (NXDOMAIN, NOERROR etcc...) 159 | * RRCOUNT: the number of RR sent back in the response packet 160 | * POLICY: it's the policy, if present, applied to the response packet, according to an RPZ zone. This bit may be missing if the query was not rewritten. 161 | 162 | When the response packet contains more than one RR, then additional fields (or tuples, if RRCOUNT is greater than one) will apply: 163 | * RNAME: the domain name sent back 164 | * RTYPE: the response type 165 | * RCLASS: same as QCLASS 166 | * RTTL: the TTL of the record 167 | * RDATA: the valie of the RR - Remember that PDNS does log all the rewrites and additional queries (but not all RTYPEs) 168 | 169 | 170 | The sqlite backend stores the same data in a table with the following schema: 171 | 172 | ```sql 173 | CREATE TABLE IF NOT EXISTS logs ( 174 | ts INTEGER NOT NULL, 175 | querier VARCHAR(48), 176 | id INTEGER NOT NULL, 177 | qtype VARCHAR(10), 178 | qclass VARCHAR(10), 179 | qname VARCHAR(256), 180 | rcode VARCHAR(16), 181 | rcount INTEGER, 182 | rname VARCHAR(256), 183 | rtype VARCHAR(10), 184 | rclass VARCHAR(10), 185 | rttl INTEGER, 186 | rdata VARCHAR(256), 187 | policy VARCHAR(100) 188 | ) 189 | ``` 190 | The meaning of the columns are identical to the corresponding text version. 191 | 192 | 193 | Please note that a SIGHUP signal delivered to the daemon will flush the log files to disk and will allow for log rotation, closing and reopening all files. 194 | 195 | 196 | DEVELOPEMENT 197 | ------------ 198 | - Source hosted at [GitHub](https://github.com/spamhays/pdns-logger) 199 | - Report issues, questions, feature requests on [GitHub Issues](https://github.com/spamhaus/pdns-logger/issues) 200 | 201 | Authors 202 | ------- 203 | [Massimo Cetra] (http://www.ctrix.it/) 204 | 205 | 206 | Enjoy! 207 | -------------------------------------------------------------------------------- /src/pdns-logger.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Powerdns logger daemon 3 | * ---------------------- 4 | * 5 | * This Source Code Form is subject to the terms of the 6 | * Mozilla Public License, v. 2.0. 7 | * If a copy of the MPL was not distributed with this 8 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 9 | * 10 | * Copyright (C) 2017, Spamhaus Technology Ltd, London 11 | * 12 | * The Initial developer of the Original code is: 13 | * Massimo Cetra 14 | * 15 | */ 16 | 17 | #include 18 | #include 19 | #include "pdns-logger.h" 20 | 21 | static globals_t globals; 22 | 23 | /* ************************************************************************ */ 24 | /* ************************************************************************ */ 25 | /* ************************************************************************ */ 26 | 27 | static int engines_count = 0; 28 | static pdns_logger_t engines[3]; 29 | 30 | pdns_status_t pdns_loggers_log(void *pbm) { 31 | int t; 32 | 33 | for (t = 0; t < engines_count; t++) { 34 | if (engines[t].log != NULL) { 35 | engines[t].log(pbm); 36 | } 37 | } 38 | 39 | return PDNS_OK; 40 | } 41 | 42 | static pdns_status_t pdns_loggers_rotate(void) { 43 | int t; 44 | 45 | for (t = 0; t < engines_count; t++) { 46 | if (engines[t].rotate != NULL) { 47 | engines[t].rotate(); 48 | } 49 | } 50 | 51 | return PDNS_OK; 52 | } 53 | 54 | static pdns_status_t loggers_initialize(const char *conf) { 55 | int t; 56 | memset(engines, 0, sizeof(engines)); 57 | 58 | engines[engines_count++] = logfile_engine; 59 | engines[engines_count++] = syslog_engine; 60 | engines[engines_count++] = sqlite_engine; 61 | 62 | for (t = 0; t < engines_count; t++) { 63 | if (engines[t].start != NULL) { 64 | engines[t].start(conf); 65 | } 66 | } 67 | 68 | return PDNS_OK; 69 | } 70 | 71 | static pdns_status_t loggers_halt(void) { 72 | int t; 73 | 74 | for (t = 0; t < engines_count; t++) { 75 | if (engines[t].stop != NULL) { 76 | engines[t].stop(); 77 | } 78 | } 79 | 80 | return PDNS_OK; 81 | } 82 | 83 | /* ************************************************************************ */ 84 | /* ************************************************************************ */ 85 | /* ************************************************************************ */ 86 | 87 | static pdns_status_t fork_and_close_parent(void) { 88 | FILE *filed; 89 | pid_t pid = 0; 90 | pid_t sid; 91 | 92 | if ((pid = fork())) { 93 | fprintf(stderr, "Going to background (PID: %d)\n", (int) pid); 94 | return PDNS_OK; 95 | } 96 | 97 | /* Create a new SID for the child process */ 98 | sid = setsid(); 99 | if (sid < 0) { 100 | fprintf(stderr, "Cannot setsid() the child process\n"); 101 | return PDNS_NO; 102 | } 103 | 104 | filed = freopen("/dev/null", "r", stdin); 105 | filed = freopen("/dev/null", "w", stdout); 106 | filed = freopen("/dev/null", "w", stderr); 107 | 108 | (void) filed; /* To remove nasty warnings! */ 109 | 110 | return PDNS_FORK; 111 | } 112 | 113 | static void signal_rotate(int sig) { 114 | (void) sig; 115 | fprintf(stderr, "Rotating logfiles...\n"); 116 | pdns_loggers_rotate(); 117 | return; 118 | } 119 | 120 | static void signal_stop(int sig) { 121 | (void) sig; 122 | 123 | globals.running = 0; 124 | 125 | return; 126 | } 127 | 128 | static pdns_status_t parse_cli(globals_t * conf, int argc, char **argv) { 129 | int c; 130 | 131 | while ((c = getopt(argc, argv, "hvc:f")) != -1) { 132 | switch (c) { 133 | case 'h': 134 | printf("\n"); 135 | printf("Usage: pdns-collector [options]\n"); 136 | printf("Options:\n"); 137 | printf(" -c configfile Location of the config file (default: %s)\n", DEFAULT_CONFIG_FILE); 138 | printf(" -f Do not fork and stay in foreground\n"); 139 | printf(" -h Print this message and exit.\n"); 140 | //printf(" -v Verbose mode, display config options and stats\n"); 141 | printf("\n"); 142 | return PDNS_OK; 143 | break; 144 | case 'c': 145 | conf->config_file = strdup(optarg); 146 | if (conf->verbose) { 147 | printf("Options file set to %s\n", conf->config_file); 148 | } 149 | break; 150 | case 'f': 151 | conf->foreground = 1; 152 | break; 153 | 154 | case 'v': 155 | conf->verbose = 1; 156 | break; 157 | 158 | case '?': 159 | if (optopt == 'c') { 160 | printf("Option -%c requires an argument.\n", optopt); 161 | return PDNS_NO; 162 | } else if (isprint(optopt)) { 163 | printf("Unknown option `-%c'.\n", optopt); 164 | return PDNS_NO; 165 | } else { 166 | printf("Unknown option character `\\x%x'.\n", optopt); 167 | return PDNS_NO; 168 | } 169 | break; 170 | 171 | default: 172 | printf("Error parsing command line options\n"); 173 | return PDNS_NO; 174 | } 175 | } 176 | 177 | return PDNS_OK; 178 | } 179 | 180 | int main(int argc, char **argv) { 181 | memset(&globals, 0, sizeof(globals_t)); 182 | 183 | if (parse_cli(&globals, argc, argv) != PDNS_OK) { 184 | fprintf(stderr, "Error parsing cli options. Exiting.\n"); 185 | exit(EXIT_FAILURE); 186 | } 187 | 188 | if (zstr(globals.config_file)) { 189 | globals.config_file = strdup(DEFAULT_CONFIG_FILE); 190 | } 191 | 192 | if (parse_config_file(globals.config_file, &globals) != PDNS_OK) { 193 | fprintf(stderr, "Error parsing config file ('%s'). Exiting.\n", globals.config_file ? globals.config_file : "not set"); 194 | exit(EXIT_FAILURE); 195 | } 196 | 197 | if (!globals.allow_root) { 198 | uid_t current_uid = getuid(); 199 | 200 | if (current_uid == 0) { 201 | fprintf(stderr, "Please don't start this program as root.\n"); 202 | //exit(EXIT_FAILURE); 203 | } 204 | } 205 | 206 | loggers_initialize(globals.config_file); 207 | 208 | signal(SIGINT, signal_stop); 209 | signal(SIGTERM, signal_stop); 210 | signal(SIGPIPE, SIG_IGN); 211 | signal(SIGHUP, signal_rotate); 212 | 213 | if (!globals.foreground) { 214 | pdns_status_t status; 215 | status = fork_and_close_parent(); 216 | 217 | if (status == PDNS_OK) { 218 | exit(EXIT_SUCCESS); 219 | } else if (status == PDNS_FORK) { 220 | /* Properly forked, we're the backfround child. */ 221 | } else { 222 | fprintf(stderr, "Cannot fork and push the process to background."); 223 | exit(EXIT_FAILURE); 224 | } 225 | } 226 | 227 | globals.running = 1; 228 | 229 | if (pdns_socket_run(&globals) != PDNS_OK) { 230 | fprintf(stderr, "Cannot start the socket process. Is there another daemon already listening ?\n"); 231 | exit(EXIT_FAILURE); 232 | } 233 | 234 | loggers_halt(); 235 | 236 | fprintf(stderr, "Terminating...\n"); 237 | 238 | safe_free(globals.user); 239 | safe_free(globals.group); 240 | safe_free(globals.config_file); 241 | 242 | return 0; 243 | } 244 | -------------------------------------------------------------------------------- /src/pdns-logger-protobuf.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Powerdns logger daemon 3 | * ---------------------- 4 | * 5 | * This Source Code Form is subject to the terms of the 6 | * Mozilla Public License, v. 2.0. 7 | * If a copy of the MPL was not distributed with this 8 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 9 | * 10 | * Copyright (C) 2017, Spamhaus Technology Ltd, London 11 | * 12 | * The Initial developer of the Original code is: 13 | * Massimo Cetra 14 | * 15 | */ 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | #include "pdns-logger.h" 23 | #include "dnsmessage.pb-c.h" 24 | 25 | #define MAX_BUFFER_SIZE 8192 26 | 27 | static pdns_status_t protobuf_parse(unsigned char *buf, size_t blen) { 28 | PBDNSMessage *msg; 29 | 30 | msg = pbdnsmessage__unpack(NULL, blen, (uint8_t *) buf); 31 | if (msg == NULL) { 32 | assert(0); 33 | return PDNS_NO; 34 | } else { 35 | #ifdef DEBUG 36 | size_t sz = pbdnsmessage__get_packed_size(msg); 37 | fprintf(stderr, "Decoded message size %zu\n", sz); 38 | #endif 39 | pdns_loggers_log(msg); 40 | } 41 | 42 | pbdnsmessage__free_unpacked(msg, NULL); 43 | 44 | return PDNS_OK; 45 | } 46 | 47 | static pdns_status_t protobuf_extract(unsigned char *buf, size_t * blen) { 48 | uint16_t *pplen, plen; 49 | unsigned char *pbuf; 50 | 51 | if (*blen < sizeof(uint16_t)) { 52 | return PDNS_RETRY; 53 | } 54 | #ifdef DEBUG 55 | fprintf(stderr, "bytes: %d %d (over %zu)\n", *buf, *(buf + 1), *blen); 56 | #endif 57 | 58 | while (1) { 59 | pplen = (uint16_t *) buf; 60 | plen = ntohs(*pplen); 61 | 62 | if (*blen >= plen + sizeof(uint16_t)) { 63 | /* Decode is possible */ 64 | #ifdef DEBUG 65 | fprintf(stderr, "Decoding (pblen = %d)\n", plen); 66 | #endif 67 | pbuf = buf + 2; 68 | 69 | protobuf_parse(pbuf, plen); 70 | memmove(buf, buf + plen + 2, *blen - plen - 2); 71 | *blen = *blen - plen - 2; 72 | 73 | #ifdef DEBUG 74 | fprintf(stderr, "Remaining (blen = %zu)\n", *blen); 75 | #endif 76 | if (*blen == 0) { 77 | return PDNS_OK; 78 | } 79 | } else { 80 | #ifdef DEBUG 81 | fprintf(stderr, "Retrying (blen = %zu pblen = %d)\n", *blen, plen); 82 | #endif 83 | return PDNS_RETRY; 84 | } 85 | } 86 | 87 | return PDNS_OK; 88 | } 89 | 90 | static void *socket_thread_exec(void *data) { 91 | int flags; 92 | int *psocket = (int *) data; 93 | int socket = *psocket; 94 | size_t bsize = 0; 95 | unsigned char buffer[MAX_BUFFER_SIZE]; 96 | 97 | /* Set socket non-blocking */ 98 | flags = fcntl(socket, F_GETFL, 0); 99 | if (flags == -1) { 100 | return PDNS_NO; 101 | } 102 | 103 | flags |= !O_NONBLOCK; 104 | if (fcntl(socket, F_SETFL, flags) == -1) { 105 | return PDNS_NO; 106 | } 107 | 108 | while (1) { 109 | int nbytes; 110 | 111 | if (bsize == MAX_BUFFER_SIZE) { 112 | #ifdef DEBUG 113 | fprintf(stderr, "Client buffer full!\n"); 114 | #endif 115 | /* Buffer full, should not happen. Let's disconnect the client */ 116 | break; 117 | } 118 | 119 | nbytes = read(socket, buffer + bsize, sizeof(buffer) - bsize); 120 | if (nbytes < 0) { 121 | /* Error */ 122 | break; 123 | } else if (nbytes == 0) { 124 | /* EOF */ 125 | break; 126 | } else { 127 | pdns_status_t status = PDNS_RETRY; 128 | 129 | #ifdef DEBUG 130 | fprintf(stderr, "bytes: %d %d <\n", *buffer, *(buffer + 1)); 131 | fprintf(stderr, "Reading %d bytes from socket, appending at offset %zu\n", nbytes, bsize); 132 | #endif 133 | bsize += nbytes; 134 | 135 | status = protobuf_extract(buffer, &bsize); 136 | if (status == PDNS_NO) { 137 | break; 138 | } else if (status == PDNS_RETRY) { 139 | /* Don't alter the buffer */ 140 | } else if (status == PDNS_OK) { 141 | /* We should alter the buffer */ 142 | } else { 143 | /* Should never happen */ 144 | assert(0); 145 | } 146 | 147 | } 148 | } 149 | 150 | #ifdef DEBUG 151 | fprintf(stderr, "Disconnecting client\n"); 152 | #endif 153 | close(socket); 154 | 155 | return NULL; 156 | } 157 | 158 | static pdns_status_t socket_start_thread(int socket) { 159 | pthread_t thread; 160 | 161 | pthread_create(&thread, NULL, &socket_thread_exec, &socket); 162 | 163 | return PDNS_OK; 164 | } 165 | 166 | static pdns_status_t socket_loop(globals_t * conf) { 167 | int i; 168 | struct sockaddr_in client_sa; 169 | fd_set active_fd_set, read_fd_set; 170 | 171 | FD_ZERO(&active_fd_set); 172 | FD_SET(conf->socket, &active_fd_set); 173 | 174 | while (conf->running) { 175 | read_fd_set = active_fd_set; 176 | 177 | if (select(FD_SETSIZE, &read_fd_set, NULL, NULL, NULL) < 0) { 178 | continue; 179 | } 180 | 181 | usleep(1000000 / 10); /* Let's slow things down ... */ 182 | 183 | for (i = 0; i < FD_SETSIZE; ++i) { 184 | if (FD_ISSET(i, &read_fd_set)) { 185 | if (i == conf->socket) { 186 | /* Connection request on original socket. */ 187 | int new; 188 | size_t size; 189 | 190 | size = sizeof(client_sa); 191 | new = accept(conf->socket, (struct sockaddr *) &client_sa, (socklen_t *) & size); 192 | 193 | if (new < 0) { 194 | fprintf(stderr, "Cannot accept connection from client.\n"); 195 | } else { 196 | fprintf(stderr, "Connection from host %s, port %d.\n", inet_ntoa(client_sa.sin_addr), ntohs(client_sa.sin_port)); 197 | socket_start_thread(new); 198 | } 199 | } else { 200 | /* Should never happen */ 201 | assert(0); 202 | } 203 | } 204 | } 205 | } 206 | 207 | return PDNS_OK; 208 | } 209 | 210 | static pdns_status_t socket_start(globals_t * conf) { 211 | int flags; 212 | struct sockaddr_in sa; 213 | 214 | conf->socket = socket(AF_INET, SOCK_STREAM, 0); 215 | if (conf->socket == -1) { 216 | return PDNS_NO; 217 | } 218 | 219 | sa.sin_family = AF_INET; 220 | sa.sin_addr.s_addr = INADDR_ANY; 221 | sa.sin_port = htons(conf->bind_port); 222 | 223 | flags = 1; 224 | if (setsockopt(conf->socket, SOL_SOCKET, SO_REUSEADDR, &flags, sizeof(flags)) < 0) { 225 | fprintf(stderr, "Cannot set SO_REUSEADDR\n"); 226 | } 227 | 228 | if (bind(conf->socket, (struct sockaddr *) &sa, sizeof(sa)) < 0) { 229 | fprintf(stderr, "Bind failed. Error\n"); 230 | return PDNS_NO; 231 | } 232 | 233 | flags = fcntl(conf->socket, F_GETFL, 0); 234 | if (flags == -1) { 235 | return PDNS_NO; 236 | } 237 | 238 | flags |= O_NONBLOCK; 239 | if (fcntl(conf->socket, F_SETFL, flags) == -1) { 240 | return PDNS_NO; 241 | } 242 | 243 | if (listen(conf->socket, SOMAXCONN) < 0) { 244 | return PDNS_NO; 245 | } 246 | 247 | return PDNS_OK; 248 | } 249 | 250 | static pdns_status_t socket_close(globals_t * conf) { 251 | close(conf->socket); 252 | return PDNS_OK; 253 | } 254 | 255 | pdns_status_t pdns_socket_run(globals_t * globals) { 256 | if (socket_start(globals) == PDNS_OK) { 257 | socket_loop(globals); 258 | return socket_close(globals); 259 | } 260 | 261 | return PDNS_NO; 262 | } 263 | -------------------------------------------------------------------------------- /cmake/HeadersChecks.cmake: -------------------------------------------------------------------------------- 1 | include(CheckIncludeFiles) 2 | 3 | CHECK_INCLUDE_FILES(sys/types.h HAVE_SYS_TYPES_H) 4 | CHECK_INCLUDE_FILES(sys/param.h HAVE_SYS_PARAM_H) 5 | CHECK_INCLUDE_FILES(sys/time.h HAVE_SYS_TIME_H) 6 | CHECK_INCLUDE_FILES(sys/sockio.h HAVE_SYS_SOCKIO_H) 7 | CHECK_INCLUDE_FILES(sys/ioctl.h HAVE_SYS_IOCTL_H) 8 | CHECK_INCLUDE_FILES(sys/select.h HAVE_SYS_SELECT_H) 9 | CHECK_INCLUDE_FILES(sys/prctl.h HAVE_SYS_PRCTL_H) 10 | CHECK_INCLUDE_FILES(sys/stat.h HAVE_SYS_STAT_H) 11 | CHECK_INCLUDE_FILES(sys/wait.h HAVE_SYS_WAIT_H) 12 | CHECK_INCLUDE_FILES(sys/filio.h HAVE_SYS_FILIO_H) 13 | CHECK_INCLUDE_FILES(sys/file.h HAVE_SYS_FILE_H) 14 | CHECK_INCLUDE_FILES(sys/sysinfo.h HAVE_SYS_SYSINFO_H) 15 | CHECK_INCLUDE_FILES(sys/kstat.h HAVE_SYS_KSTAT_H) 16 | CHECK_INCLUDE_FILES(sys/signal.h HAVE_SYS_SIGNAL_H) 17 | CHECK_INCLUDE_FILES(sys/loadavg.h HAVE_SYS_LOADAVG_H) 18 | CHECK_INCLUDE_FILES(netdb.h HAVE_NETDB_H) 19 | CHECK_INCLUDE_FILES(ifaddrs.h HAVE_IFADDRS_H) 20 | CHECK_INCLUDE_FILES(inttypes.h HAVE_INTTYPES_H) 21 | CHECK_INCLUDE_FILES(arpa/inet.h HAVE_ARPA_INET_H) 22 | CHECK_INCLUDE_FILES(arpa/nameser.h HAVE_ARPA_NAMESER_H) 23 | CHECK_INCLUDE_FILES(unistd.h HAVE_UNISTD_H) 24 | CHECK_INCLUDE_FILES(syslog.h HAVE_SYSLOG_H) 25 | CHECK_INCLUDE_FILES(pwd.h HAVE_PWD_H) 26 | CHECK_INCLUDE_FILES(grp.h HAVE_GRP_H) 27 | CHECK_INCLUDE_FILES(malloc.h HAVE_MALLOC_H) 28 | CHECK_INCLUDE_FILES(alloca.h HAVE_ALLOCA_H) 29 | CHECK_INCLUDE_FILES(sys/malloc.h HAVE_SYS_MALLOC_H) 30 | CHECK_INCLUDE_FILES(io.h HAVE_IO_H) 31 | CHECK_INCLUDE_FILES(sched.h HAVE_SCHED_H) 32 | CHECK_INCLUDE_FILES(signal.h HAVE_SIGNAL_H) 33 | CHECK_INCLUDE_FILES(process.h HAVE_PROCESS_H) 34 | CHECK_INCLUDE_FILES(io.h HAVE_IO_H) 35 | CHECK_INCLUDE_FILES(dlfcn.h HAVE_DLFCN_H) 36 | CHECK_INCLUDE_FILES(net/if_dl.h HAVE_NET_DL_H) 37 | CHECK_INCLUDE_FILES(kvm.h HAVE_KVM_H) 38 | CHECK_INCLUDE_FILES(kstat.h HAVE_KSTAT_H) 39 | CHECK_INCLUDE_FILES(sys/param.h HAVE_SYS_PARAM_H) 40 | CHECK_INCLUDE_FILES(fcntl.h HAVE_FCNTL_H) 41 | CHECK_INCLUDE_FILES(utime.h HAVE_UTIME_H) 42 | CHECK_INCLUDE_FILES(sys/uio.h HAVE_SYS_UIO_H) 43 | CHECK_INCLUDE_FILES(limits.h HAVE_LIMITS_H) 44 | CHECK_INCLUDE_FILES(sys/socket.h HAVE_SYS_SOCKET_H) 45 | CHECK_INCLUDE_FILES(sys/mman.h HAVE_SYS_MMAN_H) 46 | 47 | CHECK_C_SOURCE_COMPILES("#include \n#include \n int main(void) { setpriority(PRIO_PROCESS, getpid(), -10); }" HAVE_SETPRIORITY) 48 | CHECK_C_SOURCE_COMPILES("#include \n#include \n int main(void) { struct rlimit lim = { RLIM_INFINITY, RLIM_INFINITY }; setrlimit(RLIMIT_MEMLOCK, &lim); }" HAVE_RLIMIT) 49 | CHECK_C_SOURCE_COMPILES("#include \n int main(void) { mlockall(MCL_CURRENT | MCL_FUTURE); }" HAVE_MLOCKALL) 50 | 51 | # OpenBSD fails with this test 52 | IF (NOT HAVE_SYS_SOCKET_H) 53 | CHECK_C_SOURCE_COMPILES("#include \n#include \nint main(void) { };" HAVE_SYS_SOCKET_H_TMP) 54 | IF ( HAVE_SYS_SOCKET_H_TMP ) 55 | SET(HAVE_SYS_SOCKET_H 1) 56 | ENDIF ( HAVE_SYS_SOCKET_H_TMP ) 57 | ENDIF (NOT HAVE_SYS_SOCKET_H) 58 | 59 | CHECK_INCLUDE_FILES(netinet/in.h HAVE_NETINET_IN_H) 60 | # OpenBSD fails with this test 61 | IF (NOT HAVE_NETINET_IN_H) 62 | CHECK_C_SOURCE_COMPILES("#include \n#include \nint main(void) { };" HAVE_NETINET_IN_H_TMP) 63 | IF ( HAVE_NETINET_IN_H_TMP ) 64 | SET(HAVE_NETINET_IN_H 1) 65 | ENDIF ( HAVE_NETINET_IN_H_TMP ) 66 | ENDIF (NOT HAVE_NETINET_IN_H) 67 | 68 | 69 | CHECK_INCLUDE_FILES(netinet/if.h HAVE_NETINET_IF_H) 70 | CHECK_INCLUDE_FILES(netinet/ip.h HAVE_NETINET_IP_H) 71 | CHECK_INCLUDE_FILES(netinet/in6.h HAVE_NETINET_IN6_H) 72 | CHECK_INCLUDE_FILES(netinet/ip6.h HAVE_NETINET_IP6_H) 73 | CHECK_INCLUDE_FILES(netinet/tcp.h HAVE_NETINET_TCP_H) 74 | 75 | 76 | # OpenBSD fails with this test 77 | IF (NOT HAVE_SYS_MMAN_H) 78 | CHECK_C_SOURCE_COMPILES("#include \n#include \nint main(void) { };" HAVE_SYS_MMAN_H_TMP) 79 | IF ( HAVE_SYS_MMAN_H_TMP ) 80 | SET(HAVE_SYS_MMAN_H 1) 81 | ENDIF ( HAVE_SYS_MMAN_H_TMP ) 82 | ENDIF (NOT HAVE_SYS_MMAN_H) 83 | 84 | 85 | CHECK_INCLUDE_FILES(sys/sysctl.h HAVE_SYS_SYSCTL_H) 86 | # Freebsd fails with this test 87 | IF (NOT HAVE_SYS_SYSCTL_H) 88 | CHECK_C_SOURCE_COMPILES("#include \n#include \nint main(void) { };" HAVE_SYS_SYSCTL_H_TMP) 89 | IF ( HAVE_SYS_SYSCTL_H_TMP ) 90 | SET(HAVE_SYS_SYSCTL_H 1) 91 | ENDIF ( HAVE_SYS_SYSCTL_H_TMP ) 92 | ENDIF (NOT HAVE_SYS_SYSCTL_H) 93 | 94 | IF (NOT HAVE_SYS_SYSCTL_H) 95 | CHECK_C_SOURCE_COMPILES("#include \n#include \n#include \nint main(void) { };" HAVE_SYS_SYSCTL_H_TMP2) 96 | IF ( HAVE_SYS_SYSCTL_H_TMP2 ) 97 | SET(HAVE_SYS_SYSCTL_H 1) 98 | ENDIF ( HAVE_SYS_SYSCTL_H_TMP2 ) 99 | ENDIF (NOT HAVE_SYS_SYSCTL_H) 100 | 101 | 102 | 103 | 104 | CHECK_INCLUDE_FILES(sys/resource.h HAVE_SYS_RESOURCE_H) 105 | # OpenBSD fails with sys/resource.h 106 | IF ( NOT HAVE_SYS_RESOURCE_H ) 107 | CHECK_C_SOURCE_COMPILES("#include \n#include \n#include \nint main(void) { return 0; };" HAVE_SYS_RESOURCE_H_TMP) 108 | IF ( HAVE_SYS_RESOURCE_H_TMP ) 109 | SET(HAVE_SYS_RESOURCE_H 1) 110 | ENDIF ( HAVE_SYS_RESOURCE_H_TMP ) 111 | ENDIF ( NOT HAVE_SYS_RESOURCE_H ) 112 | 113 | 114 | 115 | 116 | CHECK_INCLUDE_FILES(net/if.h HAVE_NET_IF_H) 117 | CHECK_INCLUDE_FILES(net/if_mib.h HAVE_NET_IF_MIB_H) 118 | CHECK_INCLUDE_FILES(net/if_arp.h HAVE_NET_IF_ARP_H) 119 | 120 | IF (NOT HAVE_NET_IF_H) 121 | CHECK_C_SOURCE_COMPILES("#include \n#include \n#include \nint main(void) { return 0; };" HAVE_NET_IF_H_TMP) 122 | IF ( HAVE_NET_IF_H_TMP ) 123 | SET(HAVE_NET_IF_H 1) 124 | ENDIF ( HAVE_NET_IF_H_TMP ) 125 | ENDIF (NOT HAVE_NET_IF_H) 126 | 127 | IF ( NOT HAVE_NET_IF_MIB_H ) 128 | CHECK_C_SOURCE_COMPILES("#include \n#include \n#include \n#include \nint main(void) { return 0; };" HAVE_NET_IF_MIB_H_TMP) 129 | IF ( HAVE_NET_IF_MIB_H_TMP ) 130 | SET(HAVE_NET_IF_MIB_H 1) 131 | ENDIF ( HAVE_NET_IF_MIB_H_TMP ) 132 | ENDIF ( NOT HAVE_NET_IF_MIB_H ) 133 | 134 | IF ( NOT HAVE_NET_IF_ARP_H ) 135 | CHECK_C_SOURCE_COMPILES("#include \n#include \n#include \n#include \nint main(void) { return 0; };" HAVE_NET_IF_ARP_H_TMP) 136 | IF ( HAVE_NET_IF_ARP_H_TMP ) 137 | SET(HAVE_NET_IF_ARP_H 1) 138 | ENDIF ( HAVE_NET_IF_ARP_H_TMP ) 139 | ENDIF ( NOT HAVE_NET_IF_ARP_H ) 140 | 141 | 142 | CHECK_C_SOURCE_COMPILES("#include \nint main(void) { struct tm t; localtime_r(0, &t); return 0; };" HAVE_LOCALTIME_R) 143 | CHECK_C_SOURCE_COMPILES("#include \nint main(void) { struct tm t; gmtime_r(0, &t); return 0; };" HAVE_GMTIME_R) 144 | 145 | CHECK_C_SOURCE_COMPILES("#include \nint main(void) { struct tm t; t.tm_gmtoff = 0; return 0; };" HAVE_STRUCT_TM_TM_GMTOFF) 146 | CHECK_C_SOURCE_COMPILES("#include \nint main(void) { struct tm t; t.__tm_gmtoff = 0; return 0; };" HAVE_STRUCT_TM___TM_GMTOFF) 147 | CHECK_C_SOURCE_COMPILES("#include \nint main(void) { struct tm t; t.tm_zone = \"\"; return 0; };" HAVE_STRUCT_TM_TM_ZONE) 148 | 149 | CHECK_C_SOURCE_COMPILES("#include \nint main(void) { int foo = AF_INET6; return 0; };" HAVE_AF_INET6) 150 | CHECK_C_SOURCE_COMPILES("#include \n#include \nint main(void) { int foo = PF_INET6; return 0; };" HAVE_PF_INET6) 151 | 152 | CHECK_C_SOURCE_COMPILES("#include \n#include \nint main(void) { struct sockaddr_in6 foo; return 0; };" HAVE_STRUCT_SOCKADDR_IN6) 153 | 154 | CHECK_C_SOURCE_COMPILES("#include \nint main(void) { struct iovec foo; return 0; };" HAVE_STRUCT_IOVEC) 155 | 156 | CHECK_C_SOURCE_COMPILES("#include \n#include \n#include \nint main(void) { struct addrinfo foo; return 0; };" HAVE_STRUCT_ADDRINFO) 157 | 158 | CHECK_C_SOURCE_COMPILES("#include \n#include \nint main(void) { long b=0; int sockfd=2; setsockopt(sockfd, SOL_SOCKET, SO_NONBLOCK, &b, sizeof(b)) return 0; };" HAVE_SETSOCKOPT_SO_NONBLOCK) 159 | 160 | CHECK_C_SOURCE_COMPILES("#include \n#include \nint main(void) { int sockfd; fcntl(sockfd, F_SETFL, O_NONBLOCK); return 0; };" HAVE_FCNTL_O_NONBLOCK) 161 | CHECK_C_SOURCE_COMPILES("#include \nint main(void) { sig_atomic_t foo; return 0; };" HAVE_SIG_ATOMIC_T) 162 | 163 | -------------------------------------------------------------------------------- /src/dnsmessage.pb-c.h: -------------------------------------------------------------------------------- 1 | /* Generated by the protocol buffer compiler. DO NOT EDIT! */ 2 | /* Generated from: dnsmessage.proto */ 3 | 4 | #ifndef PROTOBUF_C_dnsmessage_2eproto__INCLUDED 5 | #define PROTOBUF_C_dnsmessage_2eproto__INCLUDED 6 | 7 | #include 8 | 9 | PROTOBUF_C__BEGIN_DECLS 10 | #if PROTOBUF_C_VERSION_NUMBER < 1000000 11 | #error This file was generated by a newer version of protoc-c which is incompatible with your libprotobuf-c headers. Please update your headers. 12 | #elif 1002001 < PROTOBUF_C_MIN_COMPILER_VERSION 13 | #error This file was generated by an older version of protoc-c which is incompatible with your libprotobuf-c headers. Please regenerate this file with a newer version of protoc-c. 14 | #endif 15 | typedef struct _PBDNSMessage PBDNSMessage; 16 | typedef struct _PBDNSMessage__DNSQuestion PBDNSMessage__DNSQuestion; 17 | typedef struct _PBDNSMessage__DNSResponse PBDNSMessage__DNSResponse; 18 | typedef struct _PBDNSMessage__DNSResponse__DNSRR PBDNSMessage__DNSResponse__DNSRR; 19 | 20 | /* --- enums --- */ 21 | 22 | typedef enum _PBDNSMessage__Type { 23 | PBDNSMESSAGE__TYPE__DNSQueryType = 1, 24 | PBDNSMESSAGE__TYPE__DNSResponseType = 2, 25 | PBDNSMESSAGE__TYPE__DNSOutgoingQueryType = 3, 26 | PBDNSMESSAGE__TYPE__DNSIncomingResponseType = 4 PROTOBUF_C__FORCE_ENUM_TO_BE_INT_SIZE(PBDNSMESSAGE__TYPE) 27 | } PBDNSMessage__Type; 28 | typedef enum _PBDNSMessage__SocketFamily { 29 | /* 30 | * IPv4 (RFC 791) 31 | */ 32 | PBDNSMESSAGE__SOCKET_FAMILY__INET = 1, 33 | /* 34 | * IPv6 (RFC 2460) 35 | */ 36 | PBDNSMESSAGE__SOCKET_FAMILY__INET6 = 2 PROTOBUF_C__FORCE_ENUM_TO_BE_INT_SIZE(PBDNSMESSAGE__SOCKET_FAMILY) 37 | } PBDNSMessage__SocketFamily; 38 | typedef enum _PBDNSMessage__SocketProtocol { 39 | /* 40 | * User Datagram Protocol (RFC 768) 41 | */ 42 | PBDNSMESSAGE__SOCKET_PROTOCOL__UDP = 1, 43 | /* 44 | * Transmission Control Protocol (RFC 793) 45 | */ 46 | PBDNSMESSAGE__SOCKET_PROTOCOL__TCP = 2 PROTOBUF_C__FORCE_ENUM_TO_BE_INT_SIZE(PBDNSMESSAGE__SOCKET_PROTOCOL) 47 | } PBDNSMessage__SocketProtocol; 48 | 49 | /* --- messages --- */ 50 | 51 | struct _PBDNSMessage__DNSQuestion { 52 | ProtobufCMessage base; 53 | char *qname; 54 | protobuf_c_boolean has_qtype; 55 | uint32_t qtype; 56 | protobuf_c_boolean has_qclass; 57 | uint32_t qclass; 58 | }; 59 | #define PBDNSMESSAGE__DNSQUESTION__INIT \ 60 | { PROTOBUF_C_MESSAGE_INIT (&pbdnsmessage__dnsquestion__descriptor) \ 61 | , NULL, 0,0, 0,0 } 62 | 63 | struct _PBDNSMessage__DNSResponse__DNSRR { 64 | ProtobufCMessage base; 65 | char *name; 66 | protobuf_c_boolean has_type; 67 | uint32_t type; 68 | protobuf_c_boolean has_class_; 69 | uint32_t class_; 70 | protobuf_c_boolean has_ttl; 71 | uint32_t ttl; 72 | protobuf_c_boolean has_rdata; 73 | ProtobufCBinaryData rdata; 74 | }; 75 | #define PBDNSMESSAGE__DNSRESPONSE__DNSRR__INIT \ 76 | { PROTOBUF_C_MESSAGE_INIT (&pbdnsmessage__dnsresponse__dnsrr__descriptor) \ 77 | , NULL, 0,0, 0,0, 0,0, 0,{0,NULL} } 78 | 79 | struct _PBDNSMessage__DNSResponse { 80 | ProtobufCMessage base; 81 | protobuf_c_boolean has_rcode; 82 | uint32_t rcode; 83 | size_t n_rrs; 84 | PBDNSMessage__DNSResponse__DNSRR **rrs; 85 | /* 86 | * Filtering policy (RPZ or Lua) applied 87 | */ 88 | char *appliedpolicy; 89 | /* 90 | * Additional tags 91 | */ 92 | size_t n_tags; 93 | char **tags; 94 | /* 95 | * Time of the corresponding query reception (seconds since epoch) 96 | */ 97 | protobuf_c_boolean has_querytimesec; 98 | uint32_t querytimesec; 99 | /* 100 | * Time of the corresponding query reception (additional micro-seconds) 101 | */ 102 | protobuf_c_boolean has_querytimeusec; 103 | uint32_t querytimeusec; 104 | }; 105 | #define PBDNSMESSAGE__DNSRESPONSE__INIT \ 106 | { PROTOBUF_C_MESSAGE_INIT (&pbdnsmessage__dnsresponse__descriptor) \ 107 | , 0,0, 0,NULL, NULL, 0,NULL, 0,0, 0,0 } 108 | 109 | struct _PBDNSMessage { 110 | ProtobufCMessage base; 111 | PBDNSMessage__Type type; 112 | /* 113 | * UUID, shared by the query and the response 114 | */ 115 | protobuf_c_boolean has_messageid; 116 | ProtobufCBinaryData messageid; 117 | /* 118 | * UUID of the server emitting the protobuf message 119 | */ 120 | protobuf_c_boolean has_serveridentity; 121 | ProtobufCBinaryData serveridentity; 122 | protobuf_c_boolean has_socketfamily; 123 | PBDNSMessage__SocketFamily socketfamily; 124 | protobuf_c_boolean has_socketprotocol; 125 | PBDNSMessage__SocketProtocol socketprotocol; 126 | /* 127 | * DNS requestor (client) 128 | */ 129 | protobuf_c_boolean has_from; 130 | ProtobufCBinaryData from; 131 | /* 132 | * DNS responder (server) 133 | */ 134 | protobuf_c_boolean has_to; 135 | ProtobufCBinaryData to; 136 | /* 137 | * Size of the query or response on the wire 138 | */ 139 | protobuf_c_boolean has_inbytes; 140 | uint64_t inbytes; 141 | /* 142 | * Time of message reception (seconds since epoch) 143 | */ 144 | protobuf_c_boolean has_timesec; 145 | uint32_t timesec; 146 | /* 147 | * Time of message reception (additional micro-seconds) 148 | */ 149 | protobuf_c_boolean has_timeusec; 150 | uint32_t timeusec; 151 | /* 152 | * ID of the query/response as found in the DNS header 153 | */ 154 | protobuf_c_boolean has_id; 155 | uint32_t id; 156 | PBDNSMessage__DNSQuestion *question; 157 | PBDNSMessage__DNSResponse *response; 158 | /* 159 | * EDNS Client Subnet value 160 | */ 161 | protobuf_c_boolean has_originalrequestorsubnet; 162 | ProtobufCBinaryData originalrequestorsubnet; 163 | /* 164 | * Username of the requestor 165 | */ 166 | char *requestorid; 167 | /* 168 | * UUID of the incoming query that initiated this outgoing query or incoming response 169 | */ 170 | protobuf_c_boolean has_initialrequestid; 171 | ProtobufCBinaryData initialrequestid; 172 | }; 173 | #define PBDNSMESSAGE__INIT \ 174 | { PROTOBUF_C_MESSAGE_INIT (&pbdnsmessage__descriptor) \ 175 | , 0, 0,{0,NULL}, 0,{0,NULL}, 0,0, 0,0, 0,{0,NULL}, 0,{0,NULL}, 0,0, 0,0, 0,0, 0,0, NULL, NULL, 0,{0,NULL}, NULL, 0,{0,NULL} } 176 | 177 | /* PBDNSMessage__DNSQuestion methods */ 178 | void pbdnsmessage__dnsquestion__init(PBDNSMessage__DNSQuestion * message); 179 | /* PBDNSMessage__DNSResponse__DNSRR methods */ 180 | void pbdnsmessage__dnsresponse__dnsrr__init(PBDNSMessage__DNSResponse__DNSRR * message); 181 | /* PBDNSMessage__DNSResponse methods */ 182 | void pbdnsmessage__dnsresponse__init(PBDNSMessage__DNSResponse * message); 183 | /* PBDNSMessage methods */ 184 | void pbdnsmessage__init(PBDNSMessage * message); 185 | size_t pbdnsmessage__get_packed_size(const PBDNSMessage * message); 186 | size_t pbdnsmessage__pack(const PBDNSMessage * message, uint8_t * out); 187 | size_t pbdnsmessage__pack_to_buffer(const PBDNSMessage * message, ProtobufCBuffer * buffer); 188 | PBDNSMessage *pbdnsmessage__unpack(ProtobufCAllocator * allocator, size_t len, const uint8_t * data); 189 | void pbdnsmessage__free_unpacked(PBDNSMessage * message, ProtobufCAllocator * allocator); 190 | /* --- per-message closures --- */ 191 | 192 | typedef void (*PBDNSMessage__DNSQuestion_Closure) 193 | (const PBDNSMessage__DNSQuestion * message, void *closure_data); 194 | typedef void (*PBDNSMessage__DNSResponse__DNSRR_Closure) 195 | (const PBDNSMessage__DNSResponse__DNSRR * message, void *closure_data); 196 | typedef void (*PBDNSMessage__DNSResponse_Closure) 197 | (const PBDNSMessage__DNSResponse * message, void *closure_data); 198 | typedef void (*PBDNSMessage_Closure) 199 | (const PBDNSMessage * message, void *closure_data); 200 | 201 | /* --- services --- */ 202 | 203 | /* --- descriptors --- */ 204 | 205 | extern const ProtobufCMessageDescriptor pbdnsmessage__descriptor; 206 | extern const ProtobufCMessageDescriptor pbdnsmessage__dnsquestion__descriptor; 207 | extern const ProtobufCMessageDescriptor pbdnsmessage__dnsresponse__descriptor; 208 | extern const ProtobufCMessageDescriptor pbdnsmessage__dnsresponse__dnsrr__descriptor; 209 | extern const ProtobufCEnumDescriptor pbdnsmessage__type__descriptor; 210 | extern const ProtobufCEnumDescriptor pbdnsmessage__socket_family__descriptor; 211 | extern const ProtobufCEnumDescriptor pbdnsmessage__socket_protocol__descriptor; 212 | 213 | PROTOBUF_C__END_DECLS 214 | #endif /* PROTOBUF_C_dnsmessage_2eproto__INCLUDED */ 215 | -------------------------------------------------------------------------------- /src/pdns-logger-syslog.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Powerdns logger daemon 3 | * ---------------------- 4 | * 5 | * This Source Code Form is subject to the terms of the 6 | * Mozilla Public License, v. 2.0. 7 | * If a copy of the MPL was not distributed with this 8 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 9 | * 10 | * Copyright (C) 2017, Spamhaus Technology Ltd, London 11 | * 12 | * The Initial developer of the Original code is: 13 | * Massimo Cetra 14 | * 15 | */ 16 | 17 | #include 18 | #include "inih/ini.h" 19 | #include "pdns-logger.h" 20 | #include "dnsmessage.pb-c.h" 21 | 22 | static struct { 23 | int facility; 24 | const char *name; 25 | } facility_names[] = { 26 | { 27 | LOG_AUTH, "auth"}, { 28 | LOG_AUTHPRIV, "authpriv"}, { 29 | LOG_CRON, "cron"}, { 30 | LOG_DAEMON, "daemon"}, { 31 | LOG_FTP, "ftp"}, { 32 | LOG_KERN, "kern"}, { 33 | LOG_LOCAL0, "local0"}, { 34 | LOG_LOCAL1, "local1"}, { 35 | LOG_LOCAL2, "local2"}, { 36 | LOG_LOCAL3, "local3"}, { 37 | LOG_LOCAL4, "local4"}, { 38 | LOG_LOCAL5, "local5"}, { 39 | LOG_LOCAL6, "local6"}, { 40 | LOG_LOCAL7, "local7"}, { 41 | LOG_LPR, "lpr"}, { 42 | LOG_MAIL, "mail"}, { 43 | LOG_NEWS, "news"}, { 44 | LOG_SYSLOG, "syslog"}, { 45 | LOG_USER, "user"}, { 46 | LOG_UUCP, "uucp"},}; 47 | 48 | static char *ident = "pdns-logger"; 49 | static char *facility = "daemon"; 50 | static char rewrites_only = 1; 51 | static char disabled = 0; 52 | 53 | static int logfacility_lookup(const char *nfacility, int *logfacility) { 54 | unsigned int t; 55 | 56 | if (logfacility == NULL) { 57 | return 0; 58 | } 59 | 60 | for (t = 0; t < sizeof(facility_names) / sizeof(facility_names[0]); t++) { 61 | if (!strncmp(facility_names[t].name, nfacility, strlen(facility_names[t].name) + 1)) { 62 | *logfacility = facility_names[t].facility; 63 | return 1; 64 | } 65 | } 66 | 67 | *logfacility = LOG_DAEMON; 68 | 69 | return 0; 70 | } 71 | 72 | static int opt_handler(void *user, const char *section, const char *name, const char *value, int lineno) { 73 | (void) user; 74 | 75 | if (zstr(section) || zstr(name) || zstr(value)) { 76 | return 1; 77 | } 78 | 79 | if (!strncmp(section, "syslog", sizeof("syslog"))) { 80 | if (!strncmp(name, "ident", sizeof("ident"))) { 81 | } else if (!strncmp(name, "facility", sizeof("facility"))) { 82 | } else if (!strncmp(name, "level", sizeof("level"))) { 83 | } else if (!strncmp(name, "only-rewrites", sizeof("only-rewrites"))) { 84 | rewrites_only = atoi(value) ? 1 : 0; 85 | } else if (!strncmp(name, "disabled", sizeof("disabled"))) { 86 | disabled = atoi(value) ? 1 : 0; 87 | } else { 88 | fprintf(stderr, "Unmanaged INI option '%s' at line %d\n", name, lineno); 89 | } 90 | return 1; 91 | } 92 | 93 | return 1; 94 | } 95 | 96 | static pdns_status_t syslog_init(const char *inifile) { 97 | int logf; 98 | 99 | if (zstr(inifile)) { 100 | return PDNS_NO; 101 | } 102 | 103 | if (ini_parse(inifile, opt_handler, NULL) != 0) { 104 | fprintf(stderr, "syslog: Can't read .ini file: '%s'\n", inifile); 105 | return PDNS_NO; 106 | } 107 | 108 | if (disabled) { 109 | fprintf(stderr, "syslog: Disabled according to configuration\n"); 110 | return PDNS_OK; 111 | } 112 | 113 | logfacility_lookup(facility, &logf); 114 | 115 | openlog(!zstr(ident) ? ident : "pdns-logger", LOG_NDELAY | LOG_PID, logf); 116 | 117 | return PDNS_OK; 118 | } 119 | 120 | static pdns_status_t syslog_rotate(void) { 121 | return PDNS_OK; 122 | } 123 | 124 | static pdns_status_t syslog_stop(void) { 125 | closelog(); 126 | return PDNS_OK; 127 | } 128 | 129 | #define write_log() \ 130 | syslog(LOG_NOTICE, "%s", str); 131 | 132 | //fprintf(stderr, "%s\n", str); 133 | 134 | static pdns_status_t syslog_log(void *rawpb) { 135 | PBDNSMessage *msg = rawpb; 136 | PBDNSMessage__DNSQuestion *q; 137 | PBDNSMessage__DNSResponse *r; 138 | int sz, pc; 139 | char str[1024] = ""; 140 | char tmp[1024] = ""; 141 | 142 | if (disabled) { 143 | return PDNS_OK; 144 | } 145 | 146 | if (msg == NULL || msg->response == NULL) { 147 | return PDNS_OK; 148 | } 149 | 150 | if (rewrites_only != 0) { 151 | if (msg->response != NULL && zstr(msg->response->appliedpolicy)) { 152 | return PDNS_OK; 153 | } 154 | } 155 | 156 | sz = sizeof(str) - 1; 157 | 158 | if (msg->has_id) { 159 | pc = snprintf(tmp, sizeof(tmp), "QID: %d ", msg->id); 160 | strncat(str, tmp, sz); 161 | sz -= pc; 162 | } 163 | 164 | if (msg->has_from) { 165 | if (msg->from.len == 4) { 166 | char ip[INET6_ADDRSTRLEN]; 167 | 168 | inet_ntop(AF_INET, (const void *) msg->from.data, ip, sizeof(ip)); 169 | 170 | pc = snprintf(tmp, sizeof(tmp), "from: %s ", ip); 171 | strncat(str, tmp, sz); 172 | sz -= pc; 173 | } else if (msg->from.len == 16) { 174 | char ip[INET6_ADDRSTRLEN]; 175 | 176 | inet_ntop(AF_INET6, (const void *) msg->from.data, ip, sizeof(ip)); 177 | 178 | pc = snprintf(tmp, sizeof(tmp), "from: %s ", ip); 179 | strncat(str, tmp, sz); 180 | sz -= pc; 181 | } 182 | } 183 | 184 | if (msg->has_originalrequestorsubnet) { 185 | assert(0); 186 | } 187 | 188 | q = msg->question; 189 | if (q != NULL) { 190 | if (q->has_qtype) { 191 | pc = snprintf(tmp, sizeof(tmp), "qtype: %s ", pdns_logger_type2p(q->qtype)); 192 | strncat(str, tmp, sz); 193 | sz -= pc; 194 | } 195 | 196 | if (q->has_qclass) { 197 | pc = snprintf(tmp, sizeof(tmp), "qclass: %s ", pdns_logger_class2p(q->qclass)); 198 | strncat(str, tmp, sz); 199 | sz -= pc; 200 | } 201 | 202 | pc = snprintf(tmp, sizeof(tmp), "qname: %s ", q->qname); 203 | strncat(str, tmp, sz); 204 | sz -= pc; 205 | } 206 | 207 | r = msg->response; 208 | if (r != NULL) { 209 | if (r->has_rcode) { 210 | pc = snprintf(tmp, sizeof(tmp), "rcode: %s ", pdns_logger_rcode2p(r->rcode)); 211 | strncat(str, tmp, sz); 212 | sz -= pc; 213 | } 214 | 215 | pc = snprintf(tmp, sizeof(tmp), "rrcount: %zu ", r->n_rrs); 216 | strncat(str, tmp, sz); 217 | sz -= pc; 218 | 219 | if (!zstr(r->appliedpolicy)) { 220 | pc = snprintf(tmp, sizeof(tmp), "policy: '%s' ", r->appliedpolicy); 221 | strncat(str, tmp, sz); 222 | sz -= pc; 223 | } 224 | 225 | if (r->n_rrs > 0) { 226 | unsigned int t; 227 | PBDNSMessage__DNSResponse__DNSRR *rr; 228 | 229 | for (t = 1; t <= r->n_rrs; t++) { 230 | rr = r->rrs[t - 1]; 231 | 232 | pc = snprintf(tmp, sizeof(tmp), "rname-%d: %s ", t, rr->name); 233 | strncat(str, tmp, sz); 234 | sz -= pc; 235 | 236 | if (rr->has_type) { 237 | pc = snprintf(tmp, sizeof(tmp), "rtype-%d: %s ", t, pdns_logger_type2p(rr->type)); 238 | strncat(str, tmp, sz); 239 | sz -= pc; 240 | } 241 | 242 | if (rr->has_class_) { 243 | pc = snprintf(tmp, sizeof(tmp), "rclass-%d: %s ", t, pdns_logger_class2p(rr->class_)); 244 | strncat(str, tmp, sz); 245 | sz -= pc; 246 | } 247 | 248 | if (rr->has_ttl) { 249 | pc = snprintf(tmp, sizeof(tmp), "rttl-%d: %d ", t, rr->ttl); 250 | strncat(str, tmp, sz); 251 | sz -= pc; 252 | } 253 | 254 | if (rr->has_rdata) { 255 | if (rr->has_type && rr->type == 1 && rr->rdata.len == 4) { 256 | char ip[INET6_ADDRSTRLEN]; 257 | 258 | inet_ntop(AF_INET, (const void *) rr->rdata.data, ip, sizeof(ip)); 259 | 260 | pc = snprintf(tmp, sizeof(tmp), "rdata-%d: %s ", t, ip); 261 | strncat(str, tmp, sz); 262 | sz -= pc; 263 | } else if (rr->has_type && rr->type == 28 && rr->rdata.len == 16) { 264 | char ip[INET6_ADDRSTRLEN]; 265 | 266 | inet_ntop(AF_INET6, (const void *) rr->rdata.data, ip, sizeof(ip)); 267 | 268 | pc = snprintf(tmp, sizeof(tmp), "rdata-%d: %s ", t, ip); 269 | strncat(str, tmp, sz); 270 | sz -= pc; 271 | } else if (rr->has_type && ((rr->type == 2) || (rr->type == 5) || (rr->type == 6) || (rr->type == 15))) { 272 | /* CNAME works */ 273 | /* NS SOA MX do not seem to pass any data */ 274 | pc = snprintf(tmp, sizeof(tmp), "rdata-%d: %s ", t, rr->rdata.data); 275 | strncat(str, tmp, sz); 276 | sz -= pc; 277 | } else { 278 | pc = snprintf(tmp, sizeof(tmp), "rdata (not supported) "); 279 | strncat(str, tmp, sz); 280 | sz -= pc; 281 | } 282 | } 283 | 284 | write_log(); 285 | } 286 | } else { 287 | write_log(); 288 | } 289 | } else { 290 | write_log(); 291 | } 292 | 293 | return PDNS_OK; 294 | } 295 | 296 | pdns_logger_t syslog_engine = { 297 | syslog_init, 298 | syslog_rotate, 299 | syslog_stop, 300 | syslog_log 301 | }; 302 | -------------------------------------------------------------------------------- /src/pdns-logger-file.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Powerdns logger daemon 3 | * ---------------------- 4 | * 5 | * This Source Code Form is subject to the terms of the 6 | * Mozilla Public License, v. 2.0. 7 | * If a copy of the MPL was not distributed with this 8 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 9 | * 10 | * Copyright (C) 2017, Spamhaus Technology Ltd, London 11 | * 12 | * The Initial developer of the Original code is: 13 | * Massimo Cetra 14 | * 15 | */ 16 | 17 | #include "inih/ini.h" 18 | #include "pdns-logger.h" 19 | #include "dnsmessage.pb-c.h" 20 | 21 | static FILE *fp = NULL; 22 | static char *file = NULL; 23 | static int force_flush = 0; 24 | static char rewrites_only = 1; 25 | static char disabled = 0; 26 | 27 | static int opt_handler(void *user, const char *section, const char *name, const char *value, int lineno) { 28 | (void) user; 29 | 30 | if (zstr(section) || zstr(name) || zstr(value)) { 31 | return 1; 32 | } 33 | 34 | if (!strncmp(section, "logfile", sizeof("logfile"))) { 35 | if (!strncmp(name, "logfile", sizeof("logfile"))) { 36 | file = strdup(value); 37 | } else if (!strncmp(name, "force-flush", sizeof("force-flush"))) { 38 | force_flush = atoi(value) ? 1 : 0; 39 | } else if (!strncmp(name, "only-rewrites", sizeof("only-rewrites"))) { 40 | rewrites_only = atoi(value) ? 1 : 0; 41 | } else if (!strncmp(name, "disabled", sizeof("disabled"))) { 42 | disabled = atoi(value) ? 1 : 0; 43 | } else { 44 | fprintf(stderr, "Unmanaged INI option '%s' at line %d\n", name, lineno); 45 | } 46 | return 1; 47 | } 48 | 49 | return 1; 50 | } 51 | 52 | static pdns_status_t logfile_init(const char *inifile) { 53 | if (zstr(inifile)) { 54 | return PDNS_NO; 55 | } 56 | 57 | if (ini_parse(inifile, opt_handler, NULL) != 0) { 58 | fprintf(stderr, "logfile: Can't read .ini file: '%s'\n", inifile); 59 | return PDNS_NO; 60 | } 61 | 62 | if (disabled) { 63 | fprintf(stderr, "logfile: Disabled according to configuration\n"); 64 | return PDNS_OK; 65 | } 66 | 67 | if (zstr(file)) { 68 | fprintf(stderr, "logfile: no log file set. Disabling.\n"); 69 | return PDNS_NO; 70 | } 71 | 72 | fp = fopen(file, "a"); 73 | if (fp == NULL) { 74 | fprintf(stderr, "logfile: cannot open '%s' for writing\n", file); 75 | return PDNS_NO; 76 | } 77 | 78 | return PDNS_OK; 79 | } 80 | 81 | static pdns_status_t logfile_rotate(void) { 82 | if (fp != NULL) { 83 | fp = freopen(file, "a", fp); 84 | if (fp == NULL) { 85 | fprintf(stderr, "logfile: cannot open '%s' for writing\n", file); 86 | return PDNS_NO; 87 | } 88 | } 89 | 90 | return PDNS_OK; 91 | } 92 | 93 | static pdns_status_t logfile_stop(void) { 94 | safe_free(file); 95 | 96 | if (fp != NULL) { 97 | fclose(fp); 98 | } 99 | 100 | return PDNS_OK; 101 | } 102 | 103 | #define write_log() \ 104 | if (fp != NULL) { \ 105 | fprintf(fp, "%s\n", str); \ 106 | if (force_flush) { \ 107 | fflush(fp); \ 108 | } \ 109 | } 110 | 111 | //fprintf(stderr, "%s\n", str); 112 | 113 | static pdns_status_t logfile_log(void *rawpb) { 114 | PBDNSMessage *msg = rawpb; 115 | PBDNSMessage__DNSQuestion *q; 116 | PBDNSMessage__DNSResponse *r; 117 | int sz, pc; 118 | char str[4096] = ""; 119 | char tmp[4096] = ""; 120 | 121 | if (disabled) { 122 | return PDNS_OK; 123 | } 124 | 125 | if (msg == NULL || msg->response == NULL) { 126 | return PDNS_OK; 127 | } 128 | 129 | if (rewrites_only != 0) { 130 | if (msg->response != NULL && zstr(msg->response->appliedpolicy)) { 131 | return PDNS_OK; 132 | } 133 | } 134 | 135 | sz = sizeof(str) - 1; 136 | 137 | //adding timestampt to file log 138 | //format : Jan 01 2022 log... 139 | char mounthString[4]; 140 | const char * months[12] = {"Jan", "Feb", "Mar", "Apr", "May", "June", "July", "Aug", "Sep", "Oct", "Nov", "Dec"}; 141 | time_t rawtime; 142 | struct tm * timeinfo; 143 | 144 | time(&rawtime); 145 | timeinfo = localtime(&rawtime); 146 | 147 | //convert int to string mounth 148 | if (timeinfo->tm_mon >= 0 && timeinfo->tm_mon < 12 ){ 149 | snprintf(mounthString, 4, months[timeinfo->tm_mon]); 150 | }else{ 151 | snprintf(mounthString, 4, "N/A "); 152 | } 153 | pc=snprintf (tmp, sizeof(tmp), " %s %d %d %d:%d:%d ", mounthString, 154 | timeinfo->tm_mday , timeinfo->tm_year + 1900, 155 | timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec); 156 | 157 | strncat(str, tmp, sz); 158 | sz -= pc; 159 | 160 | if (msg->has_id) { 161 | pc = snprintf(tmp, sizeof(tmp), "QID: %d ", msg->id); 162 | strncat(str, tmp, sz); 163 | sz -= pc; 164 | } 165 | 166 | if (msg->has_from) { 167 | if (msg->from.len == 4) { 168 | char ip[INET6_ADDRSTRLEN]; 169 | 170 | inet_ntop(AF_INET, (const void *) msg->from.data, ip, sizeof(ip)); 171 | 172 | pc = snprintf(tmp, sizeof(tmp), "from: %s ", ip); 173 | strncat(str, tmp, sz); 174 | sz -= pc; 175 | } else if (msg->from.len == 16) { 176 | char ip[INET6_ADDRSTRLEN]; 177 | 178 | inet_ntop(AF_INET6, (const void *) msg->from.data, ip, sizeof(ip)); 179 | 180 | pc = snprintf(tmp, sizeof(tmp), "from: %s ", ip); 181 | strncat(str, tmp, sz); 182 | sz -= pc; 183 | } 184 | } 185 | 186 | if (msg->has_originalrequestorsubnet) { 187 | assert(0); 188 | } 189 | 190 | q = msg->question; 191 | if (q != NULL) { 192 | if (q->has_qtype) { 193 | pc = snprintf(tmp, sizeof(tmp), "qtype: %s ", pdns_logger_type2p(q->qtype)); 194 | strncat(str, tmp, sz); 195 | sz -= pc; 196 | } 197 | 198 | if (q->has_qclass) { 199 | pc = snprintf(tmp, sizeof(tmp), "qclass: %s ", pdns_logger_class2p(q->qclass)); 200 | strncat(str, tmp, sz); 201 | sz -= pc; 202 | } 203 | 204 | pc = snprintf(tmp, sizeof(tmp), "qname: %s ", q->qname); 205 | strncat(str, tmp, sz); 206 | sz -= pc; 207 | } 208 | 209 | r = msg->response; 210 | if (r != NULL) { 211 | if (r->has_rcode) { 212 | pc = snprintf(tmp, sizeof(tmp), "rcode: %s ", pdns_logger_rcode2p(r->rcode)); 213 | strncat(str, tmp, sz); 214 | sz -= pc; 215 | } 216 | 217 | pc = snprintf(tmp, sizeof(tmp), "rrcount: %zu ", r->n_rrs); 218 | strncat(str, tmp, sz); 219 | sz -= pc; 220 | 221 | if (!zstr(r->appliedpolicy)) { 222 | pc = snprintf(tmp, sizeof(tmp), "policy: '%s' ", r->appliedpolicy); 223 | strncat(str, tmp, sz); 224 | sz -= pc; 225 | } 226 | 227 | if (r->n_rrs > 0) { 228 | unsigned int t; 229 | PBDNSMessage__DNSResponse__DNSRR *rr; 230 | 231 | for (t = 1; t <= r->n_rrs; t++) { 232 | rr = r->rrs[t - 1]; 233 | 234 | pc = snprintf(tmp, sizeof(tmp), "rname-%d: %s ", t, rr->name); 235 | strncat(str, tmp, sz); 236 | sz -= pc; 237 | 238 | if (rr->has_type) { 239 | pc = snprintf(tmp, sizeof(tmp), "rtype-%d: %s ", t, pdns_logger_type2p(rr->type)); 240 | strncat(str, tmp, sz); 241 | sz -= pc; 242 | } 243 | 244 | if (rr->has_class_) { 245 | pc = snprintf(tmp, sizeof(tmp), "rclass-%d: %s ", t, pdns_logger_class2p(rr->class_)); 246 | strncat(str, tmp, sz); 247 | sz -= pc; 248 | } 249 | 250 | if (rr->has_ttl) { 251 | pc = snprintf(tmp, sizeof(tmp), "rttl-%d: %d ", t, rr->ttl); 252 | strncat(str, tmp, sz); 253 | sz -= pc; 254 | } 255 | 256 | if (rr->has_rdata) { 257 | if (rr->has_type && rr->type == 1 && rr->rdata.len == 4) { 258 | char ip[INET6_ADDRSTRLEN]; 259 | 260 | inet_ntop(AF_INET, (const void *) rr->rdata.data, ip, sizeof(ip)); 261 | 262 | pc = snprintf(tmp, sizeof(tmp), "rdata-%d: %s ", t, ip); 263 | strncat(str, tmp, sz); 264 | sz -= pc; 265 | } else if (rr->has_type && rr->type == 28 && rr->rdata.len == 16) { 266 | char ip[INET6_ADDRSTRLEN]; 267 | 268 | inet_ntop(AF_INET6, (const void *) rr->rdata.data, ip, sizeof(ip)); 269 | 270 | pc = snprintf(tmp, sizeof(tmp), "rdata-%d: %s ", t, ip); 271 | strncat(str, tmp, sz); 272 | sz -= pc; 273 | } else if (rr->has_type && ((rr->type == 2) || (rr->type == 5) || (rr->type == 6) || (rr->type == 15))) { 274 | /* CNAME works */ 275 | /* NS SOA MX do not seem to pass any data */ 276 | pc = snprintf(tmp, sizeof(tmp), "rdata-%d: %s ", t, rr->rdata.data); 277 | strncat(str, tmp, sz); 278 | sz -= pc; 279 | } else { 280 | pc = snprintf(tmp, sizeof(tmp), "rdata (not supported) "); 281 | strncat(str, tmp, sz); 282 | sz -= pc; 283 | } 284 | } 285 | 286 | write_log(); 287 | } 288 | } else { 289 | write_log(); 290 | } 291 | } else { 292 | write_log(); 293 | } 294 | 295 | return PDNS_OK; 296 | } 297 | 298 | pdns_logger_t logfile_engine = { 299 | logfile_init, 300 | logfile_rotate, 301 | logfile_stop, 302 | logfile_log 303 | }; 304 | -------------------------------------------------------------------------------- /src/pdns-logger-sqlite.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Powerdns logger daemon 3 | * ---------------------- 4 | * 5 | * This Source Code Form is subject to the terms of the 6 | * Mozilla Public License, v. 2.0. 7 | * If a copy of the MPL was not distributed with this 8 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. 9 | * 10 | * Copyright (C) 2017, Spamhaus Technology Ltd, London 11 | * 12 | * The Initial developer of the Original code is: 13 | * Massimo Cetra 14 | * 15 | */ 16 | 17 | #include 18 | #include 19 | 20 | #include "inih/ini.h" 21 | #include "pdns-logger.h" 22 | #include "dnsmessage.pb-c.h" 23 | 24 | static char *dbfile = NULL; 25 | static struct sqlite3 *db = NULL; 26 | static char rewrites_only = 1; 27 | static fifo_t *fifo = NULL; 28 | static pthread_t bgthread; 29 | static char bgrunning = 0; 30 | static char disabled = 0; 31 | static char autocommit = 1; 32 | 33 | /* *************************************************************************** */ 34 | /* *************************************************************************** */ 35 | /* *************************************************************************** */ 36 | 37 | /* *INDENT-OFF* */ 38 | 39 | #define SQL_CREATE_TABLE \ 40 | "CREATE TABLE IF NOT EXISTS logs ( " \ 41 | " ts INTEGER NOT NULL, " \ 42 | " querier VARCHAR(48), " \ 43 | " id INTEGER NOT NULL, " \ 44 | " qtype VARCHAR(10), " \ 45 | " qclass VARCHAR(10), " \ 46 | " qname VARCHAR(256), " \ 47 | " rcode VARCHAR(16), " \ 48 | " rcount INTEGER, " \ 49 | " rname VARCHAR(256), " \ 50 | " rtype VARCHAR(10), " \ 51 | " rclass VARCHAR(10), " \ 52 | " rttl INTEGER, " \ 53 | " rdata VARCHAR(256), " \ 54 | " policy VARCHAR(100)" \ 55 | ")" 56 | 57 | // EDNS 58 | 59 | #define SQL_INSERT \ 60 | "INSERT INTO logs (" \ 61 | " ts, querier, id, qtype, qclass, qname, rcode, rcount, rname, rtype, rclass, rttl, rdata, policy " \ 62 | ") VALUES (" \ 63 | " %ld, '%q', %d, '%q', '%q', '%q', '%q', %d, '%q', '%q', '%q', %ld, '%q', '%q' " \ 64 | ")" 65 | 66 | #define SQL_CREATE_INDEX \ 67 | "CREATE INDEX IF NOT EXISTS logs_ts_idx ON logs(ts);" \ 68 | "CREATE INDEX IF NOT EXISTS logs_querier_idx ON logs(querier);" \ 69 | "CREATE INDEX IF NOT EXISTS logs_qname_idx ON logs(qname);" \ 70 | "CREATE INDEX IF NOT EXISTS logs_policy_idx ON logs(policy);" 71 | 72 | /* *INDENT-ON* */ 73 | 74 | /* *************************************************************************** */ 75 | /* *************************************************************************** */ 76 | /* *************************************************************************** */ 77 | 78 | static pdns_status_t db_flush(void); 79 | 80 | static int counter = 0; 81 | static pdns_status_t db_exec(const char *sql, char log) { 82 | int res; 83 | char *zErr = NULL; 84 | 85 | counter++; 86 | 87 | res = sqlite3_exec(db, sql, NULL, NULL, &zErr); 88 | if (res != 0) { 89 | if (zErr != NULL) { 90 | if (log != 0) { 91 | fprintf(stderr, "Error executing query: %s (%s)\n", sql, zErr); 92 | } 93 | sqlite3_free(zErr); 94 | } 95 | return PDNS_NO; 96 | } 97 | 98 | /* From time to time, flush the tables... */ 99 | if (counter >= 50) { 100 | counter = 0; 101 | db_flush(); 102 | } 103 | 104 | if (zErr != NULL) { 105 | sqlite3_free(zErr); 106 | } 107 | 108 | return PDNS_OK; 109 | } 110 | 111 | static pdns_status_t db_flush(void) { 112 | if ( autocommit == 0 ) { 113 | if (!sqlite3_get_autocommit(db)) { 114 | printf("Flushing and committing SQLite3 DB\n"); 115 | db_exec("COMMIT", 1); 116 | } 117 | db_exec("BEGIN", 1); 118 | } 119 | 120 | return PDNS_OK; 121 | } 122 | 123 | static pdns_status_t db_open(const char *file) { 124 | int err; 125 | 126 | err = sqlite3_open_v2(file, &db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL); 127 | if (err != SQLITE_OK) { 128 | fprintf(stderr, "sqlite: cannot open sqlite database file '%s'\n", file); 129 | return PDNS_NO; 130 | } 131 | 132 | db_exec(SQL_CREATE_TABLE, 1); 133 | db_exec(SQL_CREATE_INDEX, 1); 134 | 135 | db_flush(); 136 | 137 | return PDNS_OK; 138 | } 139 | 140 | static pdns_status_t db_close(void) { 141 | sqlite3_close(db); 142 | return PDNS_OK; 143 | } 144 | 145 | /* *************************************************************************** */ 146 | /* *************************************************************************** */ 147 | /* *************************************************************************** */ 148 | 149 | static void *bg_thread_exec(void *data) { 150 | char *sql; 151 | 152 | (void) data; 153 | 154 | bgrunning = 1; 155 | 156 | while (bgrunning) { 157 | sql = fifo_pop_item(fifo); 158 | if (sql != NULL) { 159 | db_exec(sql, 1); 160 | sqlite3_free(sql); 161 | } 162 | } 163 | return NULL; 164 | } 165 | 166 | static void bg_thread_stop(void) { 167 | bgrunning = 0; 168 | pthread_join(bgthread, NULL); 169 | return; 170 | } 171 | 172 | static pdns_status_t bg_thread_start(void) { 173 | pthread_create(&bgthread, NULL, &bg_thread_exec, NULL); 174 | return PDNS_OK; 175 | } 176 | 177 | /* *************************************************************************** */ 178 | /* *************************************************************************** */ 179 | /* *************************************************************************** */ 180 | 181 | static int opt_handler(void *user, const char *section, const char *name, const char *value, int lineno) { 182 | (void) user; 183 | 184 | if (zstr(section) || zstr(name) || zstr(value)) { 185 | return 1; 186 | } 187 | 188 | if (!strncmp(section, "sqlite3", sizeof("sqlite3"))) { 189 | if (!strncmp(name, "dbfile", sizeof("dbfile"))) { 190 | dbfile = strdup(value); 191 | } else if (!strncmp(name, "only-rewrites", sizeof("only-rewrites"))) { 192 | rewrites_only = atoi(value) ? 1 : 0; 193 | } else if (!strncmp(name, "disabled", sizeof("disabled"))) { 194 | disabled = atoi(value) ? 1 : 0; 195 | } else if (!strncmp(name, "autocommit", sizeof("autocommit"))) { 196 | autocommit = atoi(value) ? 1 : 0; 197 | } else { 198 | fprintf(stderr, "Unmanaged INI option '%s' at line %d\n", name, lineno); 199 | } 200 | return 1; 201 | } 202 | return 1; 203 | } 204 | 205 | static pdns_status_t logsqlite_init(const char *inifile) { 206 | if (zstr(inifile)) { 207 | fprintf(stderr, "logsqlite: No inifile to read\n"); 208 | return PDNS_NO; 209 | } 210 | 211 | if (ini_parse(inifile, opt_handler, NULL) != 0) { 212 | fprintf(stderr, "logsqlite: Can't read .ini file: '%s'\n", inifile); 213 | return PDNS_NO; 214 | } 215 | 216 | if (disabled) { 217 | fprintf(stderr, "logsqlite: Disabled according to configuration\n"); 218 | return PDNS_OK; 219 | } 220 | 221 | if (zstr(dbfile)) { 222 | fprintf(stderr, "logsqlite: DB file is not set\n"); 223 | return PDNS_NO; 224 | } 225 | 226 | fifo = fifo_init(); 227 | bg_thread_start(); 228 | 229 | return db_open(dbfile); 230 | } 231 | 232 | static pdns_status_t logsqlite_rotate(void) { 233 | if (db != NULL) { 234 | fifo_lock(fifo); 235 | db_close(); 236 | db_open(dbfile); 237 | fifo_unlock(fifo); 238 | } 239 | return PDNS_OK; 240 | } 241 | 242 | static pdns_status_t logsqlite_stop(void) { 243 | bg_thread_stop(); 244 | return db_close(); 245 | } 246 | 247 | /* *INDENT-OFF* */ 248 | #define prepare_sql() \ 249 | sql = sqlite3_mprintf(SQL_INSERT, \ 250 | ts, \ 251 | !zstr(from) ? from : "", \ 252 | msgid, \ 253 | qtype ? qtype : "", \ 254 | qclass ? qclass : "", \ 255 | qname ? qname : "", \ 256 | rcode ? rcode : "", \ 257 | rcount, \ 258 | rname ? rname : "", \ 259 | rtype ? rtype : "", \ 260 | rclass ? rclass : "", \ 261 | rttl, \ 262 | rdata ? rdata : "", \ 263 | policy ? policy : "" \ 264 | ); 265 | /* *INDENT-ON* */ 266 | 267 | static pdns_status_t logsqlite_log(void *rawpb) { 268 | char *sql = NULL; 269 | char ip4[INET6_ADDRSTRLEN]; 270 | char ip6[INET6_ADDRSTRLEN]; 271 | PBDNSMessage *msg = rawpb; 272 | PBDNSMessage__DNSQuestion *q; 273 | PBDNSMessage__DNSResponse *r; 274 | int ts = 0; 275 | char from[INET6_ADDRSTRLEN] = ""; 276 | int msgid = 0; 277 | const char *qtype = NULL; 278 | const char *qclass = NULL; 279 | const char *qname = NULL; 280 | const char *rcode = NULL; 281 | int rcount = 0; 282 | char *rname = NULL; 283 | const char *rtype = NULL; 284 | const char *rclass = NULL; 285 | int rttl = 0; 286 | char *rdata = NULL; 287 | char *policy = NULL; 288 | 289 | 290 | if (disabled) { 291 | return PDNS_OK; 292 | } 293 | 294 | if (msg == NULL || msg->response == NULL) { 295 | return PDNS_OK; 296 | } 297 | 298 | if (rewrites_only != 0) { 299 | if (msg->response != NULL && zstr(msg->response->appliedpolicy)) { 300 | return PDNS_OK; 301 | } 302 | } 303 | 304 | if (msg->has_timesec) { 305 | ts = msg->timesec; 306 | } 307 | 308 | if (msg->has_from) { 309 | if (msg->from.len == 4) { 310 | inet_ntop(AF_INET, (const void *) msg->from.data, from, sizeof(from)); 311 | } else if (msg->from.len == 16) { 312 | inet_ntop(AF_INET6, (const void *) msg->from.data, from, sizeof(from)); 313 | } 314 | } 315 | 316 | if (msg->has_id) { 317 | msgid = msg->id; 318 | } 319 | 320 | q = msg->question; 321 | if (q != NULL) { 322 | if (q->has_qtype) { 323 | qtype = pdns_logger_type2p(q->qtype); 324 | } 325 | 326 | if (q->has_qclass) { 327 | qclass = pdns_logger_class2p(q->qclass); 328 | } 329 | 330 | qname = q->qname; 331 | } 332 | 333 | r = msg->response; 334 | if (r != NULL) { 335 | if (r->has_rcode) { 336 | rcode = pdns_logger_rcode2p(r->rcode); 337 | } 338 | 339 | if (!zstr(r->appliedpolicy)) { 340 | policy = r->appliedpolicy; 341 | } 342 | 343 | rcount = r->n_rrs; 344 | 345 | if (r->n_rrs > 0) { 346 | unsigned int t; 347 | PBDNSMessage__DNSResponse__DNSRR *rr; 348 | 349 | for (t = 1; t <= r->n_rrs; t++) { 350 | rr = r->rrs[t - 1]; 351 | rname = rr->name; 352 | 353 | if (rr->has_type) { 354 | rtype = pdns_logger_type2p(rr->type); 355 | } 356 | 357 | if (rr->has_class_) { 358 | rclass = pdns_logger_class2p(rr->class_); 359 | } 360 | 361 | if (rr->has_ttl) { 362 | rttl = rr->ttl; 363 | } 364 | 365 | if (rr->has_rdata) { 366 | if (rr->has_type && rr->type == 1 && rr->rdata.len == 4) { 367 | inet_ntop(AF_INET, (const void *) rr->rdata.data, ip4, sizeof(ip4)); 368 | rdata = ip4; 369 | } else if (rr->has_type && rr->type == 28 && rr->rdata.len == 16) { 370 | inet_ntop(AF_INET6, (const void *) rr->rdata.data, ip6, sizeof(ip6)); 371 | rdata = ip6; 372 | } else if (rr->has_type && ((rr->type == 2) || (rr->type == 5) || (rr->type == 6) || (rr->type == 15))) { 373 | rdata = (char *) rr->rdata.data; 374 | } else { 375 | rdata = "[Not Supported]"; 376 | } 377 | } 378 | prepare_sql(); 379 | fifo_push_item(fifo, sql); 380 | } 381 | } else { 382 | prepare_sql(); 383 | fifo_push_item(fifo, sql); 384 | } 385 | } else { 386 | prepare_sql(); 387 | fifo_push_item(fifo, sql); 388 | } 389 | 390 | return PDNS_OK; 391 | } 392 | 393 | pdns_logger_t sqlite_engine = { 394 | logsqlite_init, 395 | logsqlite_rotate, 396 | logsqlite_stop, 397 | logsqlite_log 398 | }; 399 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | Mozilla Public License Version 2.0 2 | ================================== 3 | 4 | 1. Definitions 5 | -------------- 6 | 7 | 1.1. "Contributor" 8 | means each individual or legal entity that creates, contributes to 9 | the creation of, or owns Covered Software. 10 | 11 | 1.2. "Contributor Version" 12 | means the combination of the Contributions of others (if any) used 13 | by a Contributor and that particular Contributor's Contribution. 14 | 15 | 1.3. "Contribution" 16 | means Covered Software of a particular Contributor. 17 | 18 | 1.4. "Covered Software" 19 | means Source Code Form to which the initial Contributor has attached 20 | the notice in Exhibit A, the Executable Form of such Source Code 21 | Form, and Modifications of such Source Code Form, in each case 22 | including portions thereof. 23 | 24 | 1.5. "Incompatible With Secondary Licenses" 25 | means 26 | 27 | (a) that the initial Contributor has attached the notice described 28 | in Exhibit B to the Covered Software; or 29 | 30 | (b) that the Covered Software was made available under the terms of 31 | version 1.1 or earlier of the License, but not also under the 32 | terms of a Secondary License. 33 | 34 | 1.6. "Executable Form" 35 | means any form of the work other than Source Code Form. 36 | 37 | 1.7. "Larger Work" 38 | means a work that combines Covered Software with other material, in 39 | a separate file or files, that is not Covered Software. 40 | 41 | 1.8. "License" 42 | means this document. 43 | 44 | 1.9. "Licensable" 45 | means having the right to grant, to the maximum extent possible, 46 | whether at the time of the initial grant or subsequently, any and 47 | all of the rights conveyed by this License. 48 | 49 | 1.10. "Modifications" 50 | means any of the following: 51 | 52 | (a) any file in Source Code Form that results from an addition to, 53 | deletion from, or modification of the contents of Covered 54 | Software; or 55 | 56 | (b) any new file in Source Code Form that contains any Covered 57 | Software. 58 | 59 | 1.11. "Patent Claims" of a Contributor 60 | means any patent claim(s), including without limitation, method, 61 | process, and apparatus claims, in any patent Licensable by such 62 | Contributor that would be infringed, but for the grant of the 63 | License, by the making, using, selling, offering for sale, having 64 | made, import, or transfer of either its Contributions or its 65 | Contributor Version. 66 | 67 | 1.12. "Secondary License" 68 | means either the GNU General Public License, Version 2.0, the GNU 69 | Lesser General Public License, Version 2.1, the GNU Affero General 70 | Public License, Version 3.0, or any later versions of those 71 | licenses. 72 | 73 | 1.13. "Source Code Form" 74 | means the form of the work preferred for making modifications. 75 | 76 | 1.14. "You" (or "Your") 77 | means an individual or a legal entity exercising rights under this 78 | License. For legal entities, "You" includes any entity that 79 | controls, is controlled by, or is under common control with You. For 80 | purposes of this definition, "control" means (a) the power, direct 81 | or indirect, to cause the direction or management of such entity, 82 | whether by contract or otherwise, or (b) ownership of more than 83 | fifty percent (50%) of the outstanding shares or beneficial 84 | ownership of such entity. 85 | 86 | 2. License Grants and Conditions 87 | -------------------------------- 88 | 89 | 2.1. Grants 90 | 91 | Each Contributor hereby grants You a world-wide, royalty-free, 92 | non-exclusive license: 93 | 94 | (a) under intellectual property rights (other than patent or trademark) 95 | Licensable by such Contributor to use, reproduce, make available, 96 | modify, display, perform, distribute, and otherwise exploit its 97 | Contributions, either on an unmodified basis, with Modifications, or 98 | as part of a Larger Work; and 99 | 100 | (b) under Patent Claims of such Contributor to make, use, sell, offer 101 | for sale, have made, import, and otherwise transfer either its 102 | Contributions or its Contributor Version. 103 | 104 | 2.2. Effective Date 105 | 106 | The licenses granted in Section 2.1 with respect to any Contribution 107 | become effective for each Contribution on the date the Contributor first 108 | distributes such Contribution. 109 | 110 | 2.3. Limitations on Grant Scope 111 | 112 | The licenses granted in this Section 2 are the only rights granted under 113 | this License. No additional rights or licenses will be implied from the 114 | distribution or licensing of Covered Software under this License. 115 | Notwithstanding Section 2.1(b) above, no patent license is granted by a 116 | Contributor: 117 | 118 | (a) for any code that a Contributor has removed from Covered Software; 119 | or 120 | 121 | (b) for infringements caused by: (i) Your and any other third party's 122 | modifications of Covered Software, or (ii) the combination of its 123 | Contributions with other software (except as part of its Contributor 124 | Version); or 125 | 126 | (c) under Patent Claims infringed by Covered Software in the absence of 127 | its Contributions. 128 | 129 | This License does not grant any rights in the trademarks, service marks, 130 | or logos of any Contributor (except as may be necessary to comply with 131 | the notice requirements in Section 3.4). 132 | 133 | 2.4. Subsequent Licenses 134 | 135 | No Contributor makes additional grants as a result of Your choice to 136 | distribute the Covered Software under a subsequent version of this 137 | License (see Section 10.2) or under the terms of a Secondary License (if 138 | permitted under the terms of Section 3.3). 139 | 140 | 2.5. Representation 141 | 142 | Each Contributor represents that the Contributor believes its 143 | Contributions are its original creation(s) or it has sufficient rights 144 | to grant the rights to its Contributions conveyed by this License. 145 | 146 | 2.6. Fair Use 147 | 148 | This License is not intended to limit any rights You have under 149 | applicable copyright doctrines of fair use, fair dealing, or other 150 | equivalents. 151 | 152 | 2.7. Conditions 153 | 154 | Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted 155 | in Section 2.1. 156 | 157 | 3. Responsibilities 158 | ------------------- 159 | 160 | 3.1. Distribution of Source Form 161 | 162 | All distribution of Covered Software in Source Code Form, including any 163 | Modifications that You create or to which You contribute, must be under 164 | the terms of this License. You must inform recipients that the Source 165 | Code Form of the Covered Software is governed by the terms of this 166 | License, and how they can obtain a copy of this License. You may not 167 | attempt to alter or restrict the recipients' rights in the Source Code 168 | Form. 169 | 170 | 3.2. Distribution of Executable Form 171 | 172 | If You distribute Covered Software in Executable Form then: 173 | 174 | (a) such Covered Software must also be made available in Source Code 175 | Form, as described in Section 3.1, and You must inform recipients of 176 | the Executable Form how they can obtain a copy of such Source Code 177 | Form by reasonable means in a timely manner, at a charge no more 178 | than the cost of distribution to the recipient; and 179 | 180 | (b) You may distribute such Executable Form under the terms of this 181 | License, or sublicense it under different terms, provided that the 182 | license for the Executable Form does not attempt to limit or alter 183 | the recipients' rights in the Source Code Form under this License. 184 | 185 | 3.3. Distribution of a Larger Work 186 | 187 | You may create and distribute a Larger Work under terms of Your choice, 188 | provided that You also comply with the requirements of this License for 189 | the Covered Software. If the Larger Work is a combination of Covered 190 | Software with a work governed by one or more Secondary Licenses, and the 191 | Covered Software is not Incompatible With Secondary Licenses, this 192 | License permits You to additionally distribute such Covered Software 193 | under the terms of such Secondary License(s), so that the recipient of 194 | the Larger Work may, at their option, further distribute the Covered 195 | Software under the terms of either this License or such Secondary 196 | License(s). 197 | 198 | 3.4. Notices 199 | 200 | You may not remove or alter the substance of any license notices 201 | (including copyright notices, patent notices, disclaimers of warranty, 202 | or limitations of liability) contained within the Source Code Form of 203 | the Covered Software, except that You may alter any license notices to 204 | the extent required to remedy known factual inaccuracies. 205 | 206 | 3.5. Application of Additional Terms 207 | 208 | You may choose to offer, and to charge a fee for, warranty, support, 209 | indemnity or liability obligations to one or more recipients of Covered 210 | Software. However, You may do so only on Your own behalf, and not on 211 | behalf of any Contributor. You must make it absolutely clear that any 212 | such warranty, support, indemnity, or liability obligation is offered by 213 | You alone, and You hereby agree to indemnify every Contributor for any 214 | liability incurred by such Contributor as a result of warranty, support, 215 | indemnity or liability terms You offer. You may include additional 216 | disclaimers of warranty and limitations of liability specific to any 217 | jurisdiction. 218 | 219 | 4. Inability to Comply Due to Statute or Regulation 220 | --------------------------------------------------- 221 | 222 | If it is impossible for You to comply with any of the terms of this 223 | License with respect to some or all of the Covered Software due to 224 | statute, judicial order, or regulation then You must: (a) comply with 225 | the terms of this License to the maximum extent possible; and (b) 226 | describe the limitations and the code they affect. Such description must 227 | be placed in a text file included with all distributions of the Covered 228 | Software under this License. Except to the extent prohibited by statute 229 | or regulation, such description must be sufficiently detailed for a 230 | recipient of ordinary skill to be able to understand it. 231 | 232 | 5. Termination 233 | -------------- 234 | 235 | 5.1. The rights granted under this License will terminate automatically 236 | if You fail to comply with any of its terms. However, if You become 237 | compliant, then the rights granted under this License from a particular 238 | Contributor are reinstated (a) provisionally, unless and until such 239 | Contributor explicitly and finally terminates Your grants, and (b) on an 240 | ongoing basis, if such Contributor fails to notify You of the 241 | non-compliance by some reasonable means prior to 60 days after You have 242 | come back into compliance. Moreover, Your grants from a particular 243 | Contributor are reinstated on an ongoing basis if such Contributor 244 | notifies You of the non-compliance by some reasonable means, this is the 245 | first time You have received notice of non-compliance with this License 246 | from such Contributor, and You become compliant prior to 30 days after 247 | Your receipt of the notice. 248 | 249 | 5.2. If You initiate litigation against any entity by asserting a patent 250 | infringement claim (excluding declaratory judgment actions, 251 | counter-claims, and cross-claims) alleging that a Contributor Version 252 | directly or indirectly infringes any patent, then the rights granted to 253 | You by any and all Contributors for the Covered Software under Section 254 | 2.1 of this License shall terminate. 255 | 256 | 5.3. In the event of termination under Sections 5.1 or 5.2 above, all 257 | end user license agreements (excluding distributors and resellers) which 258 | have been validly granted by You or Your distributors under this License 259 | prior to termination shall survive termination. 260 | 261 | ************************************************************************ 262 | * * 263 | * 6. Disclaimer of Warranty * 264 | * ------------------------- * 265 | * * 266 | * Covered Software is provided under this License on an "as is" * 267 | * basis, without warranty of any kind, either expressed, implied, or * 268 | * statutory, including, without limitation, warranties that the * 269 | * Covered Software is free of defects, merchantable, fit for a * 270 | * particular purpose or non-infringing. The entire risk as to the * 271 | * quality and performance of the Covered Software is with You. * 272 | * Should any Covered Software prove defective in any respect, You * 273 | * (not any Contributor) assume the cost of any necessary servicing, * 274 | * repair, or correction. This disclaimer of warranty constitutes an * 275 | * essential part of this License. No use of any Covered Software is * 276 | * authorized under this License except under this disclaimer. * 277 | * * 278 | ************************************************************************ 279 | 280 | ************************************************************************ 281 | * * 282 | * 7. Limitation of Liability * 283 | * -------------------------- * 284 | * * 285 | * Under no circumstances and under no legal theory, whether tort * 286 | * (including negligence), contract, or otherwise, shall any * 287 | * Contributor, or anyone who distributes Covered Software as * 288 | * permitted above, be liable to You for any direct, indirect, * 289 | * special, incidental, or consequential damages of any character * 290 | * including, without limitation, damages for lost profits, loss of * 291 | * goodwill, work stoppage, computer failure or malfunction, or any * 292 | * and all other commercial damages or losses, even if such party * 293 | * shall have been informed of the possibility of such damages. This * 294 | * limitation of liability shall not apply to liability for death or * 295 | * personal injury resulting from such party's negligence to the * 296 | * extent applicable law prohibits such limitation. Some * 297 | * jurisdictions do not allow the exclusion or limitation of * 298 | * incidental or consequential damages, so this exclusion and * 299 | * limitation may not apply to You. * 300 | * * 301 | ************************************************************************ 302 | 303 | 8. Litigation 304 | ------------- 305 | 306 | Any litigation relating to this License may be brought only in the 307 | courts of a jurisdiction where the defendant maintains its principal 308 | place of business and such litigation shall be governed by laws of that 309 | jurisdiction, without reference to its conflict-of-law provisions. 310 | Nothing in this Section shall prevent a party's ability to bring 311 | cross-claims or counter-claims. 312 | 313 | 9. Miscellaneous 314 | ---------------- 315 | 316 | This License represents the complete agreement concerning the subject 317 | matter hereof. If any provision of this License is held to be 318 | unenforceable, such provision shall be reformed only to the extent 319 | necessary to make it enforceable. Any law or regulation which provides 320 | that the language of a contract shall be construed against the drafter 321 | shall not be used to construe this License against a Contributor. 322 | 323 | 10. Versions of the License 324 | --------------------------- 325 | 326 | 10.1. New Versions 327 | 328 | Mozilla Foundation is the license steward. Except as provided in Section 329 | 10.3, no one other than the license steward has the right to modify or 330 | publish new versions of this License. Each version will be given a 331 | distinguishing version number. 332 | 333 | 10.2. Effect of New Versions 334 | 335 | You may distribute the Covered Software under the terms of the version 336 | of the License under which You originally received the Covered Software, 337 | or under the terms of any subsequent version published by the license 338 | steward. 339 | 340 | 10.3. Modified Versions 341 | 342 | If you create software not governed by this License, and you want to 343 | create a new license for such software, you may create and use a 344 | modified version of this License if you rename the license and remove 345 | any references to the name of the license steward (except to note that 346 | such modified license differs from this License). 347 | 348 | 10.4. Distributing Source Code Form that is Incompatible With Secondary 349 | Licenses 350 | 351 | If You choose to distribute Source Code Form that is Incompatible With 352 | Secondary Licenses under the terms of this version of the License, the 353 | notice described in Exhibit B of this License must be attached. 354 | 355 | Exhibit A - Source Code Form License Notice 356 | ------------------------------------------- 357 | 358 | This Source Code Form is subject to the terms of the Mozilla Public 359 | License, v. 2.0. If a copy of the MPL was not distributed with this 360 | file, You can obtain one at http://mozilla.org/MPL/2.0/. 361 | 362 | If it is not possible or desirable to put the notice in a particular 363 | file, then You may include the notice in a location (such as a LICENSE 364 | file in a relevant directory) where a recipient would be likely to look 365 | for such a notice. 366 | 367 | You may add additional accurate notices of copyright ownership. 368 | 369 | Exhibit B - "Incompatible With Secondary Licenses" Notice 370 | --------------------------------------------------------- 371 | 372 | This Source Code Form is "Incompatible With Secondary Licenses", as 373 | defined by the Mozilla Public License, v. 2.0. 374 | -------------------------------------------------------------------------------- /src/dnsmessage.pb-c.c: -------------------------------------------------------------------------------- 1 | /* Generated by the protocol buffer compiler. DO NOT EDIT! */ 2 | /* Generated from: dnsmessage.proto */ 3 | 4 | /* Do not generate deprecated warnings for self */ 5 | #ifndef PROTOBUF_C__NO_DEPRECATED 6 | #define PROTOBUF_C__NO_DEPRECATED 7 | #endif 8 | 9 | #include "dnsmessage.pb-c.h" 10 | void pbdnsmessage__dnsquestion__init(PBDNSMessage__DNSQuestion * message) { 11 | static PBDNSMessage__DNSQuestion init_value = PBDNSMESSAGE__DNSQUESTION__INIT; 12 | *message = init_value; 13 | } 14 | void pbdnsmessage__dnsresponse__dnsrr__init(PBDNSMessage__DNSResponse__DNSRR * message) { 15 | static PBDNSMessage__DNSResponse__DNSRR init_value = PBDNSMESSAGE__DNSRESPONSE__DNSRR__INIT; 16 | *message = init_value; 17 | } 18 | void pbdnsmessage__dnsresponse__init(PBDNSMessage__DNSResponse * message) { 19 | static PBDNSMessage__DNSResponse init_value = PBDNSMESSAGE__DNSRESPONSE__INIT; 20 | *message = init_value; 21 | } 22 | void pbdnsmessage__init(PBDNSMessage * message) { 23 | static PBDNSMessage init_value = PBDNSMESSAGE__INIT; 24 | *message = init_value; 25 | } 26 | size_t pbdnsmessage__get_packed_size(const PBDNSMessage * message) { 27 | assert(message->base.descriptor == &pbdnsmessage__descriptor); 28 | return protobuf_c_message_get_packed_size((const ProtobufCMessage *) (message)); 29 | } 30 | size_t pbdnsmessage__pack(const PBDNSMessage * message, uint8_t * out) { 31 | assert(message->base.descriptor == &pbdnsmessage__descriptor); 32 | return protobuf_c_message_pack((const ProtobufCMessage *) message, out); 33 | } 34 | size_t pbdnsmessage__pack_to_buffer(const PBDNSMessage * message, ProtobufCBuffer * buffer) { 35 | assert(message->base.descriptor == &pbdnsmessage__descriptor); 36 | return protobuf_c_message_pack_to_buffer((const ProtobufCMessage *) message, buffer); 37 | } 38 | PBDNSMessage *pbdnsmessage__unpack(ProtobufCAllocator * allocator, size_t len, const uint8_t * data) { 39 | return (PBDNSMessage *) 40 | protobuf_c_message_unpack(&pbdnsmessage__descriptor, allocator, len, data); 41 | } 42 | void pbdnsmessage__free_unpacked(PBDNSMessage * message, ProtobufCAllocator * allocator) { 43 | assert(message->base.descriptor == &pbdnsmessage__descriptor); 44 | protobuf_c_message_free_unpacked((ProtobufCMessage *) message, allocator); 45 | } 46 | 47 | static const ProtobufCFieldDescriptor pbdnsmessage__dnsquestion__field_descriptors[3] = { 48 | { 49 | "qName", 50 | 1, 51 | PROTOBUF_C_LABEL_OPTIONAL, 52 | PROTOBUF_C_TYPE_STRING, 53 | 0, /* quantifier_offset */ 54 | offsetof(PBDNSMessage__DNSQuestion, qname), 55 | NULL, 56 | NULL, 57 | 0, /* flags */ 58 | 0, NULL, NULL /* reserved1,reserved2, etc */ 59 | }, 60 | { 61 | "qType", 62 | 2, 63 | PROTOBUF_C_LABEL_OPTIONAL, 64 | PROTOBUF_C_TYPE_UINT32, 65 | offsetof(PBDNSMessage__DNSQuestion, has_qtype), 66 | offsetof(PBDNSMessage__DNSQuestion, qtype), 67 | NULL, 68 | NULL, 69 | 0, /* flags */ 70 | 0, NULL, NULL /* reserved1,reserved2, etc */ 71 | }, 72 | { 73 | "qClass", 74 | 3, 75 | PROTOBUF_C_LABEL_OPTIONAL, 76 | PROTOBUF_C_TYPE_UINT32, 77 | offsetof(PBDNSMessage__DNSQuestion, has_qclass), 78 | offsetof(PBDNSMessage__DNSQuestion, qclass), 79 | NULL, 80 | NULL, 81 | 0, /* flags */ 82 | 0, NULL, NULL /* reserved1,reserved2, etc */ 83 | }, 84 | }; 85 | static const unsigned pbdnsmessage__dnsquestion__field_indices_by_name[] = { 86 | 2, /* field[2] = qClass */ 87 | 0, /* field[0] = qName */ 88 | 1, /* field[1] = qType */ 89 | }; 90 | static const ProtobufCIntRange pbdnsmessage__dnsquestion__number_ranges[1 + 1] = { 91 | {1, 0}, 92 | {0, 3} 93 | }; 94 | const ProtobufCMessageDescriptor pbdnsmessage__dnsquestion__descriptor = { 95 | PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, 96 | "PBDNSMessage.DNSQuestion", 97 | "DNSQuestion", 98 | "PBDNSMessage__DNSQuestion", 99 | "", 100 | sizeof(PBDNSMessage__DNSQuestion), 101 | 3, 102 | pbdnsmessage__dnsquestion__field_descriptors, 103 | pbdnsmessage__dnsquestion__field_indices_by_name, 104 | 1, pbdnsmessage__dnsquestion__number_ranges, 105 | (ProtobufCMessageInit) pbdnsmessage__dnsquestion__init, 106 | NULL, NULL, NULL /* reserved[123] */ 107 | }; 108 | static const ProtobufCFieldDescriptor pbdnsmessage__dnsresponse__dnsrr__field_descriptors[5] = { 109 | { 110 | "name", 111 | 1, 112 | PROTOBUF_C_LABEL_OPTIONAL, 113 | PROTOBUF_C_TYPE_STRING, 114 | 0, /* quantifier_offset */ 115 | offsetof(PBDNSMessage__DNSResponse__DNSRR, name), 116 | NULL, 117 | NULL, 118 | 0, /* flags */ 119 | 0, NULL, NULL /* reserved1,reserved2, etc */ 120 | }, 121 | { 122 | "type", 123 | 2, 124 | PROTOBUF_C_LABEL_OPTIONAL, 125 | PROTOBUF_C_TYPE_UINT32, 126 | offsetof(PBDNSMessage__DNSResponse__DNSRR, has_type), 127 | offsetof(PBDNSMessage__DNSResponse__DNSRR, type), 128 | NULL, 129 | NULL, 130 | 0, /* flags */ 131 | 0, NULL, NULL /* reserved1,reserved2, etc */ 132 | }, 133 | { 134 | "class", 135 | 3, 136 | PROTOBUF_C_LABEL_OPTIONAL, 137 | PROTOBUF_C_TYPE_UINT32, 138 | offsetof(PBDNSMessage__DNSResponse__DNSRR, has_class_), 139 | offsetof(PBDNSMessage__DNSResponse__DNSRR, class_), 140 | NULL, 141 | NULL, 142 | 0, /* flags */ 143 | 0, NULL, NULL /* reserved1,reserved2, etc */ 144 | }, 145 | { 146 | "ttl", 147 | 4, 148 | PROTOBUF_C_LABEL_OPTIONAL, 149 | PROTOBUF_C_TYPE_UINT32, 150 | offsetof(PBDNSMessage__DNSResponse__DNSRR, has_ttl), 151 | offsetof(PBDNSMessage__DNSResponse__DNSRR, ttl), 152 | NULL, 153 | NULL, 154 | 0, /* flags */ 155 | 0, NULL, NULL /* reserved1,reserved2, etc */ 156 | }, 157 | { 158 | "rdata", 159 | 5, 160 | PROTOBUF_C_LABEL_OPTIONAL, 161 | PROTOBUF_C_TYPE_BYTES, 162 | offsetof(PBDNSMessage__DNSResponse__DNSRR, has_rdata), 163 | offsetof(PBDNSMessage__DNSResponse__DNSRR, rdata), 164 | NULL, 165 | NULL, 166 | 0, /* flags */ 167 | 0, NULL, NULL /* reserved1,reserved2, etc */ 168 | }, 169 | }; 170 | static const unsigned pbdnsmessage__dnsresponse__dnsrr__field_indices_by_name[] = { 171 | 2, /* field[2] = class */ 172 | 0, /* field[0] = name */ 173 | 4, /* field[4] = rdata */ 174 | 3, /* field[3] = ttl */ 175 | 1, /* field[1] = type */ 176 | }; 177 | static const ProtobufCIntRange pbdnsmessage__dnsresponse__dnsrr__number_ranges[1 + 1] = { 178 | {1, 0}, 179 | {0, 5} 180 | }; 181 | const ProtobufCMessageDescriptor pbdnsmessage__dnsresponse__dnsrr__descriptor = { 182 | PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, 183 | "PBDNSMessage.DNSResponse.DNSRR", 184 | "DNSRR", 185 | "PBDNSMessage__DNSResponse__DNSRR", 186 | "", 187 | sizeof(PBDNSMessage__DNSResponse__DNSRR), 188 | 5, 189 | pbdnsmessage__dnsresponse__dnsrr__field_descriptors, 190 | pbdnsmessage__dnsresponse__dnsrr__field_indices_by_name, 191 | 1, pbdnsmessage__dnsresponse__dnsrr__number_ranges, 192 | (ProtobufCMessageInit) pbdnsmessage__dnsresponse__dnsrr__init, 193 | NULL, NULL, NULL /* reserved[123] */ 194 | }; 195 | static const ProtobufCFieldDescriptor pbdnsmessage__dnsresponse__field_descriptors[6] = { 196 | { 197 | "rcode", 198 | 1, 199 | PROTOBUF_C_LABEL_OPTIONAL, 200 | PROTOBUF_C_TYPE_UINT32, 201 | offsetof(PBDNSMessage__DNSResponse, has_rcode), 202 | offsetof(PBDNSMessage__DNSResponse, rcode), 203 | NULL, 204 | NULL, 205 | 0, /* flags */ 206 | 0, NULL, NULL /* reserved1,reserved2, etc */ 207 | }, 208 | { 209 | "rrs", 210 | 2, 211 | PROTOBUF_C_LABEL_REPEATED, 212 | PROTOBUF_C_TYPE_MESSAGE, 213 | offsetof(PBDNSMessage__DNSResponse, n_rrs), 214 | offsetof(PBDNSMessage__DNSResponse, rrs), 215 | &pbdnsmessage__dnsresponse__dnsrr__descriptor, 216 | NULL, 217 | 0, /* flags */ 218 | 0, NULL, NULL /* reserved1,reserved2, etc */ 219 | }, 220 | { 221 | "appliedPolicy", 222 | 3, 223 | PROTOBUF_C_LABEL_OPTIONAL, 224 | PROTOBUF_C_TYPE_STRING, 225 | 0, /* quantifier_offset */ 226 | offsetof(PBDNSMessage__DNSResponse, appliedpolicy), 227 | NULL, 228 | NULL, 229 | 0, /* flags */ 230 | 0, NULL, NULL /* reserved1,reserved2, etc */ 231 | }, 232 | { 233 | "tags", 234 | 4, 235 | PROTOBUF_C_LABEL_REPEATED, 236 | PROTOBUF_C_TYPE_STRING, 237 | offsetof(PBDNSMessage__DNSResponse, n_tags), 238 | offsetof(PBDNSMessage__DNSResponse, tags), 239 | NULL, 240 | NULL, 241 | 0, /* flags */ 242 | 0, NULL, NULL /* reserved1,reserved2, etc */ 243 | }, 244 | { 245 | "queryTimeSec", 246 | 5, 247 | PROTOBUF_C_LABEL_OPTIONAL, 248 | PROTOBUF_C_TYPE_UINT32, 249 | offsetof(PBDNSMessage__DNSResponse, has_querytimesec), 250 | offsetof(PBDNSMessage__DNSResponse, querytimesec), 251 | NULL, 252 | NULL, 253 | 0, /* flags */ 254 | 0, NULL, NULL /* reserved1,reserved2, etc */ 255 | }, 256 | { 257 | "queryTimeUsec", 258 | 6, 259 | PROTOBUF_C_LABEL_OPTIONAL, 260 | PROTOBUF_C_TYPE_UINT32, 261 | offsetof(PBDNSMessage__DNSResponse, has_querytimeusec), 262 | offsetof(PBDNSMessage__DNSResponse, querytimeusec), 263 | NULL, 264 | NULL, 265 | 0, /* flags */ 266 | 0, NULL, NULL /* reserved1,reserved2, etc */ 267 | }, 268 | }; 269 | static const unsigned pbdnsmessage__dnsresponse__field_indices_by_name[] = { 270 | 2, /* field[2] = appliedPolicy */ 271 | 4, /* field[4] = queryTimeSec */ 272 | 5, /* field[5] = queryTimeUsec */ 273 | 0, /* field[0] = rcode */ 274 | 1, /* field[1] = rrs */ 275 | 3, /* field[3] = tags */ 276 | }; 277 | static const ProtobufCIntRange pbdnsmessage__dnsresponse__number_ranges[1 + 1] = { 278 | {1, 0}, 279 | {0, 6} 280 | }; 281 | const ProtobufCMessageDescriptor pbdnsmessage__dnsresponse__descriptor = { 282 | PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, 283 | "PBDNSMessage.DNSResponse", 284 | "DNSResponse", 285 | "PBDNSMessage__DNSResponse", 286 | "", 287 | sizeof(PBDNSMessage__DNSResponse), 288 | 6, 289 | pbdnsmessage__dnsresponse__field_descriptors, 290 | pbdnsmessage__dnsresponse__field_indices_by_name, 291 | 1, pbdnsmessage__dnsresponse__number_ranges, 292 | (ProtobufCMessageInit) pbdnsmessage__dnsresponse__init, 293 | NULL, NULL, NULL /* reserved[123] */ 294 | }; 295 | static const ProtobufCEnumValue pbdnsmessage__type__enum_values_by_number[4] = { 296 | {"DNSQueryType", "PBDNSMESSAGE__TYPE__DNSQueryType", 1}, 297 | {"DNSResponseType", "PBDNSMESSAGE__TYPE__DNSResponseType", 2}, 298 | {"DNSOutgoingQueryType", "PBDNSMESSAGE__TYPE__DNSOutgoingQueryType", 3}, 299 | {"DNSIncomingResponseType", "PBDNSMESSAGE__TYPE__DNSIncomingResponseType", 4}, 300 | }; 301 | static const ProtobufCIntRange pbdnsmessage__type__value_ranges[] = { 302 | {1, 0}, {0, 4} 303 | }; 304 | static const ProtobufCEnumValueIndex pbdnsmessage__type__enum_values_by_name[4] = { 305 | {"DNSIncomingResponseType", 3}, 306 | {"DNSOutgoingQueryType", 2}, 307 | {"DNSQueryType", 0}, 308 | {"DNSResponseType", 1}, 309 | }; 310 | const ProtobufCEnumDescriptor pbdnsmessage__type__descriptor = { 311 | PROTOBUF_C__ENUM_DESCRIPTOR_MAGIC, 312 | "PBDNSMessage.Type", 313 | "Type", 314 | "PBDNSMessage__Type", 315 | "", 316 | 4, 317 | pbdnsmessage__type__enum_values_by_number, 318 | 4, 319 | pbdnsmessage__type__enum_values_by_name, 320 | 1, 321 | pbdnsmessage__type__value_ranges, 322 | NULL, NULL, NULL, NULL /* reserved[1234] */ 323 | }; 324 | static const ProtobufCEnumValue pbdnsmessage__socket_family__enum_values_by_number[2] = { 325 | {"INET", "PBDNSMESSAGE__SOCKET_FAMILY__INET", 1}, 326 | {"INET6", "PBDNSMESSAGE__SOCKET_FAMILY__INET6", 2}, 327 | }; 328 | static const ProtobufCIntRange pbdnsmessage__socket_family__value_ranges[] = { 329 | {1, 0}, {0, 2} 330 | }; 331 | static const ProtobufCEnumValueIndex pbdnsmessage__socket_family__enum_values_by_name[2] = { 332 | {"INET", 0}, 333 | {"INET6", 1}, 334 | }; 335 | const ProtobufCEnumDescriptor pbdnsmessage__socket_family__descriptor = { 336 | PROTOBUF_C__ENUM_DESCRIPTOR_MAGIC, 337 | "PBDNSMessage.SocketFamily", 338 | "SocketFamily", 339 | "PBDNSMessage__SocketFamily", 340 | "", 341 | 2, 342 | pbdnsmessage__socket_family__enum_values_by_number, 343 | 2, 344 | pbdnsmessage__socket_family__enum_values_by_name, 345 | 1, 346 | pbdnsmessage__socket_family__value_ranges, 347 | NULL, NULL, NULL, NULL /* reserved[1234] */ 348 | }; 349 | static const ProtobufCEnumValue pbdnsmessage__socket_protocol__enum_values_by_number[2] = { 350 | {"UDP", "PBDNSMESSAGE__SOCKET_PROTOCOL__UDP", 1}, 351 | {"TCP", "PBDNSMESSAGE__SOCKET_PROTOCOL__TCP", 2}, 352 | }; 353 | static const ProtobufCIntRange pbdnsmessage__socket_protocol__value_ranges[] = { 354 | {1, 0}, {0, 2} 355 | }; 356 | static const ProtobufCEnumValueIndex pbdnsmessage__socket_protocol__enum_values_by_name[2] = { 357 | {"TCP", 1}, 358 | {"UDP", 0}, 359 | }; 360 | const ProtobufCEnumDescriptor pbdnsmessage__socket_protocol__descriptor = { 361 | PROTOBUF_C__ENUM_DESCRIPTOR_MAGIC, 362 | "PBDNSMessage.SocketProtocol", 363 | "SocketProtocol", 364 | "PBDNSMessage__SocketProtocol", 365 | "", 366 | 2, 367 | pbdnsmessage__socket_protocol__enum_values_by_number, 368 | 2, 369 | pbdnsmessage__socket_protocol__enum_values_by_name, 370 | 1, 371 | pbdnsmessage__socket_protocol__value_ranges, 372 | NULL, NULL, NULL, NULL /* reserved[1234] */ 373 | }; 374 | static const ProtobufCFieldDescriptor pbdnsmessage__field_descriptors[16] = { 375 | { 376 | "type", 377 | 1, 378 | PROTOBUF_C_LABEL_REQUIRED, 379 | PROTOBUF_C_TYPE_ENUM, 380 | 0, /* quantifier_offset */ 381 | offsetof(PBDNSMessage, type), 382 | &pbdnsmessage__type__descriptor, 383 | NULL, 384 | 0, /* flags */ 385 | 0, NULL, NULL /* reserved1,reserved2, etc */ 386 | }, 387 | { 388 | "messageId", 389 | 2, 390 | PROTOBUF_C_LABEL_OPTIONAL, 391 | PROTOBUF_C_TYPE_BYTES, 392 | offsetof(PBDNSMessage, has_messageid), 393 | offsetof(PBDNSMessage, messageid), 394 | NULL, 395 | NULL, 396 | 0, /* flags */ 397 | 0, NULL, NULL /* reserved1,reserved2, etc */ 398 | }, 399 | { 400 | "serverIdentity", 401 | 3, 402 | PROTOBUF_C_LABEL_OPTIONAL, 403 | PROTOBUF_C_TYPE_BYTES, 404 | offsetof(PBDNSMessage, has_serveridentity), 405 | offsetof(PBDNSMessage, serveridentity), 406 | NULL, 407 | NULL, 408 | 0, /* flags */ 409 | 0, NULL, NULL /* reserved1,reserved2, etc */ 410 | }, 411 | { 412 | "socketFamily", 413 | 4, 414 | PROTOBUF_C_LABEL_OPTIONAL, 415 | PROTOBUF_C_TYPE_ENUM, 416 | offsetof(PBDNSMessage, has_socketfamily), 417 | offsetof(PBDNSMessage, socketfamily), 418 | &pbdnsmessage__socket_family__descriptor, 419 | NULL, 420 | 0, /* flags */ 421 | 0, NULL, NULL /* reserved1,reserved2, etc */ 422 | }, 423 | { 424 | "socketProtocol", 425 | 5, 426 | PROTOBUF_C_LABEL_OPTIONAL, 427 | PROTOBUF_C_TYPE_ENUM, 428 | offsetof(PBDNSMessage, has_socketprotocol), 429 | offsetof(PBDNSMessage, socketprotocol), 430 | &pbdnsmessage__socket_protocol__descriptor, 431 | NULL, 432 | 0, /* flags */ 433 | 0, NULL, NULL /* reserved1,reserved2, etc */ 434 | }, 435 | { 436 | "from", 437 | 6, 438 | PROTOBUF_C_LABEL_OPTIONAL, 439 | PROTOBUF_C_TYPE_BYTES, 440 | offsetof(PBDNSMessage, has_from), 441 | offsetof(PBDNSMessage, from), 442 | NULL, 443 | NULL, 444 | 0, /* flags */ 445 | 0, NULL, NULL /* reserved1,reserved2, etc */ 446 | }, 447 | { 448 | "to", 449 | 7, 450 | PROTOBUF_C_LABEL_OPTIONAL, 451 | PROTOBUF_C_TYPE_BYTES, 452 | offsetof(PBDNSMessage, has_to), 453 | offsetof(PBDNSMessage, to), 454 | NULL, 455 | NULL, 456 | 0, /* flags */ 457 | 0, NULL, NULL /* reserved1,reserved2, etc */ 458 | }, 459 | { 460 | "inBytes", 461 | 8, 462 | PROTOBUF_C_LABEL_OPTIONAL, 463 | PROTOBUF_C_TYPE_UINT64, 464 | offsetof(PBDNSMessage, has_inbytes), 465 | offsetof(PBDNSMessage, inbytes), 466 | NULL, 467 | NULL, 468 | 0, /* flags */ 469 | 0, NULL, NULL /* reserved1,reserved2, etc */ 470 | }, 471 | { 472 | "timeSec", 473 | 9, 474 | PROTOBUF_C_LABEL_OPTIONAL, 475 | PROTOBUF_C_TYPE_UINT32, 476 | offsetof(PBDNSMessage, has_timesec), 477 | offsetof(PBDNSMessage, timesec), 478 | NULL, 479 | NULL, 480 | 0, /* flags */ 481 | 0, NULL, NULL /* reserved1,reserved2, etc */ 482 | }, 483 | { 484 | "timeUsec", 485 | 10, 486 | PROTOBUF_C_LABEL_OPTIONAL, 487 | PROTOBUF_C_TYPE_UINT32, 488 | offsetof(PBDNSMessage, has_timeusec), 489 | offsetof(PBDNSMessage, timeusec), 490 | NULL, 491 | NULL, 492 | 0, /* flags */ 493 | 0, NULL, NULL /* reserved1,reserved2, etc */ 494 | }, 495 | { 496 | "id", 497 | 11, 498 | PROTOBUF_C_LABEL_OPTIONAL, 499 | PROTOBUF_C_TYPE_UINT32, 500 | offsetof(PBDNSMessage, has_id), 501 | offsetof(PBDNSMessage, id), 502 | NULL, 503 | NULL, 504 | 0, /* flags */ 505 | 0, NULL, NULL /* reserved1,reserved2, etc */ 506 | }, 507 | { 508 | "question", 509 | 12, 510 | PROTOBUF_C_LABEL_OPTIONAL, 511 | PROTOBUF_C_TYPE_MESSAGE, 512 | 0, /* quantifier_offset */ 513 | offsetof(PBDNSMessage, question), 514 | &pbdnsmessage__dnsquestion__descriptor, 515 | NULL, 516 | 0, /* flags */ 517 | 0, NULL, NULL /* reserved1,reserved2, etc */ 518 | }, 519 | { 520 | "response", 521 | 13, 522 | PROTOBUF_C_LABEL_OPTIONAL, 523 | PROTOBUF_C_TYPE_MESSAGE, 524 | 0, /* quantifier_offset */ 525 | offsetof(PBDNSMessage, response), 526 | &pbdnsmessage__dnsresponse__descriptor, 527 | NULL, 528 | 0, /* flags */ 529 | 0, NULL, NULL /* reserved1,reserved2, etc */ 530 | }, 531 | { 532 | "originalRequestorSubnet", 533 | 14, 534 | PROTOBUF_C_LABEL_OPTIONAL, 535 | PROTOBUF_C_TYPE_BYTES, 536 | offsetof(PBDNSMessage, has_originalrequestorsubnet), 537 | offsetof(PBDNSMessage, originalrequestorsubnet), 538 | NULL, 539 | NULL, 540 | 0, /* flags */ 541 | 0, NULL, NULL /* reserved1,reserved2, etc */ 542 | }, 543 | { 544 | "requestorId", 545 | 15, 546 | PROTOBUF_C_LABEL_OPTIONAL, 547 | PROTOBUF_C_TYPE_STRING, 548 | 0, /* quantifier_offset */ 549 | offsetof(PBDNSMessage, requestorid), 550 | NULL, 551 | NULL, 552 | 0, /* flags */ 553 | 0, NULL, NULL /* reserved1,reserved2, etc */ 554 | }, 555 | { 556 | "initialRequestId", 557 | 16, 558 | PROTOBUF_C_LABEL_OPTIONAL, 559 | PROTOBUF_C_TYPE_BYTES, 560 | offsetof(PBDNSMessage, has_initialrequestid), 561 | offsetof(PBDNSMessage, initialrequestid), 562 | NULL, 563 | NULL, 564 | 0, /* flags */ 565 | 0, NULL, NULL /* reserved1,reserved2, etc */ 566 | }, 567 | }; 568 | static const unsigned pbdnsmessage__field_indices_by_name[] = { 569 | 5, /* field[5] = from */ 570 | 10, /* field[10] = id */ 571 | 7, /* field[7] = inBytes */ 572 | 15, /* field[15] = initialRequestId */ 573 | 1, /* field[1] = messageId */ 574 | 13, /* field[13] = originalRequestorSubnet */ 575 | 11, /* field[11] = question */ 576 | 14, /* field[14] = requestorId */ 577 | 12, /* field[12] = response */ 578 | 2, /* field[2] = serverIdentity */ 579 | 3, /* field[3] = socketFamily */ 580 | 4, /* field[4] = socketProtocol */ 581 | 8, /* field[8] = timeSec */ 582 | 9, /* field[9] = timeUsec */ 583 | 6, /* field[6] = to */ 584 | 0, /* field[0] = type */ 585 | }; 586 | static const ProtobufCIntRange pbdnsmessage__number_ranges[1 + 1] = { 587 | {1, 0}, 588 | {0, 16} 589 | }; 590 | const ProtobufCMessageDescriptor pbdnsmessage__descriptor = { 591 | PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, 592 | "PBDNSMessage", 593 | "PBDNSMessage", 594 | "PBDNSMessage", 595 | "", 596 | sizeof(PBDNSMessage), 597 | 16, 598 | pbdnsmessage__field_descriptors, 599 | pbdnsmessage__field_indices_by_name, 600 | 1, pbdnsmessage__number_ranges, 601 | (ProtobufCMessageInit) pbdnsmessage__init, 602 | NULL, NULL, NULL /* reserved[123] */ 603 | }; 604 | --------------------------------------------------------------------------------