command-socket.dox 7.97 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199
// Copyright (C) 2015 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.

/**
 @page ctrlSocket Control Channel

@section ctrlSocketOverview Control Channel Overview

In many cases it is useful to manage certain aspects of the DHCP servers.
DHCPv4 component in Kea supports control channel. It allows external entity
(e.g. a tool run by a sysadmin or a script) to influence the server and extract
certain information out from it. Several notable examples envisaged are:
reconfiguration, statistics retrival and manipulation and shutdown.

@todo: Update this text once control channel support in DHCPv6 is added.

Communication over control channel is conducted using JSON structures.
Currently (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
structure in the following format:

@code
{
    "command": "foo", 
    "arguments": {
        "param_foo": "value1",
        "param_bar": "value2",
        ...
    }
}
@endcode

command field is mandatory. Depending on the actual command, the arguments field
may be absent, it may contain a single parameter or a map or parameters.  The
exact format is command specific. The server will process incoming command and
send a response:

@code
{
    "result": 0|1,
    "text": "textual description",
    "arguments": {
        "argument1": "value1",
        "argument2": "value2",
        ...
    }
}
@endcode

Result designates outcome of the command. 0 means a success and 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 map always appears, even if there are no parameters.

@section ctrlSocketClient 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:
@code
socat UNIX:/var/run/kea/kea4.sock -
@endcode
You then can type JSON commands an get responses (also in JSON format).

2. Here's an example C code that connects and gets a list of supported commands:
@code
// Copyright (C) 2015 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.

#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;
}
@endcode

@section ctrlSocketImpl Control Channel Implementation

Control Channel is implemented in @ref isc::config::CommandMgr. It is a signleton
class that allows registration of callbacks that handle specific commands.
It internally supports a single command: @c 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:
- @ref isc::config::CommandMgr::registerCommand, which allows registration of
  additional commands.
- @ref isc::config::CommandMgr::deregisterCommand, which allows removing previously
  registered command.
- @ref isc::config::CommandMgr::processCommand, which allows handling specified
  command.

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):

- @ref isc::config::CommandMgr::openCommandSocket that passes structure defined
  in the configuration file. Currently only two parameters are supported: socket-type
  (which must contain value 'unix') and socket-name (which contains unix path for
  the named socket to be created). This method calls @ref 
  isc::config::CommandSocketFactory::create method, which in turn calls type specific
  creation method. Again, currently only UNIX type is supported, but the factory
  class is expected to be extended to cover additional types.
- @ref isc::config::CommandMgr::closeCommandSocket() - it is used to close the
  socket. It calls @ref isc::config::CommandSocketFactory::close method that may
  do type specific closure operations. In particular, for UNIX socket, it also
  deletes the file after socket was closed.

@section ctrlSocketConnections Accepting connections

Command channel is connection oriented communication. In that sense it is
different than all other communications supported so far in Kea. To facilitate
connections, several mechanisms were implemented. Once control socket is opened,
a special callback (@ref isc::config::CommandMgr::connectionAcceptor) is
installed to process incoming connections. When select called in
@ref isc::dhcp::IfaceMgr::receive4 indicates that there is some data to be
processed, this callback calls accept, which creates a new socket for handling
this particular incoming connection. Also, it install another callback 
(@ref isc::config::CommandMgr::commandReader) that will process incoming
data or will close the socket when necessary. CommandReader reads data from
incoming socket and attempts to parse it as JSON structures. If successful,
it calls isc::config::CommandMgr::processCommand(), serializes the structure
returned and attempts to send it back.

@todo Currently commands and responses up to 64KB are supported. It was deemed
sufficient for the current needs, but in the future we may need to extend
it to handle bigger structures.

*/