Kea 2.5.8
Control Channel

Control Channel Overview

In many cases it is useful to manage certain aspects of the DHCP servers while they are running. In Kea, this may be done via the Control Channel. Control Channel allows an external entity (e.g. a tool run by a sysadmin or a script) to issue commands to the server which can influence its behavior or retrieve information from it. Several notable examples envisioned are: reconfiguration, statistics retrieval and manipulation, and shutdown.

Communication over Control Channel is conducted using JSON structures. As of Kea 0.9.2, the only supported communication channel is UNIX stream socket, but additional types may be added in the future.

If configured, Kea will open a socket and will listen for any incoming connections. A process connecting to this socket is expected to send JSON commands structured as follows:

{
"command": "foo",
"arguments": {
"param_foo": "value1",
"param_bar": "value2",
...
}
}
  • command - is the name of command to execute and is mandatory.
  • arguments - contain a single parameter or a map or parameters required to carry out the given command. The exact content and format is command specific.

The server will process the incoming command and then send a response of the form:

{
"result": 0|1,
"text": "textual description",
"arguments": {
"argument1": "value1",
"argument2": "value2",
...
}
}
  • result - indicates the outcome of the command. A value of 0 means a success while any non-zero value designates an error. Currently 1 is used as a generic error, but additional error codes may be added in the future.
  • text field - typically appears when result is non-zero and contains description of the error encountered.
  • arguments - is a map of additional data values returned by the server, specific to the command issue. The map is always present, even if it contains no data values.

Using Control Channel

Here are two examples of how to access the Control Channel:

  1. Use socat tool, which is available in many Linux and BSD distributions. See http://www.dest-unreach.org/socat/ for details. To use it:
    socat UNIX:/var/run/kea/kea4.sock -
    You then can type JSON commands and get responses (also in JSON format).
  2. Here's an example C code that connects and gets a list of supported commands:
    // Copyright (C) 2015-2020 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/.
    #include <sys/socket.h>
    #include <sys/un.h>
    #include <stdio.h>
    #include <string.h>
    #include <unistd.h>
    int main(int argc, const char* argv[]) {
    if (argc != 2) {
    printf("Usage: %s socket_path\n", argv[0]);
    return (1);
    }
    // Create UNIX stream socket.
    int socket_fd;
    if ((socket_fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
    {
    perror("Failed to create UNIX stream");
    return (1);
    }
    // Specify the address to connect to (unix path)
    struct sockaddr_un srv_addr;
    memset(&srv_addr, 0, sizeof(struct sockaddr_un));
    srv_addr.sun_family = AF_UNIX;
    strcpy(srv_addr.sun_path, argv[1]);
    socklen_t len = sizeof(srv_addr);
    // Try to connect.
    if (connect(socket_fd, (struct sockaddr*) &srv_addr, len) == -1) {
    perror("Failed to connect");
    return (1);
    }
    // Send a command to list all available commands.
    char buf[1024];
    sprintf(buf, "{ \"command\": \"list-commands\" }");
    int bytes_sent = send(socket_fd, buf, strlen(buf), 0);
    printf("%d bytes sent\n", bytes_sent);
    // Receive a response (should be JSON formatted list of commands)
    int bytes_rcvd = recv(socket_fd, buf, sizeof(buf), 0);
    printf("%d bytes received: [%s]\n", bytes_rcvd, buf);
    // Close the socket
    close(socket_fd);
    return 0;
    }
    int main(int argc, char *argv[])
    Definition: agent/main.cc:16

Control Channel Implementation

Control Channel is implemented in isc::config::CommandMgr. It is a singleton class that allows registration of callbacks that handle specific commands. It internally supports a single command: list-commands that returns a list of supported commands. This component is expected to be shared among all daemons.

There are 3 main methods that are expected to be used by developers:

There are also two methods for managing control sockets. They are not expected to be used directly, unless someone implements a new Control Channel (e.g. TCP or HTTPS connection):

Kea servers use CommandMgr to register handlers for various commands they support natively. However, it is possible extend a set of supported commands using hooks framework. See Using Callouts as Command handlers how to implement support for your own control commands in Kea.

Accepting connections

The isc::config::CommandMgr is implemented using boost ASIO and uses asynchronous calls to accept new connections and receive commands from the controlling clients. ASIO uses IO service object to run asynchronous calls. Thus, before the server can use the isc::config::CommandMgr it must provide it with a common instance of the isc::asiolink::IOService object using isc::config::CommandMgr::setIOService. The server's main loop must contain calls to isc::asiolink::IOService::run or isc::asiolink::IOService::poll or their variants to invoke Command Manager's handlers as required for processing control requests.

Multi-Threading Consideration for Control Channel

The control channel utilities are not thread safe but they are used only by the main thread so in most cases it does not matter. For instance the assumption that only at most one command can be executed at a given time can be done. Of course this has its limit: when the command changes the configuration or is incompatible with a simultaneous packet processing the multi-threading mode must be checked and service threads stopped.