ctrl_dhcp6_srv.h 16.3 KB
Newer Older
1
// Copyright (C) 2012-2019 Internet Systems Consortium, Inc. ("ISC")
2
//
3 4 5
// 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/.
6 7 8 9

#ifndef CTRL_DHCPV6_SRV_H
#define CTRL_DHCPV6_SRV_H

10
#include <asiolink/asio_wrapper.h>
11
#include <asiolink/asiolink.h>
12
#include <cc/data.h>
13
#include <cc/command_interpreter.h>
14
#include <database/database_connection.h>
15
#include <dhcpsrv/timer_mgr.h>
16
#include <dhcp6/dhcp6_srv.h>
17 18 19 20 21 22

namespace isc {
namespace dhcp {

/// @brief Controlled version of the DHCPv6 server
///
23 24
/// This is a class that is responsible for DHCPv6 server being controllable,
/// by reading configuration file from disk.
25 26 27 28 29
class ControlledDhcpv6Srv : public isc::dhcp::Dhcpv6Srv {
public:

    /// @brief Constructor
    ///
30
    /// @param server_port UDP port to be opened for DHCP traffic
31 32 33
    /// @param client_port UDP port where all responses are sent to.
    ControlledDhcpv6Srv(uint16_t server_port = DHCP6_SERVER_PORT,
                        uint16_t client_port = 0);
34 35

    /// @brief Destructor.
Tomek Mrugalski's avatar
Tomek Mrugalski committed
36
    virtual ~ControlledDhcpv6Srv();
37

38
    /// @brief Initializes the server.
39
    ///
40 41
    /// It reads the JSON file from disk or may perform any other setup
    /// operation. In particular, it also install signal handlers.
42
    ///
43
    /// This method may throw if initialization fails.
Tomek Mrugalski's avatar
Tomek Mrugalski committed
44
    void init(const std::string& config_file);
45

Francis Dupont's avatar
Francis Dupont committed
46
    /// @brief Loads specific configuration file
47 48 49 50 51 52 53 54 55 56 57 58
    ///
    /// This utility method is called whenever we know a filename of the config
    /// and need to load it. It calls config-set command once the content of
    /// the file has been loaded and verified to be a sane JSON configuration.
    /// config-set handler will process the config file (apply it as current
    /// configuration).
    ///
    /// @param file_name name of the file to be loaded
    /// @return status of the file loading and outcome of config-set
    isc::data::ConstElementPtr
    loadConfigFile(const std::string& file_name);

Tomek Mrugalski's avatar
Tomek Mrugalski committed
59
    /// @brief Performs cleanup, immediately before termination
60
    ///
Tomek Mrugalski's avatar
Tomek Mrugalski committed
61
    /// This method performs final clean up, just before the Dhcpv6Srv object
62
    /// is destroyed. Currently it is a no-op.
63
    void cleanup();
64 65 66 67

    /// @brief Initiates shutdown procedure for the whole DHCPv6 server.
    void shutdown();

Tomek Mrugalski's avatar
Tomek Mrugalski committed
68 69 70 71 72 73 74
    /// @brief command processor
    ///
    /// This method is uniform for all config backends. It processes received
    /// command (as a string + JSON arguments). Internally, it's just a
    /// wrapper that calls process*Command() methods and catches exceptions
    /// in them.
    ///
Tomek Mrugalski's avatar
Tomek Mrugalski committed
75 76
    /// Currently supported commands are:
    /// - config-reload
77
    /// - config-test
Francis Dupont's avatar
Francis Dupont committed
78
    /// - leases-reclaim
79
    /// - libreload
80
    /// - shutdown
Francis Dupont's avatar
Francis Dupont committed
81
    /// ...
Tomek Mrugalski's avatar
Tomek Mrugalski committed
82
    ///
Tomek Mrugalski's avatar
Tomek Mrugalski committed
83
    /// @note It never throws.
84
    ///
85
    /// @param command Text representation of the command (e.g. "shutdown")
86
    /// @param args Optional parameters
87 88 89
    ///
    /// @return status of the command
    static isc::data::ConstElementPtr
Tomek Mrugalski's avatar
Tomek Mrugalski committed
90
    processCommand(const std::string& command, isc::data::ConstElementPtr args);
91

Tomek Mrugalski's avatar
Tomek Mrugalski committed
92
    /// @brief configuration processor
93
    ///
Tomek Mrugalski's avatar
Tomek Mrugalski committed
94
    /// This is a method for handling incoming configuration updates.
Tomek Mrugalski's avatar
Tomek Mrugalski committed
95 96
    /// This method should be called by all configuration backends when the
    /// server is starting up or when configuration has changed.
97 98 99 100 101 102 103 104
    ///
    /// As pointer to this method is used a callback in ASIO used in
    /// ModuleCCSession, it has to be static.
    ///
    /// @param new_config textual representation of the new configuration
    ///
    /// @return status of the config update
    static isc::data::ConstElementPtr
Tomek Mrugalski's avatar
Tomek Mrugalski committed
105
    processConfig(isc::data::ConstElementPtr new_config);
106

Francis Dupont's avatar
Francis Dupont committed
107 108 109 110
    /// @brief Configuration checker
    ///
    /// This is a method for checking incoming configuration.
    ///
111
    /// @param new_config JSON representation of the new configuration
Francis Dupont's avatar
Francis Dupont committed
112 113 114 115 116
    ///
    /// @return status of the config check
    isc::data::ConstElementPtr
    checkConfig(isc::data::ConstElementPtr new_config);

Tomek Mrugalski's avatar
Tomek Mrugalski committed
117
    /// @brief returns pointer to the sole instance of Dhcpv6Srv
118
    ///
Tomek Mrugalski's avatar
Tomek Mrugalski committed
119
    /// @return server instance (may return NULL, if called before server is spawned)
Tomek Mrugalski's avatar
Tomek Mrugalski committed
120 121 122 123
    static ControlledDhcpv6Srv* getInstance() {
        return (server_);
    }

124
private:
125

Tomek Mrugalski's avatar
Tomek Mrugalski committed
126 127
    /// @brief Callback that will be called from iface_mgr when data
    /// is received over control socket.
128 129
    ///
    /// This static callback method is called from IfaceMgr::receive6() method,
Tomek Mrugalski's avatar
Tomek Mrugalski committed
130
    /// when there is a new command or configuration sent over control socket
131
    /// (that was sent from some yet unspecified sender).
132 133
    static void sessionReader(void);

Tomek Mrugalski's avatar
Tomek Mrugalski committed
134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157
    /// @brief handler for processing 'shutdown' command
    ///
    /// This handler processes shutdown command, which initializes shutdown
    /// procedure.
    /// @param command (parameter ignored)
    /// @param args (parameter ignored)
    ///
    /// @return status of the command
    isc::data::ConstElementPtr
    commandShutdownHandler(const std::string& command,
                           isc::data::ConstElementPtr args);

    /// @brief handler for processing 'libreload' command
    ///
    /// This handler processes libreload command, which unloads all hook
    /// libraries and reloads them.
    ///
    /// @param command (parameter ignored)
    /// @param args (parameter ignored)
    ///
    /// @return status of the command
    isc::data::ConstElementPtr
    commandLibReloadHandler(const std::string& command,
                            isc::data::ConstElementPtr args);
158

Tomek Mrugalski's avatar
Tomek Mrugalski committed
159 160 161 162 163 164 165 166 167 168 169 170
    /// @brief handler for processing 'config-reload' command
    ///
    /// This handler processes config-reload command, which processes
    /// configuration specified in args parameter.
    ///
    /// @param command (parameter ignored)
    /// @param args configuration to be processed
    ///
    /// @return status of the command
    isc::data::ConstElementPtr
    commandConfigReloadHandler(const std::string& command,
                               isc::data::ConstElementPtr args);
171

172 173 174 175 176 177 178 179
    /// @brief handler for processing 'get-config' command
    ///
    /// This handler processes get-config command, which retrieves
    /// the current configuration and returns it in response.
    ///
    /// @param command (ignored)
    /// @param args (ignored)
    /// @return current configuration wrapped in a response
180
    isc::data::ConstElementPtr
181
    commandConfigGetHandler(const std::string& command,
182 183
                            isc::data::ConstElementPtr args);

184 185
    /// @brief handler for processing 'write-config' command
    ///
Josh Soref's avatar
Josh Soref committed
186
    /// This handle processes write-config command, which writes the
187 188 189 190 191 192 193 194 195 196 197 198 199 200
    /// current configuration to disk. This command takes one optional
    /// parameter called filename. If specified, the current configuration
    /// will be written to that file. If not specified, the file used during
    /// Kea start-up will be used. To avoid any exploits, the path is
    /// always relative and .. is not allowed in the filename. This is
    /// a security measure against exploiting file writes remotely.
    ///
    /// @param command (ignored)
    /// @param args may contain optional string argument filename
    /// @return status of the configuration file write
    isc::data::ConstElementPtr
    commandConfigWriteHandler(const std::string& command,
                              isc::data::ConstElementPtr args);

201
    /// @brief handler for processing 'config-set' command
202
    ///
203
    /// This handler processes config-set command, which processes
204 205 206 207
    /// configuration specified in args parameter.
    /// @param command (parameter ignored)
    /// @param args configuration to be processed. Expected format:
    /// map containing Dhcp6 map that contains DHCPv6 server configuration.
208 209
    /// May also contain Logging map that specifies logging configuration
    /// for backward compatibility.
210 211 212
    ///
    /// @return status of the command
    isc::data::ConstElementPtr
213
    commandConfigSetHandler(const std::string& command,
214 215
                            isc::data::ConstElementPtr args);

Francis Dupont's avatar
Francis Dupont committed
216 217 218 219 220 221 222
    /// @brief handler for processing 'config-test' command
    ///
    /// This handler processes config-test command, which checks
    /// configuration specified in args parameter.
    /// @param command (parameter ignored)
    /// @param args configuration to be checked. Expected format:
    /// map containing Dhcp6 map that contains DHCPv6 server configuration.
223 224
    /// May also contain Logging map that specifies logging configuration
    /// for backward compatibility.
Francis Dupont's avatar
Francis Dupont committed
225 226 227 228 229
    ///
    /// @return status of the command
    isc::data::ConstElementPtr
    commandConfigTestHandler(const std::string& command,
                             isc::data::ConstElementPtr args);
230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250

    /// @brief A handler for processing 'dhcp-disable' command.
    ///
    /// @param command command name (ignored).
    /// @param args aguments for the command. It must be a map and
    /// it may include optional 'max-period' parameter.
    ///
    /// @return result of the command.
    isc::data::ConstElementPtr
    commandDhcpDisableHandler(const std::string& command,
                              isc::data::ConstElementPtr args);

    /// @brief A handler for processing 'dhcp-enable' command.
    ///
    /// @param command command name (ignored)
    /// @param args arguments for the command (ignored).
    ///
    /// @return result of the command.
    isc::data::ConstElementPtr
    commandDhcpEnableHandler(const std::string& command,
                             isc::data::ConstElementPtr args);
Francis Dupont's avatar
Francis Dupont committed
251 252

    /// @Brief handler for processing 'version-get' command
Francis Dupont's avatar
Francis Dupont committed
253 254 255 256
    ///
    /// This handler processes version-get command, which returns
    /// over the control channel the -v and -V command line arguments.
    /// @param command (parameter ignored)
257
    /// @param args (parameter ignored)
Francis Dupont's avatar
Francis Dupont committed
258 259 260 261 262 263 264 265 266 267 268 269
    ///
    /// @return status of the command with the version in text and
    /// the extended version in arguments.
    isc::data::ConstElementPtr
    commandVersionGetHandler(const std::string& command,
                             isc::data::ConstElementPtr args);

    /// @brief handler for processing 'build-report' command
    ///
    /// This handler processes build-report command, which returns
    /// over the control channel the -W command line argument.
    /// @param command (parameter ignored)
270
    /// @param args (parameter ignored)
Francis Dupont's avatar
Francis Dupont committed
271 272 273 274 275 276
    ///
    /// @return status of the command with the config report
    isc::data::ConstElementPtr
    commandBuildReportHandler(const std::string& command,
                              isc::data::ConstElementPtr args);

Francis Dupont's avatar
Francis Dupont committed
277
    /// @brief Handler for processing 'leases-reclaim' command
278 279
    ///
    /// This handler processes leases-reclaim command, which triggers
Francis Dupont's avatar
Francis Dupont committed
280 281
    /// the leases reclamation immediately.
    /// No limit for processing time or number of processed leases applies.
282 283
    ///
    /// @param command (parameter ignored)
Francis Dupont's avatar
Francis Dupont committed
284 285 286
    /// @param args arguments map { "remove": <bool> }
    ///        if true a lease is removed when it is reclaimed,
    ///        if false its state is changed to "expired-reclaimed".
287
    ///
Francis Dupont's avatar
Francis Dupont committed
288 289
    /// @return status of the command (should be success unless args
    ///         was not a Bool Element).
290 291 292 293
    isc::data::ConstElementPtr
    commandLeasesReclaimHandler(const std::string& command,
                                isc::data::ConstElementPtr args);

294
    /// @brief handler for server-tag-get command
295
    ///
296
    /// This method handles the server-tag-get command, which retrieves
297 298
    /// the current server tag and returns it in response.
    ///
299 300 301
    /// @param command (ignored)
    /// @param args (ignored)
    /// @return current configuration wrapped in a response
302 303 304 305
    isc::data::ConstElementPtr
    commandServerTagGetHandler(const std::string& command,
                               isc::data::ConstElementPtr args);

306 307 308 309 310 311 312
    /// @brief Reclaims expired IPv6 leases and reschedules timer.
    ///
    /// This is a wrapper method for @c AllocEngine::reclaimExpiredLeases6.
    /// It reschedules the timer for leases reclamation upon completion of
    /// this method.
    ///
    /// @param max_leases Maximum number of leases to be reclaimed.
Francis Dupont's avatar
Francis Dupont committed
313
    /// @param timeout Maximum amount of time that the reclamation routine
314 315 316 317
    /// may be processing expired leases, expressed in milliseconds.
    /// @param remove_lease A boolean value indicating if the lease should
    /// be removed when it is reclaimed (if true) or it should be left in the
    /// database in the "expired-reclaimed" state (if false).
318 319 320 321
    /// @param max_unwarned_cycles A number of consecutive processing cycles
    /// of expired leases, after which the system issues a warning if there
    /// are still expired leases in the database. If this value is 0, the
    /// warning is never issued.
322
    void reclaimExpiredLeases(const size_t max_leases, const uint16_t timeout,
323 324 325
                              const bool remove_lease,
                              const uint16_t max_unwarned_cycles);

326 327 328 329 330 331 332 333 334 335 336

    /// @brief Deletes reclaimed leases and reschedules the timer.
    ///
    /// This is a wrapper method for @c AllocEngine::deleteExpiredReclaimed6.
    /// It reschedules the timer for leases reclamation upon completion of
    /// this method.
    ///
    /// @param secs Minimum number of seconds after which a lease can be
    /// deleted.
    void deleteExpiredReclaimedLeases(const uint32_t secs);

337
    /// @brief Attempts to reconnect the server to the DB backend managers
338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353
    ///
    /// This is a self-rescheduling function that attempts to reconnect to the
    /// server's DB backends after connectivity to one or more have been
    /// lost.  Upon entry it will attempt to reconnect via @ref CfgDdbAccess::
    /// createManagers.  If this is succesful, DHCP servicing is re-enabled and
    /// server returns to normal operation.
    ///
    /// If reconnection fails and the maximum number of retries has not been
    /// exhausted, it will schedule a call to itself to occur at the
    /// configured retry interval. DHCP service remains disabled.
    ///
    /// If the maximum number of retries has been exhausted an error is logged
    /// and the server shuts down.
    /// @param db_reconnect_ctl pointer to the ReconnectCtl containing the
    /// configured reconnect parameters
    ///
354
    void dbReconnect(db::ReconnectCtlPtr db_reconnect_ctl);
355 356

    /// @brief Callback DB backends should invoke upon loss of connectivity
357 358 359 360 361 362 363 364 365 366 367 368 369 370 371
    ///
    /// This function is invoked by DB backends when they detect a loss of
    /// connectivity.  The parameter, db_reconnect_ctl, conveys the configured
    /// maximum number of reconnect retries as well as the interval to wait
    /// between retry attempts.
    ///
    /// If either value is zero, reconnect is presumed to be disabled and
    /// the function will returns false.  This instructs the DB backend
    /// layer (the caller) to treat the connectivity loss as fatal.
    ///
    /// Otherwise, the function saves db_reconnect_ctl and invokes
    /// dbReconnect to initiate the reconnect process.
    ///
    /// @param db_reconnect_ctl pointer to the ReconnectCtl containing the
    /// configured reconnect parameters
372
    bool dbLostCallback(db::ReconnectCtlPtr db_reconnect_ctl);
373

374 375 376 377 378 379 380 381 382 383 384 385 386 387
    /// @brief Callback invoked periodically to fetch configuration updates
    /// from the Config Backends.
    ///
    /// This method calls @c CBControlDHCPv6::databaseConfigFetch and then
    /// reschedules the timer.
    ///
    /// @param srv_cfg Server configuration holding the database credentials
    /// and server tag.
    /// @param failure_count pointer to failure counter which causes this
    /// callback to stop scheduling the timer after 10 consecutive failures
    /// to fetch the updates.
    void cbFetchUpdates(const SrvConfigPtr& srv_cfg,
                        boost::shared_ptr<unsigned> failure_count);

388 389 390 391 392 393 394 395 396 397 398 399 400 401
    /// @brief Static pointer to the sole instance of the DHCP server.
    ///
    /// This is required for config and command handlers to gain access to
    /// the server. Some of them need to be static methods.
    static ControlledDhcpv6Srv* server_;

    /// @brief IOService object, used for all ASIO operations.
    isc::asiolink::IOService io_service_;

    /// @brief Instance of the @c TimerMgr.
    ///
    /// Shared pointer to the instance of timer @c TimerMgr is held here to
    /// make sure that the @c TimerMgr outlives instance of this class.
    TimerMgrPtr timer_mgr_;
402 403 404 405 406 407
};

}; // namespace isc::dhcp
}; // namespace isc

#endif