summaryrefslogtreecommitdiffstats
path: root/doc/devel
diff options
context:
space:
mode:
Diffstat (limited to 'doc/devel')
-rw-r--r--doc/devel/Doxyfile2850
-rw-r--r--doc/devel/Doxyfile-xml7
-rw-r--r--doc/devel/Makefile.am25
-rw-r--r--doc/devel/Makefile.in566
-rw-r--r--doc/devel/README5
-rw-r--r--doc/devel/bison.dox450
-rw-r--r--doc/devel/config-backend.dox121
-rw-r--r--doc/devel/congestion-handling.dox452
-rw-r--r--doc/devel/contribute.dox16
-rw-r--r--doc/devel/cross-compile.dox226
-rw-r--r--doc/devel/debug.dox26
-rw-r--r--doc/devel/doc.dox86
-rw-r--r--doc/devel/fuzz.dox303
-rw-r--r--doc/devel/mainpage.dox160
-rw-r--r--doc/devel/performance.dox15
-rw-r--r--doc/devel/qa.dox52
-rw-r--r--doc/devel/terminology.dox28
-rw-r--r--doc/devel/unit-tests.dox613
18 files changed, 6001 insertions, 0 deletions
diff --git a/doc/devel/Doxyfile b/doc/devel/Doxyfile
new file mode 100644
index 0000000..967d656
--- /dev/null
+++ b/doc/devel/Doxyfile
@@ -0,0 +1,2850 @@
+# Doxyfile 1.10.0
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project.
+#
+# All text after a double hash (##) is considered a comment and is placed in
+# front of the TAG it is preceding.
+#
+# All text after a single hash (#) is considered a comment and will be ignored.
+# The format is:
+# TAG = value [value, ...]
+# For lists, items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (\" \").
+#
+# Note:
+#
+# Use doxygen to compare the used configuration file with the template
+# configuration file:
+# doxygen -x [configFile]
+# Use doxygen to compare the used configuration file with the template
+# configuration file without replacing the environment variables or CMake type
+# replacement variables:
+# doxygen -x_noenv [configFile]
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the configuration
+# file that follow. The default is UTF-8 which is also the encoding used for all
+# text before the first occurrence of this tag. Doxygen uses libiconv (or the
+# iconv built into libc) for the transcoding. See
+# https://www.gnu.org/software/libiconv/ for the list of possible encodings.
+# The default value is: UTF-8.
+
+DOXYFILE_ENCODING = UTF-8
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by
+# double-quotes, unless you are using Doxywizard) that should identify the
+# project for which the documentation is generated. This name is used in the
+# title of most generated pages and in a few other places.
+# The default value is: My Project.
+
+PROJECT_NAME = Kea
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number. This
+# could be handy for archiving the generated documentation or if some version
+# control system is used.
+
+PROJECT_NUMBER =
+
+# Using the PROJECT_BRIEF tag one can provide an optional one line description
+# for a project that appears at the top of each page and should give viewer a
+# quick idea about the purpose of the project. Keep the description short.
+
+PROJECT_BRIEF =
+
+# With the PROJECT_LOGO tag one can specify a logo or an icon that is included
+# in the documentation. The maximum height of the logo should not exceed 55
+# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy
+# the logo to the output directory.
+
+PROJECT_LOGO = ../images/kea-logo-100x70.png
+
+# With the PROJECT_ICON tag one can specify an icon that is included in the tabs
+# when the HTML document is shown. Doxygen will copy the logo to the output
+# directory.
+
+PROJECT_ICON =
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path
+# into which the generated documentation will be written. If a relative path is
+# entered, it will be relative to the location where doxygen was started. If
+# left blank the current directory will be used.
+
+OUTPUT_DIRECTORY = html
+
+# If the CREATE_SUBDIRS tag is set to YES then doxygen will create up to 4096
+# sub-directories (in 2 levels) under the output directory of each output format
+# and will distribute the generated files over these directories. Enabling this
+# option can be useful when feeding doxygen a huge amount of source files, where
+# putting all generated files in the same directory would otherwise causes
+# performance problems for the file system. Adapt CREATE_SUBDIRS_LEVEL to
+# control the number of sub-directories.
+# The default value is: NO.
+
+CREATE_SUBDIRS = YES
+
+# Controls the number of sub-directories that will be created when
+# CREATE_SUBDIRS tag is set to YES. Level 0 represents 16 directories, and every
+# level increment doubles the number of directories, resulting in 4096
+# directories at level 8 which is the default and also the maximum value. The
+# sub-directories are organized in 2 levels, the first level always has a fixed
+# number of 16 directories.
+# Minimum value: 0, maximum value: 8, default value: 8.
+# This tag requires that the tag CREATE_SUBDIRS is set to YES.
+
+CREATE_SUBDIRS_LEVEL = 8
+
+# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII
+# characters to appear in the names of generated files. If set to NO, non-ASCII
+# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode
+# U+3044.
+# The default value is: NO.
+
+ALLOW_UNICODE_NAMES = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Bulgarian,
+# Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, Dutch, English
+# (United States), Esperanto, Farsi (Persian), Finnish, French, German, Greek,
+# Hindi, Hungarian, Indonesian, Italian, Japanese, Japanese-en (Japanese with
+# English messages), Korean, Korean-en (Korean with English messages), Latvian,
+# Lithuanian, Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese,
+# Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish,
+# Swedish, Turkish, Ukrainian and Vietnamese.
+# The default value is: English.
+
+OUTPUT_LANGUAGE = English
+
+# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member
+# descriptions after the members that are listed in the file and class
+# documentation (similar to Javadoc). Set to NO to disable this.
+# The default value is: YES.
+
+BRIEF_MEMBER_DESC = YES
+
+# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief
+# description of a member or function before the detailed description
+#
+# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+# The default value is: YES.
+
+REPEAT_BRIEF = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator that is
+# used to form the text in various listings. Each string in this list, if found
+# as the leading text of the brief description, will be stripped from the text
+# and the result, after processing the whole list, is used as the annotated
+# text. Otherwise, the brief description is used as-is. If left blank, the
+# following values are used ($name is automatically replaced with the name of
+# the entity):The $name class, The $name widget, The $name file, is, provides,
+# specifies, contains, represents, a, an and the.
+
+ABBREVIATE_BRIEF =
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# doxygen will generate a detailed section even if there is only a brief
+# description.
+# The default value is: NO.
+
+ALWAYS_DETAILED_SEC = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+# The default value is: NO.
+
+INLINE_INHERITED_MEMB = NO
+
+# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path
+# before files name in the file list and in the header files. If set to NO the
+# shortest path that makes the file name unique will be used
+# The default value is: YES.
+
+FULL_PATH_NAMES = NO
+
+# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path.
+# Stripping is only done if one of the specified strings matches the left-hand
+# part of the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the path to
+# strip.
+#
+# Note that you can specify absolute paths here, but also relative paths, which
+# will be relative from the directory where doxygen is started.
+# This tag requires that the tag FULL_PATH_NAMES is set to YES.
+
+STRIP_FROM_PATH =
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the
+# path mentioned in the documentation of a class, which tells the reader which
+# header file to include in order to use a class. If left blank only the name of
+# the header file containing the class definition is used. Otherwise one should
+# specify the list of include paths that are normally passed to the compiler
+# using the -I flag.
+
+STRIP_FROM_INC_PATH =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but
+# less readable) file names. This can be useful is your file systems doesn't
+# support long names like on DOS, Mac, or CD-ROM.
+# The default value is: NO.
+
+SHORT_NAMES = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the
+# first line (until the first dot) of a Javadoc-style comment as the brief
+# description. If set to NO, the Javadoc-style will behave just like regular Qt-
+# style comments (thus requiring an explicit @brief command for a brief
+# description.)
+# The default value is: NO.
+
+JAVADOC_AUTOBRIEF = YES
+
+# If the JAVADOC_BANNER tag is set to YES then doxygen will interpret a line
+# such as
+# /***************
+# as being the beginning of a Javadoc-style comment "banner". If set to NO, the
+# Javadoc-style will behave just like regular comments and it will not be
+# interpreted by doxygen.
+# The default value is: NO.
+
+JAVADOC_BANNER = NO
+
+# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first
+# line (until the first dot) of a Qt-style comment as the brief description. If
+# set to NO, the Qt-style will behave just like regular Qt-style comments (thus
+# requiring an explicit \brief command for a brief description.)
+# The default value is: NO.
+
+QT_AUTOBRIEF = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a
+# multi-line C++ special comment block (i.e. a block of //! or /// comments) as
+# a brief description. This used to be the default behavior. The new default is
+# to treat a multi-line C++ comment block as a detailed description. Set this
+# tag to YES if you prefer the old behavior instead.
+#
+# Note that setting this tag to YES also means that rational rose comments are
+# not recognized any more.
+# The default value is: NO.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# By default Python docstrings are displayed as preformatted text and doxygen's
+# special commands cannot be used. By setting PYTHON_DOCSTRING to NO the
+# doxygen's special commands can be used and the contents of the docstring
+# documentation blocks is shown as doxygen documentation.
+# The default value is: YES.
+
+PYTHON_DOCSTRING = YES
+
+# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the
+# documentation from any documented member that it re-implements.
+# The default value is: YES.
+
+INHERIT_DOCS = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new
+# page for each member. If set to NO, the documentation of a member will be part
+# of the file/class/namespace that contains it.
+# The default value is: NO.
+
+SEPARATE_MEMBER_PAGES = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen
+# uses this value to replace tabs by spaces in code fragments.
+# Minimum value: 1, maximum value: 16, default value: 4.
+
+TAB_SIZE = 4
+
+# This tag can be used to specify a number of aliases that act as commands in
+# the documentation. An alias has the form:
+# name=value
+# For example adding
+# "sideeffect=@par Side Effects:^^"
+# will allow you to put the command \sideeffect (or @sideeffect) in the
+# documentation, which will result in a user-defined paragraph with heading
+# "Side Effects:". Note that you cannot put \n's in the value part of an alias
+# to insert newlines (in the resulting output). You can put ^^ in the value part
+# of an alias to insert a newline as if a physical newline was in the original
+# file. When you need a literal { or } or , in the value part of an alias you
+# have to escape them by means of a backslash (\), this can lead to conflicts
+# with the commands \{ and \} for these it is advised to use the version @{ and
+# @} or use a double escape (\\{ and \\})
+
+ALIASES =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
+# only. Doxygen will then generate output that is more tailored for C. For
+# instance, some of the names that are used will be different. The list of all
+# members will be omitted, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_FOR_C = NO
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or
+# Python sources only. Doxygen will then generate output that is more tailored
+# for that language. For instance, namespaces will be presented as packages,
+# qualified scopes will look different, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_JAVA = NO
+
+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
+# sources. Doxygen will then generate output that is tailored for Fortran.
+# The default value is: NO.
+
+OPTIMIZE_FOR_FORTRAN = NO
+
+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
+# sources. Doxygen will then generate output that is tailored for VHDL.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_VHDL = NO
+
+# Set the OPTIMIZE_OUTPUT_SLICE tag to YES if your project consists of Slice
+# sources only. Doxygen will then generate output that is more tailored for that
+# language. For instance, namespaces will be presented as modules, types will be
+# separated into more groups, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_SLICE = NO
+
+# Doxygen selects the parser to use depending on the extension of the files it
+# parses. With this tag you can assign which parser to use for a given
+# extension. Doxygen has a built-in mapping, but you can override or extend it
+# using this tag. The format is ext=language, where ext is a file extension, and
+# language is one of the parsers supported by doxygen: IDL, Java, JavaScript,
+# Csharp (C#), C, C++, Lex, D, PHP, md (Markdown), Objective-C, Python, Slice,
+# VHDL, Fortran (fixed format Fortran: FortranFixed, free formatted Fortran:
+# FortranFree, unknown formatted Fortran: Fortran. In the later case the parser
+# tries to guess whether the code is fixed or free formatted code, this is the
+# default for Fortran type files). For instance to make doxygen treat .inc files
+# as Fortran files (default is PHP), and .f files as C (default is Fortran),
+# use: inc=Fortran f=C.
+#
+# Note: For files without extension you can use no_extension as a placeholder.
+#
+# Note that for custom extensions you also need to set FILE_PATTERNS otherwise
+# the files are not read by doxygen. When specifying no_extension you should add
+# * to the FILE_PATTERNS.
+#
+# Note see also the list of default file extension mappings.
+
+EXTENSION_MAPPING =
+
+# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments
+# according to the Markdown format, which allows for more readable
+# documentation. See https://daringfireball.net/projects/markdown/ for details.
+# The output of markdown processing is further processed by doxygen, so you can
+# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in
+# case of backward compatibilities issues.
+# The default value is: YES.
+
+MARKDOWN_SUPPORT = YES
+
+# When the TOC_INCLUDE_HEADINGS tag is set to a non-zero value, all headings up
+# to that level are automatically included in the table of contents, even if
+# they do not have an id attribute.
+# Note: This feature currently applies only to Markdown headings.
+# Minimum value: 0, maximum value: 99, default value: 5.
+# This tag requires that the tag MARKDOWN_SUPPORT is set to YES.
+
+TOC_INCLUDE_HEADINGS = 5
+
+# The MARKDOWN_ID_STYLE tag can be used to specify the algorithm used to
+# generate identifiers for the Markdown headings. Note: Every identifier is
+# unique.
+# Possible values are: DOXYGEN use a fixed 'autotoc_md' string followed by a
+# sequence number starting at 0 and GITHUB use the lower case version of title
+# with any whitespace replaced by '-' and punctuation characters removed.
+# The default value is: DOXYGEN.
+# This tag requires that the tag MARKDOWN_SUPPORT is set to YES.
+
+MARKDOWN_ID_STYLE = DOXYGEN
+
+# When enabled doxygen tries to link words that correspond to documented
+# classes, or namespaces to their corresponding documentation. Such a link can
+# be prevented in individual cases by putting a % sign in front of the word or
+# globally by setting AUTOLINK_SUPPORT to NO.
+# The default value is: YES.
+
+AUTOLINK_SUPPORT = YES
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
+# to include (a tag file for) the STL sources as input, then you should set this
+# tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string);
+# versus func(std::string) {}). This also make the inheritance and collaboration
+# diagrams that involve STL classes more complete and accurate.
+# The default value is: NO.
+
+BUILTIN_STL_SUPPORT = YES
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+# The default value is: NO.
+
+CPP_CLI_SUPPORT = NO
+
+# Set the SIP_SUPPORT tag to YES if your project consists of sip (see:
+# https://www.riverbankcomputing.com/software/sip/intro) sources only. Doxygen
+# will parse them like normal C++ but will assume all classes use public instead
+# of private inheritance when no explicit protection keyword is present.
+# The default value is: NO.
+
+SIP_SUPPORT = NO
+
+# For Microsoft's IDL there are propget and propput attributes to indicate
+# getter and setter methods for a property. Setting this option to YES will make
+# doxygen to replace the get and set methods by a property in the documentation.
+# This will only work if the methods are indeed getting or setting a simple
+# type. If this is not the case, or you want to show the methods anyway, you
+# should set this option to NO.
+# The default value is: YES.
+
+IDL_PROPERTY_SUPPORT = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+# The default value is: NO.
+
+DISTRIBUTE_GROUP_DOC = NO
+
+# If one adds a struct or class to a group and this option is enabled, then also
+# any nested class or struct is added to the same group. By default this option
+# is disabled and one has to add nested compounds explicitly via \ingroup.
+# The default value is: NO.
+
+GROUP_NESTED_COMPOUNDS = NO
+
+# Set the SUBGROUPING tag to YES to allow class member groups of the same type
+# (for instance a group of public functions) to be put as a subgroup of that
+# type (e.g. under the Public Functions section). Set it to NO to prevent
+# subgrouping. Alternatively, this can be done per class using the
+# \nosubgrouping command.
+# The default value is: YES.
+
+SUBGROUPING = YES
+
+# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions
+# are shown inside the group in which they are included (e.g. using \ingroup)
+# instead of on a separate page (for HTML and Man pages) or section (for LaTeX
+# and RTF).
+#
+# Note that this feature does not work in combination with
+# SEPARATE_MEMBER_PAGES.
+# The default value is: NO.
+
+INLINE_GROUPED_CLASSES = NO
+
+# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions
+# with only public data fields or simple typedef fields will be shown inline in
+# the documentation of the scope in which they are defined (i.e. file,
+# namespace, or group documentation), provided this scope is documented. If set
+# to NO, structs, classes, and unions are shown on a separate page (for HTML and
+# Man pages) or section (for LaTeX and RTF).
+# The default value is: NO.
+
+INLINE_SIMPLE_STRUCTS = NO
+
+# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or
+# enum is documented as struct, union, or enum with the name of the typedef. So
+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
+# with name TypeT. When disabled the typedef will appear as a member of a file,
+# namespace, or class. And the struct will be named TypeS. This can typically be
+# useful for C code in case the coding convention dictates that all compound
+# types are typedef'ed and only the typedef is referenced, never the tag name.
+# The default value is: NO.
+
+TYPEDEF_HIDES_STRUCT = NO
+
+# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This
+# cache is used to resolve symbols given their name and scope. Since this can be
+# an expensive process and often the same symbol appears multiple times in the
+# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small
+# doxygen will become slower. If the cache is too large, memory is wasted. The
+# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range
+# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536
+# symbols. At the end of a run doxygen will report the cache usage and suggest
+# the optimal cache size from a speed point of view.
+# Minimum value: 0, maximum value: 9, default value: 0.
+
+LOOKUP_CACHE_SIZE = 0
+
+# The NUM_PROC_THREADS specifies the number of threads doxygen is allowed to use
+# during processing. When set to 0 doxygen will based this on the number of
+# cores available in the system. You can set it explicitly to a value larger
+# than 0 to get more control over the balance between CPU load and processing
+# speed. At this moment only the input processing can be done using multiple
+# threads. Since this is still an experimental feature the default is set to 1,
+# which effectively disables parallel processing. Please report any issues you
+# encounter. Generating dot graphs in parallel is controlled by the
+# DOT_NUM_THREADS setting.
+# Minimum value: 0, maximum value: 32, default value: 1.
+
+NUM_PROC_THREADS = 1
+
+# If the TIMESTAMP tag is set different from NO then each generated page will
+# contain the date or date and time when the page was generated. Setting this to
+# NO can help when comparing the output of multiple runs.
+# Possible values are: YES, NO, DATETIME and DATE.
+# The default value is: NO.
+
+TIMESTAMP = YES
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in
+# documentation are documented, even if no documentation was available. Private
+# class members and static file members will be hidden unless the
+# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES.
+# Note: This will also disable the warnings about undocumented members that are
+# normally produced when WARNINGS is set to YES.
+# The default value is: NO.
+
+EXTRACT_ALL = YES
+
+# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will
+# be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PRIVATE = NO
+
+# If the EXTRACT_PRIV_VIRTUAL tag is set to YES, documented private virtual
+# methods of a class will be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PRIV_VIRTUAL = NO
+
+# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal
+# scope will be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PACKAGE = NO
+
+# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be
+# included in the documentation.
+# The default value is: NO.
+
+EXTRACT_STATIC = NO
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined
+# locally in source files will be included in the documentation. If set to NO,
+# only classes defined in header files are included. Does not have any effect
+# for Java sources.
+# The default value is: YES.
+
+EXTRACT_LOCAL_CLASSES = YES
+
+# This flag is only useful for Objective-C code. If set to YES, local methods,
+# which are defined in the implementation section but not in the interface are
+# included in the documentation. If set to NO, only methods in the interface are
+# included.
+# The default value is: NO.
+
+EXTRACT_LOCAL_METHODS = NO
+
+# If this flag is set to YES, the members of anonymous namespaces will be
+# extracted and appear in the documentation as a namespace called
+# 'anonymous_namespace{file}', where file will be replaced with the base name of
+# the file that contains the anonymous namespace. By default anonymous namespace
+# are hidden.
+# The default value is: NO.
+
+EXTRACT_ANON_NSPACES = NO
+
+# If this flag is set to YES, the name of an unnamed parameter in a declaration
+# will be determined by the corresponding definition. By default unnamed
+# parameters remain unnamed in the output.
+# The default value is: YES.
+
+RESOLVE_UNNAMED_PARAMS = YES
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all
+# undocumented members inside documented classes or files. If set to NO these
+# members will be included in the various overviews, but no documentation
+# section is generated. This option has no effect if EXTRACT_ALL is enabled.
+# The default value is: NO.
+
+HIDE_UNDOC_MEMBERS = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy. If set
+# to NO, these classes will be included in the various overviews. This option
+# will also hide undocumented C++ concepts if enabled. This option has no effect
+# if EXTRACT_ALL is enabled.
+# The default value is: NO.
+
+HIDE_UNDOC_CLASSES = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend
+# declarations. If set to NO, these declarations will be included in the
+# documentation.
+# The default value is: NO.
+
+HIDE_FRIEND_COMPOUNDS = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any
+# documentation blocks found inside the body of a function. If set to NO, these
+# blocks will be appended to the function's detailed documentation block.
+# The default value is: NO.
+
+HIDE_IN_BODY_DOCS = NO
+
+# The INTERNAL_DOCS tag determines if documentation that is typed after a
+# \internal command is included. If the tag is set to NO then the documentation
+# will be excluded. Set it to YES to include the internal documentation.
+# The default value is: NO.
+
+INTERNAL_DOCS = NO
+
+# With the correct setting of option CASE_SENSE_NAMES doxygen will better be
+# able to match the capabilities of the underlying filesystem. In case the
+# filesystem is case sensitive (i.e. it supports files in the same directory
+# whose names only differ in casing), the option must be set to YES to properly
+# deal with such files in case they appear in the input. For filesystems that
+# are not case sensitive the option should be set to NO to properly deal with
+# output files written for symbols that only differ in casing, such as for two
+# classes, one named CLASS and the other named Class, and to also support
+# references to files without having to specify the exact matching casing. On
+# Windows (including Cygwin) and MacOS, users should typically set this option
+# to NO, whereas on Linux or other Unix flavors it should typically be set to
+# YES.
+# Possible values are: SYSTEM, NO and YES.
+# The default value is: SYSTEM.
+
+CASE_SENSE_NAMES = YES
+
+# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with
+# their full class and namespace scopes in the documentation. If set to YES, the
+# scope will be hidden.
+# The default value is: NO.
+
+HIDE_SCOPE_NAMES = NO
+
+# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will
+# append additional text to a page's title, such as Class Reference. If set to
+# YES the compound reference will be hidden.
+# The default value is: NO.
+
+HIDE_COMPOUND_REFERENCE= NO
+
+# If the SHOW_HEADERFILE tag is set to YES then the documentation for a class
+# will show which file needs to be included to use the class.
+# The default value is: YES.
+
+SHOW_HEADERFILE = YES
+
+# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of
+# the files that are included by a file in the documentation of that file.
+# The default value is: YES.
+
+SHOW_INCLUDE_FILES = YES
+
+# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each
+# grouped member an include statement to the documentation, telling the reader
+# which file to include in order to use the member.
+# The default value is: NO.
+
+SHOW_GROUPED_MEMB_INC = NO
+
+# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include
+# files with double quotes in the documentation rather than with sharp brackets.
+# The default value is: NO.
+
+FORCE_LOCAL_INCLUDES = NO
+
+# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the
+# documentation for inline members.
+# The default value is: YES.
+
+INLINE_INFO = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the
+# (detailed) documentation of file and class members alphabetically by member
+# name. If set to NO, the members will appear in declaration order.
+# The default value is: YES.
+
+SORT_MEMBER_DOCS = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief
+# descriptions of file, namespace and class members alphabetically by member
+# name. If set to NO, the members will appear in declaration order. Note that
+# this will also influence the order of the classes in the class list.
+# The default value is: NO.
+
+SORT_BRIEF_DOCS = YES
+
+# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the
+# (brief and detailed) documentation of class members so that constructors and
+# destructors are listed first. If set to NO the constructors will appear in the
+# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS.
+# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief
+# member documentation.
+# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting
+# detailed member documentation.
+# The default value is: NO.
+
+SORT_MEMBERS_CTORS_1ST = YES
+
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy
+# of group names into alphabetical order. If set to NO the group names will
+# appear in their defined order.
+# The default value is: NO.
+
+SORT_GROUP_NAMES = YES
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by
+# fully-qualified names, including namespaces. If set to NO, the class list will
+# be sorted only by class name, not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the alphabetical
+# list.
+# The default value is: NO.
+
+SORT_BY_SCOPE_NAME = NO
+
+# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper
+# type resolution of all parameters of a function it will reject a match between
+# the prototype and the implementation of a member function even if there is
+# only one candidate or it is obvious which candidate to choose by doing a
+# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still
+# accept a match between prototype and implementation in such cases.
+# The default value is: NO.
+
+STRICT_PROTO_MATCHING = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo
+# list. This list is created by putting \todo commands in the documentation.
+# The default value is: YES.
+
+GENERATE_TODOLIST = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test
+# list. This list is created by putting \test commands in the documentation.
+# The default value is: YES.
+
+GENERATE_TESTLIST = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug
+# list. This list is created by putting \bug commands in the documentation.
+# The default value is: YES.
+
+GENERATE_BUGLIST = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO)
+# the deprecated list. This list is created by putting \deprecated commands in
+# the documentation.
+# The default value is: YES.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional documentation
+# sections, marked by \if <section_label> ... \endif and \cond <section_label>
+# ... \endcond blocks.
+
+ENABLED_SECTIONS =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the
+# initial value of a variable or macro / define can have for it to appear in the
+# documentation. If the initializer consists of more lines than specified here
+# it will be hidden. Use a value of 0 to hide initializers completely. The
+# appearance of the value of individual variables and macros / defines can be
+# controlled using \showinitializer or \hideinitializer command in the
+# documentation regardless of this setting.
+# Minimum value: 0, maximum value: 10000, default value: 30.
+
+MAX_INITIALIZER_LINES = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at
+# the bottom of the documentation of classes and structs. If set to YES, the
+# list will mention the files that were used to generate the documentation.
+# The default value is: YES.
+
+SHOW_USED_FILES = YES
+
+# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This
+# will remove the Files entry from the Quick Index and from the Folder Tree View
+# (if specified).
+# The default value is: YES.
+
+SHOW_FILES = YES
+
+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces
+# page. This will remove the Namespaces entry from the Quick Index and from the
+# Folder Tree View (if specified).
+# The default value is: YES.
+
+SHOW_NAMESPACES = YES
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from
+# the version control system). Doxygen will invoke the program by executing (via
+# popen()) the command command input-file, where command is the value of the
+# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided
+# by doxygen. Whatever the program writes to standard output is used as the file
+# version. For an example see the documentation.
+
+FILE_VERSION_FILTER =
+
+# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
+# by doxygen. The layout file controls the global structure of the generated
+# output files in an output format independent way. To create the layout file
+# that represents doxygen's defaults, run doxygen with the -l option. You can
+# optionally specify a file name after the option, if omitted DoxygenLayout.xml
+# will be used as the name of the layout file. See also section "Changing the
+# layout of pages" for information.
+#
+# Note that if you run doxygen from a directory containing a file called
+# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE
+# tag is left empty.
+
+LAYOUT_FILE =
+
+# The CITE_BIB_FILES tag can be used to specify one or more bib files containing
+# the reference definitions. This must be a list of .bib files. The .bib
+# extension is automatically appended if omitted. This requires the bibtex tool
+# to be installed. See also https://en.wikipedia.org/wiki/BibTeX for more info.
+# For LaTeX the style of the bibliography can be controlled using
+# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the
+# search path. See also \cite for info how to create references.
+
+CITE_BIB_FILES =
+
+#---------------------------------------------------------------------------
+# Configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated to
+# standard output by doxygen. If QUIET is set to YES this implies that the
+# messages are off.
+# The default value is: NO.
+
+QUIET = YES
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES
+# this implies that the warnings are on.
+#
+# Tip: Turn warnings on while writing the documentation.
+# The default value is: YES.
+
+WARNINGS = YES
+
+# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate
+# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag
+# will automatically be disabled.
+# The default value is: YES.
+
+WARN_IF_UNDOCUMENTED = YES
+
+# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as documenting some parameters in
+# a documented function twice, or documenting parameters that don't exist or
+# using markup commands wrongly.
+# The default value is: YES.
+
+WARN_IF_DOC_ERROR = YES
+
+# If WARN_IF_INCOMPLETE_DOC is set to YES, doxygen will warn about incomplete
+# function parameter documentation. If set to NO, doxygen will accept that some
+# parameters have no documentation without warning.
+# The default value is: YES.
+
+WARN_IF_INCOMPLETE_DOC = YES
+
+# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that
+# are documented, but have no documentation for their parameters or return
+# value. If set to NO, doxygen will only warn about wrong parameter
+# documentation, but not about the absence of documentation. If EXTRACT_ALL is
+# set to YES then this flag will automatically be disabled. See also
+# WARN_IF_INCOMPLETE_DOC
+# The default value is: NO.
+
+WARN_NO_PARAMDOC = NO
+
+# If WARN_IF_UNDOC_ENUM_VAL option is set to YES, doxygen will warn about
+# undocumented enumeration values. If set to NO, doxygen will accept
+# undocumented enumeration values. If EXTRACT_ALL is set to YES then this flag
+# will automatically be disabled.
+# The default value is: NO.
+
+WARN_IF_UNDOC_ENUM_VAL = NO
+
+# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when
+# a warning is encountered. If the WARN_AS_ERROR tag is set to FAIL_ON_WARNINGS
+# then doxygen will continue running as if WARN_AS_ERROR tag is set to NO, but
+# at the end of the doxygen process doxygen will return with a non-zero status.
+# If the WARN_AS_ERROR tag is set to FAIL_ON_WARNINGS_PRINT then doxygen behaves
+# like FAIL_ON_WARNINGS but in case no WARN_LOGFILE is defined doxygen will not
+# write the warning messages in between other messages but write them at the end
+# of a run, in case a WARN_LOGFILE is defined the warning messages will be
+# besides being in the defined file also be shown at the end of a run, unless
+# the WARN_LOGFILE is defined as - i.e. standard output (stdout) in that case
+# the behavior will remain as with the setting FAIL_ON_WARNINGS.
+# Possible values are: NO, YES, FAIL_ON_WARNINGS and FAIL_ON_WARNINGS_PRINT.
+# The default value is: NO.
+
+WARN_AS_ERROR = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that doxygen
+# can produce. The string should contain the $file, $line, and $text tags, which
+# will be replaced by the file and line number from which the warning originated
+# and the warning text. Optionally the format may contain $version, which will
+# be replaced by the version of the file (if it could be obtained via
+# FILE_VERSION_FILTER)
+# See also: WARN_LINE_FORMAT
+# The default value is: $file:$line: $text.
+
+WARN_FORMAT = "$file:$line: $text"
+
+# In the $text part of the WARN_FORMAT command it is possible that a reference
+# to a more specific place is given. To make it easier to jump to this place
+# (outside of doxygen) the user can define a custom "cut" / "paste" string.
+# Example:
+# WARN_LINE_FORMAT = "'vi $file +$line'"
+# See also: WARN_FORMAT
+# The default value is: at line $line of file $file.
+
+WARN_LINE_FORMAT = "at line $line of file $file"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning and error
+# messages should be written. If left blank the output is written to standard
+# error (stderr). In case the file specified cannot be opened for writing the
+# warning and error messages are written to standard error. When as file - is
+# specified the warning and error messages are written to standard output
+# (stdout).
+
+WARN_LOGFILE =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag is used to specify the files and/or directories that contain
+# documented source files. You may enter file names like myfile.cpp or
+# directories like /usr/src/myproject. Separate the files or directories with
+# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
+# Note: If this tag is empty the current directory is searched.
+
+INPUT = ../../src/bin/agent \
+ ../../src/bin/d2 \
+ ../../src/bin/dhcp4 \
+ ../../src/bin/dhcp6 \
+ ../../src/bin/lfc \
+ ../../src/bin/netconf \
+ ../../src/bin/perfdhcp \
+ ../../src/hooks/dhcp/bootp \
+ ../../src/hooks/dhcp/flex_option \
+ ../../src/hooks/dhcp/high_availability \
+ ../../src/hooks/dhcp/lease_cmds \
+ ../../src/hooks/dhcp/perfmon \
+ ../../src/hooks/dhcp/stat_cmds \
+ ../../src/hooks/dhcp/user_chk \
+ ../../src/lib/asiodns \
+ ../../src/lib/asiolink \
+ ../../src/lib/cc \
+ ../../src/lib/config \
+ ../../src/lib/config_backend \
+ ../../src/lib/cryptolink \
+ ../../src/lib/d2srv \
+ ../../src/lib/database \
+ ../../src/lib/dhcp \
+ ../../src/lib/dhcp_ddns \
+ ../../src/lib/dhcpsrv \
+ ../../src/lib/dhcpsrv/parsers \
+ ../../src/lib/dns \
+ ../../src/lib/eval \
+ ../../src/lib/exceptions \
+ ../../src/lib/hooks \
+ ../../src/lib/http \
+ ../../src/lib/log \
+ ../../src/lib/log/compiler \
+ ../../src/lib/log/interprocess \
+ ../../src/lib/mysql \
+ ../../src/lib/pgsql \
+ ../../src/lib/process \
+ ../../src/lib/process/cfgrpt \
+ ../../src/lib/stats \
+ ../../src/lib/tcp \
+ ../../src/lib/testutils \
+ ../../src/lib/util \
+ ../../src/lib/util/encode \
+ ../../src/lib/util/io \
+ ../../src/lib/util/unittests \
+ ../../src/lib/yang \
+ .
+
+# This tag can be used to specify the character encoding of the source files
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
+# libiconv (or the iconv built into libc) for the transcoding. See the libiconv
+# documentation (see:
+# https://www.gnu.org/software/libiconv/) for the list of possible encodings.
+# See also: INPUT_FILE_ENCODING
+# The default value is: UTF-8.
+
+INPUT_ENCODING = UTF-8
+
+# This tag can be used to specify the character encoding of the source files
+# that doxygen parses The INPUT_FILE_ENCODING tag can be used to specify
+# character encoding on a per file pattern basis. Doxygen will compare the file
+# name with each pattern and apply the encoding instead of the default
+# INPUT_ENCODING) if there is a match. The character encodings are a list of the
+# form: pattern=encoding (like *.php=ISO-8859-1). See cfg_input_encoding
+# "INPUT_ENCODING" for further information on supported encodings.
+
+INPUT_FILE_ENCODING =
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and
+# *.h) to filter out the source-files in the directories.
+#
+# Note that for custom extensions or not directly supported extensions you also
+# need to set EXTENSION_MAPPING for the extension otherwise the files are not
+# read by doxygen.
+#
+# Note the list of default checked file patterns might differ from the list of
+# default file extension mappings.
+#
+# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cxxm,
+# *.cpp, *.cppm, *.ccm, *.c++, *.c++m, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl,
+# *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp, *.h++, *.ixx, *.l, *.cs, *.d,
+# *.php, *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown, *.md, *.mm, *.dox (to
+# be provided as doxygen C comment), *.py, *.pyw, *.f90, *.f95, *.f03, *.f08,
+# *.f18, *.f, *.for, *.vhd, *.vhdl, *.ucf, *.qsf and *.ice.
+
+FILE_PATTERNS = *.c \
+ *.cc \
+ *.h \
+ *.hpp \
+ *.dox
+
+# The RECURSIVE tag can be used to specify whether or not subdirectories should
+# be searched for input files as well.
+# The default value is: NO.
+
+RECURSIVE = NO
+
+# The EXCLUDE tag can be used to specify files and/or directories that should be
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+#
+# Note that relative paths are relative to the directory from which doxygen is
+# run.
+
+EXCLUDE = ../../src/lib/dns/master_lexer.cc \
+ ../../src/lib/dns/rdataclass.cc \
+ ../../src/lib/eval/lexer.cc
+
+# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
+# directories that are symbolic links (a Unix file system feature) are excluded
+# from the input.
+# The default value is: NO.
+
+EXCLUDE_SYMLINKS = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories.
+#
+# Note that the wildcards are matched against the file with absolute path, so to
+# exclude all test directories for example use the pattern */test/*
+
+EXCLUDE_PATTERNS = */*-placeholder.* \
+ */cpp/*.py
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
+# (namespaces, classes, functions, etc.) that should be excluded from the
+# output. The symbol name can be a fully qualified name, a word, or if the
+# wildcard * is used, a substring. Examples: ANamespace, AClass,
+# ANamespace::AClass, ANamespace::*Test
+
+EXCLUDE_SYMBOLS =
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or directories
+# that contain example code fragments that are included (see the \include
+# command).
+
+EXAMPLE_PATH =
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and
+# *.h) to filter out the source-files in the directories. If left blank all
+# files are included.
+
+EXAMPLE_PATTERNS =
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude commands
+# irrespective of the value of the RECURSIVE tag.
+# The default value is: NO.
+
+EXAMPLE_RECURSIVE = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or directories
+# that contain images that are to be included in the documentation (see the
+# \image command).
+
+IMAGE_PATH = ../images \
+ ../../src/lib/hooks/images \
+ ../../src/bin/d2/images \
+ ../../src/lib/dhcpsrv/images
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command:
+#
+# <filter> <input-file>
+#
+# where <filter> is the value of the INPUT_FILTER tag, and <input-file> is the
+# name of an input file. Doxygen will then use the output that the filter
+# program writes to standard output. If FILTER_PATTERNS is specified, this tag
+# will be ignored.
+#
+# Note that the filter must not add or remove lines; it is applied before the
+# code is scanned, but not when the output code is generated. If lines are added
+# or removed, the anchors will not be placed correctly.
+#
+# Note that doxygen will use the data processed and written to standard output
+# for further processing, therefore nothing else, like debug statements or used
+# commands (so in case of a Windows batch file always use @echo OFF), should be
+# written to standard output.
+#
+# Note that for custom extensions or not directly supported extensions you also
+# need to set EXTENSION_MAPPING for the extension otherwise the files are not
+# properly processed by doxygen.
+
+INPUT_FILTER =
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis. Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match. The filters are a list of the form: pattern=filter
+# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how
+# filters are used. If the FILTER_PATTERNS tag is empty or if none of the
+# patterns match the file name, INPUT_FILTER is applied.
+#
+# Note that for custom extensions or not directly supported extensions you also
+# need to set EXTENSION_MAPPING for the extension otherwise the files are not
+# properly processed by doxygen.
+
+FILTER_PATTERNS =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will also be used to filter the input files that are used for
+# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES).
+# The default value is: NO.
+
+FILTER_SOURCE_FILES = NO
+
+# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file
+# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and
+# it is also possible to disable source filtering for a specific pattern using
+# *.ext= (so without naming a filter).
+# This tag requires that the tag FILTER_SOURCE_FILES is set to YES.
+
+FILTER_SOURCE_PATTERNS =
+
+# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that
+# is part of the input, its contents will be placed on the main page
+# (index.html). This can be useful if you have a project on for instance GitHub
+# and want to reuse the introduction page also for the doxygen output.
+
+USE_MDFILE_AS_MAINPAGE =
+
+# The Fortran standard specifies that for fixed formatted Fortran code all
+# characters from position 72 are to be considered as comment. A common
+# extension is to allow longer lines before the automatic comment starts. The
+# setting FORTRAN_COMMENT_AFTER will also make it possible that longer lines can
+# be processed before the automatic comment starts.
+# Minimum value: 7, maximum value: 10000, default value: 72.
+
+FORTRAN_COMMENT_AFTER = 72
+
+#---------------------------------------------------------------------------
+# Configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will be
+# generated. Documented entities will be cross-referenced with these sources.
+#
+# Note: To get rid of all source code in the generated output, make sure that
+# also VERBATIM_HEADERS is set to NO.
+# The default value is: NO.
+
+SOURCE_BROWSER = YES
+
+# Setting the INLINE_SOURCES tag to YES will include the body of functions,
+# multi-line macros, enums or list initialized variables directly into the
+# documentation.
+# The default value is: NO.
+
+INLINE_SOURCES = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any
+# special comment blocks from generated source code fragments. Normal C, C++ and
+# Fortran comments will always remain visible.
+# The default value is: YES.
+
+STRIP_CODE_COMMENTS = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES then for each documented
+# entity all documented functions referencing it will be listed.
+# The default value is: NO.
+
+REFERENCED_BY_RELATION = YES
+
+# If the REFERENCES_RELATION tag is set to YES then for each documented function
+# all documented entities called/used by that function will be listed.
+# The default value is: NO.
+
+REFERENCES_RELATION = YES
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set
+# to YES then the hyperlinks from functions in REFERENCES_RELATION and
+# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will
+# link to the documentation.
+# The default value is: YES.
+
+REFERENCES_LINK_SOURCE = YES
+
+# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the
+# source code will show a tooltip with additional information such as prototype,
+# brief description and links to the definition and documentation. Since this
+# will make the HTML file larger and loading of large files a bit slower, you
+# can opt to disable this feature.
+# The default value is: YES.
+# This tag requires that the tag SOURCE_BROWSER is set to YES.
+
+SOURCE_TOOLTIPS = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code will
+# point to the HTML generated by the htags(1) tool instead of doxygen built-in
+# source browser. The htags tool is part of GNU's global source tagging system
+# (see https://www.gnu.org/software/global/global.html). You will need version
+# 4.8.6 or higher.
+#
+# To use it do the following:
+# - Install the latest version of global
+# - Enable SOURCE_BROWSER and USE_HTAGS in the configuration file
+# - Make sure the INPUT points to the root of the source tree
+# - Run doxygen as normal
+#
+# Doxygen will invoke htags (and that will in turn invoke gtags), so these
+# tools must be available from the command line (i.e. in the search path).
+#
+# The result: instead of the source browser generated by doxygen, the links to
+# source code will now point to the output of htags.
+# The default value is: NO.
+# This tag requires that the tag SOURCE_BROWSER is set to YES.
+
+USE_HTAGS = NO
+
+# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a
+# verbatim copy of the header file for each class for which an include is
+# specified. Set to NO to disable this.
+# See also: Section \class.
+# The default value is: YES.
+
+VERBATIM_HEADERS = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all
+# compounds will be generated. Enable this if the project contains a lot of
+# classes, structs, unions or interfaces.
+# The default value is: YES.
+
+ALPHABETICAL_INDEX = YES
+
+# The IGNORE_PREFIX tag can be used to specify a prefix (or a list of prefixes)
+# that should be ignored while generating the index headers. The IGNORE_PREFIX
+# tag works for classes, function and member names. The entity will be placed in
+# the alphabetical list under the first letter of the entity name that remains
+# after removing the prefix.
+# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
+
+IGNORE_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output
+# The default value is: YES.
+
+GENERATE_HTML = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: html.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_OUTPUT = ../html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each
+# generated HTML page (for example: .htm, .php, .asp).
+# The default value is: .html.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_FILE_EXTENSION = .html
+
+# The HTML_HEADER tag can be used to specify a user-defined HTML header file for
+# each generated HTML page. If the tag is left blank doxygen will generate a
+# standard header.
+#
+# To get valid HTML the header file that includes any scripts and style sheets
+# that doxygen needs, which is dependent on the configuration options used (e.g.
+# the setting GENERATE_TREEVIEW). It is highly recommended to start with a
+# default header using
+# doxygen -w html new_header.html new_footer.html new_stylesheet.css
+# YourConfigFile
+# and then modify the file new_header.html. See also section "Doxygen usage"
+# for information on how to generate the default header that doxygen normally
+# uses.
+# Note: The header is subject to change so you typically have to regenerate the
+# default header when upgrading to a newer version of doxygen. For a description
+# of the possible markers and block names see the documentation.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_HEADER =
+
+# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each
+# generated HTML page. If the tag is left blank doxygen will generate a standard
+# footer. See HTML_HEADER for more information on how to generate a default
+# footer and what special commands can be used inside the footer. See also
+# section "Doxygen usage" for information on how to generate the default footer
+# that doxygen normally uses.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_FOOTER =
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style
+# sheet that is used by each HTML page. It can be used to fine-tune the look of
+# the HTML output. If left blank doxygen will generate a default style sheet.
+# See also section "Doxygen usage" for information on how to generate the style
+# sheet that doxygen normally uses.
+# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as
+# it is more robust and this tag (HTML_STYLESHEET) will in the future become
+# obsolete.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_STYLESHEET =
+
+# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined
+# cascading style sheets that are included after the standard style sheets
+# created by doxygen. Using this option one can overrule certain style aspects.
+# This is preferred over using HTML_STYLESHEET since it does not replace the
+# standard style sheet and is therefore more robust against future updates.
+# Doxygen will copy the style sheet files to the output directory.
+# Note: The order of the extra style sheet files is of importance (e.g. the last
+# style sheet in the list overrules the setting of the previous ones in the
+# list).
+# Note: Since the styling of scrollbars can currently not be overruled in
+# Webkit/Chromium, the styling will be left out of the default doxygen.css if
+# one or more extra stylesheets have been specified. So if scrollbar
+# customization is desired it has to be added explicitly. For an example see the
+# documentation.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_EXTRA_STYLESHEET =
+
+# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the HTML output directory. Note
+# that these files will be copied to the base HTML output directory. Use the
+# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these
+# files. In the HTML_STYLESHEET file, use the file name only. Also note that the
+# files will be copied as-is; there are no commands or markers available.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_EXTRA_FILES =
+
+# The HTML_COLORSTYLE tag can be used to specify if the generated HTML output
+# should be rendered with a dark or light theme.
+# Possible values are: LIGHT always generate light mode output, DARK always
+# generate dark mode output, AUTO_LIGHT automatically set the mode according to
+# the user preference, use light mode if no preference is set (the default),
+# AUTO_DARK automatically set the mode according to the user preference, use
+# dark mode if no preference is set and TOGGLE allow to user to switch between
+# light and dark mode via a button.
+# The default value is: AUTO_LIGHT.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE = AUTO_LIGHT
+
+# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
+# will adjust the colors in the style sheet and background images according to
+# this color. Hue is specified as an angle on a color-wheel, see
+# https://en.wikipedia.org/wiki/Hue for more information. For instance the value
+# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300
+# purple, and 360 is red again.
+# Minimum value: 0, maximum value: 359, default value: 220.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_HUE = 220
+
+# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors
+# in the HTML output. For a value of 0 the output will use gray-scales only. A
+# value of 255 will produce the most vivid colors.
+# Minimum value: 0, maximum value: 255, default value: 100.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_SAT = 100
+
+# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the
+# luminance component of the colors in the HTML output. Values below 100
+# gradually make the output lighter, whereas values above 100 make the output
+# darker. The value divided by 100 is the actual gamma applied, so 80 represents
+# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not
+# change the gamma.
+# Minimum value: 40, maximum value: 240, default value: 80.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_GAMMA = 80
+
+# If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML
+# documentation will contain a main index with vertical navigation menus that
+# are dynamically created via JavaScript. If disabled, the navigation index will
+# consists of multiple levels of tabs that are statically embedded in every HTML
+# page. Disable this option to support browsers that do not have JavaScript,
+# like the Qt help browser.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_DYNAMIC_MENUS = YES
+
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
+# documentation will contain sections that can be hidden and shown after the
+# page has loaded.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_DYNAMIC_SECTIONS = YES
+
+# If the HTML_CODE_FOLDING tag is set to YES then classes and functions can be
+# dynamically folded and expanded in the generated HTML source code.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_CODE_FOLDING = YES
+
+# If the HTML_COPY_CLIPBOARD tag is set to YES then doxygen will show an icon in
+# the top right corner of code and text fragments that allows the user to copy
+# its content to the clipboard. Note this only works if supported by the browser
+# and the web page is served via a secure context (see:
+# https://www.w3.org/TR/secure-contexts/), i.e. using the https: or file:
+# protocol.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COPY_CLIPBOARD = YES
+
+# Doxygen stores a couple of settings persistently in the browser (via e.g.
+# cookies). By default these settings apply to all HTML pages generated by
+# doxygen across all projects. The HTML_PROJECT_COOKIE tag can be used to store
+# the settings under a project specific key, such that the user preferences will
+# be stored separately.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_PROJECT_COOKIE =
+
+# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries
+# shown in the various tree structured indices initially; the user can expand
+# and collapse entries dynamically later on. Doxygen will expand the tree to
+# such a level that at most the specified number of entries are visible (unless
+# a fully collapsed tree already exceeds this amount). So setting the number of
+# entries 1 will produce a full collapsed tree by default. 0 is a special value
+# representing an infinite number of entries and will result in a full expanded
+# tree by default.
+# Minimum value: 0, maximum value: 9999, default value: 100.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_INDEX_NUM_ENTRIES = 100
+
+# If the GENERATE_DOCSET tag is set to YES, additional index files will be
+# generated that can be used as input for Apple's Xcode 3 integrated development
+# environment (see:
+# https://developer.apple.com/xcode/), introduced with OSX 10.5 (Leopard). To
+# create a documentation set, doxygen will generate a Makefile in the HTML
+# output directory. Running make will produce the docset in that directory and
+# running make install will install the docset in
+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at
+# startup. See https://developer.apple.com/library/archive/featuredarticles/Doxy
+# genXcode/_index.html for more information.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_DOCSET = NO
+
+# This tag determines the name of the docset feed. A documentation feed provides
+# an umbrella under which multiple documentation sets from a single provider
+# (such as a company or product suite) can be grouped.
+# The default value is: Doxygen generated docs.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_FEEDNAME = "Doxygen generated docs"
+
+# This tag determines the URL of the docset feed. A documentation feed provides
+# an umbrella under which multiple documentation sets from a single provider
+# (such as a company or product suite) can be grouped.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_FEEDURL =
+
+# This tag specifies a string that should uniquely identify the documentation
+# set bundle. This should be a reverse domain-name style string, e.g.
+# com.mycompany.MyDocSet. Doxygen will append .docset to the name.
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_BUNDLE_ID = org.doxygen.Project
+
+# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify
+# the documentation publisher. This should be a reverse domain-name style
+# string, e.g. com.mycompany.MyDocSet.documentation.
+# The default value is: org.doxygen.Publisher.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_PUBLISHER_ID = org.doxygen.Publisher
+
+# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher.
+# The default value is: Publisher.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_PUBLISHER_NAME = Publisher
+
+# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three
+# additional HTML index files: index.hhp, index.hhc, and index.hhk. The
+# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop
+# on Windows. In the beginning of 2021 Microsoft took the original page, with
+# a.o. the download links, offline the HTML help workshop was already many years
+# in maintenance mode). You can download the HTML help workshop from the web
+# archives at Installation executable (see:
+# http://web.archive.org/web/20160201063255/http://download.microsoft.com/downlo
+# ad/0/A/9/0A939EF6-E31C-430F-A3DF-DFAE7960D564/htmlhelp.exe).
+#
+# The HTML Help Workshop contains a compiler that can convert all HTML output
+# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML
+# files are now used as the Windows 98 help format, and will replace the old
+# Windows help format (.hlp) on all Windows platforms in the future. Compressed
+# HTML files also contain an index, a table of contents, and you can search for
+# words in the documentation. The HTML workshop also contains a viewer for
+# compressed HTML files.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_HTMLHELP = NO
+
+# The CHM_FILE tag can be used to specify the file name of the resulting .chm
+# file. You can add a path in front of the file if the result should not be
+# written to the html output directory.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+CHM_FILE =
+
+# The HHC_LOCATION tag can be used to specify the location (absolute path
+# including file name) of the HTML help compiler (hhc.exe). If non-empty,
+# doxygen will try to run the HTML help compiler on the generated index.hhp.
+# The file has to be specified with full path.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+HHC_LOCATION =
+
+# The GENERATE_CHI flag controls if a separate .chi index file is generated
+# (YES) or that it should be included in the main .chm file (NO).
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+GENERATE_CHI = NO
+
+# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc)
+# and project file content.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+CHM_INDEX_ENCODING =
+
+# The BINARY_TOC flag controls whether a binary table of contents is generated
+# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it
+# enables the Previous and Next buttons.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+BINARY_TOC = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members to
+# the table of contents of the HTML help documentation and to the tree view.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+TOC_EXPAND = NO
+
+# The SITEMAP_URL tag is used to specify the full URL of the place where the
+# generated documentation will be placed on the server by the user during the
+# deployment of the documentation. The generated sitemap is called sitemap.xml
+# and placed on the directory specified by HTML_OUTPUT. In case no SITEMAP_URL
+# is specified no sitemap is generated. For information about the sitemap
+# protocol see https://www.sitemaps.org
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+SITEMAP_URL =
+
+# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
+# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that
+# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help
+# (.qch) of the generated HTML documentation.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_QHP = NO
+
+# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify
+# the file name of the resulting .qch file. The path specified is relative to
+# the HTML output folder.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QCH_FILE =
+
+# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help
+# Project output. For more information please see Qt Help Project / Namespace
+# (see:
+# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace).
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_NAMESPACE =
+
+# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt
+# Help Project output. For more information please see Qt Help Project / Virtual
+# Folders (see:
+# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual-folders).
+# The default value is: doc.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_VIRTUAL_FOLDER = doc
+
+# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom
+# filter to add. For more information please see Qt Help Project / Custom
+# Filters (see:
+# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_CUST_FILTER_NAME =
+
+# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the
+# custom filter to add. For more information please see Qt Help Project / Custom
+# Filters (see:
+# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_CUST_FILTER_ATTRS =
+
+# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
+# project's filter section matches. Qt Help Project / Filter Attributes (see:
+# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#filter-attributes).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_SECT_FILTER_ATTRS =
+
+# The QHG_LOCATION tag can be used to specify the location (absolute path
+# including file name) of Qt's qhelpgenerator. If non-empty doxygen will try to
+# run qhelpgenerator on the generated .qhp file.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHG_LOCATION =
+
+# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be
+# generated, together with the HTML files, they form an Eclipse help plugin. To
+# install this plugin and make it available under the help contents menu in
+# Eclipse, the contents of the directory containing the HTML and XML files needs
+# to be copied into the plugins directory of eclipse. The name of the directory
+# within the plugins directory should be the same as the ECLIPSE_DOC_ID value.
+# After copying Eclipse needs to be restarted before the help appears.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_ECLIPSEHELP = NO
+
+# A unique identifier for the Eclipse help plugin. When installing the plugin
+# the directory name containing the HTML and XML files should also have this
+# name. Each documentation set should have its own identifier.
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES.
+
+ECLIPSE_DOC_ID = org.doxygen.Project
+
+# If you want full control over the layout of the generated HTML pages it might
+# be necessary to disable the index and replace it with your own. The
+# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top
+# of each HTML page. A value of NO enables the index and the value YES disables
+# it. Since the tabs in the index contain the same information as the navigation
+# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+DISABLE_INDEX = NO
+
+# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
+# structure should be generated to display hierarchical information. If the tag
+# value is set to YES, a side panel will be generated containing a tree-like
+# index structure (just like the one that is generated for HTML Help). For this
+# to work a browser that supports JavaScript, DHTML, CSS and frames is required
+# (i.e. any modern browser). Windows users are probably better off using the
+# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can
+# further fine tune the look of the index (see "Fine-tuning the output"). As an
+# example, the default style sheet generated by doxygen has an example that
+# shows how to put an image at the root of the tree instead of the PROJECT_NAME.
+# Since the tree basically has the same information as the tab index, you could
+# consider setting DISABLE_INDEX to YES when enabling this option.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_TREEVIEW = YES
+
+# When both GENERATE_TREEVIEW and DISABLE_INDEX are set to YES, then the
+# FULL_SIDEBAR option determines if the side bar is limited to only the treeview
+# area (value NO) or if it should extend to the full height of the window (value
+# YES). Setting this to YES gives a layout similar to
+# https://docs.readthedocs.io with more room for contents, but less room for the
+# project logo, title, and description. If either GENERATE_TREEVIEW or
+# DISABLE_INDEX is set to NO, this option has no effect.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+FULL_SIDEBAR = NO
+
+# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that
+# doxygen will group on one line in the generated HTML documentation.
+#
+# Note that a value of 0 will completely suppress the enum values from appearing
+# in the overview section.
+# Minimum value: 0, maximum value: 20, default value: 4.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+ENUM_VALUES_PER_LINE = 4
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used
+# to set the initial width (in pixels) of the frame in which the tree is shown.
+# Minimum value: 0, maximum value: 1500, default value: 250.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+TREEVIEW_WIDTH = 180
+
+# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to
+# external symbols imported via tag files in a separate window.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+EXT_LINKS_IN_WINDOW = NO
+
+# If the OBFUSCATE_EMAILS tag is set to YES, doxygen will obfuscate email
+# addresses.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+OBFUSCATE_EMAILS = YES
+
+# If the HTML_FORMULA_FORMAT option is set to svg, doxygen will use the pdf2svg
+# tool (see https://github.com/dawbarton/pdf2svg) or inkscape (see
+# https://inkscape.org) to generate formulas as SVG images instead of PNGs for
+# the HTML output. These images will generally look nicer at scaled resolutions.
+# Possible values are: png (the default) and svg (looks nicer but requires the
+# pdf2svg or inkscape tool).
+# The default value is: png.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_FORMULA_FORMAT = png
+
+# Use this tag to change the font size of LaTeX formulas included as images in
+# the HTML documentation. When you change the font size after a successful
+# doxygen run you need to manually remove any form_*.png images from the HTML
+# output directory to force them to be regenerated.
+# Minimum value: 8, maximum value: 50, default value: 10.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+FORMULA_FONTSIZE = 10
+
+# The FORMULA_MACROFILE can contain LaTeX \newcommand and \renewcommand commands
+# to create new LaTeX commands to be used in formulas as building blocks. See
+# the section "Including formulas" for details.
+
+FORMULA_MACROFILE =
+
+# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see
+# https://www.mathjax.org) which uses client side JavaScript for the rendering
+# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX
+# installed or if you want to formulas look prettier in the HTML output. When
+# enabled you may also need to install MathJax separately and configure the path
+# to it using the MATHJAX_RELPATH option.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+USE_MATHJAX = NO
+
+# With MATHJAX_VERSION it is possible to specify the MathJax version to be used.
+# Note that the different versions of MathJax have different requirements with
+# regards to the different settings, so it is possible that also other MathJax
+# settings have to be changed when switching between the different MathJax
+# versions.
+# Possible values are: MathJax_2 and MathJax_3.
+# The default value is: MathJax_2.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_VERSION = MathJax_2
+
+# When MathJax is enabled you can set the default output format to be used for
+# the MathJax output. For more details about the output format see MathJax
+# version 2 (see:
+# http://docs.mathjax.org/en/v2.7-latest/output.html) and MathJax version 3
+# (see:
+# http://docs.mathjax.org/en/latest/web/components/output.html).
+# Possible values are: HTML-CSS (which is slower, but has the best
+# compatibility. This is the name for Mathjax version 2, for MathJax version 3
+# this will be translated into chtml), NativeMML (i.e. MathML. Only supported
+# for NathJax 2. For MathJax version 3 chtml will be used instead.), chtml (This
+# is the name for Mathjax version 3, for MathJax version 2 this will be
+# translated into HTML-CSS) and SVG.
+# The default value is: HTML-CSS.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_FORMAT = HTML-CSS
+
+# When MathJax is enabled you need to specify the location relative to the HTML
+# output directory using the MATHJAX_RELPATH option. The destination directory
+# should contain the MathJax.js script. For instance, if the mathjax directory
+# is located at the same level as the HTML output directory, then
+# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax
+# Content Delivery Network so you can quickly see the result without installing
+# MathJax. However, it is strongly recommended to install a local copy of
+# MathJax from https://www.mathjax.org before deployment. The default value is:
+# - in case of MathJax version 2: https://cdn.jsdelivr.net/npm/mathjax@2
+# - in case of MathJax version 3: https://cdn.jsdelivr.net/npm/mathjax@3
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_RELPATH =
+
+# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax
+# extension names that should be enabled during MathJax rendering. For example
+# for MathJax version 2 (see
+# https://docs.mathjax.org/en/v2.7-latest/tex.html#tex-and-latex-extensions):
+# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols
+# For example for MathJax version 3 (see
+# http://docs.mathjax.org/en/latest/input/tex/extensions/index.html):
+# MATHJAX_EXTENSIONS = ams
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_EXTENSIONS =
+
+# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces
+# of code that will be used on startup of the MathJax code. See the MathJax site
+# (see:
+# http://docs.mathjax.org/en/v2.7-latest/output.html) for more details. For an
+# example see the documentation.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_CODEFILE =
+
+# When the SEARCHENGINE tag is enabled doxygen will generate a search box for
+# the HTML output. The underlying search engine uses javascript and DHTML and
+# should work on any modern browser. Note that when using HTML help
+# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET)
+# there is already a search function so this one should typically be disabled.
+# For large projects the javascript based search engine can be slow, then
+# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to
+# search using the keyboard; to jump to the search box use <access key> + S
+# (what the <access key> is depends on the OS and browser, but it is typically
+# <CTRL>, <ALT>/<option>, or both). Inside the search box use the <cursor down
+# key> to jump into the search results window, the results can be navigated
+# using the <cursor keys>. Press <Enter> to select an item or <escape> to cancel
+# the search. The filter options can be selected when the cursor is inside the
+# search box by pressing <Shift>+<cursor down>. Also here use the <cursor keys>
+# to select a filter and <Enter> or <escape> to activate or cancel the filter
+# option.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+SEARCHENGINE = NO
+
+# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
+# implemented using a web server instead of a web client using JavaScript. There
+# are two flavors of web server based searching depending on the EXTERNAL_SEARCH
+# setting. When disabled, doxygen will generate a PHP script for searching and
+# an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing
+# and searching needs to be provided by external tools. See the section
+# "External Indexing and Searching" for details.
+# The default value is: NO.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SERVER_BASED_SEARCH = NO
+
+# When EXTERNAL_SEARCH tag is enabled doxygen will no longer generate the PHP
+# script for searching. Instead the search results are written to an XML file
+# which needs to be processed by an external indexer. Doxygen will invoke an
+# external search engine pointed to by the SEARCHENGINE_URL option to obtain the
+# search results.
+#
+# Doxygen ships with an example indexer (doxyindexer) and search engine
+# (doxysearch.cgi) which are based on the open source search engine library
+# Xapian (see:
+# https://xapian.org/).
+#
+# See the section "External Indexing and Searching" for details.
+# The default value is: NO.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTERNAL_SEARCH = NO
+
+# The SEARCHENGINE_URL should point to a search engine hosted by a web server
+# which will return the search results when EXTERNAL_SEARCH is enabled.
+#
+# Doxygen ships with an example indexer (doxyindexer) and search engine
+# (doxysearch.cgi) which are based on the open source search engine library
+# Xapian (see:
+# https://xapian.org/). See the section "External Indexing and Searching" for
+# details.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SEARCHENGINE_URL =
+
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed
+# search data is written to a file for indexing by an external tool. With the
+# SEARCHDATA_FILE tag the name of this file can be specified.
+# The default file is: searchdata.xml.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SEARCHDATA_FILE = searchdata.xml
+
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the
+# EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is
+# useful in combination with EXTRA_SEARCH_MAPPINGS to search through multiple
+# projects and redirect the results back to the right project.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTERNAL_SEARCH_ID =
+
+# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen
+# projects other than the one defined by this configuration file, but that are
+# all added to the same external search index. Each project needs to have a
+# unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id of
+# to a relative location where the documentation can be found. The format is:
+# EXTRA_SEARCH_MAPPINGS = tagname1=loc1 tagname2=loc2 ...
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTRA_SEARCH_MAPPINGS =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES, doxygen will generate LaTeX output.
+# The default value is: YES.
+
+GENERATE_LATEX = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: latex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_OUTPUT = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked.
+#
+# Note that when not enabling USE_PDFLATEX the default is latex when enabling
+# USE_PDFLATEX the default is pdflatex and when in the later case latex is
+# chosen this is overwritten by pdflatex. For specific output languages the
+# default can have been set differently, this depends on the implementation of
+# the output language.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_CMD_NAME = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to generate
+# index for LaTeX.
+# Note: This tag is used in the Makefile / make.bat.
+# See also: LATEX_MAKEINDEX_CMD for the part in the generated output file
+# (.tex).
+# The default file is: makeindex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+MAKEINDEX_CMD_NAME = makeindex
+
+# The LATEX_MAKEINDEX_CMD tag can be used to specify the command name to
+# generate index for LaTeX. In case there is no backslash (\) as first character
+# it will be automatically added in the LaTeX code.
+# Note: This tag is used in the generated output file (.tex).
+# See also: MAKEINDEX_CMD_NAME for the part in the Makefile / make.bat.
+# The default value is: makeindex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_MAKEINDEX_CMD = makeindex
+
+# If the COMPACT_LATEX tag is set to YES, doxygen generates more compact LaTeX
+# documents. This may be useful for small projects and may help to save some
+# trees in general.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+COMPACT_LATEX = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used by the
+# printer.
+# Possible values are: a4 (210 x 297 mm), letter (8.5 x 11 inches), legal (8.5 x
+# 14 inches) and executive (7.25 x 10.5 inches).
+# The default value is: a4.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+PAPER_TYPE = a4
+
+# The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names
+# that should be included in the LaTeX output. The package can be specified just
+# by its name or with the correct syntax as to be used with the LaTeX
+# \usepackage command. To get the times font for instance you can specify :
+# EXTRA_PACKAGES=times or EXTRA_PACKAGES={times}
+# To use the option intlimits with the amsmath package you can specify:
+# EXTRA_PACKAGES=[intlimits]{amsmath}
+# If left blank no extra packages will be included.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+EXTRA_PACKAGES =
+
+# The LATEX_HEADER tag can be used to specify a user-defined LaTeX header for
+# the generated LaTeX document. The header should contain everything until the
+# first chapter. If it is left blank doxygen will generate a standard header. It
+# is highly recommended to start with a default header using
+# doxygen -w latex new_header.tex new_footer.tex new_stylesheet.sty
+# and then modify the file new_header.tex. See also section "Doxygen usage" for
+# information on how to generate the default header that doxygen normally uses.
+#
+# Note: Only use a user-defined header if you know what you are doing!
+# Note: The header is subject to change so you typically have to regenerate the
+# default header when upgrading to a newer version of doxygen. The following
+# commands have a special meaning inside the header (and footer): For a
+# description of the possible markers and block names see the documentation.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_HEADER =
+
+# The LATEX_FOOTER tag can be used to specify a user-defined LaTeX footer for
+# the generated LaTeX document. The footer should contain everything after the
+# last chapter. If it is left blank doxygen will generate a standard footer. See
+# LATEX_HEADER for more information on how to generate a default footer and what
+# special commands can be used inside the footer. See also section "Doxygen
+# usage" for information on how to generate the default footer that doxygen
+# normally uses. Note: Only use a user-defined footer if you know what you are
+# doing!
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_FOOTER =
+
+# The LATEX_EXTRA_STYLESHEET tag can be used to specify additional user-defined
+# LaTeX style sheets that are included after the standard style sheets created
+# by doxygen. Using this option one can overrule certain style aspects. Doxygen
+# will copy the style sheet files to the output directory.
+# Note: The order of the extra style sheet files is of importance (e.g. the last
+# style sheet in the list overrules the setting of the previous ones in the
+# list).
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_EXTRA_STYLESHEET =
+
+# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the LATEX_OUTPUT output
+# directory. Note that the files will be copied as-is; there are no commands or
+# markers available.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_EXTRA_FILES =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated is
+# prepared for conversion to PDF (using ps2pdf or pdflatex). The PDF file will
+# contain links (just like the HTML output) instead of page references. This
+# makes the output suitable for online browsing using a PDF viewer.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+PDF_HYPERLINKS = NO
+
+# If the USE_PDFLATEX tag is set to YES, doxygen will use the engine as
+# specified with LATEX_CMD_NAME to generate the PDF file directly from the LaTeX
+# files. Set this option to YES, to get a higher quality PDF documentation.
+#
+# See also section LATEX_CMD_NAME for selecting the engine.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+USE_PDFLATEX = NO
+
+# The LATEX_BATCHMODE tag signals the behavior of LaTeX in case of an error.
+# Possible values are: NO same as ERROR_STOP, YES same as BATCH, BATCH In batch
+# mode nothing is printed on the terminal, errors are scrolled as if <return> is
+# hit at every error; missing files that TeX tries to input or request from
+# keyboard input (\read on a not open input stream) cause the job to abort,
+# NON_STOP In nonstop mode the diagnostic message will appear on the terminal,
+# but there is no possibility of user interaction just like in batch mode,
+# SCROLL In scroll mode, TeX will stop only for missing files to input or if
+# keyboard input is necessary and ERROR_STOP In errorstop mode, TeX will stop at
+# each error, asking for user intervention.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_BATCHMODE = NO
+
+# If the LATEX_HIDE_INDICES tag is set to YES then doxygen will not include the
+# index chapters (such as File Index, Compound Index, etc.) in the output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_HIDE_INDICES = NO
+
+# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
+# bibliography, e.g. plainnat, or ieeetr. See
+# https://en.wikipedia.org/wiki/BibTeX and \cite for more info.
+# The default value is: plain.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_BIB_STYLE = plain
+
+# The LATEX_EMOJI_DIRECTORY tag is used to specify the (relative or absolute)
+# path from which the emoji images will be read. If a relative path is entered,
+# it will be relative to the LATEX_OUTPUT directory. If left blank the
+# LATEX_OUTPUT directory will be used.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_EMOJI_DIRECTORY =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES, doxygen will generate RTF output. The
+# RTF output is optimized for Word 97 and may not look too pretty with other RTF
+# readers/editors.
+# The default value is: NO.
+
+GENERATE_RTF = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: rtf.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_OUTPUT = rtf
+
+# If the COMPACT_RTF tag is set to YES, doxygen generates more compact RTF
+# documents. This may be useful for small projects and may help to save some
+# trees in general.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+COMPACT_RTF = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated will
+# contain hyperlink fields. The RTF file will contain links (just like the HTML
+# output) instead of page references. This makes the output suitable for online
+# browsing using Word or some other Word compatible readers that support those
+# fields.
+#
+# Note: WordPad (write) and others do not support links.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_HYPERLINKS = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's
+# configuration file, i.e. a series of assignments. You only have to provide
+# replacements, missing definitions are set to their default value.
+#
+# See also section "Doxygen usage" for information on how to generate the
+# default style sheet that doxygen normally uses.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_STYLESHEET_FILE =
+
+# Set optional variables used in the generation of an RTF document. Syntax is
+# similar to doxygen's configuration file. A template extensions file can be
+# generated using doxygen -e rtf extensionFile.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_EXTENSIONS_FILE =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES, doxygen will generate man pages for
+# classes and files.
+# The default value is: NO.
+
+GENERATE_MAN = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it. A directory man3 will be created inside the directory specified by
+# MAN_OUTPUT.
+# The default directory is: man.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_OUTPUT = man
+
+# The MAN_EXTENSION tag determines the extension that is added to the generated
+# man pages. In case the manual section does not start with a number, the number
+# 3 is prepended. The dot (.) at the beginning of the MAN_EXTENSION tag is
+# optional.
+# The default value is: .3.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_EXTENSION = .3
+
+# The MAN_SUBDIR tag determines the name of the directory created within
+# MAN_OUTPUT in which the man pages are placed. If defaults to man followed by
+# MAN_EXTENSION with the initial . removed.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_SUBDIR =
+
+# If the MAN_LINKS tag is set to YES and doxygen generates man output, then it
+# will generate one additional man file for each entity documented in the real
+# man page(s). These additional files only source the real man page, but without
+# them the man command would be unable to find the correct page.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_LINKS = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES, doxygen will generate an XML file that
+# captures the structure of the code including all documentation.
+# The default value is: NO.
+
+GENERATE_XML = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: xml.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_OUTPUT = xml
+
+# If the XML_PROGRAMLISTING tag is set to YES, doxygen will dump the program
+# listings (including syntax highlighting and cross-referencing information) to
+# the XML output. Note that enabling this will significantly increase the size
+# of the XML output.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_PROGRAMLISTING = NO
+
+# If the XML_NS_MEMB_FILE_SCOPE tag is set to YES, doxygen will include
+# namespace members in file scope as well, matching the HTML output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_NS_MEMB_FILE_SCOPE = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the DOCBOOK output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_DOCBOOK tag is set to YES, doxygen will generate Docbook files
+# that can be used to generate PDF.
+# The default value is: NO.
+
+GENERATE_DOCBOOK = NO
+
+# The DOCBOOK_OUTPUT tag is used to specify where the Docbook pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be put in
+# front of it.
+# The default directory is: docbook.
+# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
+
+DOCBOOK_OUTPUT = docbook
+
+#---------------------------------------------------------------------------
+# Configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES, doxygen will generate an
+# AutoGen Definitions (see https://autogen.sourceforge.net/) file that captures
+# the structure of the code including all documentation. Note that this feature
+# is still experimental and incomplete at the moment.
+# The default value is: NO.
+
+GENERATE_AUTOGEN_DEF = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to Sqlite3 output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_SQLITE3 tag is set to YES doxygen will generate a Sqlite3
+# database with symbols found by doxygen stored in tables.
+# The default value is: NO.
+
+GENERATE_SQLITE3 = NO
+
+# The SQLITE3_OUTPUT tag is used to specify where the Sqlite3 database will be
+# put. If a relative path is entered the value of OUTPUT_DIRECTORY will be put
+# in front of it.
+# The default directory is: sqlite3.
+# This tag requires that the tag GENERATE_SQLITE3 is set to YES.
+
+SQLITE3_OUTPUT = sqlite3
+
+# The SQLITE3_RECREATE_DB tag is set to YES, the existing doxygen_sqlite3.db
+# database file will be recreated with each doxygen run. If set to NO, doxygen
+# will warn if a database file is already found and not modify it.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_SQLITE3 is set to YES.
+
+SQLITE3_RECREATE_DB = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES, doxygen will generate a Perl module
+# file that captures the structure of the code including all documentation.
+#
+# Note that this feature is still experimental and incomplete at the moment.
+# The default value is: NO.
+
+GENERATE_PERLMOD = NO
+
+# If the PERLMOD_LATEX tag is set to YES, doxygen will generate the necessary
+# Makefile rules, Perl scripts and LaTeX code to be able to generate PDF and DVI
+# output from the Perl module output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_LATEX = NO
+
+# If the PERLMOD_PRETTY tag is set to YES, the Perl module output will be nicely
+# formatted so it can be parsed by a human reader. This is useful if you want to
+# understand what is going on. On the other hand, if this tag is set to NO, the
+# size of the Perl module output will be much smaller and Perl will parse it
+# just the same.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_PRETTY = YES
+
+# The names of the make variables in the generated doxyrules.make file are
+# prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. This is useful
+# so different doxyrules.make files included by the same Makefile don't
+# overwrite each other's variables.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES, doxygen will evaluate all
+# C-preprocessor directives found in the sources and include files.
+# The default value is: YES.
+
+ENABLE_PREPROCESSING = YES
+
+# If the MACRO_EXPANSION tag is set to YES, doxygen will expand all macro names
+# in the source code. If set to NO, only conditional compilation will be
+# performed. Macro expansion can be done in a controlled way by setting
+# EXPAND_ONLY_PREDEF to YES.
+# The default value is: NO.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+MACRO_EXPANSION = YES
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then
+# the macro expansion is limited to the macros specified with the PREDEFINED and
+# EXPAND_AS_DEFINED tags.
+# The default value is: NO.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+EXPAND_ONLY_PREDEF = YES
+
+# If the SEARCH_INCLUDES tag is set to YES, the include files in the
+# INCLUDE_PATH will be searched if a #include is found.
+# The default value is: YES.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+SEARCH_INCLUDES = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by the
+# preprocessor. Note that the INCLUDE_PATH is not recursive, so the setting of
+# RECURSIVE has no effect here.
+# This tag requires that the tag SEARCH_INCLUDES is set to YES.
+
+INCLUDE_PATH =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will be
+# used.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+INCLUDE_FILE_PATTERNS =
+
+# The PREDEFINED tag can be used to specify one or more macro names that are
+# defined before the preprocessor is started (similar to the -D option of e.g.
+# gcc). The argument of the tag is a list of macros of the form: name or
+# name=definition (no spaces). If the definition and the "=" are omitted, "=1"
+# is assumed. To prevent a macro definition from being undefined via #undef or
+# recursively expanded use the := operator instead of the = operator.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+PREDEFINED =
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
+# tag can be used to specify a list of macro names that should be expanded. The
+# macro definition that is found in the sources will be used. Use the PREDEFINED
+# tag if you want to use a different macro definition that overrules the
+# definition found in the source code.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+EXPAND_AS_DEFINED =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will
+# remove all references to function-like macros that are alone on a line, have
+# an all uppercase name, and do not end with a semicolon. Such function macros
+# are typically used for boiler-plate code, and will confuse the parser if not
+# removed.
+# The default value is: YES.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+SKIP_FUNCTION_MACROS = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES tag can be used to specify one or more tag files. For each tag
+# file the location of the external documentation should be added. The format of
+# a tag file without this location is as follows:
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where loc1 and loc2 can be relative or absolute paths or URLs. See the
+# section "Linking to external documentation" for more information about the use
+# of tag files.
+# Note: Each tag file must have a unique name (where the name does NOT include
+# the path). If a tag file is not located in the directory in which doxygen is
+# run, you must also specify the path to the tagfile here.
+
+TAGFILES =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create a
+# tag file that is based on the input files it reads. See section "Linking to
+# external documentation" for more information about the usage of tag files.
+
+GENERATE_TAGFILE =
+
+# If the ALLEXTERNALS tag is set to YES, all external classes and namespaces
+# will be listed in the class and namespace index. If set to NO, only the
+# inherited external classes will be listed.
+# The default value is: NO.
+
+ALLEXTERNALS = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES, all external groups will be listed
+# in the topic index. If set to NO, only the current project's groups will be
+# listed.
+# The default value is: YES.
+
+EXTERNAL_GROUPS = YES
+
+# If the EXTERNAL_PAGES tag is set to YES, all external pages will be listed in
+# the related pages index. If set to NO, only the current project's pages will
+# be listed.
+# The default value is: YES.
+
+EXTERNAL_PAGES = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to diagram generator tools
+#---------------------------------------------------------------------------
+
+# If set to YES the inheritance and collaboration graphs will hide inheritance
+# and usage relations if the target is undocumented or is not a class.
+# The default value is: YES.
+
+HIDE_UNDOC_RELATIONS = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz (see:
+# https://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent
+# Bell Labs. The other options in this section have no effect if this option is
+# set to NO
+# The default value is: NO.
+
+HAVE_DOT = YES
+
+# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is allowed
+# to run in parallel. When set to 0 doxygen will base this on the number of
+# processors available in the system. You can set it explicitly to a value
+# larger than 0 to get control over the balance between CPU load and processing
+# speed.
+# Minimum value: 0, maximum value: 32, default value: 0.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_NUM_THREADS = 0
+
+# DOT_COMMON_ATTR is common attributes for nodes, edges and labels of
+# subgraphs. When you want a differently looking font in the dot files that
+# doxygen generates you can specify fontname, fontcolor and fontsize attributes.
+# For details please see <a href=https://graphviz.org/doc/info/attrs.html>Node,
+# Edge and Graph Attributes specification</a> You need to make sure dot is able
+# to find the font, which can be done by putting it in a standard location or by
+# setting the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the
+# directory containing the font. Default graphviz fontsize is 14.
+# The default value is: fontname=Helvetica,fontsize=10.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_COMMON_ATTR = "fontname=Helvetica,fontsize=10"
+
+# DOT_EDGE_ATTR is concatenated with DOT_COMMON_ATTR. For elegant style you can
+# add 'arrowhead=open, arrowtail=open, arrowsize=0.5'. <a
+# href=https://graphviz.org/doc/info/arrows.html>Complete documentation about
+# arrows shapes.</a>
+# The default value is: labelfontname=Helvetica,labelfontsize=10.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_EDGE_ATTR = "labelfontname=Helvetica,labelfontsize=10"
+
+# DOT_NODE_ATTR is concatenated with DOT_COMMON_ATTR. For view without boxes
+# around nodes set 'shape=plain' or 'shape=plaintext' <a
+# href=https://www.graphviz.org/doc/info/shapes.html>Shapes specification</a>
+# The default value is: shape=box,height=0.2,width=0.4.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_NODE_ATTR = "shape=box,height=0.2,width=0.4"
+
+# You can set the path where dot can find font specified with fontname in
+# DOT_COMMON_ATTR and others dot attributes.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTPATH =
+
+# If the CLASS_GRAPH tag is set to YES or GRAPH or BUILTIN then doxygen will
+# generate a graph for each documented class showing the direct and indirect
+# inheritance relations. In case the CLASS_GRAPH tag is set to YES or GRAPH and
+# HAVE_DOT is enabled as well, then dot will be used to draw the graph. In case
+# the CLASS_GRAPH tag is set to YES and HAVE_DOT is disabled or if the
+# CLASS_GRAPH tag is set to BUILTIN, then the built-in generator will be used.
+# If the CLASS_GRAPH tag is set to TEXT the direct and indirect inheritance
+# relations will be shown as texts / links. Explicit enabling an inheritance
+# graph or choosing a different representation for an inheritance graph of a
+# specific class, can be accomplished by means of the command \inheritancegraph.
+# Disabling an inheritance graph can be accomplished by means of the command
+# \hideinheritancegraph.
+# Possible values are: NO, YES, TEXT, GRAPH and BUILTIN.
+# The default value is: YES.
+
+CLASS_GRAPH = YES
+
+# If the COLLABORATION_GRAPH tag is set to YES then doxygen will generate a
+# graph for each documented class showing the direct and indirect implementation
+# dependencies (inheritance, containment, and class references variables) of the
+# class with other documented classes. Explicit enabling a collaboration graph,
+# when COLLABORATION_GRAPH is set to NO, can be accomplished by means of the
+# command \collaborationgraph. Disabling a collaboration graph can be
+# accomplished by means of the command \hidecollaborationgraph.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+COLLABORATION_GRAPH = NO
+
+# If the GROUP_GRAPHS tag is set to YES then doxygen will generate a graph for
+# groups, showing the direct groups dependencies. Explicit enabling a group
+# dependency graph, when GROUP_GRAPHS is set to NO, can be accomplished by means
+# of the command \groupgraph. Disabling a directory graph can be accomplished by
+# means of the command \hidegroupgraph. See also the chapter Grouping in the
+# manual.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GROUP_GRAPHS = YES
+
+# If the UML_LOOK tag is set to YES, doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+UML_LOOK = NO
+
+# If the UML_LOOK tag is enabled, the fields and methods are shown inside the
+# class node. If there are many fields or methods and many nodes the graph may
+# become too big to be useful. The UML_LIMIT_NUM_FIELDS threshold limits the
+# number of items for each type to make the size more manageable. Set this to 0
+# for no limit. Note that the threshold may be exceeded by 50% before the limit
+# is enforced. So when you set the threshold to 10, up to 15 fields may appear,
+# but if the number exceeds 15, the total amount of fields shown is limited to
+# 10.
+# Minimum value: 0, maximum value: 100, default value: 10.
+# This tag requires that the tag UML_LOOK is set to YES.
+
+UML_LIMIT_NUM_FIELDS = 10
+
+# If the DOT_UML_DETAILS tag is set to NO, doxygen will show attributes and
+# methods without types and arguments in the UML graphs. If the DOT_UML_DETAILS
+# tag is set to YES, doxygen will add type and arguments for attributes and
+# methods in the UML graphs. If the DOT_UML_DETAILS tag is set to NONE, doxygen
+# will not generate fields with class member information in the UML graphs. The
+# class diagrams will look similar to the default class diagrams but using UML
+# notation for the relationships.
+# Possible values are: NO, YES and NONE.
+# The default value is: NO.
+# This tag requires that the tag UML_LOOK is set to YES.
+
+DOT_UML_DETAILS = NO
+
+# The DOT_WRAP_THRESHOLD tag can be used to set the maximum number of characters
+# to display on a single line. If the actual line length exceeds this threshold
+# significantly it will be wrapped across multiple lines. Some heuristics are
+# applied to avoid ugly line breaks.
+# Minimum value: 0, maximum value: 1000, default value: 17.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_WRAP_THRESHOLD = 17
+
+# If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and
+# collaboration graphs will show the relations between templates and their
+# instances.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+TEMPLATE_RELATIONS = NO
+
+# If the INCLUDE_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are set to
+# YES then doxygen will generate a graph for each documented file showing the
+# direct and indirect include dependencies of the file with other documented
+# files. Explicit enabling an include graph, when INCLUDE_GRAPH is is set to NO,
+# can be accomplished by means of the command \includegraph. Disabling an
+# include graph can be accomplished by means of the command \hideincludegraph.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INCLUDE_GRAPH = YES
+
+# If the INCLUDED_BY_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are
+# set to YES then doxygen will generate a graph for each documented file showing
+# the direct and indirect include dependencies of the file with other documented
+# files. Explicit enabling an included by graph, when INCLUDED_BY_GRAPH is set
+# to NO, can be accomplished by means of the command \includedbygraph. Disabling
+# an included by graph can be accomplished by means of the command
+# \hideincludedbygraph.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INCLUDED_BY_GRAPH = YES
+
+# If the CALL_GRAPH tag is set to YES then doxygen will generate a call
+# dependency graph for every global function or class method.
+#
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable call graphs for selected
+# functions only using the \callgraph command. Disabling a call graph can be
+# accomplished by means of the command \hidecallgraph.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CALL_GRAPH = YES
+
+# If the CALLER_GRAPH tag is set to YES then doxygen will generate a caller
+# dependency graph for every global function or class method.
+#
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable caller graphs for selected
+# functions only using the \callergraph command. Disabling a caller graph can be
+# accomplished by means of the command \hidecallergraph.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CALLER_GRAPH = NO
+
+# If the GRAPHICAL_HIERARCHY tag is set to YES then doxygen will graphical
+# hierarchy of all classes instead of a textual one.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GRAPHICAL_HIERARCHY = YES
+
+# If the DIRECTORY_GRAPH tag is set to YES then doxygen will show the
+# dependencies a directory has on other directories in a graphical way. The
+# dependency relations are determined by the #include relations between the
+# files in the directories. Explicit enabling a directory graph, when
+# DIRECTORY_GRAPH is set to NO, can be accomplished by means of the command
+# \directorygraph. Disabling a directory graph can be accomplished by means of
+# the command \hidedirectorygraph.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DIRECTORY_GRAPH = YES
+
+# The DIR_GRAPH_MAX_DEPTH tag can be used to limit the maximum number of levels
+# of child directories generated in directory dependency graphs by dot.
+# Minimum value: 1, maximum value: 25, default value: 1.
+# This tag requires that the tag DIRECTORY_GRAPH is set to YES.
+
+DIR_GRAPH_MAX_DEPTH = 1
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot. For an explanation of the image formats see the section
+# output formats in the documentation of the dot tool (Graphviz (see:
+# https://www.graphviz.org/)).
+# Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order
+# to make the SVG files visible in IE 9+ (other browsers do not have this
+# requirement).
+# Possible values are: png, jpg, gif, svg, png:gd, png:gd:gd, png:cairo,
+# png:cairo:gd, png:cairo:cairo, png:cairo:gdiplus, png:gdiplus and
+# png:gdiplus:gdiplus.
+# The default value is: png.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_IMAGE_FORMAT = png
+
+# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to
+# enable generation of interactive SVG images that allow zooming and panning.
+#
+# Note that this requires a modern browser other than Internet Explorer. Tested
+# and working are Firefox, Chrome, Safari, and Opera.
+# Note: For IE 9+ you need to set HTML_FILE_EXTENSION to xhtml in order to make
+# the SVG files visible. Older versions of IE do not have SVG support.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INTERACTIVE_SVG = NO
+
+# The DOT_PATH tag can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_PATH =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the \dotfile
+# command).
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOTFILE_DIRS =
+
+# You can include diagrams made with dia in doxygen documentation. Doxygen will
+# then run dia to produce the diagram and insert it in the documentation. The
+# DIA_PATH tag allows you to specify the directory where the dia binary resides.
+# If left empty dia is assumed to be found in the default search path.
+
+DIA_PATH =
+
+# The DIAFILE_DIRS tag can be used to specify one or more directories that
+# contain dia files that are included in the documentation (see the \diafile
+# command).
+
+DIAFILE_DIRS =
+
+# When using plantuml, the PLANTUML_JAR_PATH tag should be used to specify the
+# path where java can find the plantuml.jar file or to the filename of jar file
+# to be used. If left blank, it is assumed PlantUML is not used or called during
+# a preprocessing step. Doxygen will generate a warning when it encounters a
+# \startuml command in this case and will not generate output for the diagram.
+
+PLANTUML_JAR_PATH =
+
+# When using plantuml, the PLANTUML_CFG_FILE tag can be used to specify a
+# configuration file for plantuml.
+
+PLANTUML_CFG_FILE =
+
+# When using plantuml, the specified paths are searched for files specified by
+# the !include statement in a plantuml block.
+
+PLANTUML_INCLUDE_PATH =
+
+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes
+# that will be shown in the graph. If the number of nodes in a graph becomes
+# larger than this value, doxygen will truncate the graph, which is visualized
+# by representing a node as a red box. Note that doxygen if the number of direct
+# children of the root node in a graph is already larger than
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note that
+# the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+# Minimum value: 0, maximum value: 10000, default value: 50.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_GRAPH_MAX_NODES = 400
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the graphs
+# generated by dot. A depth value of 3 means that only nodes reachable from the
+# root by following a path via at most 3 edges will be shown. Nodes that lay
+# further from the root node will be omitted. Note that setting this option to 1
+# or 2 may greatly reduce the computation time needed for large code bases. Also
+# note that the size of a graph can be further restricted by
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+# Minimum value: 0, maximum value: 1000, default value: 0.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+MAX_DOT_GRAPH_DEPTH = 0
+
+# Set the DOT_MULTI_TARGETS tag to YES to allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10) support
+# this, this feature is disabled by default.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_MULTI_TARGETS = NO
+
+# If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page
+# explaining the meaning of the various boxes and arrows in the dot generated
+# graphs.
+# Note: This tag requires that UML_LOOK isn't set, i.e. the doxygen internal
+# graphical representation for inheritance and collaboration diagrams is used.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GENERATE_LEGEND = YES
+
+# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate
+# files that are used to generate the various graphs.
+#
+# Note: This setting is not only used for dot files but also for msc temporary
+# files.
+# The default value is: YES.
+
+DOT_CLEANUP = YES
+
+# You can define message sequence charts within doxygen comments using the \msc
+# command. If the MSCGEN_TOOL tag is left empty (the default), then doxygen will
+# use a built-in version of mscgen tool to produce the charts. Alternatively,
+# the MSCGEN_TOOL tag can also specify the name an external tool. For instance,
+# specifying prog as the value, doxygen will call the tool as prog -T
+# <outfile_format> -o <outputfile> <inputfile>. The external tool should support
+# output file formats "png", "eps", "svg", and "ismap".
+
+MSCGEN_TOOL =
+
+# The MSCFILE_DIRS tag can be used to specify one or more directories that
+# contain msc files that are included in the documentation (see the \mscfile
+# command).
+
+MSCFILE_DIRS =
diff --git a/doc/devel/Doxyfile-xml b/doc/devel/Doxyfile-xml
new file mode 100644
index 0000000..ae5be8a
--- /dev/null
+++ b/doc/devel/Doxyfile-xml
@@ -0,0 +1,7 @@
+# This is a doxygen configuration for generating XML output as well as HTML.
+#
+# Inherit everything from our default Doxyfile except GENERATE_XML, which
+# will be reset to YES
+
+@INCLUDE = Doxyfile
+GENERATE_XML = YES
diff --git a/doc/devel/Makefile.am b/doc/devel/Makefile.am
new file mode 100644
index 0000000..30d819b
--- /dev/null
+++ b/doc/devel/Makefile.am
@@ -0,0 +1,25 @@
+EXTRA_DIST =
+EXTRA_DIST += Doxyfile Doxyfile-xml
+EXTRA_DIST += bison.dox
+EXTRA_DIST += config-backend.dox
+EXTRA_DIST += congestion-handling.dox
+EXTRA_DIST += contribute.dox
+EXTRA_DIST += cross-compile.dox
+EXTRA_DIST += debug.dox
+EXTRA_DIST += doc.dox
+EXTRA_DIST += fuzz.dox
+EXTRA_DIST += mainpage.dox
+EXTRA_DIST += qa.dox
+EXTRA_DIST += terminology.dox
+EXTRA_DIST += unit-tests.dox
+EXTRA_DIST += performance.dox
+
+all: # do nothing, used only by developers manually
+
+devel:
+ mkdir -p $(builddir)/html
+ (cat $(srcdir)/Doxyfile; echo PROJECT_NUMBER=$(PACKAGE_VERSION)) | doxygen - > $(builddir)/html/doxygen.log 2> $(builddir)/html/doxygen-error.log
+ echo `grep -i ": warning:" $(builddir)/html/doxygen-error.log | wc -l` warnings/errors detected.
+
+clean-local:
+ rm -rf html
diff --git a/doc/devel/Makefile.in b/doc/devel/Makefile.in
new file mode 100644
index 0000000..98cf008
--- /dev/null
+++ b/doc/devel/Makefile.in
@@ -0,0 +1,566 @@
+# Makefile.in generated by automake 1.16.5 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2021 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+VPATH = @srcdir@
+am__is_gnu_make = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = doc/devel
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4macros/ax_boost_for_kea.m4 \
+ $(top_srcdir)/m4macros/ax_cpp14.m4 \
+ $(top_srcdir)/m4macros/ax_cpp20.m4 \
+ $(top_srcdir)/m4macros/ax_crypto.m4 \
+ $(top_srcdir)/m4macros/ax_find_library.m4 \
+ $(top_srcdir)/m4macros/ax_gssapi.m4 \
+ $(top_srcdir)/m4macros/ax_gtest.m4 \
+ $(top_srcdir)/m4macros/ax_isc_rpath.m4 \
+ $(top_srcdir)/m4macros/ax_netconf.m4 \
+ $(top_srcdir)/m4macros/libtool.m4 \
+ $(top_srcdir)/m4macros/ltoptions.m4 \
+ $(top_srcdir)/m4macros/ltsugar.m4 \
+ $(top_srcdir)/m4macros/ltversion.m4 \
+ $(top_srcdir)/m4macros/lt~obsolete.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
+SOURCES =
+DIST_SOURCES =
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+am__DIST_COMMON = $(srcdir)/Makefile.in README
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+ASCIIDOC = @ASCIIDOC@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BOOST_INCLUDES = @BOOST_INCLUDES@
+BOOST_LIBS = @BOOST_LIBS@
+BOTAN_TOOL = @BOTAN_TOOL@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CONTRIB_DIR = @CONTRIB_DIR@
+CPPFLAGS = @CPPFLAGS@
+CRYPTO_CFLAGS = @CRYPTO_CFLAGS@
+CRYPTO_INCLUDES = @CRYPTO_INCLUDES@
+CRYPTO_LDFLAGS = @CRYPTO_LDFLAGS@
+CRYPTO_LIBS = @CRYPTO_LIBS@
+CRYPTO_PACKAGE = @CRYPTO_PACKAGE@
+CRYPTO_RPATH = @CRYPTO_RPATH@
+CSCOPE = @CSCOPE@
+CTAGS = @CTAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DISTCHECK_BOOST_CONFIGURE_FLAG = @DISTCHECK_BOOST_CONFIGURE_FLAG@
+DISTCHECK_CONTRIB_CONFIGURE_FLAG = @DISTCHECK_CONTRIB_CONFIGURE_FLAG@
+DISTCHECK_CRYPTO_CONFIGURE_FLAG = @DISTCHECK_CRYPTO_CONFIGURE_FLAG@
+DISTCHECK_GSSAPI_CONFIGURE_FLAG = @DISTCHECK_GSSAPI_CONFIGURE_FLAG@
+DISTCHECK_GTEST_CONFIGURE_FLAG = @DISTCHECK_GTEST_CONFIGURE_FLAG@
+DISTCHECK_KEA_SHELL_CONFIGURE_FLAG = @DISTCHECK_KEA_SHELL_CONFIGURE_FLAG@
+DISTCHECK_LIBYANGCPP_CONFIGURE_FLAG = @DISTCHECK_LIBYANGCPP_CONFIGURE_FLAG@
+DISTCHECK_LIBYANG_CONFIGURE_FLAG = @DISTCHECK_LIBYANG_CONFIGURE_FLAG@
+DISTCHECK_LOG4CPLUS_CONFIGURE_FLAG = @DISTCHECK_LOG4CPLUS_CONFIGURE_FLAG@
+DISTCHECK_MYSQL_CONFIGURE_FLAG = @DISTCHECK_MYSQL_CONFIGURE_FLAG@
+DISTCHECK_PERFDHCP_CONFIGURE_FLAG = @DISTCHECK_PERFDHCP_CONFIGURE_FLAG@
+DISTCHECK_PGSQL_CONFIGURE_FLAG = @DISTCHECK_PGSQL_CONFIGURE_FLAG@
+DISTCHECK_PREMIUM_CONFIGURE_FLAG = @DISTCHECK_PREMIUM_CONFIGURE_FLAG@
+DISTCHECK_SYSREPOCPP_CONFIGURE_FLAG = @DISTCHECK_SYSREPOCPP_CONFIGURE_FLAG@
+DISTCHECK_SYSREPO_CONFIGURE_FLAG = @DISTCHECK_SYSREPO_CONFIGURE_FLAG@
+DLLTOOL = @DLLTOOL@
+DPKG = @DPKG@
+DPKGQUERY = @DPKGQUERY@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+ETAGS = @ETAGS@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+FILECMD = @FILECMD@
+GENHTML = @GENHTML@
+GREP = @GREP@
+GSSAPI_CFLAGS = @GSSAPI_CFLAGS@
+GSSAPI_LIBS = @GSSAPI_LIBS@
+GTEST_CONFIG = @GTEST_CONFIG@
+GTEST_INCLUDES = @GTEST_INCLUDES@
+GTEST_LDADD = @GTEST_LDADD@
+GTEST_LDFLAGS = @GTEST_LDFLAGS@
+GTEST_SOURCE = @GTEST_SOURCE@
+HAVE_NETCONF = @HAVE_NETCONF@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+KEA_CXXFLAGS = @KEA_CXXFLAGS@
+KEA_SRCID = @KEA_SRCID@
+KRB5_CONFIG = @KRB5_CONFIG@
+LCOV = @LCOV@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIBYANGCPP_CPPFLAGS = @LIBYANGCPP_CPPFLAGS@
+LIBYANGCPP_INCLUDEDIR = @LIBYANGCPP_INCLUDEDIR@
+LIBYANGCPP_LIBS = @LIBYANGCPP_LIBS@
+LIBYANGCPP_PREFIX = @LIBYANGCPP_PREFIX@
+LIBYANGCPP_VERSION = @LIBYANGCPP_VERSION@
+LIBYANG_CPPFLAGS = @LIBYANG_CPPFLAGS@
+LIBYANG_INCLUDEDIR = @LIBYANG_INCLUDEDIR@
+LIBYANG_LIBS = @LIBYANG_LIBS@
+LIBYANG_PREFIX = @LIBYANG_PREFIX@
+LIBYANG_VERSION = @LIBYANG_VERSION@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LOG4CPLUS_INCLUDES = @LOG4CPLUS_INCLUDES@
+LOG4CPLUS_LIBS = @LOG4CPLUS_LIBS@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQL_CPPFLAGS = @MYSQL_CPPFLAGS@
+MYSQL_LIBS = @MYSQL_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PACKAGE_VERSION_TYPE = @PACKAGE_VERSION_TYPE@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PDFLATEX = @PDFLATEX@
+PERL = @PERL@
+PGSQL_CPPFLAGS = @PGSQL_CPPFLAGS@
+PGSQL_LIBS = @PGSQL_LIBS@
+PKGPYTHONDIR = @PKGPYTHONDIR@
+PKG_CONFIG = @PKG_CONFIG@
+PLANTUML = @PLANTUML@
+PREMIUM_DIR = @PREMIUM_DIR@
+PYTHON = @PYTHON@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+RANLIB = @RANLIB@
+SED = @SED@
+SEP = @SEP@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SPHINXBUILD = @SPHINXBUILD@
+SRPD_PLUGINS_PATH = @SRPD_PLUGINS_PATH@
+SR_PLUGINS_PATH = @SR_PLUGINS_PATH@
+SR_REPO_PATH = @SR_REPO_PATH@
+STRIP = @STRIP@
+SYSREPOCPP_CPPFLAGS = @SYSREPOCPP_CPPFLAGS@
+SYSREPOCPP_INCLUDEDIR = @SYSREPOCPP_INCLUDEDIR@
+SYSREPOCPP_LIBS = @SYSREPOCPP_LIBS@
+SYSREPOCPP_PREFIX = @SYSREPOCPP_PREFIX@
+SYSREPOCPP_VERSION = @SYSREPOCPP_VERSION@
+SYSREPO_CPPFLAGS = @SYSREPO_CPPFLAGS@
+SYSREPO_INCLUDEDIR = @SYSREPO_INCLUDEDIR@
+SYSREPO_LIBS = @SYSREPO_LIBS@
+SYSREPO_PREFIX = @SYSREPO_PREFIX@
+SYSREPO_VERSION = @SYSREPO_VERSION@
+USE_LCOV = @USE_LCOV@
+VALGRIND = @VALGRIND@
+VERSION = @VERSION@
+WARNING_GCC_44_STRICT_ALIASING_CFLAG = @WARNING_GCC_44_STRICT_ALIASING_CFLAG@
+XMLLINT = @XMLLINT@
+YACC = @YACC@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+EXTRA_DIST = Doxyfile Doxyfile-xml bison.dox config-backend.dox \
+ congestion-handling.dox contribute.dox cross-compile.dox \
+ debug.dox doc.dox fuzz.dox mainpage.dox qa.dox terminology.dox \
+ unit-tests.dox performance.dox
+all: all-am
+
+.SUFFIXES:
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign doc/devel/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --foreign doc/devel/Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+tags TAGS:
+
+ctags CTAGS:
+
+cscope cscopelist:
+
+distdir: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-local mostlyclean-am
+
+distclean: distclean-am
+ -rm -f Makefile
+distclean-am: clean-am distclean-generic
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-generic mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: install-am install-strip
+
+.PHONY: all all-am check check-am clean clean-generic clean-libtool \
+ clean-local cscopelist-am ctags-am distclean distclean-generic \
+ distclean-libtool distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am install-man \
+ install-pdf install-pdf-am install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+ tags-am uninstall uninstall-am
+
+.PRECIOUS: Makefile
+
+
+all: # do nothing, used only by developers manually
+
+devel:
+ mkdir -p $(builddir)/html
+ (cat $(srcdir)/Doxyfile; echo PROJECT_NUMBER=$(PACKAGE_VERSION)) | doxygen - > $(builddir)/html/doxygen.log 2> $(builddir)/html/doxygen-error.log
+ echo `grep -i ": warning:" $(builddir)/html/doxygen-error.log | wc -l` warnings/errors detected.
+
+clean-local:
+ rm -rf html
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/doc/devel/README b/doc/devel/README
new file mode 100644
index 0000000..4cb53d4
--- /dev/null
+++ b/doc/devel/README
@@ -0,0 +1,5 @@
+This is a folder with content for Doxygen.
+This is used by developers and is not used directly in official builds.
+
+To build doxygen documentation run:
+make devel
diff --git a/doc/devel/bison.dox b/doc/devel/bison.dox
new file mode 100644
index 0000000..4c96302
--- /dev/null
+++ b/doc/devel/bison.dox
@@ -0,0 +1,450 @@
+// Copyright (C) 2017-2021 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+/**
+@page parser Flex/Bison Parsers
+
+@section parserIntro Parser background
+
+Kea's data format of choice is JSON (defined in https://tools.ietf.org/html/rfc7159), which is used
+in configuration files, in the command channel and also when communicating between the DHCP servers
+and the DHCP-DDNS component. It is almost certain to be used as the data format for any new
+features.
+
+Historically, Kea used the @ref isc::data::Element::fromJSON and @ref
+isc::data::Element::fromJSONFile methods to parse data expected to be in JSON syntax. This in-house
+parser was developed back in the early days of Kea when it was part of BIND 10. Its main advantages
+were that it didn't have any external dependencies and that it was already available in the source
+tree when Kea development started. On the other hand, it was very difficult to modify (several
+attempts to implement more robust comments had failed) and lacked a number of features. Also, it was
+a pure JSON parser, so accepted anything as long as the content was correct JSON. (This caused some
+problems: for example, the syntactic checks were conducted late in the parsing process, by which
+time some of the information, e.g. line numbers, was no longer available. To print meaningful error
+messages, the Kea team had to develop a way to store filename, line and column information.
+Unfortunately this gave rise to other problems such as data duplication.) The output from these
+parsers was a tree of @ref isc::data::Element objects using shared pointers. This part of the
+processing we can refer to as phase 1.
+
+The Element tree was then processed by set of dedicated parsers. Each
+parser was able to handle its own context, e.g. global, subnet list,
+subnet, pool etc. This step took the tree generated in phase 1, parsed
+it and generated an output configuration (e.g. @ref
+isc::dhcp::SrvConfig) or dynamic structures
+(e.g. isc::data::Host). During this stage, a large number of parser
+objects derived from DhcpConfigParser could be instantiated for each
+scope and instance of data (e.g. to parse 1000 host reservation
+entries a thousand dedicated parsers were created). For convenience,
+this step is called phase 2.
+
+Other issues with the old parsers are discussed here: @ref dhcpv6ConfigParserBison (this section is
+focused on DHCPv6, but the same issues affected DHCPv4 and D2) and here:
+https://gitlab.isc.org/isc-projects/kea/wikis/designs/simple-parser-design.
+
+@section parserBisonIntro Flex/Bison Based Parser
+
+To solve the issue of phase 1 mentioned earlier, a new parser has been developed that is based on
+the "flex and "bison" tools. The following text uses DHCPv6 as an example, but the same principle
+applies to DHCPv4 and D2; CA will likely to follow. The new parser consists of two core elements
+with a wrapper around them. The following descriptions are slightly oversimplified in order to
+convey the intent; a more detailed description is available in subsequent sections.
+
+-# Flex lexical analyzer (src/bin/dhcp6/dhcp6_lexer.ll): this is essentially a set of
+ regular expressions and C++ code that creates new tokens that represent whatever
+ was just parsed. This lexical analyzer (lexer) will be called iteratively by bison until the whole
+ input text is parsed or an error is encountered. For example, a snippet of the
+ code might look like this:
+ @code
+ \"socket-type\" {
+ return isc::dhcp::Dhcp6Parser::make_SOCKET_TYPE(driver.loc_);
+ }
+ @endcode
+ This tells the flex that if encounters "socket-type" (quoted), then it should
+ create a token SOCKET_TYPE and pass to it its current location (that's the
+ file name, line and column numbers).
+
+-# Bison grammar (src/bin/dhcp6/dhcp6_parser.yy): the module that defines the syntax. Grammar and
+ syntax are perhaps fancy words, but they simply define what is allowed and where. Bison grammar
+ starts with a list of tokens. Those tokens are defined only by name ("here's the list of possible
+ tokens that could appear"). What constitutes a token is actually defined in the lexer. The
+ grammar define how the incoming tokens are expected to fall into their places together. Let's
+ take an example of the following input text:
+ @code
+ {
+ "Dhcp6":
+ {
+ "renew-timer": 100
+ }
+ }
+ @endcode
+ The lexer would generate the following sequence of tokens: LCURLY_BRACKET, DHCP6, COLON,
+ LCURLY_BRACKET, RENEW_TIMER, COLON, INTEGER (a token with a value of 100), RCURLY_BRACKET,
+ RCURLY_BRACKET, END. The bison grammar recognizes that the sequence forms a valid sentence and
+ that there are no errors and act upon it. (Whereas if the left and right braces in the above
+ example were exchanged, the bison module would identify the sequence as syntactically incorrect.)
+
+-# Parser context. As there is some information that needs to be passed between parser and lexer,
+ @ref isc::dhcp::Parser6Context is a convenience wrapper around those two bundled together. It
+ also works as a nice encapsulation, hiding all the flex/bison details underneath.
+
+@section parserBuild Building Flex/Bison Code
+
+The only input file used by flex is the .ll file and the only input file used by bison is the .yy
+file. When making changes to the lexer or parser, only those two files are edited. When processed,
+the two tools generate a number of .h, .hh and .cc files. The major ones have the same name as their
+.ll and .yy counterparts (e.g. dhcp6_lexer.cc, dhcp6_parser.cc and dhcp6_parser.h etc.), but an
+additional file is also created: location.hh. Those are internal bison headers that are needed for
+compilation.
+
+To avoid the need for every user to have flex and bison installed, the output files are generated
+when the .ll or .yy files are altered and are stored in the Kea repository. To generate those files,
+issue the following sequence of commands from the top-level Kea directory:
+
+@code
+./configure --enable-generate-parser
+cd src/bin/dhcp6
+make parser
+@endcode
+
+Strictly speaking, the comment "make parser" is not necessary. If you updated the .ll or .yy file,
+the regular "make" command should pick those changes up. However, since one source file generates
+multiple output files and you are likely to be using a multi-process build (by specifying the "-j"
+switch on the "make" command), there may be odd side effects: explicitly rebuilding the files
+manually by using "make parser" avoids any trouble.
+
+One problem brought on by use of flex/bison is tool version dependency. If one developer uses
+version A of those tools and another developer uses B, the files generated by the different version
+may be significantly different. This causes all sorts of problems, e.g. coverity/cpp-check issues
+may appear and disappear: in short, it can cause all sorts of general unhappiness. To avoid those
+problems, the Kea team generates the flex/bison files on a dedicated machine. See KeaRegen page
+on ISC internal wiki for details.
+
+@section parserFlex Flex Detailed
+
+Earlier sections described the lexer in a bit of an over-simplified way. The .ll file contains a
+number of elements in addition to the regular expressions and they're not as simple as was
+described.
+
+The file starts with a number of sections separated by percent (%) signs. Depending on which section
+code is written in, it may be interpreted by flex, copied verbatim to the output .cc file, copied to
+the output .h file or copied to both.
+
+There is an initial section that defines flex options. These are somewhat documented, but the
+documentation for it may be a bit cryptic. When developing new parsers, it's best to start by
+copying whatever we have for DHCPv6 and tweak as needed.
+
+Next comes the flex conditions. They are defined with %%x and they define a state of the lexer. A
+good example of a state may be comment. Once the lexer detects that a comment's beginning, it
+switches to a certain condition (by calling BEGIN(COMMENT) for example) and the code then ignores
+whatever follows (especially strings that look like valid tokens) until the comment is closed (when
+it returns to the default condition by calling BEGIN(INITIAL)). This is something that is not
+frequently used and the only use cases for it are the forementioned comments and file inclusions.
+
+After this come the syntactic contexts. Let's assume we have a parser that uses an "ip-address"
+regular expression (regexp) that would return the IP_ADDRESS token. Whenever we want to allow
+"ip-address", the grammar allows the IP_ADDRESS token to appear. When the lexer is called, it will
+match the regexp, generate the IP_ADDRESS token and the parser will carry out its duty. This works
+fine as long as you have very specific grammar that defines everything. Sadly, that's not the case
+in DHCP as we have hooks. Hook libraries can have parameters that are defined by third party
+developers and they can pick whatever parameter names they want, including "ip-address". Another
+example could be Dhcp4 and Dhcp6 configurations defined in a single file. The grammar defining
+"Dhcp6" main contain a clause that says "Dhcp4" may contain any generic JSON. However, the lexer may
+find the "ip-address" string in the "Dhcp4" configuration and will say that it's not a part of
+generic JSON, but a dedicated IP_ADDRESS token instead. The parser will then complain and the whole
+thing would end up in failure. It was to solve this problem that syntactic contexts were introduced.
+They tell the lexer whether input strings have specific or generic meaning. For example, when
+parsing host reservations, the lexer is expected to report the IP_ADDRESS token if "ip-address" is
+detected. However, when parsing generic JSON, upon encountering "ip-address" it should return a
+STRING with a value of "ip-address". The list of all contexts is enumerated in @ref
+isc::dhcp::Parser6Context::ParserContext.
+
+For a DHCPv6-specific description of the conflict avoidance, see @ref dhcp6ParserConflicts.
+
+@section parserGrammar Bison Grammar
+
+Bison has much better documentation than flex. Its latest version seems to be available here:
+https://www.gnu.org/software/bison/manual. Bison is a LALR(1) parser, which essentially means that
+it is able to parse (separate and analyze) any text that is described by set of rules. You can see
+the more formal description here: https://en.wikipedia.org/wiki/LALR_parser, but the plain English
+explanation is that you define a set of rules and bison will walk through input text trying to match
+the content to those rules. While doing so, it will be allowed to peek at most one symbol (token)
+ahead.
+
+As an example, let's take a closer look at the bison grammar we have for DHCPv6. It is defined
+in src/bin/dhcp6/dhcp6_parser.yy. Here's a simplified excerpt:
+
+@code
+// This defines a global Dhcp6 object.
+dhcp6_object: DHCP6 COLON LCURLY_BRACKET global_params RCURLY_BRACKET;
+
+// This defines all parameters that may appear in the Dhcp6 object.
+// It can either contain a global_param (defined below) or a
+// global_params list, followed by a comma followed by a global_param.
+// Note this definition is recursive and can expand to a single
+// instance of global_param or multiple instances separated by commas.
+// This is how bison handles variable number of parameters.
+global_params: global_param
+ | global_params COMMA global_param
+ ;
+
+// These are the parameters that are allowed in the top-level for
+// Dhcp6.
+global_param: preferred_lifetime
+ | valid_lifetime
+ | renew_timer
+ | rebind_timer
+ | subnet6_list
+ | interfaces_config
+ | lease_database
+ | hosts_database
+ | mac_sources
+ | relay_supplied_options
+ | host_reservation_identifiers
+ | client_classes
+ | option_data_list
+ | hooks_libraries
+ | expired_leases_processing
+ | server_id
+ | dhcp4o6_port
+ ;
+
+renew_timer: RENEW_TIMER COLON INTEGER;
+
+// Many other definitions follow.
+@endcode
+
+The code above defines parameters that may appear in the Dhcp6 object declaration. One important
+trick to understand is understand the way to handle variable number of parameters. In bison it is
+most convenient to present them as recursive lists: in this example, global_params defined in a way
+that allows any number of global_param instances allowing the grammar to be easily extensible. If
+one needs to add a new global parameter, just add it to the global_param list.
+
+This type of definition has several levels, each representing logical structure of the configuration
+data. We start with global scope, then step into a Dhcp6 object that has a Subnet6 list, which in
+turn has Subnet6 instances, each of which has pools list and so on. Each level is represented as a
+separate rule.
+
+The "leaf" rules (that don't contain any other rules) must be defined by a series of tokens. An
+example of such a rule is renew_timer, above. It is defined as a series of 3 tokens: RENEW_TIMER,
+COLON and INTEGER.
+
+Speaking of integers, it is worth noting that some tokens can have values. Those values are defined
+using %token clause. For example, dhcp6_parser.yy contains the following:
+
+@code
+%token <std::string> STRING "constant string"
+%token <int64_t> INTEGER "integer"
+%token <double> FLOAT "floating point"
+%token <bool> BOOLEAN "boolean"
+@endcode
+
+The first line says that the token STRING has a type of std::string and when referring to this token
+in error messages, it should be printed as "constant string".
+
+In principle, it is valid to define just the grammar without any corresponding C++ code to it. Bison
+will go through the whole input text, match the rules and will either say the input adhered to the
+rules (parsing successful) or not (parsing failed). This may be a useful step when developing new
+parser, but it has no practical value. To perform specific actions, bison allows the injection of
+C++ code at almost any point. For example we could augment the parsing of renew_timer with some
+extra code:
+
+@code
+renew_timer: RENEW_TIMER {
+ cout << "renew-timer token detected, so far so good" << endl;
+} COLON {
+ cout << "colon detected!" << endl;
+} INTEGER {
+ uint32_t timer = $3;
+ cout << "Got the renew-timer value: " << timer << endl;
+ ElementPtr prf(new IntElement($3, ctx.loc2pos(@3)));
+ ctx.stack_.back()->set("renew-timer", prf);
+};
+@endcode
+
+This example showcases several important things. First, the ability to insert code at almost any
+step is very useful. It's also a powerful debugging tool.
+
+Second, some tokens are valueless (e.g. "renew-timer" when represented as the RENEW_TIMER token has
+no value), but some have values. In particular, the INTEGER token has value which can be extracted
+by $ followed by a number that represents its order, so $3 means "a value of third token or action
+in this rule". If needed, the location of specific token (filename, line and column) can be
+accessed with @ followed by a number that represents token number, e.g. @3 in the example above
+returns exact location of INTEGER token.
+
+Also, some rules may have values. This is not used often, but there are specific cases when it's
+convenient. Let's take a look at the following excerpt from dhcp6_parser.yy:
+
+@code
+ncr_protocol: NCR_PROTOCOL {
+ ctx.enter(ctx.NCR_PROTOCOL); (1)
+} COLON ncr_protocol_value {
+ ctx.stack_.back()->set("ncr-protocol", $4); (3)
+ ctx.leave(); (4)
+};
+
+ncr_protocol_value:
+ UDP { $$ = ElementPtr(new StringElement("UDP", ctx.loc2pos(@1))); }
+ | TCP { $$ = ElementPtr(new StringElement("TCP", ctx.loc2pos(@1))); } (2)
+ ;
+@endcode
+
+(The numbers in brackets at the end of some lines do not appear in the code; they are used identify
+the statements in the following discussion.)
+
+The "ncr-protocol" parameter accepts one of two values: either tcp or udp. To handle such a case, we
+first enter the NCR_PROTOCOL context to tell the lexer that we're in this scope. The lexer will then
+know that any incoming string of text that is either "UDP" or "TCP" should be represented as one of
+the TCP or UDP tokens. The parser knows that after NCR_PROTOCOL there will be a colon followed by an
+ncr_protocol_value. The rule for ncr_protocol_value says it can be either the TCP token or the UDP
+token. Let's assume the input text is:
+@code
+"ncr-protocol": "TCP"
+@endcode
+
+Here's how the parser will handle it. First, it will attempt to match the rule for ncr_protocol. It
+will discover the first token is NCR_PROTOCOL. As a result, it will run the code (1), which will
+tell lexer to parse incoming tokens as ncr protocol values. The next token is expected to be COLON
+and the one after that the ncr_protocol_value. The lexer has already been switched into the
+NCR_PROTOCOL context, so it will recognize "TCP" as TCP token, not as a string with a value of
+"TCP". The parser will receive that token and match the line (2), which creates an appropriate
+representation that will be used as the rule's value ($$). Finally, the parser will unroll back to
+ncr_protocol rule and execute the code in lines (3) and (4). Line (3) picks the value set up in
+line (2) and adds it to the stack of values. Finally, line (4) tells the lexer that we finished the
+NCR protocol parsing and it can go back to whatever state it was before.
+
+@section parserBisonStack Generating the Element Tree in Bison
+
+The bison parser keeps matching rules until it reaches the end of input file. During that process,
+the code needs to build a hierarchy (a tree) of inter-connected Element objects that represents the
+parsed text. @ref isc::data::Element has a complex structure that defines parent-child relation
+differently depending on the type of parent (ae.g. a map and a list refer to their children in
+different ways). This requires the code to be aware of the parent content. In general, every time a
+new scope (an opening curly bracket in input text) is encountered, the code pushes new Element to
+the stack (see @ref isc::dhcp::Parser6Context::stack_) and every time the scope closes (a closing
+curly bracket in input text) the element is removed from the stack. With this approach, we always
+have access to the parent element as it's the last element on the stack. For example, when parsing
+preferred-lifetime, the code does the following:
+
+@code
+preferred_lifetime: PREFERRED_LIFETIME COLON INTEGER {
+ ElementPtr prf(new IntElement($3, ctx.loc2pos(@3)));
+ ctx.stack_.back()->set("preferred-lifetime", prf);
+}
+@endcode
+
+The first line creates an instance of IntElement with a value of the token. The second line adds it
+to the current map (current = the last on the stack). This approach has a very nice property of
+being generic. This rule can be referenced from both global and subnet scope (and possibly other
+scopes as well) and the code will add the IntElement object to whatever is last on the stack, be it
+global, subnet or perhaps even something else (maybe one day we will allow preferred lifetime to be
+defined on a per pool or per host basis?).
+
+@section parserSubgrammar Parsing a Partial Configuration
+
+All the explanations so far assumed that we're operating in a default case of receiving the
+configuration as a whole. That is the case during startup and reconfiguration. However, both DHCPv4
+and DHCPv6 support certain cases when the input text is not the whole configuration, but rather
+certain parts of it. There are several examples of such cases. The most common are unit-tests. They
+typically don't have the outermost { } or Dhcp6 object, but simply define whatever parameters are
+being tested. Second, we have the command channel that will, in the near future, contain parts of
+the configuration, depending on the command. For example, "add-reservation" will contain a host
+reservation only.
+
+Bison by default does not support multiple start rules, but there's a trick that can provide such a
+capability. The trick assumes that the starting rule may allow one of the artificial tokens that
+represent the scope expected. For example, when called from the "add-reservation" command, the
+artificial token will be SUB_RESERVATION and it will trigger the parser to bypass the global braces
+{ and } and the "Dhcp6" token and jump immediately to the sub_reservation.
+
+This trick is also implemented in the lexer. A flag called start_token_flag, when initially set to
+true, will cause the lexer to emit an artificial token once, before parsing any input whatsoever.
+
+This optional feature can be skipped altogether if you don't plan to parse parts of the
+configuration.
+
+@section parserBisonExtend Extending the Grammar
+
+Adding new parameters to existing parsers is very easy once you get hold of the concept of what the
+grammar rules represent. The first step is to understand where the parameter is to be
+allowed. Typically a new parameter is allowed in one scope and only over time is it added to other
+scopes. Recently support for a 4o6-interface-id parameter has been added. That is a parameter that
+can be defined in a subnet and takes a string argument. You can see the actual change conducted in
+this commit: (https://github.com/isc-projects/kea/commit/9fccdbf54c4611dc10111ad8ff96d36cad59e1d6).
+
+Here's the complete set of changes that were necessary.
+
+1. Define a new token in dhcp6_parser.yy:
+ @code
+ SUBNET_4O6_INTERFACE_ID "4o6-interface-id"
+ @endcode
+ This defines a token called SUBNET_4O6_INTERFACE_ID that, when it needs to
+ be printed, e.g. in an error message, will be represented as "4o6-interface-id".
+
+2. Tell the lexer how to recognize the new parameter:
+ @code
+ \"4o6-interface-id\" {
+ switch(driver.ctx_) {
+ case isc::dhcp::Parser4Context::SUBNET4:
+ return isc::dhcp::Dhcp4Parser::make_SUBNET_4O6_INTERFACE_ID(driver.loc_);
+ default:
+ return isc::dhcp::Dhcp4Parser::make_STRING("4o6-interface-id", driver.loc_);
+ }
+ }
+ @endcode
+ It tells the parser that when in Subnet4 context, an incoming "4o6-interface-id" string should be
+ represented as the SUBNET_4O6_INTERFACE_ID token. In any other context, it should be represented
+ as a string.
+
+3. Add the rule that will define the value. A user is expected to add something like
+ @code
+ "4o6-interface-id": "whatever"
+ @endcode
+ The rule to match this and similar statements looks as follows:
+ @code
+ subnet_4o6_interface_id: SUBNET_4O6_INTERFACE_ID {
+ ctx.enter(ctx.NO_KEYWORD);
+ } COLON STRING {
+ ElementPtr iface(new StringElement($4, ctx.loc2pos(@4)));
+ ctx.stack_.back()->set("4o6-interface-id", iface);
+ ctx.leave();
+ };
+ @endcode
+ Here's a good example of the context use. We have no idea what sort of interface-id the user will
+ use. Typically that will be an integer, but it may be something weird that happens to match our
+ reserved keywords. Therefore we switch to no keyword context. This tells the lexer to interpret
+ everything as string, integer or float.
+
+4. Finally, extend the existing subnet4_param that defines all allowed parameters
+ in the Subnet4 scope to also cover our new parameter (the new line marked with *):
+ @code
+ subnet4_param: valid_lifetime
+ | renew_timer
+ | rebind_timer
+ | option_data_list
+ | pools_list
+ | subnet
+ | interface
+ | interface_id
+ | id
+ | rapid_commit
+ | client_class
+ | reservations
+ | reservation_mode
+ | relay
+ | match_client_id
+ | authoritative
+ | next_server
+ | subnet_4o6_interface
+ | subnet_4o6_interface_id (*)
+ | subnet_4o6_subnet
+ | unknown_map_entry
+ ;
+ @endcode
+
+5. Regenerate the flex/bison files by typing "make parser".
+
+6. Run the unit-tests that you wrote before you touched any of the bison stuff. You did write them
+ in advance, right?
+*/
diff --git a/doc/devel/config-backend.dox b/doc/devel/config-backend.dox
new file mode 100644
index 0000000..7991307
--- /dev/null
+++ b/doc/devel/config-backend.dox
@@ -0,0 +1,121 @@
+// Copyright (C) 2014-2023 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+/**
+
+ @page configBackend Kea Configuration Backends
+
+@section configBackendIntro Introduction
+
+Kea started as a sub-project in BIND10 that used a program (called
+bindctl) to deliver configuration information to its modules. This
+potentially allowed for modules to get their configuration information
+in a variety of ways using what were known as configuration backends.
+After BIND10 was cancelled, the Kea project briefly tried to maintain
+backward compatibility with the BIND10 framework, but the effort
+was discontinued due to lack of interest.
+
+Currently the Kea team does not plan to develop any additional
+configuration backends. Instead, effort is being focused on enhancing
+the current control channel (see @ref ctrlSocket) to be as flexible
+as possible. If you are thinking about developing new ways to
+configure Kea, the recommendation is to write an external piece of
+software that will communicate with Kea using this channel.
+
+@section configBackendHistoric Alternate Configuration Backends
+
+While this section currently has no practical value, it may become useful
+one day to develop a minimalistic, stripped down Kea version that does
+not have any command interface at all. This could prove useful for running
+Kea in embedded regime.
+
+The following steps are needed for the DHCPv4 server to be able to
+process a new method of configuration. (It is assumed that the
+modified component is DHCPv4. Similar approach applies to the other
+components: DHCPv6 or DHCP-DDNS):
+
+-# Write your own implementation of isc::dhcp::ControlledDhcpv4Srv::init(),
+ isc::dhcp::ControlledDhcpv4Srv::init() and isc::dhcp::ControlledDhcpv4Srv::cleanup(),
+ and put it in the src/bin/dhcp4 directory (e.g. as foo_controller.cc).
+-# Modify src/bin/dhcp4/Makefile.am to include your file (e.g. foo_controller.cc) in
+ the build.
+-# Modify the AC_ARG_WITH(kea-config,...) macro in configure.ac to include an
+ entry for your configuration backend.
+-# Add your own AM_CONDITIONAL(CONFIG_BACKEND_FOO, ...) and
+ AC_DEFINE(CONFIG_BACKEND_FOO, ...) macros to configure.ac (following the
+ above-mentioned AC_ARG_WITH macro) to set the C++ macro for your backend.
+-# Modify the sanity check in configure.ac to allow your configuration backend name.
+
+Optionally you can also:
+
+-# Implement unit tests for your backend in the src/bin/dhcp4/tests directory.
+-# Modify src/bin/dhcp4/tests/Makefile.am to include the file(s) containing the
+ unit tests.
+
+@section configBackendJSONDesign The JSON Configuration Backend
+
+The following are some details of the JSON backend framework.
+
+-# Each backend uses the common code for configuration and command
+ processing callbacks. They all assume that JSON formatted parameters are sent
+ and they are expected to return well formatted JSON responses. The exact
+ format of configuration and commands is module-specific.<br/><br/>
+-# A command handler handles the reading the configuration from a
+ file. Its main responsibility is to load the configuration and process
+ it. The JSON backend must call that handler when starting up the server.
+ This is implemented in configure() in the kea_controller.cc files
+ in src/bin/dhcp4 and src/bin/dhcp6 directories.<br/><br/>
+-# The current JSON parser in @ref
+ isc::data::Element::fromJSON() has been extended to allow optional
+ preprocessing. For now, that capability simply removes whole-line
+ comments starting with the hash character, but it is expected to grow over
+ time (in-line comments and file inclusions are the obvious envisaged
+ additions). This is implemented in @ref isc::data::Element::fromJSONFile.<br/><br/>
+-# The current format of the BIND10 configuration file (BIND 10 stored its
+ configuration in (installation directory) /var/bind10/b10-config.db) has been
+ retained as the configuration file format. Its actual naming is now arbitrary
+ and left up to the user (it is passed as a parameter to the -c command line
+ option). From the implementation perspective, this is slight change
+ from the BIND10 days, as back then a subset of the configuration was received by
+ the daemon processes. Nowadays the whole configuration is passed. To take a
+ specific example, the following is how b10-config.db looked many years ago:
+ @code
+ {
+ "Init": { ... }
+ "Dhcp4": {
+ "subnet4" { subnet definitions here },
+ "option-data" { option data here },
+ "interfaces": [ "eth0" ],
+ ...
+ },
+ "Dhcp6": {
+ "subnet6" { subnet definitions here },
+ "option-data" { option data here },
+ "interfaces": [ "eth0" ],
+ ...
+ },
+ "Logging": {
+ "Loggers": [{"name": *, "severity": "DEBUG" }]
+ }
+ }
+ @endcode
+ The Kea components used to receive only relevant parts of it (e.g. Kea4
+ received configuration data that only contained the content of the Dhcp4 element).
+ Now each component receives all of it: the code
+ iterates over the top level elements and picks the appropriate
+ tree (or get the element by name). That approach makes the common configuration
+ (such as the logging initialization code) very easy to share among Kea4, Kea6 and
+ DHCP-DDNS.<br/><br/>
+-# The .spec files used in BIND 10 by the control program to validate commands
+ have been removed in 1.4.<br/><br/>
+-# A shell script has been added (as src/bin/keactrl/keactrl) to
+ start, stop and reconfigure the daemons. Its only
+ job is to pass the configuration file to each daemon and remember its PID file, so
+ that sending signals is possible (for configuration reload or shutdown). It is also
+ able to print out a status.<br/><br/>
+-# The capability to share the same configuration file between servers and
+ agents, and the Logging toplevel entry, were removed in 1.7.10.
+*/
diff --git a/doc/devel/congestion-handling.dox b/doc/devel/congestion-handling.dox
new file mode 100644
index 0000000..83079e8
--- /dev/null
+++ b/doc/devel/congestion-handling.dox
@@ -0,0 +1,452 @@
+// Copyright (C) 2018-2023 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+/**
+
+@page congestionHandling Congestion Handling in Kea DHCP Servers
+
+@section background What is Congestion?
+Congestion occurs when servers are subjected to client queries
+faster than they can be fulfilled. Subsequently, the servers begin
+accumulating a backlog of pending queries. The longer the high rate of
+traffic continues the farther behind the servers fall. Depending on the
+client implementations, those that fail to get leases either give up or simply
+continue to retry forever. In the former case, the server may eventually
+recover. The latter case is vicious cycle from which the server is unable
+to escape.
+
+In a well-planned deployment, the number and capacity of servers is matched
+to the maximum client loads expected. As long as capacity is matched to
+load, congestion does not occur. If the load is routinely too heavy, then
+the deployment needs to be re-evaluated. Congestion typically occurs when
+there is a network event that causes overly large numbers of clients to
+simultaneously need leases such as recovery after a network outage.
+
+@section introduction Congestion Handling Overview
+
+Kea 1.5.0 introduces a new feature referred to as Congestion Handling. The
+goal of Congestion Handling is to help the servers mitigate the peak
+in traffic by fulfilling as many of the most relevant requests as possible
+until it subsides.
+
+Prior to Kea 1.5.0, Kea DHCP servers read inbound packets directly
+from the interface sockets in the main application thread. This meant that
+packets waiting to be processed were held in socket buffers themselves. Once
+these buffers fill any new packets are discarded. Under swamped conditions
+the servers can end up processing client packets that may no longer be
+relevant, or worse are redundant. In other words, the packets waiting in
+the FIFO socket buffers become increasingly stale.
+
+Congestion Handling offers the ability to configure the server to use a
+separate thread to read packets from the interface socket buffers. As the
+thread reads packets from the buffers they are added to an internal "packet
+queue". The server's main application thread processes packets from this queue
+rather than the socket buffers. By structuring it this way, we've introduced
+a configurable layer which can make decisions on which packets to process,
+how to store them, and the order in which they are processed by the server.
+
+The default packet queue implementation for both Kea DHCPv4 and DHCPv6 servers
+is a simple ring buffer. Once it reaches capacity, new packets get added to
+the back of queue by discarding packets from the front of queue. Rather than
+always discarding the newest packets, we now always discard the oldest
+packets. The capacity of the buffer (i.e. the maximum number of packets the
+buffer can contain) is configurable.
+
+@section custom-implementations Custom Packet Queues
+
+It is possible to replace the default packet queue implementation with a
+custom implementation by registering it with your Kea server via a hook
+library. The steps for doing this are listed below:
+
+-# Develop a derivation of the interface isc::dhcp::PacketQueue
+-# Registering and un-registering your implementation via Hook library
+-# Configure your Kea server to use your derivation
+
+(If you are not familiar with writing Kea hook libraries, you may wish to
+read @ref hooksdgDevelopersGuide before continuing).
+
+@subsection packet-queue-derivation Developing isc::dhcp::PacketQueue Derivations
+ @subsection packet-queue-derivation-basics The Basics
+
+Your custom packet queue must derive from the class template,
+isc::dhcp::PacketQueue. The class is almost entirely abstract and
+deliberately brief to provide developers wide latitude in the internals
+of their solutions.
+
+The template argument, @c PacketTypePtr, is expected to be either
+isc::dhcp::Pkt4Ptr or isc::dhcp::Pkt6Ptr, depending upon which
+protocol the implementation will handle. Please note that the
+while following text and examples largely focus on DHCPv4 out
+of convenience as the concepts are identical for DHCPv6. For
+completeness there are code snippets at the end of this
+chapter for DHCPv6.
+
+The two primary functions of interest are:
+
+-# isc::dhcp::PacketQueue::enqueuePacket() - This function is invoked by
+the receiver thread each time a packet has been read from an interface
+socket buffer and should be added to the queue. It is passed a pointer to
+the unpacked client packet (isc::dhcp::Pkt4Ptr or isc::dhcp::Pkt6Ptr), and
+a reference to the isc::dhcp::SocketInfo describing the interface socket
+from which the packet was read. Your derivation is free to use whatever
+logic you deem appropriate to decide if a given packet should be added
+to the queue or dropped. The socket information is passed along to be used
+(or not) in your decision making. The simplest derivation would add every
+packet, every time.
+
+-# isc::dhcp::PacketQueue::dequeuePacket() - This function is invoked by the
+server's main thread whenever the receiver thread indicates that packets are
+ready. Which packet is dequeued and returned is entirely up to your
+derivation.
+
+The remaining functions that you'll need to implement are self-explanatory.
+
+How your actual "queue" is implemented is entirely up to you. Kea's default
+implementation using a ring buffer based on Boost's boost::circular_buffer
+(please refer to isc::dhcp::PacketQueueRing, isc::dhcp::PacketQueueRing4 and
+isc::dhcp::PacketQueueRing6). The most critical aspects to remember when
+developing your implementation are:
+
+-# It MUST be thread safe since queuing and dequeuing packets are done by
+separate threads. (You might considering using std::mutex and std::lock_guard).
+
+-# Its efficiency (or lack thereof) will have a direct impact on server
+performance. You will have to consider the dynamics of your deployment
+to determine where the trade-off lies between the volume of packets responded
+to and preferring to respond to some subset of those packets.
+
+ @subsection packet-queue-derivation-factory Defining a Factory
+
+isc::dhcp::IfaceMgr using two derivations of isc::dhcp::PacketQueueMgr (one for
+DHCPv4 and one for DHCPv6), to register queue implementations and instantiate
+the appropriate queue type based the current configuration. In order to
+register your queue implementation your hook library must provide a factory
+function that will be used to create packet queues. This function will be
+invoked by the server during the configuration process to instantiate the
+appropriate queue type. For DHCPv4, the factory should be as follows:
+
+@code
+ PackQueue4Ptr factory(isc::data::ConstElementPtr parameters)
+@endcode
+
+and for DHCPv6:
+
+@code
+ PackQueue6Ptr factory(isc::data::ConstElementPtr parameters)
+@endcode
+
+The factory's only argument is an isc::data::ConstElementPtr. This is will be
+an isc::data::MapElement instance containing the contents of the configuration
+element "dhcp-queue-control" from the Kea server's configuration. It will
+always have the following two values:
+
+-# "enable-queue" - used by isc::dhcp::IfaceMgr to know whether
+congestion handling is enabled. Your implementation need not do anything
+with this value.
+
+-# "queue-type" - name of the registered queue implementation to use.
+It is used by isc::dhcp::IfaceMgr to invoke the appropriate queue factory.
+Your implementation must pass this value through to the isc::dhcp::PacketQueue
+constructor.
+
+Beyond that you may add whatever additional values you may require. In
+other words, the content is arbitrary so long as it is valid JSON. It is
+up to your factory implementation to examine the contents and use them
+to construct a queue instance.
+
+ @subsection packet-queue-derivation-example An Example
+
+Let's suppose you wish to develop a queue for DHCPv4 and your implementation
+requires two configurable parameters: capacity and threshold. Your class
+declaration might look something like this:
+
+@code
+class YourPacketQueue4 : public isc::dhcp::PacketQueue<isc::dhcp::Pkt4Ptr> {
+public:
+
+ // Logical name you will register your factory under.
+ static const std::string QUEUE_TYPE;
+
+ // Factory for instantiating queue instances.
+ static isc::dhcp::PacketQueue4Ptr factory(isc::data::ConstElementPtr params);
+
+ // Constructor
+ YourPacketQueue4(const std::string& queue_type, size_t capacity, size_t threshold)
+ : isc::dhcp::PacketQueue<isc::dhcp::Pkt4Ptr>(queue_type) {
+
+ // your constructor steps here
+ }
+
+ // Adds a packet to your queue using your secret formula based on threshold.
+ virtual void enqueuePacket(isc::dhcp::Pkt4Ptr packet, const dhcp::SocketInfo& source);
+
+ // Fetches the next packet to process from your queue using your other secret formula.
+ virtual isc::dhcp::Pkt4Ptr dequeuePacket();
+
+ : // Imagine you prototyped the rest of the functions
+
+};
+@endcode
+
+Your factory implementation would then look something like this:
+
+@code
+
+const std::string QUEUE_TYPE = "Your-Q4";
+
+isc::dhcp::PacketQueue4Ptr
+YourPacketQueue4::factory(isc::data::ConstElementPtr parameters) {
+
+ // You need queue-type to pass into the base class.
+ // It's guaranteed to be here.
+ std::string queue_type = isc::data::SimpleParser::getString(parameters, "queue-type");
+
+ // Now you need to fetch your required parameters.
+ size_t capacity;
+ try {
+ capacity = isc::data::SimpleParser::getInteger(parameters, "capacity");
+ } catch (const std::exception& ex) {
+ isc_throw(isc::dhcp::InvalidQueueParameter, "YourPacketQueue4:factory:"
+ " 'capacity' parameter is missing/invalid: " << ex.what());
+ }
+
+ size_t threshold;
+ try {
+ threshold = isc::data::SimpleParser::getInteger(parameters, "threshold");
+ } catch (const std::exception& ex) {
+ isc_throw(isc::dhcp::InvalidQueueParameter, "YourPacketQueue4:factory:"
+ " 'threshold' parameter is missing/invalid: " << ex.what());
+ }
+
+ // You should be all set to create your queue instance!
+ isc::dhcp::PacketQueue4Ptr queue(new YourPacketQueue4(queue_type, capacity, threshold));
+ return (queue);
+}
+
+@endcode
+
+Kea's configuration parser cannot know your parameter requirements and thus
+can only flag JSON syntax errors. Thus it is important for your factory to
+validate your parameters according to your requirements and throw meaningful
+exceptions when they are not met. This allows users to know what to correct.
+
+@subsection packet-queue-registration Registering Your Implementation
+
+All hook libraries must provide a load() and unload() function. Your hook
+library should register you queue factory during load() and un-register it
+during unload(). Picking up with the our example, those functions might
+look something like this:
+
+@code
+// This function is called when the library is loaded.
+//
+// param - handle library handle (we aren't using it)
+// return - 0 when initialization is successful, 1 otherwise
+int load(LibraryHandle& /* handle */) {
+ try {
+ // Here you register your DHCPv4 queue factory
+ isc::dhcp::IfaceMgr::instance().getPacketQueueMgr4()->
+ registerPacketQueueFactory(YourPacketQueue4::QUEUE_TYPE,
+ YourPacketQueue::factory);
+ } catch (const std::exception& ex) {
+ LOG_ERROR(your_logger, YOUR_LOAD_FAILED)
+ .arg(ex.what());
+ return (1);
+ }
+
+ LOG_INFO(your_logger, YOUR_LOAD_OK);
+ return (0);
+}
+
+// This function is called when the library is unloaded.
+//
+// return - 0 if deregistration was successful, 1 otherwise
+int unload() {
+
+ // You need to remove your queue factory. This must be done to make sure
+ // your queue instance is destroyed before your library is unloaded.
+ isc::dhcp::IfaceMgr::instance().getPacketQueueMgr4()->
+ unregisterPacketQueueFactory(YourPacketQueue4::QUEUE_TYPE);
+
+ LOG_INFO(your_logger, YOUR_UNLOAD_OK);
+ return (0);
+}
+@endcode
+
+@subsection packet-queue-factory Configuring Kea to use YourPacketQueue4
+
+You're almost there. You developed your implementation, you've unit tested it
+(You did unit test it right?). Now you just have to tell Kea to load it and
+use it. Continuing with the example, your kea-dhcp4 configuration would need
+to look something like this:
+
+@code
+{
+"Dhcp4":
+{
+ ...
+
+ "hooks-libraries": [
+ {
+ # Loading your hook library!
+ "library": "/somepath/lib/libyour_packet_queue.so"
+ }
+
+ # any other hook libs
+ ],
+
+ ...
+
+ "dhcp-queue-control": {
+ "enable-queue": true,
+ "queue-type": "Your-Q4",
+ "capacity" : 100,
+ "threshold" : 75
+ },
+
+ ...
+}
+@endcode
+
+@subsection packet-queue-example-dhcpv6 DHCPv6 Example Snippets
+
+For completeness, this section includes the example from above
+implemented for DHCPv6.
+
+DHCPv6 Class declaration:
+
+@code
+class YourPacketQueue6 : public isc::dhcp::PacketQueue<isc::dhcp::Pkt6Ptr> {
+public:
+
+ // Logical name you will register your factory under.
+ static const std::string QUEUE_TYPE;
+
+ // Factory for instantiating queue instances.
+ static isc::dhcp::PacketQueue6Ptr factory(isc::data::ConstElementPtr params);
+
+ // Constructor
+ YourPacketQueue6(const std::string& queue_type, size_t capacity, size_t threshold)
+ : isc::dhcp::PacketQueue<isc::dhcp::Pkt6Ptr>(queue_type) {
+
+ // your constructor steps here
+ }
+
+ // Adds a packet to your queue using your secret formula based on threshold.
+ virtual void enqueuePacket(isc::dhcp::Pkt6Ptr packet, const dhcp::SocketInfo& source);
+
+ // Fetches the next packet to process from your queue using your other secret formula.
+ virtual isc::dhcp::Pkt6Ptr dequeuePacket();
+
+ : // Imagine you prototyped the rest of the functions
+
+};
+@endcode
+
+DHCPv6 Factory implementation:
+
+@code
+const std::string QUEUE_TYPE = "Your-Q6";
+
+isc::dhcp::PacketQueue6Ptr
+YourPacketQueue6::factory(isc::data::ConstElementPtr parameters) {
+
+ // You need queue-type to pass into the base class.
+ // It's guaranteed to be here.
+ std::string queue_type = isc::data::SimpleParser::getString(parameters, "queue-type");
+
+ // Now you need to fetch your required parameters.
+ size_t capacity;
+ try {
+ capacity = isc::data::SimpleParser::getInteger(parameters, "capacity");
+ } catch (const std::exception& ex) {
+ isc_throw(isc::dhcp::InvalidQueueParameter, "YourPacketQueue6:factory:"
+ " 'capacity' parameter is missing/invalid: " << ex.what());
+ }
+
+ size_t threshold;
+ try {
+ threshold = isc::data::SimpleParser::getInteger(parameters, "threshold");
+ } catch (const std::exception& ex) {
+ isc_throw(isc::dhcp::InvalidQueueParameter, "YourPacketQueue6:factory:"
+ " 'threshold' parameter is missing/invalid: " << ex.what());
+ }
+
+ // You should be all set to create your queue instance!
+ isc::dhcp::PacketQueue6Ptr queue(new YourPacketQueue6(queue_type, capacity, threshold));
+ return (queue);
+}
+@endcode
+
+DHCPv6 Hook load/unload functions
+
+@code
+// This function is called when the library is loaded.
+//
+// param - handle library handle (we aren't using it)
+// return - 0 when initialization is successful, 1 otherwise
+int load(LibraryHandle& /* handle */) {
+ try {
+ // Here you register your DHCPv6 queue factory
+ isc::dhcp::IfaceMgr::instance().getPacketQueueMgr6()->
+ registerPacketQueueFactory(YourPacketQueue6::QUEUE_TYPE,
+ YourPacketQueue::factory);
+ } catch (const std::exception& ex) {
+ LOG_ERROR(your_logger, YOUR_LOAD_FAILED)
+ .arg(ex.what());
+ return (1);
+ }
+
+ LOG_INFO(your_logger, YOUR_LOAD_OK);
+ return (0);
+}
+
+// This function is called when the library is unloaded.
+//
+// return - 0 if deregistration was successful, 1 otherwise
+int unload() {
+
+ // You need to remove your queue factory. This must be done to make sure
+ // your queue instance is destroyed before your library is unloaded.
+ isc::dhcp::IfaceMgr::instance().getPacketQueueMgr6()->
+ unregisterPacketQueueFactory(YourPacketQueue6::QUEUE_TYPE);
+
+ LOG_INFO(your_logger, YOUR_UNLOAD_OK);
+ return (0);
+}
+@endcode
+
+Server configuration for kea-dhcp6:
+
+@code
+{
+"Dhcp6":
+{
+ ...
+
+ "hooks-libraries": [
+ {
+ # Loading your hook library!
+ "library": "/somepath/lib/libyour_packet_queue.so"
+ }
+
+ # any other hook libs
+ ],
+
+ ...
+
+ "dhcp-queue-control": {
+ "enable-queue": true,
+ "queue-type": "Your-Q6",
+ "capacity" : 100,
+ "threshold" : 75
+ },
+
+ ...
+}
+@endcode
+
+*/
diff --git a/doc/devel/contribute.dox b/doc/devel/contribute.dox
new file mode 100644
index 0000000..64ddf50
--- /dev/null
+++ b/doc/devel/contribute.dox
@@ -0,0 +1,16 @@
+// Copyright (C) 2013-2019 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+/**
+
+ @page contributorGuide Kea Contributor's Guide
+
+The Contributor's Guide has been moved to a stand alone document.
+See CONTRIBUTORS.md in the top level sources or:
+
+Link: https://gitlab.isc.org/isc-projects/kea/blob/master/CONTRIBUTING.md
+
+*/
diff --git a/doc/devel/cross-compile.dox b/doc/devel/cross-compile.dox
new file mode 100644
index 0000000..cc7685e
--- /dev/null
+++ b/doc/devel/cross-compile.dox
@@ -0,0 +1,226 @@
+// Copyright (C) 2020-2022 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+/**
+
+ @page crossCompile Kea Cross-Compiling Example
+
+The idea is to install Kea on a Raspberry Pi 4 Model B running Raspbian
+operation system (e.g. the
+<a href="https://www.raspberrypi.org/software/operating-systems/">
+Raspbian Buster with desktop and recommended software</a> distribution)
+without having to compile Kea on the Raspberry Pi box itself as it
+takes some hours so using a standard Linux box with a x86_64 processor.
+
+To cross-compile anything for Raspbian you need:
+ - a cross-compiler running on x86_64 producing arm binaries
+ - either an image of system copied from a Raspberry disk or extracted
+ from a Raspbian repository.
+
+@section toolChain Cross-Compile Tool Chain
+
+A priori it is possible to compile your own tool chain or to use
+a package as the arm-linux-gnueabihf one on Ubuntu. But there is
+reported compatibility issue with old Raspberry Pi versions) so
+we recommend a pre-built dedicated tool chain for this purpose:
+<a href="https://github.com/Pro/raspi-toolchain">RaspberryPi toolchain on github</a>.
+
+The documentation of this tool chain gives a rsync command which
+copies selected parts of the Raspberry Pi root filesystem ("rootfs").
+If you have no access to a running Raspberry Pi it is still possible
+to get them following next section instructions. If you have, simply
+skip this part.
+
+@section noRaspberry How to get system and packages without a running Raspberry Pi
+
+It is not required to have access to a running Raspberry Pi.
+The system disk image is available at the Raspbian URL.
+Packages are in the Raspian repository which is given in
+sources list files in this disk image or below.
+
+The /etc/apt/sources.list file content is:
+@verbatim
+deb http://raspbian.raspberrypi.org/raspbian/ buster main contrib non-free rpi
+# Uncomment line below then 'apt-get update' to enable 'apt-get source'
+# deb-src http://raspbian.raspberrypi.org/raspbian/ buster main contrib non-free rpi
+@endverbatim
+
+and the /etc/apt/sources.list.d/raspi.list file content is:
+@verbatim
+deb http://archive.raspberrypi.org/debian/ buster main
+# Uncomment line below then 'apt-get update' to enable 'apt-get source'
+# deb-src http://archive.raspberrypi.org/debian/ buster main
+@endverbatim
+
+The disk image is a zipped image of a 4GB disk with a standard MSDOS
+boot block with two volumes:
+ - boot (useless for this purpose)
+ - rootfs (the Raspberry Pi root filesystem)
+
+The idea is to mount the rootfs on the Linux box (it can work on another
+system as soon as it supports the ext4 file system type):
+ - first use fdisk or similar tool to get the offset of the first block
+ of the rootfs (second) volume
+ - if the offset is in block unit multiply by 512 (block size)
+ - mount as root (sudo mount ...) with the loop option, the offset option,
+ the unzipped image file name and a mount point (absolute path of
+ a directory)
+If you have a SD card with Raspbian installed on it and a SD reader
+you can directly mount the rootfs from it.
+
+If a dependency (i.e. the Raspbian version of a library) is not in the
+rootfs image you need to simulate its installation:
+ - get the .deb file from a Raspbian repository
+ - extract files using the dpkg-deb -R tool on the .deb file
+ - install the files (usually in the "rootfs"/usr directory)
+The idea is the files (includes and libraries) can be found by
+the cross-compiling tool chain.
+
+It is possible to emulate a Raspberry Pi using qemu even I do not think
+it can run Kea. But at least it can run some tests as the hello world sample
+of the tool chain. Required qemu kernels can be found in
+<a href="https://github.com/dhruvvyas90/qemu-rpi-kernel">this github repo</a> with
+a documentation, which is well worth reading.
+
+@section crossCompilePitfalls Usual problems
+
+There are two usual problems when cross-compiling:
+ - have a binary for the wrong processor, e.g. either trying to run
+ an arm binary on the x86_64 box or building a x86_64 binary when
+ it will be run by the Raspberry Pi
+ - use the x86_64 system include or library instead of the Raspberry Pi
+ one from the rootfs image. Usually it gives a direct error for a library
+ but a wrong include is more subtle.
+Note that Kea has a build tool (kea-msg-compiler) but its use is optional
+so it should not be a problem. If anyway you need it simply copy it from
+a native (i.e. not cross-compiled) Kea build.
+
+@section raspbianDependencies Usual Kea Dependencies
+
+Required and optional Kea dependencies, usually available as packages:
+ - Python (built-in)
+ - libssl-dev (built-in in the full image)
+ - liblog4cplus-dev (in liblog4cplus package, load both the library and
+ the development part)
+ - libboost-system-dev (in boost-xxx, load both the boost-system and
+ the boost-libraries packages, the second includes header files)
+ - googletest (download the last release from github)
+ - doc (sphinx, texlive, etc: just generate docs on the build system)
+ - MySQL (in mysql-defaults and mariadb-* packages?)
+ - PostgreSQL (in postgresql-12?)
+
+@section prepareCrossCompile Prepare Cross Compiling
+
+This script was used with success: it sets the environment variables
+before calling ./configure.
+@code
+# change when at another location
+export ROOTFS="$HOME/rpi/rootfs"
+
+# build commands
+export BUILD=x86_64-pc-linux-gnu
+export HOST=arm-linux-gnueabihf
+export CC="${HOST}-gcc"
+export CXX="${HOST}-g++"
+export LD="${HOST}-ld"
+export AR="${HOST}-ar"
+export RANLIB="${HOST}-ranlib"
+export STRIP="${HOST}-strip"
+export NM="${HOST}-nm"
+
+# g++ flags
+CXXFLAGS="-O2 -g -isysroot ${ROOTFS} -I${ROOTFS}/usr/include"
+CXXFLAGS+=" -I${ROOTFS}/usr/include/${HOST}"
+
+# ld flags
+LDFLAGS="--sysroot=${ROOTFS}"
+LDFLAGS+=" -L/opt/cross-pi-gcc/arm-linux-gnueabihf/lib -Wl,-rpath-link,/opt/cross-pi-gcc/arm-linux-gnueabihf/lib"
+LDFLAGS+=" -L/opt/cross-pi-gcc/lib -Wl,-rpath-link,/opt/cross-pi-gcc/lib"
+LDFLAGS+=" -L${ROOTFS}/opt/vc/lib -Wl,-rpath-link,${ROOTFS}/opt/vc/lib"
+LDFLAGS+=" -L${ROOTFS}/lib/${HOST} -Wl,-rpath-link,${ROOTFS}/lib/${HOST}"
+LDFLAGS+=" -L${ROOTFS}/usr/local/lib -Wl,-rpath-link,${ROOTFS}/usr/local/lib"
+LDFLAGS+=" -L${ROOTFS}/usr/lib/${HOST} -Wl,-rpath-link,${ROOTFS}/usr/lib/${HOST}"
+LDFLAGS+=" -L${ROOTFS}/usr/lib -Wl,-rpath-link,${ROOTFS}/usr/lib"
+LDFLAGS+=" -L${ROOTFS}/usr/lib/${HOST}/blas -Wl,-rpath-link,${ROOTFS}/usr/lib/${HOST}/blas"
+LDFLAGS+=" -L${ROOTFS}/usr/lib/${HOST}/lapack -Wl,-rpath-link,${ROOTFS}/usr/lib/${HOST}/lapack"
+
+# CPU tuning (use the most generic one)
+# PI 4 (not sure for the FPU)
+# CXXFLAGS+=" -mcpu=cortex-a72 -mfpu=neon-vfpv4 -mfloat-abi=hard"
+# PI 3
+# CXXFLAGS+=" -mcpu=cortex-a53 -mfpu=neon-vfpv4 -mfloat-abi=hard"
+# PI 2
+# CXXFLAGS+=" -mcpu=cortex-a7 -mfpu=neon-vfpv4 -mfloat-abi=hard"
+# PI 1, zero, ...
+CXXFLAGS+=" -mcpu=arm1176jzf-s -mfpu=vfp -mfloat-abi=hard"
+
+export CXXFLAGS
+export LDFLAGS
+
+export PKG_CONFIG_PATH="${ROOTFS}/usr/lib/pkgconfig"
+
+export PATH=/opt/cross-pi-gcc/bin:/opt/cross-pi-gcc/libexec/gcc/arm-linux-gnueabihf/8.3.0:$PATH
+
+# libraries are in fact in ${ROOTFS}/usr/lib/${HOST} but
+# the library path can be set only for boost.
+CONF_CMD="./configure --build=${BUILD} --host=${HOST}"
+CONF_CMD+=" --with-sysroot=${ROOTFS}"
+CONF_CMD+=" --with-openssl=${ROOTFS}/usr"
+CONF_CMD+=" --with-log4cplus=${ROOTFS}/usr"
+CONF_CMD+=" --with-boost-include=${ROOTFS}/usr/include"
+CONF_CMD+=" --with-boost-lib-dir=${ROOTFS}/usr/lib/${HOST}"
+@endcode
+
+Some explanations:
+ - the rootfs was copied or mounted in rpi/rootfs in the home directory.
+ - the build system triplet is x86_64-pc-linux-gnu (processor,
+ system, application binary interface). It is returned by the config.guess
+ script so please verify.
+ - the host system triplet is arm-linux-gnueabihf. It is used as the prefix
+ for cross-compiling tools so this value is critical.
+ - all tool variables are set to the cross-compiling tool name
+ - CXXFLAGS is defined to use the rootfs image for includes. It is critical
+ it does not use any build system include.
+ - LDFLAGS is defined to use the rootfs, all cross-compiler support libraries
+ and libraries from the rootfs image. It is critical it does not use
+ any build system library.
+ - CXXFLAGS can be tuned for a specific Raspberry Pi version. Proposed
+ tuning supports all versions.
+ - even if Kea ./configure does not depends on pkgconfig its path is set.
+ - PATH is updated to find first cross-compiling tools.
+ - I did not try yet database config scripts: perhaps they detect
+ cross-compiling and produce correct paths.
+ - CONF_CMD contains the ./configure common arguments.
+
+The script can be used by:
+ - eventually run "autoreconf -i" (if sources are from git)
+ - put its content in a file, e.g. ccenv
+ - load the file by ". ccenv"
+ - configure Kea build by "$CONF_CMD <your arguments>"
+
+Known problems:
+ - AC_TRY_RUN and AC_CHECK_FILE[S] autoconf macros do not support
+ cross-compiling. They were removed from ./configure.ac in Kea 1.7.10.
+ - libtool is a disaster for cross-compiling, in particular it produces
+ silly libtool archive (.la) files. Fortunately they are useless.
+ - bad paths for mkdir or sed on Raspbian.
+ - recent Debian systems including recent Ubuntu modified libtool to
+ not accept indirect dependencies. Makefiles were updated to have no
+ such indirect dependencies in common cases as it is in Kea Makefile
+ writing guidelines.
+ - the libtool variable managing this is link_all_deplibs. You can
+ edit the libtool script to set it to unknown or yes. Or simply
+ use another Linux distrib.
+ - there is no ldd in cross-compiling tools. The table of used
+ shared libraries in available by readelf -d which is in the
+ cross-compiling tools.
+
+Final words: this is still highly experimental and does not cover
+everything. New ways to offload almost everything outside the Raspberry
+Pi are still to be found. Currently to provide Raspbian Kea packages
+is not possible for ISC.
+
+*/
diff --git a/doc/devel/debug.dox b/doc/devel/debug.dox
new file mode 100644
index 0000000..556ed2e
--- /dev/null
+++ b/doc/devel/debug.dox
@@ -0,0 +1,26 @@
+// Copyright (C) 2023 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+/**
+
+ @page debug Debugging Kea
+
+@section debugSymbols Enabling debug symbols
+
+The --enable-debug flag can be useful when developing, since it
+makes the compiler produce more abundant debugging information that
+can be read by a debugger.
+
+Some compilers don't document some of the flags, such as clang for
+-g3. However, practice shows that clang behaves the same way as g++
+in that regard. As an experiment, providing -g4 results in
+`error: unknown argument: '-g4'`, but providing -g3 succesfully
+compiles, and supposedly puts it into effect.
+
+On top of that, the flag enables log4cplus's own logging, and adds
+more sanity checks in DNS code.
+
+*/
diff --git a/doc/devel/doc.dox b/doc/devel/doc.dox
new file mode 100644
index 0000000..cde7f90
--- /dev/null
+++ b/doc/devel/doc.dox
@@ -0,0 +1,86 @@
+// Copyright (C) 2018-2021 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+/**
+
+ @page docs Building Kea Documentation
+
+ There are several types of documentation for Kea. The primary one, intended to
+ be read by users, is User's Guide. It comes in HTML, PDF and txt format. All
+ of them generated from the same sources. To generate this doc, you need to
+ run configure script with --enable-generate-docs option. sphinx has to be
+ enabled in the system.
+ You can generate this by doing:
+@code
+$ ./configure --enable-generate-docs
+$ make -C ./doc
+@endcode
+
+The output files will be generated in the ./doc/sphinx/_build directory.
+
+The ARM has an appendix that lists all Kea commands. The commands are integrated
+into RST using the tool located at doc/sphinx/api2doc.py. The basic principle
+is that for every command there is a JSON file that briefly describes the major
+aspects such as name, short description, expected syntax, expected response,
+a hook that needs to be loaded, first Kea version where it appeared, etc.
+Those JSON files are loaded by the api2doc.py tool that will generate api.txt
+that will be used by sphinx. There is no need to call this tool explicitly.
+It is called automatically when building the ARM.
+
+Since Kea 1.9.9, the ARM has an appendix with the grammar. If there were new
+parameters added, you can regenerate the grammars and the appendix with the
+following procedure:
+
+@code
+$ autoreconf -i
+$ ./configure --enable-generate-docs --enable-generate-parser
+$ cd doc
+$ make grammar
+$ make -C sphinx html
+@endcode
+
+After that, inspect the html output and make sure it's ok, review changes in
+\c doc/sphinx/grammar/ and then check in those that are something more than a date
+update. The date is there, so we (and users) can determine if the grammar
+is or isn't out of date.
+
+@section docsNewCommand Documenting new command
+
+There are several steps needed to document a new API command:
+
+ 1. Configure sources with ./configure --enable-generate-docs
+ 1. Copy src/share/api/_template.json to appropriate name.
+ 2. Remove comments from it and fill in the actual content.
+ 3. Update api_files.mk file in src/share/api/Makefile.am
+ 4. make html will generate multi-page html.
+ 5. make singlehtml will generate a single page html.
+
+A word of caution regaring editing JSON files. The files themselves need to be
+valid JSON files. They also often contain fields, such as command syntax or
+command response, there are themselves a JSON or JSON like structures. That
+means that some trickery with escaping double quotes will be involved. Note
+there is no need to escape any other character, unless you want to specify
+non-printable characters.
+
+Also, while Kea's JSON parser supports comments and multi-line string, they
+are not part of JSON standard. That means that external tools, such as python
+or Sphinx parsers are not able to deal with them. Therefore comments must
+be removed and long strings (such as command descriptions or example invocations)
+are to be presented as a list of strings ( e.g. [ "line1", "line2, "line3" ]).
+
+@section docsDevelGuide Generating Developer's Guide
+
+Generating Developer's Guide is very simple, although you need to have
+doxygen installed in your system. If you also have graphviz installed, it will
+generate nice diagrams. To generate developer's guide, do the following commands:
+
+@code
+$ ./configure
+$ cd doc/devel
+$ make devel
+@endcode
+
+*/
diff --git a/doc/devel/fuzz.dox b/doc/devel/fuzz.dox
new file mode 100644
index 0000000..f4ec931
--- /dev/null
+++ b/doc/devel/fuzz.dox
@@ -0,0 +1,303 @@
+// Copyright (C) 2017-2021 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+/**
+@page fuzzer Fuzzing Kea
+
+@section fuzzIntro Introduction
+
+Fuzzing is a software-testing technique whereby a program is presented with a
+variety of generated data as input and is monitored for abnormal conditions
+such as crashes or hangs.
+
+Fuzz testing of Kea uses the AFL (American Fuzzy Lop) program. In this, Kea is
+built using an AFL-supplied program that not only compiles the software but
+also instruments it. When run, AFL generates test cases and monitors the
+execution of Kea as it processes them. AFL will adjust the input based on
+these measurements, seeking to discover and test new execution paths.
+
+@section fuzzTypes Types of Kea Fuzzing
+
+@subsection fuzzTypeNetwork Fuzzing with Network Packets
+
+In this mode, AFL will start an instance of Kea and send it a packet of data.
+Kea reads this packet and processes it in the normal way. AFL monitors code
+paths taken by Kea and, based on this, will vary the data sent in subsequent
+packets.
+
+@subsection fuzzTypeConfig Fuzzing with Configuration Files
+
+Kea has a configuration file check mode whereby it will read a configuration
+file, report whether the file is valid, then immediately exit. Operation of
+the configuration parsing code can be tested with AFL by fuzzing the
+configuration file: AFL generates example configuration files based on a
+dictionary of valid keywords and runs Kea in configuration file check mode on
+them. As with network packet fuzzing, the behaviour of Kea is monitored and
+the content of subsequent files adjusted accordingly.
+
+@section fuzzBuild Building Kea for Fuzzing
+
+Whatever tests are done, Kea needs to be built with fuzzing in mind. The steps
+for this are:
+
+-# Install AFL on the system on which you plan to build Kea and do the fuzzing.
+ AFL may be downloaded from http://lcamtuf.coredump.cx/afl. At the time of
+ writing (August 2019), the latest version is 2.52b. AFL should be built as
+ per the instructions in the README file in the distribution. The LLVM-based
+ instrumentation programs should also be built, as per the instructions in
+ the file llvm_mode/README.llvm (also in the distribution). Note that this
+ requires that LLVM be installed on the machine used for the fuzzing.
+
+-# Build Kea. Kea should be compiled and built as usual, although the
+ following additional steps should be observed:
+ - Set the environment variable CXX to point to the afl-clang-fast++
+ compiler.
+ - Specify a value of "--prefix" on the command line to set the directory
+ into which Kea is installed.
+ - Add the "--enable-fuzz" switch to the "configure" command line.
+ .
+ For example:
+ @code
+ CXX=/opt/afl/afl-clang-fast++ ./configure --enable-fuzz --prefix=$HOME/installed
+ make
+ @endcode
+
+-# Install Kea to the directory specified by "--prefix":
+ @code
+ make install
+ @endcode
+ This step is not strictly necessary, but makes running AFL easier.
+ "libtool", used by the Kea build procedure to build executable images, puts
+ the executable in a hidden ".libs" subdirectory of the target directory and
+ creates a shell script in the target directory for running it. The wrapper
+ script handles the fact that the Kea libraries on which the executable depends
+ are not installed by fixing up the LD_LIBRARY_PATH environment variable to
+ point to them. It is possible to set the variable appropriately and use AFL
+ to run the image from the ".libs" directory; in practice, it is a lot
+ simpler to install the programs in the directories set by "--prefix" and run
+ them from there.
+
+@section fuzzRun Running the Fuzzer
+
+@subsection fuzzRunNetwork Fuzzing with Network Packets
+
+-# In this type of fuzzing, Kea is processing packets from the fuzzer over a
+ network interface. This interface could be a physical interface or it could
+ be the loopback interface. Either way, it needs to be configured with a
+ suitable IPv4 or IPv6 address depending on whether kea-dhcp4 or kea-dhcp6 is
+ being fuzzed.
+
+-# Once the interface has been decided, these need to be set in the
+ configuration file used for the test. For example, to fuzz Kea-dhcp4
+ using the loopback interface "lo" and IPv4 address 10.53.0.1, the
+ configuration file would contain the following snippet:
+ @code
+ "Dhcp4": {
+ :
+ "interfaces-config": {
+ "interfaces": ["lo/10.53.0.1"]
+ },
+ "subnet4": [
+ {
+ :
+ "interface": "lo",
+ :
+ }
+ ],
+ :
+ }
+ @endcode
+
+-# The specification of the interface and address in the configuration file
+ is used by the main Kea code. Owing to the way that the fuzzing interface
+ between Kea and AFL is implemented, the address and interface also need to
+ be specified by the environment variables KEA_AFL_INTERFACE and
+ KEA_AFL_ADDRESS. With a configuration file containing statements listed
+ above, the relevant commands are:
+ @code
+ export KEA_AFL_INTERFACE="lo"
+ export KEA_AFL_ADDRESS="10.53.0.1"
+ @endcode
+ (If kea-dhcp6 is being fuzzed, then KEA_AFL_ADDRESS should specify an IPv6
+ address.)
+
+-# The fuzzer can now be run: a suitable command line is:
+ @code
+ afl-fuzz -m 4096 -i seeds -o fuzz-out -- ./kea-dhcp6 -c kea.conf -p 9001 -P 9002
+ @endcode
+ In the above:
+ - It is assumed that the directory holding the "afl-fuzz" program is in
+ the path, otherwise include the path name when invoking it.
+ - "-m 4096" allows Kea to take up to 4096 MB of memory. (Use "ulimit" to
+ check and optionally modify the amount of virtual memory that can be used.)
+ - The "-i" switch specifies a directory (in this example, one named "seeds")
+ holding "seed" files. These are binary files that AFL will use as its
+ source for generating new packets. They can generated from a real packet
+ stream with wireshark: right click on a packet, then export as binary
+ data. Ensure that only the payload of the UDP packet is exported.
+ - The "-o" switch specifies a directory (in this example called "fuzz-out")
+ that AFL will use to hold packets it has generated and packets that it has
+ found causes crashes or hangs.
+ - "--" Separates the AFL command line from that of Kea.
+ - "./kea-dhcp6" is the program being fuzzed. As mentioned above, this
+ should be an executable image, and it will be simpler to fuzz one
+ that has been installed.
+ - The "-c" switch sets the configuration file Kea should use while being
+ fuzzed.
+ - "-p 9001 -P 9002". The port on which Kea should listen and the port to
+ which it should send replies. If omitted, Kea will try to use the default
+ DHCP ports, which are in the privileged range. Unless run with "sudo",
+ Kea will fail to open the port and Kea will exit early on: no useful
+ information will be obtained from the fuzzer.
+
+-# Check that the fuzzer is working. If run from a terminal (with a black
+ background - AFL is particular about this), AFL will bring up a curses-style
+ interface showing the progress of the fuzzing. A good indication that
+ everything is working is to look at the "total paths" figure. Initially,
+ this should increase reasonably rapidly. If not, it is likely that Kea is
+ failing to start or initialize properly and the logging output (assuming
+ this has been configured) should be examined.
+
+@subsection fuzzRunConfig Fuzzing with Configuration Files
+
+AFL can be used to check the parsing of the configuration files. In this type
+of fuzzing, AFL generates configuration files which is passes to Kea to check.
+Steps for this fuzzing are:
+
+-# Build Kea as described above.
+
+-# Create a dictionary of keywords. Although AFL will mutate the files by
+ byte swaps, bit flips and the like, better results are obtained if it can
+ create new files based on keywords that could appear in the file. The
+ dictionary is described in the AFL documentation, but in brief, the file
+ contains successive lines of the form 'variable=keyword"', e.g.
+ @code
+ PD_POOLS="pd-pools"
+ PEERADDR="peeraddr"
+ PERSIST="persist"
+ PKT="pkt"
+ PKT4="pkt4"
+ @endcode
+ "variable" can be anything, as its name is ignored by AFL. However, all the
+ variable names in the file must be different. "keyword" is a valid keyword
+ that could appear in the configuration file. The convention adopted in the
+ example above seems to work well - variables have the same name as keywords,
+ but are in uppercase and have hyphens replaced by underscores.
+
+-# Run Kea with a command line of the form:
+ @code
+ afl-fuzz -m 4096 -i seeds -o fuzz-out -x dict.dat -- ./kea-dhcp4 -t @@
+ @endcode
+ In the above command line:
+ - Everything up to and including the "--" is the AFL command. The switches
+ are as described in the previous section apart from the "-x" switch: this
+ specifies the dictionary file ("dict.dat" in this example) described
+ above.
+ - The Kea command line uses the "-t" switch to specify the configuration
+ file to check. This is specified by two consecutive "@" signs: AFL
+ will replace these with the name of a file it has created when starting
+ Kea.
+
+@section Fuzzing Internals
+
+@subsection fuzzInternalNetwork Fuzzing with Network Packets
+
+The AFL fuzzer delivers packets to Kea's stdin. Although the part of Kea
+concerning the reception of packets could have been modified to accept input
+from stdin and have Kea pick them up in the normal way, a less-intrusive method
+was adopted.
+
+The packet loop in the main server code for kea-dhcp4 and kea-dhcp6 is
+essentially:
+@code{.unparsed}
+while (not shutting down) {
+ Read and process one packet
+}
+@endcode
+When --enable-fuzz is specified, this is conceptually modified to:
+@code{.unparsed}
+while (not shutting down) {
+ Read stdin and copy data to address/port on which Kea is listening
+ Read and process one packet
+}
+@endcode
+
+Implementation is via an object of class "Fuzz". When created, it identifies
+an interface, address and port on which Kea is listening and creates the
+appropriate address structures for these. The port is passed as an argument to
+the constructor because at the point at which the object is constructed, that
+information is readily available. The interface and address are picked up from
+the environment variables mentioned above. Consideration was given to
+extracting the interface and address information from the configuration file,
+but it was decided not to do this:
+
+-# The configuration file can contain the definition of multiple interfaces;
+ if this is the case, the one being used for fuzzing is unclear.
+-# The code is much simpler if the data is extracted from environment
+ variables.
+
+Every time through the loop, the object reads the data from stdin and writes it
+to the identified address/port. Control then returns to the main Kea code,
+which finds data available on the address/port on which it is listening and
+handles the data in the normal way.
+
+In practice, the "while" line is actually:
+@code{.unparsed}
+while (__AFL_LOOP(count)) {
+@endcode
+__AFL_LOOP is a token recognized and expanded by the AFL compiler (so no need
+to "#include" a file defining it) that implements the logic for the fuzzing.
+Each time through the loop (apart from the first), it raises a SIGSTOP signal
+telling AFL that the packet has been processed and instructing it to provide
+more data. The "count" value is the number of times through the loop before
+the loop terminates and the process is allowed to exit normally. When this
+happens, AFL will start the process anew. The purpose of periodically shutting
+down the process is to avoid issues raised by the fuzzing being confused with
+any issues associated with the process running for a long time (e.g. memory
+leaks).
+
+@subsection fuzzInternalConfig Fuzzing with Configuration Files
+
+No changes were required to Kea source code to fuzz configuration files. In
+fact, other than compiling with afl-clang++ and installing the resultant
+executable, no other steps are required. In particular, there is no need to
+use the "--enable-fuzz" switch in the configuration command line (although
+doing so will not cause any problems).
+
+@subsection fuzzThreads Changes Required for Multi-Threaded Kea
+
+The early versions of the fuzzing code used a separate thread to receive the
+packets from AFL and to write them to the socket on which Kea is listening.
+The lack of synchronization proved a problem, with Kea hanging in some
+instances. Although some experiments with thread synchronization were
+successful, in the end the far simpler single-threaded implementation described
+above was adopted for the single-threaded Kea 1.6. Should Kea be modified to
+become multi-threaded, the fuzzing code will need to be changed back to reading
+the AFL input in the background.
+
+@section fuzzNotes Notes
+
+@subsection fuzzNotesUnitTests Unit Test Failures
+
+If unit tests are built when --enable-fuzzing is specified, note that tests
+which check or use the DHCP servers (i.e. the unit tests in src/bin/dhcp4,
+src/bin/dhcp6 and src/bin/kea-admin) will fail. With no AFL-related
+environment variables defined, a C++ exception will be thrown with the
+description "no fuzzing interface has been set". However, if the
+KEA_AFL_INTERFACE and KEA_AFL_ADDRESS variables are set to valid values, the
+tests will hang.
+
+Both these results are expected and should cause no concern. The exception is
+thrown by the fuzzing object constructor when it attempts to create the address
+structures for routing packets between AFL and Kea but discovers it does not
+have the necessary information. The hang is due to the fact that the AFL
+processing loop does a synchronous read from stdin, something not expected by
+the test. (Should random input be supplied on stdin, e.g. from the keyboard,
+the test will most likely fail as the input is unlikely to be that expected by
+the test.)
+
+
+*/
diff --git a/doc/devel/mainpage.dox b/doc/devel/mainpage.dox
new file mode 100644
index 0000000..5151e15
--- /dev/null
+++ b/doc/devel/mainpage.dox
@@ -0,0 +1,160 @@
+// Copyright (C) 2012-2024 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+/**
+ * @mainpage Kea Developer's Guide
+ *
+ * Welcome to the Kea Developer's Guide. This documentation is addressed at
+ * either existing or prospective Kea developers and contributors, and
+ * provides information needed to extend and maintain Kea source code.
+
+ * If you wish to write hook code - the code that is loaded by Kea at
+ * run-time and modifies its behavior, you should read the section
+ * @ref hooksdgDevelopersGuide.
+ *
+ * Kea maintenance information is divided into a number of sections.
+ * Information on DHCP-specific topics can be found
+ * in the @ref dhcpMaintenanceGuide. General topics are discussed in
+ * @ref miscellaneousTopics.
+ *
+ * If you are a user or system administrator, rather than software engineer,
+ * you should read the
+ * <a href="https://kea.readthedocs.io">Kea
+ * Administrator Reference Manual</a> instead. If you are using a beta or
+ * development version of Kea, the
+ * <a href="https://kea.readthedocs.io/">
+ * development version of the manual</a> is recommended.
+ *
+ * Regardless of your field of expertise, you are encouraged to visit the
+ * <a href="https://gitlab.isc.org/isc-projects/kea/wikis/home">Kea wikipage (https://gitlab.isc.org/isc-projects/kea/wikis/home)</a>
+ *
+ * @section contrib Contributor's Guide
+ * - @subpage contributorGuide - This page describes the process of sending
+ * a patch to ISC and what happens next. Please read it if you are considering
+ * sending us any code.
+ *
+ * @section qa Quality Assurance
+ * - @subpage qaIntro
+ * - @subpage unitTests
+ * - @subpage unitTestsEnvironmentVariables
+ * - @subpage unitTestsSanitizers
+ * - @subpage unitTestsDatabaseConfig
+ * - @subpage unitTestsSysrepo
+ * - @subpage writingShellScriptsAndTests
+ * - @subpage performance
+ * - @subpage fuzzer
+ * - @subpage qa
+ * - @subpage ciGithub
+ * - @subpage ciGitlab
+ * - @subpage ciJenkins
+ *
+ * @section hooksFramework Hooks Framework
+ * - @subpage hooksdgDevelopersGuide
+ * - @subpage dhcpv4Hooks
+ * - @subpage dhcpv6Hooks
+ * - @subpage agentHooks
+ * - @subpage d2Hooks
+ * - @subpage hooksComponentDeveloperGuide
+ * - @subpage hooksmgMaintenanceGuide
+ * - @subpage libdhcp_ha
+ * - @subpage libdhcp_user_chk
+ * - @subpage libdhcp_lease_cmds
+ * - @subpage libdhcp_stat_cmds
+ *
+ * @section dhcpMaintenanceGuide DHCP Maintenance Guide
+ * - @subpage dhcp4
+ * - @subpage dhcpv4ConfigParser
+ * - @subpage dhcpv4ConfigInherit
+ * - @subpage dhcpv4OptionsParse
+ * - @subpage dhcpv4DDNSIntegration
+ * - @subpage dhcpv4Classifier
+ * - @subpage dhcpv4ConfigBackend
+ * - @subpage dhcpv4SignalBasedReconfiguration
+ * - @subpage dhcpv4Other
+ * - @subpage dhcpv4o6Dhcp4
+ * - @subpage dhcp6
+ * - @subpage dhcpv6ConfigParser
+ * - @subpage dhcpv6ConfigInherit
+ * - @subpage dhcpv6DDNSIntegration
+ * - @subpage dhcpv6OptionsParse
+ * - @subpage dhcpv6Classifier
+ * - @subpage dhcpv6ConfigBackend
+ * - @subpage dhcpv6SignalBasedReconfiguration
+ * - @subpage dhcpv6Other
+ * - @subpage dhcpv4o6Dhcp6
+ * - @subpage congestionHandling
+ * - @subpage d2
+ * - @subpage d2ProcessDerivation
+ * - @subpage d2ConfigMgt
+ * - @subpage d2NCRReceipt
+ * - @subpage d2DDNSUpdateExecution
+ * - @subpage d2EventLoop
+ * - @subpage d2TransDetail
+ * - @subpage d2StateModel
+ * - @subpage d2TransExecExample
+ * - @subpage controlAgent
+ * - @subpage ctrlAgentHttp
+ * - @subpage ctrlAgentCreatingResponse
+ * - @subpage ctrlAgentCommandMgr
+ * - @subpage CtrlAgentSecurity
+ * - @subpage lfc
+ * - @subpage lfcProcessing
+ * - @subpage lfcFiles
+ * - @subpage ctrlSocket
+ * - @subpage ctrlSocketOverview
+ * - @subpage ctrlSocketClient
+ * - @subpage ctrlSocketImpl
+ * - @subpage ctrlSocketConnections
+ * - @subpage dhcpDatabaseBackends
+ * - @subpage configBackend
+ * - @subpage configBackendJSONDesign
+ *
+ * @section libraries Kea libraries
+ * - @subpage libutil
+ * - @subpage libasiolink
+ * - @subpage libcc
+ * - @subpage libdatabase
+ * - @subpage libdhcp
+ * - @subpage libdhcpIntro
+ * - @subpage libdhcpRelay
+ * - @subpage libdhcpIfaceMgr
+ * - @subpage libdhcpPktFilter
+ * - @subpage libdhcpPktFilter6
+ * - @subpage libdhcpErrorLogging
+ * - @subpage libstats
+ * - @subpage libdhcp_ddns
+ * - @subpage libdhcpsrv
+ * - @subpage leasemgr
+ * - @subpage cfgmgr
+ * - @subpage hostmgr
+ * - @subpage optionsConfig
+ * - @subpage allocengine
+ * - @subpage timerManager
+ * - @subpage leaseReclamationRoutine
+ * - @subpage subnetSelect
+ * - @subpage dhcp4o6Ipc
+ * - @subpage libeval
+ * - @subpage libprocess
+ * - @subpage cpl
+ * - @subpage cplSignals
+ * - @subpage libyang
+ * - @subpage libhttp
+ *
+ * @section miscellaneousTopics Miscellaneous Topics
+ * - @subpage terminology
+ * - @subpage parser
+ * - @subpage logKeaLogging
+ * - @subpage logBasicIdeas
+ * - @subpage logDeveloperUse
+ * - @subpage logNotes
+ * - @subpage LoggingApi
+ * - @subpage SocketSessionUtility
+ * - @subpage crossCompile
+ * - @subpage debug
+ * - @subpage docs
+ * - <a href="./doxygen-error.log"><b>Documentation Warnings and Errors</b></a>
+ *
+ */
diff --git a/doc/devel/performance.dox b/doc/devel/performance.dox
new file mode 100644
index 0000000..4d4420f
--- /dev/null
+++ b/doc/devel/performance.dox
@@ -0,0 +1,15 @@
+// Copyright (C) 2024 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+/**
+
+ @page performance Performance Testing
+
+ This section is for topics pertaining to Kea runtime performance.
+
+ @subpage perfdhcpInternals perfdhcp Internals
+
+*/
diff --git a/doc/devel/qa.dox b/doc/devel/qa.dox
new file mode 100644
index 0000000..d82c4e7
--- /dev/null
+++ b/doc/devel/qa.dox
@@ -0,0 +1,52 @@
+// Copyright (C) 2023 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+/**
+@page qaIntro Quality Assurance in Kea
+
+This is only a brief excerpt about some QA systems used at ISC. For more
+information, please refer to the DHCP QA department.
+
+@section ciGithub Running CI pipeline on Github
+
+While our primary environment for running CI pipeline is Jenkins hosted on AWS,
+there are some tools that are only available on github. One of such tools is
+CodeQL. CodeQL is a static analysis tool that can be used to find security
+vulnerabilities in the code. It is a part of Github Advanced Security suite.
+Github Advanced Security suite is available for free for open source projects.
+
+The job is defined in `.github/workflows/codeql.yml` file. It is configured
+to run once per week on `master` and `ci` branches. Sadly, it requires Kea
+compilation. With the runners provided on github having only 2 CPUs, it's
+a slow process. But we don't care that much - we get the results once per
+week. The results are available in the `Security` tab of the repository
+(see https://github.com/isc-projects/kea/security). This tab is only visible to
+logged in members of the isc-projects organization.
+
+@section ciGitlab Running CI pipeline on Gitlab
+
+There are several jobs configure on gitlab CI:
+
+- shellcheck
+- danger
+- dhcpdb_create-upgrade-consistency
+- duplicate-includes
+- missing-api-commands
+- missing-config-h-include
+- missing-git-attribute
+- sast-analyzer
+- flawfinder-sast
+
+The pipeline can be inspected and configure here:
+https://gitlab.isc.org/isc-projects/kea/-/ci/editor
+
+@section ciJenkins Running CI pipeline on Jenkins
+
+Jenkins is the primary CI environment. It is hosted on AWS. For details,
+see internal QA-DHCP wiki, ask on QA channel on mattermost or take a look at the
+internal `qa-dhcp` repository.
+
+*/
diff --git a/doc/devel/terminology.dox b/doc/devel/terminology.dox
new file mode 100644
index 0000000..11750ff
--- /dev/null
+++ b/doc/devel/terminology.dox
@@ -0,0 +1,28 @@
+// Copyright (C) 2017 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+/**
+@page terminology Terminology
+
+This page explains some common abbreviations and terms:
+
+- CA - Control Agent. That's a separate module that talks with Kea DHCPv4, DHCPv6 (and soon also D2)
+ over control channel and exposes their internal commands using RESTful interface.
+
+- D2 - This is a nickname of DHCP-Dynamic DNS server module. Since using the full name is awkward,
+ we often use shortened version of it: D2.
+
+- DHCP - Dynamic Host Configuration Protocol. There are two similar, but operationally different
+ protocols: DHCPv4 and DHCPv6. When v4 or v6 is not specified, the DHCP expression applies to both.
+
+- DHCPv4 - Dynamic Host Configuration Protocol for IPv4, a protocol that defines how IPv4 hosts can
+ obtain IPv4 addresses and other configuration from the servers. Defined in RFC2131.
+
+- DHCPv6 - Dynamic Host Configuration Protocol for IPv6, a protocol that defines how IPv6 hosts and
+ router can obtain IPv6 addresses, IPv6 prefixes and other configuration from the servers. Defined
+ in RFC3315.
+
+*/
diff --git a/doc/devel/unit-tests.dox b/doc/devel/unit-tests.dox
new file mode 100644
index 0000000..42d0643
--- /dev/null
+++ b/doc/devel/unit-tests.dox
@@ -0,0 +1,613 @@
+// Copyright (C) 2015-2023 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+/**
+
+ @page unitTests Building Kea with Unit Tests
+
+By default, Kea is built without unit-tests as they're used mostly by
+developers and prospective contributors. Kea's unit-tests are using
+<a href="https://github.com/google/googletest">gtest framework</a> from
+Google. Google's approach has changed over the years. For some time,
+they were very keen on not installing gtest as a normal software would
+be, but rather provide gtest as sources. This was further complicated
+with the fact that some Linux distributions packaged gtest and tried
+to mimic its installation. Kea tries its best to accommodate all typical
+situations and provides two switches to point to gtest. You can use
+`--with-gtest` or `--with-gtest-source`. Both attempt to locate gtest
+on their own. However, if neither of them can find it, you can specify
+the path explicitly. For example, on ubuntu with googletest package installed,
+you can do the following for Kea to find it:
+
+@code
+sudo apt install googletest
+./configure --with-gtest-source=/usr/src/googletest
+@endcode
+
+Depending on how you compiled or installed \c gtest (e.g. from sources
+or using some package management system) one of those two switches will
+find \c gtest. After that you make and run the unit-tests with:
+
+@code
+make
+make check
+@endcode
+
+As usual, using \c -jX option will speed up compilation. This parameter is
+even more useful for unit-tests as there are over 6000 unit-tests and their
+compilation is significantly slower than just the production Kea sources.
+
+Kea should work with reasonably recent gtest versions. We recently tried
+with 1.7.0, 1.8.0, 1.8.1 and 1.10.0.
+
+@section unitTestsEnvironmentVariables Environment Variables
+
+The following environment variable can affect the unit tests:
+
+- KEA_LOCKFILE_DIR - Specifies a directory where the logging system should
+ create its lock file. If not specified, it is <i>prefix</i>/var/run/kea,
+ where <i>prefix</i> defaults to /usr/local. This variable must not end
+ with a slash. There is one special value, "none", which instructs Kea to
+ not create a lock file at all. This may cause issues if several processes
+ log to the same file. (Also see the Kea User's Guide, section 15.3.)
+
+- KEA_LOGGER_DESTINATION - Specifies the logging destination. If not set, logged
+ messages will not be recorded anywhere. There are three special values:
+ stdout, stderr and syslog. Any other value is interpreted as a filename.
+ (Also see Kea User's Guide, section 15.3.)
+
+- KEA_LOG_CHECK_VERBOSE - Specifies the log check default verbosity. If not
+ set, unit tests using the log utils to verify that logs are generated as
+ expected are by default silent. If set, these unit tests display real
+ and expected logs.
+
+- KEA_MYSQL_HAVE_SSL - Specifies the SSL/TLS support status of MySQL.
+ When not set the corresponding MySQL global variable is read and
+ the environment of the unit test process is updated so usually this
+ variable is manually set only in order to enforce a particular status.
+
+- KEA_PIDFILE_DIR - Specifies the directory which should be used for PID files
+ as used by dhcp::Daemon or its derivatives. If not specified, the
+ default is <i>prefix</i>/var/run/kea, where <i>prefix</i> defaults to
+ /usr/local. This variable must not end with a slash.
+
+- KEA_SOCKET_TEST_DIR - If set, it specifies the directory where Unix
+ sockets are created. There is an operating system limitation on how
+ long a Unix socket path can be, typically slightly over 100
+ characters. By default unit-tests create sockets in temporary folder
+ under /tmp folder. KEA_SOCKET_TEST_DIR can be specified to instruct
+ unit-tests to use a different directory. It must not end with slash.
+
+- KEA_TEST_DB_WIPE_DATA_ONLY - Unit tests which use a Kea unit test
+ database take steps to ensure they are starting with an empty database
+ of the correct schema version. The first step taken is to simply
+ delete the transient data (such as leases, reservations, etc..), provided
+ the schema exists and is the expected version. If the schema does not
+ exist, is not the expected version, or for some reason the data wipe fails,
+ the schema will be dropped and recreated. Setting this value to "false"
+ will cause the test setup logic to always drop and create the database
+ schema. The default value is "true".
+
+- KEA_TLS_CHECK_VERBOSE - Specifies the TLS check default verbosity. If not
+ set, TLS unit tests triggering expected failures are by default silent.
+ If set, these TLS unit tests display the error messages which are very
+ dependent on the cryptographic backend and boost library versions.
+
+@note Setting KEA_TEST_DB_WIPE_DATA_ONLY to false may dramatically
+increase the time it takes each unit test to execute.
+
+- GTEST_OUTPUT - Save the test results in XML files. Make it point to a location
+where a file or directory can be safely created. If there is no file or
+directory at that location, adding a trailing slash
+`GTEST_OUTPUT=${PWD}/test-results/` will create a directory containing an XML
+file for each directory being tested. Leaving the slash out will create a single
+XML file and will put all the test results in it.
+
+- DEBUG - Set this variable to make shell tests output the commands that are
+run. They are shown just before they are effectively run. Can be set to
+anything e.g. `DEBUG=true`. `unset DEBUG` to remove this behavior.
+
+@section unitTestsSanitizers Use Sanitizers
+
+ GCC and LLVM support some sanitizers which perform additional tests
+ at runtime, for instance the ThreadSanitizer (aka TSan) detects data
+ race in executed C++ code (unfortunately on macOS it intercepts
+ signals and fails to send them to waiting select system calls so
+ some tests always fail when it is used, experiments are run with
+ different versions of Tsan).
+
+ The simplest way to enable a sanitizer is to add it to the CXXFLAGS
+ environment variable in .configure by e.g. <i>-fsanitize=thread</i>.
+
+ When enabling lcov (code coverage), some gtest functions are detected as
+ not being thread safe. It is recommended to disable lcov when enabling
+ thread sanitizer.
+
+@section unitTestsDatabaseConfig Databases Configuration for Unit Tests
+
+ With the use of databases requiring separate authorisation, there are
+ certain database-specific pre-requisites for successfully running the unit
+ tests. These are listed in the following sections.
+
+ @subsection unitTestsDatabaseUsers Database Users Required for Unit Tests
+
+ Unit tests validating database backends require that the <i>keatest</i>
+ database is created. This database should be empty. The unit tests
+ also require that the <i>keatest</i> user is created and that this user
+ is configured to access the database with a password of <i>keatest</i>.
+ Unit tests use these credentials to create database schema, run test cases
+ and drop the schema. Thus, the <i>keatest</i> user must have sufficiently
+ high privileges to create and drop tables, as well as insert and modify the
+ data within those tables.
+
+ The database backends which support read only access to the host
+ reservations databases (currently MySQL and PostgreSQL) include unit
+ tests verifying that a database user with read-only privileges can be
+ used to retrieve host reservations. Those tests require another user,
+ <i>keatest_readonly</i>, with SQL SELECT privilege to the <i>keatest</i>
+ database (i.e. without INSERT, UPDATE etc.), is also created.
+ <i>keatest_readonly</i> should also have the password <i>keatest</i>.
+
+ The following sections provide step-by-step guidelines how to setup the
+ databases for running unit tests.
+
+ @subsection mysqlUnitTestsPrerequisites MySQL Database
+
+ The steps to create the database and users are:
+
+ -# Log into MySQL as root:
+ @verbatim
+ % mysql -u root -p
+ Enter password:
+ :
+ mysql>@endverbatim\n
+ -# Create the test database. This must be called "keatest":
+ @verbatim
+ mysql> CREATE DATABASE keatest;
+ mysql>@endverbatim\n
+ -# Create the users under which the test client will connect to the database
+ (the apostrophes around the words <i>keatest</i>, <i>keatest_readonly</i>, and
+ <i>localhost</i> are required):
+ @verbatim
+ mysql> CREATE USER 'keatest'@'localhost' IDENTIFIED BY 'keatest';
+ mysql> CREATE USER 'keatest_readonly'@'localhost' IDENTIFIED BY 'keatest';
+ mysql> CREATE USER 'keatest_secure'@'localhost' IDENTIFIED BY 'keatest';
+ mysql> ALTER USER 'keatest_secure'@'localhost' REQUIRE X509;
+ mysql>@endverbatim\n
+ Some old versions of MySQL do not support the REQUIRE keyword in ALTER
+ USER. Fortunately all versions support it in GRANT even if it is less secure
+ as the requirement will apply only to commands for the database instead
+ to all connections so all commands. And of course in production many
+ stronger requirements are available: X509 only requires the user to
+ present a certificate: you can specify which certificate by requiring
+ for instance a particular Subject Name, etc.
+ -# Grant the created users permissions to access the <i>keatest</i> database
+ (again, the apostrophes around the user names and <i>localhost</i>
+ are required):
+ @verbatim
+ mysql> GRANT ALL ON keatest.* TO 'keatest'@'localhost';
+ mysql> GRANT SELECT ON keatest.* TO 'keatest_readonly'@'localhost';
+ mysql> GRANT ALL ON keatest.* TO 'keatest_secure'@'localhost';
+ mysql>@endverbatim\n
+ When the REQUIRE in ALTER USER is not supported change the last line by:
+ @verbatim
+ mysql> GRANT ALL ON keatest.* TO 'keatest_secure'@'localhost' REQUIRE X509;
+ mysql>@endverbatim\n
+ -# If you get <i>You do not have the SUPER privilege and binary logging is
+ enabled</i> error message, you need to add:
+ @verbatim
+ mysql> SET GLOBAL LOG_BIN_TRUST_FUNCTION_CREATORS = 1;
+ mysql>@endverbatim\n
+ -# Exit MySQL:
+ @verbatim
+ mysql> quit
+ Bye
+ %@endverbatim
+
+ The unit tests are run automatically when "make check" is executed (providing
+ that Kea has been built with the \c --with-mysql switch (see the installation
+ section in the <a href="https://kea.readthedocs.io/">Kea Administrator
+ Reference Manual</a>).
+
+ @subsection mysqlUnitTestsTLS MySQL Database with SSL/TLS
+
+ Usually MySQL is compiled with SSL/TLS support using OpenSSL.
+ This is easy to verify using the:
+
+@verbatim
+mysql> SHOW GLOBAL VARIABLES LIKE 'have_ssl';
+@endverbatim
+
+ The variable is documented to have three possible values:
+
+- DISABLED: compiled with TLS support but it was not configured
+
+- YES: compiled with configured TLS support
+
+- NO: not compiled with TLS support
+
+The value of this MySQL global variable is reflected by the
+KEA_MYSQL_HAVE_SSL environment variable.
+
+The keatest_secure user requires X509 so a client certificate. Of course
+in production a stricter requirement should be used, in particular when
+a client certificate should be bound to a particular user.
+
+MySQL unit tests reuse the asiolink library setup. This .my.cnf
+configuration file works with MariaDB 10.6.4:
+
+@verbatim
+[mysqld]
+ssl_cert=<kea-sources>/src/lib/asiolink/testutils/ca/kea-server.crt
+ssl_key=<kea-sources>/src/lib/asiolink/testutils/ca/kea-server.key
+ssl_ca=<kea-sources>/src/lib/asiolink/testutils/ca/kea-ca.crt
+
+[client-mariadb]
+ssl_cert=<kea-sources>/src/lib/asiolink/testutils/ca/kea-client.crt
+ssl_key=<kea-sources>/src/lib/asiolink/testutils/ca/kea-client.key
+ssl_ca=<kea-sources>/src/lib/asiolink/testutils/ca/kea-ca.crt
+ssl-verify-server-cert
+@endverbatim
+
+The last statement requires mutual authentication named two way in the
+MariaDB documentation. For MySQL versions greater than 5.7.11 this
+statement should be replaced by:
+
+@verbatim
+[client]
+...
+ssl-mode=VERIFY_IDENTITY
+@endverbatim
+
+On Debian some MySQL packages use GnuTLS instead OpenSSL to provide
+the SSL/TLS support: this is known to not work with this proposed setup.
+
+ @subsection pgsqlUnitTestsPrerequisites PostgreSQL Database
+
+ PostgreSQL set up differs from system to system. Please consult your
+ operating system-specific PostgreSQL documentation. The remainder of
+ that section uses Ubuntu 13.10 x64 (with PostgreSQL 9.0+) as an example.
+
+ On Ubuntu, PostgreSQL is installed (with <tt>sudo apt-get install
+ postgresql</tt>) under user <i>postgres</i>. To create new databases
+ or add new users, initial commands must be issued under this username:
+
+@verbatim
+$ sudo -u postgres psql postgres
+[sudo] password for thomson:
+psql (9.1.12)
+Type "help" for help.
+postgres=# CREATE USER keatest WITH PASSWORD 'keatest';
+CREATE ROLE
+postgres=# CREATE DATABASE keatest;
+CREATE DATABASE
+postgres=# GRANT ALL PRIVILEGES ON DATABASE keatest TO keatest;
+GRANT
+postgres=# \q
+@endverbatim
+
+ PostgreSQL versions earlier than 9.0 don't provide an SQL statement for granting
+ privileges on all tables in a database. In newer PostgreSQL versions, it is
+ possible to grant specific privileges on all tables within a schema.
+ However, this only affects tables which exist when the privileges are granted.
+ To ensure that the user has specific privileges to tables dynamically created
+ by the unit tests, the default schema privileges must be altered.
+
+ The following example demonstrates how to create the user <i>keatest_readonly</i>,
+ which has SELECT privilege to the tables within the <i>keatest</i> database,
+ in Postgres 9.0+. For earlier versions of Postgres, it is recommended to
+ simply grant full privileges to <i>keatest_readonly</i>, using the
+ same steps as for the <i>keatest</i> user.
+
+@verbatim
+$ psql -U postgres
+Password for user postgres:
+psql (9.1.12)
+Type "help" for help.
+
+postgres=# CREATE USER keatest_readonly WITH PASSWORD 'keatest';
+CREATE ROLE
+postgres=# \q
+
+$ psql -U keatest
+Password for user keatest:
+psql (9.1.12)
+Type "help" for help.
+
+keatest=> ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES to keatest_readonly;
+ALTER DEFAULT PRIVILEGES
+keatest=> \q
+@endverbatim
+
+ Note that the <i>keatest</i> user (rather than <i>postgres</i>) is used to grant
+ privileges to the <i>keatest_readonly</i> user. This ensures that the SELECT
+ privilege is granted only on the tables that the <i>keatest</i> user can access
+ within the public schema.
+
+ It seems this no longer works on recent versions of PostgreSQL: if you get
+ a permission problem on SELECT on the schema_version table for
+ eatest_readonly, please try with the schema loaded:
+
+@verbatim
+$ psql -h localhost -U keatest -d keatest
+Password for user keatest:
+psql (11.3 (Debian 11.3-1))
+SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, bits: 256, compression: off)
+Type "help" for help.
+
+keatest=> GRANT SELECT ON ALL TABLES IN SCHEMA public TO keatest_readonly;
+GRANT
+keatest=> \q
+@endverbatim
+
+ Now we should be able to log into the newly created database using both user
+ names:
+@verbatim
+$ psql -d keatest -U keatest
+Password for user keatest:
+psql (9.1.12)
+Type "help" for help.
+
+keatest=> \q
+
+$ psql -d keatest -U keatest_readonly
+Password for user keatest_readonly:
+psql (9.1.12)
+Type "help" for help.
+
+keatest=>
+@endverbatim
+
+ If instead of seeing keatest=> prompt, your login is refused with an error
+ code about failed peer or
+ <tt>Ident authentication failed for user "keatest"</tt>, it means that
+ PostgreSQL is configured to check unix username and reject login attempts if
+ PostgreSQL names are different. To alter that, the PostgreSQL pg_hba.conf
+ configuration file must be changed. It usually resides at
+ <tt>/var/lib/postgresql/data/pg_hba.conf</tt> or at
+ <tt>/etc/postgresql/${version}/main/pg_hba.conf</tt>, but you can find out
+ for sure by running
+ <tt>sudo -u postgres psql -t -c 'SHOW hba_file'</tt>. Make sure
+ that all the authentication methods are changed to "md5" like this:
+
+@verbatim
+local all all md5
+host all all 127.0.0.1/32 md5
+host all all ::1/128 md5
+@endverbatim
+
+ Another possible problem is that you get no password prompt. This is
+ most probably because you have no <tt>pg_hba.conf</tt> config file
+ and everybody is by default trusted. As it has a very bad effect
+ on the security you should have been warned this is a highly unsafe
+ configuration. The solution is the same, i.e., require password or
+ md5 authentication method.
+
+ If you lose the postgres user access you can first add:
+@verbatim
+local all postgres trust
+@endverbatim
+ to trust only the local postgres user. Note the postgres user can
+ be pgsql on some systems.
+
+ Please consult your PostgreSQL user manual before applying those changes as
+ those changes may expose your other databases that you run on the same system.
+ In general case, it is a poor idea to run anything of value on a system
+ that runs tests. Use caution!
+
+ The unit tests are run automatically when "make check" is executed (providing
+ that Kea has been build with the \c --with-pgsql switch (see the installation
+ section in the <a href="https://kea.readthedocs.io">Kea Administrator
+ Reference Manual</a>).
+
+@section unitTestsKerberos Kerberos Configuration for Unit Tests
+
+The GSS-TSIG hook library uses the GSS-API with Kerberos. While there are
+no doubts that the hook can be safely used with a valid Kerberos configuration
+in production, unit tests reported problems on some systems.
+
+GSS-TSIG hook unit tests use a setup inherited from bind9 with old crypto
+settings which are not allowed by default Kerberos system configuration.
+A simple workaround is to set the KRB5_CONFIG environment variable to
+a random value that doesn't match a file (e.g. KRB5_CONFIG=).
+
+@section writingShellScriptsAndTests Writing shell scripts and tests
+
+Shell tests are `shellcheck`ed. But there are other writing practices that are
+good to follow in order to keep, not only shell tests, but shell scripts in
+general, POSIX-compliant. See below:
+
+- For portability, all shell scripts should have a shebang.
+@code
+#!/bin/sh
+@endcode
+The `sh` shell can differ on various operating systems. On most systems it is
+GNU sh. Notable exceptions are Alpine which links it to ash, FreeBSD which has
+the primordial non-GNU sh, Ubuntu which links it to dash. These four shells
+should all be tested against, when adding shell scripts or making changes to
+them.
+
+- Reference variables with curly brackets.
+@code
+${var} # better
+$var
+@endcode
+For consistency with cases where you need advanced features from the variables
+which make the curly brackets mandatory. Such cases are:
+@code
+# Retrieving variable/string length...
+${#var}
+
+# Defaulting to a given value when the variable is undefined...
+${var-default}
+
+# Substituting the variable with a given value when the variable is defined...
+${var+value}
+
+# Concatenating the value of a variable with an alphanumeric constant...
+${var}constant
+@endcode
+
+- Always use `printf` instead of `echo`. There are times when a newline is not
+desired such as when you want to print on a single line from multiple points
+in your script or when you want to get the character count from an expression:
+@code
+var1='not '
+var2=' you want to ignore'
+
+# Prints the number of characters.
+printf '%s' "${var1}something${var2}" | wc -c
+# Result:
+ 32
+
+# This one prints a plus one i.e. the inherent newline.
+echo "${var1}something${var2}" | wc -c
+# Result:
+ 33
+
+# `echo` does have `-n` to suppress newline, but...
+# SC2039: In POSIX sh, echo flags are undefined.
+echo -n "${var1}something${var2}" | wc -c
+# Result:
+ 32 # sometimes, other times an error
+@endcode
+`printf` also has the benefit of separating the format from the actual variables
+which has many use cases. One such use case is coloring output with ANSI escape
+sequence codes, see the `test_finish` function in
+`src/lib/testutils/dhcp_test_lib.sh.in`, which is not possible with POSIX echo.
+
+- `set -e` should be enabled at all times to immediately fail when a command
+returns a non-zero exit code. There are times when you expect a non-zero exit
+code in your tests. This is what the `run_command` function in
+`src/lib/testutils/dhcp_test_lib.sh.in` is for. It momentarily disables the `-e`
+flag to capture the output and exit code and enables it again afterwards. The
+variables used are `${EXIT_CODE}` and `${OUTPUT}`. /dev/stderr is not captured.
+`run_command` also doesn't work with pipes and redirections. When these
+mechanisms are needed, you can always wrap your complex expression in a function
+and then call `run_command wrapping_function`. Alternatively, if you only care
+about checking for zero exit code, you can use `if` conditions.
+@code
+# The non-zero exit code does not stop script execution, but we can still adjust
+# behavior based on it.
+if maybe-failing-command; then
+ f
+else
+ g
+fi
+@endcode
+There are times when your piped or redirected command that is expected to return
+non-zero is so small or has so few instantiations that it doesn't deserve a
+separate function. Such an example could be grepping for something in a
+variable. `grep` returns a non-zero exit code if it doesn't find anything. In
+that case, you can add `|| true` at the end to signal the fact that you allow
+finding nothing like so:
+@code
+printf '%s' "${var}" | grep -F 'search-criterion' || true
+@endcode
+
+- `set -u` should be enabled at all times to immediately signal an undefined
+variable. If you're a stickler for the legacy behavior of defaulting to an empty
+space then you can reference all your variables with:
+@code
+# Default variable is an empty space.
+${var-}
+
+# Or like this if you prefer to quote the empty space.
+${var-''}
+@endcode
+
+- SC2086: Double quote to prevent globbing and word splitting.
+Even though covered by shellcheck, it's worth mentioning because shellcheck
+doesn't always warn you because of what might be a systematic deduction of when
+quoting is not needed. Globbing is a pattern matching mechanism. It's used a lot
+with the `*` wildcard character e.g. `ls *.txt`. Sometimes, you want to glob
+intentionally. In that case, you can omit quoting, but it is preferable to take
+the wildcard characters outside the variable so that you are able to quote to
+prevent other globbing and word splitting e.g.:
+@code
+# Globbing done right
+ls "${var}"*.txt
+
+# Word splitting problem
+path='/home/my user'
+ls ${path}
+
+# Result:
+ ls: cannot access '/home/my': No such file or directory
+ ls: cannot access 'user': No such file or directory
+
+# Word splitting avoided
+path='/home/my user'
+ls "${path}"
+
+# Result:
+ Desktop
+ Documents
+ Downloads
+@endcode
+If you have an expression composed of multiple variables don't just quote the
+variables. It's correct, but not readable. Quote the entire expression.
+@code
+# no
+"${var1}"some-fixed-contiguous-value"${var2}"
+
+# yes
+"${var1}some-fixed-contiguous-value${var2}"
+@endcode
+
+- Single quote expressions when no variables are inside. This is to avoid the
+need to escape special shell characters like `$`.
+
+- All shell tests are created from `.in` autoconf template files. They
+initially contain template variables like `@prefix@` which are then substituted
+with the configured values. All of these should be double quoted, not
+single-quoted since they themselves can contain shell variables that need to be
+expanded.
+
+- Use `$(...)` notation instead of legacy backticks. One important advantage is
+that the `$(...)` notation allows for nested executions.
+@code
+# SC2006 Use `$(...)` notation instead of legacy backticked `...`.
+hostname=`cat /etc/hostname`
+
+# Better
+hostname=$(cat /etc/hostname)
+
+# Nested executions
+is_ssh_open=$(nc -vz $(cat /etc/hostname).lab.isc.org 22)
+
+# Results in confusing "command not found" messages.
+is_ssh_open=`nc -vz `cat /etc/hostname`.lab.isc.org 22`
+@endcode
+
+- When using `test` and `[`, `==` is just a convenience alias for `=`. Use `=`
+because it's more widely supported. If using, `[[`, then indeed `==` has extra
+features like glob matching. But don't use `[[`, it's not part of the POSIX
+standard.
+
+- Capturing parameters in functions or scripts simply cannot be done without
+breaking POSIX compliance. In POSIX, pass the quoted parameters `"${@}"` as
+positional parameters to all the function and scripts invocations. if it gets
+too unmanageable or you need custom positional arguments then break your script
+into multiple scripts or handle all possible parameters and don't accept any
+ad-hoc parameters.
+@code
+# Neither of these preserve original quoting.
+parameters="${*}"
+parameters="${@}"
+
+# In advanced shells this could be done with lists.
+parameters=( "${@}" )
+do-something --some --other --optional --parameters "${parameters[@]}"
+
+# Proper POSIX way
+do-something --some --other --optional --parameters "${@}"
+@endcode
+
+- Never use `eval`. It doesn't preserve original quoting. Have faith that there
+are always good alternatives.
+
+ */