Coverage Report

Created: 2025-12-08 07:54

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/kea/src/bin/dhcp6/ctrl_dhcp6_srv.h
Line
Count
Source
1
// Copyright (C) 2012-2025 Internet Systems Consortium, Inc. ("ISC")
2
//
3
// This Source Code Form is subject to the terms of the Mozilla Public
4
// License, v. 2.0. If a copy of the MPL was not distributed with this
5
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
6
7
#ifndef CTRL_DHCPV6_SRV_H
8
#define CTRL_DHCPV6_SRV_H
9
10
#include <asiolink/asio_wrapper.h>
11
#include <asiolink/asiolink.h>
12
#include <cc/data.h>
13
#include <cc/command_interpreter.h>
14
#include <util/reconnect_ctl.h>
15
#include <dhcpsrv/lease_mgr.h>
16
#include <dhcpsrv/timer_mgr.h>
17
#include <dhcp6/dhcp6_srv.h>
18
19
namespace isc {
20
namespace dhcp {
21
22
/// @brief Controlled version of the DHCPv6 server
23
///
24
/// This is a class that is responsible for DHCPv6 server being controllable,
25
/// by reading configuration file from disk.
26
class ControlledDhcpv6Srv : public isc::dhcp::Dhcpv6Srv {
27
public:
28
29
    /// @brief Constructor
30
    ///
31
    /// @param server_port UDP port to be opened for DHCP traffic
32
    /// @param client_port UDP port where all responses are sent to.
33
    ControlledDhcpv6Srv(uint16_t server_port = DHCP6_SERVER_PORT,
34
                        uint16_t client_port = 0);
35
36
    /// @brief Destructor.
37
    virtual ~ControlledDhcpv6Srv();
38
39
    /// @brief Initializes the server.
40
    ///
41
    /// It reads the JSON file from disk or may perform any other setup
42
    /// operation. In particular, it also install signal handlers.
43
    ///
44
    /// This method may throw if initialization fails.
45
    void init(const std::string& config_file);
46
47
    /// @brief Configure DHCPv6 server using the configuration file specified.
48
    ///
49
    /// This function is used to both configure the DHCP server on its startup
50
    /// and dynamically reconfigure the server when SIGHUP signal is received.
51
    ///
52
    /// It fetches DHCPv6 server's configuration from the 'Dhcp6' section of
53
    /// the JSON configuration file.
54
    ///
55
    /// This utility method is called whenever we know a filename of the config
56
    /// and need to load it. It calls config-set command once the content of
57
    /// the file has been loaded and verified to be a sane JSON configuration.
58
    /// config-set handler will process the config file (apply it as current
59
    /// configuration).
60
    ///
61
    /// @param file_name name of the file to be loaded
62
    /// @return status of the file loading and outcome of config-set
63
    isc::data::ConstElementPtr
64
    loadConfigFile(const std::string& file_name);
65
66
    /// @brief Performs cleanup, immediately before termination
67
    ///
68
    /// This method performs final clean up, just before the Dhcpv6Srv object
69
    /// is destroyed. Currently it is a no-op.
70
    void cleanup();
71
72
    /// @brief Initiates shutdown procedure for the whole DHCPv6 server.
73
    /// @param exit_value integer value to the process should exit with.
74
    virtual void shutdownServer(int exit_value);
75
76
    /// @brief Configuration processor
77
    ///
78
    /// This is a method for handling incoming configuration updates.
79
    /// This method should be called by all configuration backends when the
80
    /// server is starting up or when configuration has changed.
81
    ///
82
    /// As pointer to this method is used a callback in ASIO used in
83
    /// ModuleCCSession, it has to be static.
84
    ///
85
    /// @param config textual representation of the new configuration
86
    ///
87
    /// @return status of the config update
88
    static isc::data::ConstElementPtr
89
    processConfig(isc::data::ConstElementPtr config);
90
91
    /// @brief Configuration checker
92
    ///
93
    /// This is a method for checking incoming configuration.
94
    ///
95
    /// @param config JSON representation of the new configuration
96
    ///
97
    /// @return status of the config check
98
    static isc::data::ConstElementPtr
99
    checkConfig(isc::data::ConstElementPtr config);
100
101
    /// @brief Configuration checker for hook libraries
102
    ///
103
    /// This is a method for checking incoming configuration in the hooks
104
    /// libraries. It calls dhcp4_srv_configured hook point for all hooks.
105
    ///
106
    /// @param config JSON representation of the new configuration
107
    ///
108
    /// @return status of the config check
109
    static isc::data::ConstElementPtr
110
    finishConfigHookLibraries(isc::data::ConstElementPtr config);
111
112
    /// @brief Returns pointer to the sole instance of Dhcpv6Srv
113
    ///
114
    /// @return server instance (may return NULL, if called before server is spawned)
115
48.7k
    static ControlledDhcpv6Srv* getInstance() {
116
48.7k
        return (server_);
117
48.7k
    }
118
119
private:
120
    /// @brief Callback that will be called from iface_mgr when data
121
    /// is received over control socket.
122
    ///
123
    /// This static callback method is called from IfaceMgr::receive6() method,
124
    /// when there is a new command or configuration sent over control socket
125
    /// (that was sent from some yet unspecified sender).
126
    static void sessionReader(void);
127
128
    /// @brief Handler for processing 'shutdown' command
129
    ///
130
    /// This handler processes shutdown command, which initializes shutdown
131
    /// procedure.
132
    /// @param command (parameter ignored)
133
    /// @param args (parameter ignored)
134
    ///
135
    /// @return status of the command
136
    isc::data::ConstElementPtr
137
    commandShutdownHandler(const std::string& command,
138
                           isc::data::ConstElementPtr args);
139
140
    /// @brief Handler for processing 'config-reload' command
141
    ///
142
    /// This handler processes config-reload command, which processes
143
    /// configuration specified in args parameter.
144
    ///
145
    /// @param command (parameter ignored)
146
    /// @param args configuration to be processed
147
    ///
148
    /// @return status of the command
149
    isc::data::ConstElementPtr
150
    commandConfigReloadHandler(const std::string& command,
151
                               isc::data::ConstElementPtr args);
152
153
    /// @brief handler for processing 'config-get' command
154
    ///
155
    /// This handler processes config-get command, which retrieves
156
    /// the current configuration and returns it in response.
157
    ///
158
    /// @param command (ignored)
159
    /// @param args (ignored)
160
    /// @return current configuration wrapped in a response
161
    isc::data::ConstElementPtr
162
    commandConfigGetHandler(const std::string& command,
163
                            isc::data::ConstElementPtr args);
164
165
    /// @brief handler for processing 'config-hash-get' command
166
    ///
167
    /// This handler processes config-hash-get command, which retrieves
168
    /// the hash of the current configuration and returns it in response.
169
    ///
170
    /// @param command (ignored)
171
    /// @param args (ignored)
172
    /// @return hash of current configuration wrapped in a response
173
    isc::data::ConstElementPtr
174
    commandConfigHashGetHandler(const std::string& command,
175
                                isc::data::ConstElementPtr args);
176
177
    /// @brief handler for processing 'config-write' command
178
    ///
179
    /// This handle processes config-write command, which writes the
180
    /// current configuration to disk. This command takes one optional
181
    /// parameter called filename. If specified, the current configuration
182
    /// will be written to that file. If not specified, the file used during
183
    /// Kea start-up will be used. To avoid any exploits, the target
184
    /// directory must be the same as a security measure against
185
    /// exploiting file writes remotely.
186
    ///
187
    /// @param command (ignored)
188
    /// @param args may contain optional string argument filename
189
    /// @return status of the configuration file write
190
    isc::data::ConstElementPtr
191
    commandConfigWriteHandler(const std::string& command,
192
                              isc::data::ConstElementPtr args);
193
194
    /// @brief handler for processing 'config-set' command
195
    ///
196
    /// This handler processes config-set command, which processes
197
    /// configuration specified in args parameter.
198
    /// @param command (parameter ignored)
199
    /// @param args configuration to be processed. Expected format:
200
    /// map containing Dhcp6 map that contains DHCPv6 server configuration.
201
    ///
202
    /// @return status of the command
203
    isc::data::ConstElementPtr
204
    commandConfigSetHandler(const std::string& command,
205
                            isc::data::ConstElementPtr args);
206
207
    /// @brief handler for processing 'config-test' command
208
    ///
209
    /// This handler processes config-test command, which checks
210
    /// configuration specified in args parameter.
211
    /// @param command (parameter ignored)
212
    /// @param args configuration to be checked. Expected format:
213
    /// map containing Dhcp6 map that contains DHCPv6 server configuration.
214
    ///
215
    /// @return status of the command
216
    isc::data::ConstElementPtr
217
    commandConfigTestHandler(const std::string& command,
218
                             isc::data::ConstElementPtr args);
219
220
    /// @brief A handler for processing 'dhcp-disable' command.
221
    ///
222
    /// @param command command name (ignored).
223
    /// @param args arguments for the command. It must be a map and
224
    /// it may include optional 'max-period' parameter.
225
    ///
226
    /// @return result of the command.
227
    isc::data::ConstElementPtr
228
    commandDhcpDisableHandler(const std::string& command,
229
                              isc::data::ConstElementPtr args);
230
231
    /// @brief A handler for processing 'dhcp-enable' command.
232
    ///
233
    /// @param command command name (ignored)
234
    /// @param args arguments for the command (ignored).
235
    ///
236
    /// @return result of the command.
237
    isc::data::ConstElementPtr
238
    commandDhcpEnableHandler(const std::string& command,
239
                             isc::data::ConstElementPtr args);
240
241
    /// @Brief handler for processing 'version-get' command
242
    ///
243
    /// This handler processes version-get command, which returns
244
    /// over the control channel the -v and -V command line arguments.
245
    /// @param command (parameter ignored)
246
    /// @param args (parameter ignored)
247
    ///
248
    /// @return status of the command with the version in text and
249
    /// the extended version in arguments.
250
    isc::data::ConstElementPtr
251
    commandVersionGetHandler(const std::string& command,
252
                             isc::data::ConstElementPtr args);
253
254
    /// @brief handler for processing 'build-report' command
255
    ///
256
    /// This handler processes build-report command, which returns
257
    /// over the control channel the -W command line argument.
258
    /// @param command (parameter ignored)
259
    /// @param args (parameter ignored)
260
    ///
261
    /// @return status of the command with the config report
262
    isc::data::ConstElementPtr
263
    commandBuildReportHandler(const std::string& command,
264
                              isc::data::ConstElementPtr args);
265
266
    /// @brief Handler for processing 'leases-reclaim' command
267
    ///
268
    /// This handler processes leases-reclaim command, which triggers
269
    /// the leases reclamation immediately.
270
    /// No limit for processing time or number of processed leases applies.
271
    ///
272
    /// @param command (parameter ignored)
273
    /// @param args arguments map { "remove": <bool> }
274
    ///        if true a lease is removed when it is reclaimed,
275
    ///        if false its state is changed to "expired-reclaimed".
276
    ///
277
    /// @return status of the command (should be success unless args
278
    ///         was not a Bool Element).
279
    isc::data::ConstElementPtr
280
    commandLeasesReclaimHandler(const std::string& command,
281
                                isc::data::ConstElementPtr args);
282
283
    /// @brief Handler for processing 'subnet6-select-test' command
284
    ///
285
    /// This handler processes subnet6-select-test command, which returns
286
    /// the result of DHCPv6 subnet selected.
287
    ///
288
    /// @param command (parameter ignored)
289
    /// @param args arguments map { <selector>: <value> }
290
    ///
291
    /// @return status of the command with the selection result
292
    isc::data::ConstElementPtr
293
    commandSubnet6SelectTestHandler(const std::string& command,
294
                                    isc::data::ConstElementPtr args);
295
296
    /// @brief handler for server-tag-get command
297
    ///
298
    /// This method handles the server-tag-get command, which retrieves
299
    /// the current server tag and returns it in response.
300
    ///
301
    /// @param command (ignored)
302
    /// @param args (ignored)
303
    /// @return current configuration wrapped in a response
304
    isc::data::ConstElementPtr
305
    commandServerTagGetHandler(const std::string& command,
306
                               isc::data::ConstElementPtr args);
307
308
    /// @brief handler for config-backend-pull command
309
    ///
310
    /// This method handles the config-backend-pull command, which updates
311
    /// the server configuration from the Config Backends immediately.
312
    ///
313
    /// @param command (parameter ignored)
314
    /// @param args (ignored)
315
    ///
316
    /// @return status of the command/
317
    isc::data::ConstElementPtr
318
    commandConfigBackendPullHandler(const std::string& command,
319
                                    isc::data::ConstElementPtr args);
320
321
    /// @brief handler for processing 'status-get' command
322
    ///
323
    /// This handler processes status-get command, which retrieves
324
    /// the server process information i.e. the pid and returns it in response.
325
    ///
326
    /// @param command (ignored)
327
    /// @param args (ignored)
328
    /// @return process information wrapped in a response
329
    isc::data::ConstElementPtr
330
    commandStatusGetHandler(const std::string& command,
331
                            isc::data::ConstElementPtr args);
332
333
    /// @brief handler for processing 'statistic-sample-count-set-all' command
334
    ///
335
    /// This handler processes statistic-sample-count-set-all command,
336
    /// which sets max_sample_count_ limit of all statistics and the default.
337
    /// @ref isc::stats::StatsMgr::statisticSetMaxSampleCountAllHandler
338
    ///
339
    /// @param command (ignored)
340
    /// @param args structure containing a map that contains "max-samples"
341
    /// @return process information wrapped in a response
342
    isc::data::ConstElementPtr
343
    commandStatisticSetMaxSampleCountAllHandler(const std::string& command,
344
                                                isc::data::ConstElementPtr args);
345
346
    /// @brief handler for processing 'statistic-sample-age-set-all' command
347
    ///
348
    /// This handler processes statistic-sample-age-set-all command,
349
    /// which sets max_sample_age_ limit of all statistics and the default.
350
    /// @ref isc::stats::StatsMgr::statisticSetMaxSampleAgeAllHandler
351
    ///
352
    /// @param command (ignored)
353
    /// @param args structure containing a map that contains "duration"
354
    /// @return process information wrapped in a response
355
    isc::data::ConstElementPtr
356
    commandStatisticSetMaxSampleAgeAllHandler(const std::string& command,
357
                                              isc::data::ConstElementPtr args);
358
359
    /// @brief handler for processing 'kea-lfc-start' command
360
    ///
361
    /// This handler processes kea-lfc-start command, which cleans up
362
    /// the lease file (the backup file of the memfile lease backend).
363
    /// @ref isc::dhcp::LeaseMgr::lfcStartHandler
364
    ///
365
    /// @param command (ignored)
366
    /// @param args (ignored)
367
    /// @return process information wrapped in a response
368
    isc::data::ConstElementPtr
369
    commandLfcStartHandler(const std::string& command,
370
                           isc::data::ConstElementPtr args);
371
372
    /// @brief Reclaims expired IPv6 leases and reschedules timer.
373
    ///
374
    /// This is a wrapper method for @c AllocEngine::reclaimExpiredLeases6.
375
    /// It reschedules the timer for leases reclamation upon completion of
376
    /// this method.
377
    ///
378
    /// @param max_leases Maximum number of leases to be reclaimed.
379
    /// @param timeout Maximum amount of time that the reclamation routine
380
    /// may be processing expired leases, expressed in milliseconds.
381
    /// @param remove_lease A boolean value indicating if the lease should
382
    /// be removed when it is reclaimed (if true) or it should be left in the
383
    /// database in the "expired-reclaimed" state (if false).
384
    /// @param max_unwarned_cycles A number of consecutive processing cycles
385
    /// of expired leases, after which the system issues a warning if there
386
    /// are still expired leases in the database. If this value is 0, the
387
    /// warning is never issued.
388
    void reclaimExpiredLeases(const size_t max_leases, const uint16_t timeout,
389
                              const bool remove_lease,
390
                              const uint16_t max_unwarned_cycles);
391
392
    /// @brief Deletes reclaimed leases and reschedules the timer.
393
    ///
394
    /// This is a wrapper method for @c AllocEngine::deleteExpiredReclaimed6.
395
    /// It reschedules the timer for leases reclamation upon completion of
396
    /// this method.
397
    ///
398
    /// @param secs Minimum number of seconds after which a lease can be
399
    /// deleted.
400
    void deleteExpiredReclaimedLeases(const uint32_t secs);
401
402
    /// @brief Callback DB backends should be invoked upon loss of the
403
    /// connectivity.
404
    ///
405
    /// This function is invoked by DB backends when they detect a loss of
406
    /// connectivity.  The parameter, db_reconnect_ctl, conveys the configured
407
    /// maximum number of reconnect retries as well as the interval to wait
408
    /// between retry attempts.
409
    ///
410
    /// If either value is zero, reconnect is presumed to be disabled and
411
    /// the function will schedule a shutdown and return false.  This instructs
412
    /// the DB backend layer (the caller) to treat the connectivity loss as
413
    /// fatal. It stops the DHCP service until the connection is recovered.
414
    ///
415
    /// @param db_reconnect_ctl pointer to the ReconnectCtl containing the
416
    /// configured reconnect parameters
417
    ///
418
    /// @return false if reconnect is not configured, true otherwise
419
    bool dbLostCallback(util::ReconnectCtlPtr db_reconnect_ctl);
420
421
    /// @brief Callback DB backends should be invoked upon restoration of
422
    /// connectivity.
423
    ///
424
    /// This function is invoked by DB backends when they recover the
425
    /// connectivity. It starts the DHCP service after the connection is
426
    /// recovered.
427
    ///
428
    /// @param db_reconnect_ctl pointer to the ReconnectCtl containing the
429
    /// configured reconnect parameters
430
    ///
431
    /// @return false if reconnect is not configured, true otherwise
432
    bool dbRecoveredCallback(util::ReconnectCtlPtr db_reconnect_ctl);
433
434
    /// @brief Callback DB backends should be invoked upon failing to restore
435
    /// connectivity.
436
    ///
437
    /// This function is invoked by DB backends when they fail to recover the
438
    /// connectivity. It stops the server.
439
    ///
440
    /// @param db_reconnect_ctl pointer to the ReconnectCtl containing the
441
    /// configured reconnect parameters
442
    ///
443
    /// @return false if reconnect is not configured, true otherwise
444
    bool dbFailedCallback(util::ReconnectCtlPtr db_reconnect_ctl);
445
446
    /// @brief This callback should be invoked upon failing to bind sockets.
447
    ///
448
    /// This function is invoked during the configuration of the interfaces
449
    /// when they fail to bind the service sockets. It may stop the server.
450
    ///
451
    /// @param reconnect_ctl pointer to the ReconnectCtl containing the
452
    /// configured reconnect parameters
453
    void openSocketsFailedCallback(util::ReconnectCtlPtr reconnect_ctl);
454
455
    /// @brief Callback invoked periodically to fetch configuration updates
456
    /// from the Config Backends.
457
    ///
458
    /// This method calls @c CBControlDHCPv6::databaseConfigFetch and then
459
    /// reschedules the timer.
460
    ///
461
    /// @param srv_cfg Server configuration holding the database credentials
462
    /// and server tag.
463
    /// @param failure_count pointer to failure counter which causes this
464
    /// callback to stop scheduling the timer after 10 consecutive failures
465
    /// to fetch the updates.
466
    void cbFetchUpdates(const SrvConfigPtr& srv_cfg,
467
                        boost::shared_ptr<unsigned> failure_count);
468
469
    /// @brief Static pointer to the sole instance of the DHCP server.
470
    ///
471
    /// This is required for config and command handlers to gain access to
472
    /// the server. Some of them need to be static methods.
473
    static ControlledDhcpv6Srv* server_;
474
475
    /// @brief Instance of the @c TimerMgr.
476
    ///
477
    /// Shared pointer to the instance of timer @c TimerMgr is held here to
478
    /// make sure that the @c TimerMgr outlives instance of this class.
479
    TimerMgrPtr timer_mgr_;
480
};
481
482
}  // namespace dhcp
483
}  // namespace isc
484
485
#endif