// Copyright (C) 2019-2025 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 libdhcp_flex_option Kea Flexible Option Hooks Library

@section libdhcp_flex_optionIntro Introduction

Welcome to Kea Flexible Option Hooks Library. This documentation is
addressed to developers who are interested in the internal operation
of the Flexible Option library. This file provides information needed
to understand and perhaps extend this library.

This documentation is stand-alone: you should have read and understood
the <a href="https://reports.kea.isc.org/dev_guide/">Kea
Developer's Guide</a> and in particular its section about hooks.

@section libdhcp_flex_optionUser Now To Use libdhcp_flex_option
## Introduction
libdhcp_flex_option is a hooks library which customize the option value
setting mechanism by introducing values from expression evaluation.
Instead of relying on static configured values, it allows user to define
expressions and use values of that expressions computed for options
added to response packets.

## Configuring the DHCP Modules

It must be configured as a hook library for the desired DHCP server
modules. Note that the flex_option library is installed alongside the
Kea libraries in "<install-dir>/lib" where <install-dir> is determined
by the --prefix meson setup option.  It defaults to
"/usr/local". Assuming the default value then, configuring kea-dhcp4
to load the flex_option library could be done with the following Kea4
configuration:

@code
"Dhcp4": {
    "hooks-libraries": [
        {   "library": "libdhcp_flex_option.so",
            "parameters": {
                "options": [
                    {
                        "code": 100,
                        "add": "concat(relay4[2].hex, 'abc')",
                        "csv-format": false
                    }
                ]
            }
        },
        ...
    ]
}
@endcode

To configure it for kea-dhcp6, the commands are simply as shown below:

@code
"Dhcp6": {
    "hooks-libraries": [
        {   "library": "libdhcp_flex_option.so",
            "parameters": {
                "options": [
                    {
                        "code": 100,
                        "add": "concat(relay6[0].option[37].hex, 'abc')",
                        "csv-format": false
                    }
                ]
            }
        },
        ...
    ]
}
@endcode

The sole parameter is a options list of options with:
 - @b code - Specifies the option code.
 - @b name - Specifies the option name, at least the option code or name
   must be given.
 - @b add -  Specifies the add action: it takes a string expression on
   the query packet. If the option does not already exist in the response
   packet and the expression evaluates to a not empty value, the option
   with the value is added to the response.
 - @b supersede - Specifies the supersede action: it takes a string expression
   on the query packet. If the expression evaluates to a not empty value,
   the option with the value is added to the response. If it already exists
   it is overwritten.
 - @b remove - Specifies the remove action: it takes a boolean expression
   on the query packet. If the expression evaluates to true and the option
   already exists in the response packet, the option is removed from the
   response. Only one action can be specified.
 - @b csv-format - Specifies the option format used for input. If not
   specified, it will default to false (raw data). When enabled, the option
   data will be parsed using csv format and packed according to the option
   definition.
 - @b client-class - Specifies the guard i.e. the client class the query
   must belong to.

Note for the rare options which can be empty this mechanism does not work.
The proposed solution in this case is to use a client class to set the
empty value to the option in a option-data clause.

The sub-option support is similar to the option one with in addition:
 - @b container-add - Specifies if the container option should be created
   when it does not exist (default behavior) in add and supersede actions.
 - @b container-remove - Specifies if the container option should be
   removed when the sub-option removal left it empty (default behavior)
   in remove action.
Sub-option configuration is a list in a @b sub-option entry of the container
option configuration.

## Internal operation

The first function called in @ref load() located in the
flex_option_callouts.cc. It checks if the necessary parameter is passed and
decodes the option configurations. @ref unload() free the configuration.

Kea engine checks if the library has functions that match known hook point
names. This library has two such functions: @ref pkt4_send and @ref pkt6_send,
all located in flex_option_callouts.cc.

kea-dhcp4 server calls @ref pkt4_send (and kea-dhcp6 @ref pkt6_send) with
the query and response packets. For each configured option and sub-option
the action is applied by the template @c process located in flex_option.h.
When required the expression is evaluated on the query packet and the result
is used by the action for instance to add a new option.

In case any other library sets the SKIP flag before pkt4_send or pkt6_send, an
exception with the message "the packet pack already handled" will be thrown, to
indicate that the action can not be properly performed.
To fix this, all other libraries which might set the SKIP flag must appear
in the server configuration after this library.

@section libdhcp_flex_optionMTCompatibility Multi-Threading Compatibility

The libdhcp_flex_option hooks library is compatible with multi-threading.

*/
