Commit fecfe82b authored by Stephen Morris's avatar Stephen Morris
Browse files

[2546] Merge branch 'master' into trac2546

Conflicts:
	doc/devel/mainpage.dox
	src/bin/dhcp4/ctrl_dhcp4_srv.h
	src/bin/dhcp4/dhcp4_srv.h
	src/bin/dhcp6/dhcp6.dox

Also modified the following files during the
resolution of the merge issues:
    src/bin/dhcp4/config_parser.cc
    src/bin/dhcp4/ctrl_dhcp4_srv.cc
    src/bin/dhcp4/dhcp4.dox
    src/bin/dhcp6/config_parser.cc
    src/bin/dhcp6/tests/dhcp6_srv_unittest.cc
    src/lib/dhcp/option_custom.h
    src/lib/dhcp/pkt4.h
    src/lib/dhcpsrv/database_backends.dox
parents 52d96504 550a5e0d
525. [func] tomek
b10-dhcp4: DHCPv4 server is now able to parse configuration. It
is possible to specify IPv4 subnets with dynamic pools within
them. Although configuration is accepted, it is not used yet. This
will be implemented shortly.
(Trac #2270, git de29c07129d41c96ee0d5eebdd30a1ea7fb9ac8a)
524. [func] tomek
b10-dhcp6 is now able to handle RENEW messages. Leases are
renewed and REPLY responses are sent back to clients.
(Trac #2325, git 7f6c9d057cc0a7a10f41ce7da9c8565b9ee85246)
523. [bug] muks
Fixed a problem in inmem NSEC3 lookup (for, instance when using a
zone with no non-apex names) which caused exceptions when the zone
origin was not added as an explicit NSEC3 record.
(Trac #2503, git 6fe86386be0e7598633fe35999112c1a6e3b0370)
522. [func]* jelte
Configuration of TSIG keys for b10-xfrin has changed; instead of
specifying the full TSIG key (<name>:<base64>:<algo>) it now expects
just the name, and uses the global TSIG Key Ring like all the other
components (configuration list /tsig_keys/keys).
Note: this is not automatically updated, so if you use TSIG in
xfrin, you need to update your configuration.
(Trac #1351, git e65b7b36f60f14b7abe083da411e6934cdfbae7a)
521. [func] marcin
Implemented definitions for DHCPv6 standard options identified
by codes up to 48. These definitions are now used by the DHCPv6
server to create instances of options being sent to a client.
(Trac #2491, git 0a4faa07777189ed9c25211987a1a9b574015a95)
520. [func] jelte
The system no longer prints initial log messages to stdout
regardless of what logging configuration is present, but it
temporarily stores any log messages until the configuration is
processed. If there is no specific configuration, or if the
configuration cannot be accessed, it will still fall back to stdout.
Note that there are still a few instances where output is printed,
these shall be addressed separately.
Note also that, currently, in case it falls back to stdout (such as
when it cannot connect to b10-cfgmgr), all log messages are always
printed (including debug messages), regardless of whether -v was
used. This shall also be addressed in a future change.
(Trac #2445, git 74a0abe5a6d10b28e4a3e360e87b129c232dea68)
519. [bug] muks
Fixed a problem in inmem NSEC lookup which caused assert failures
in some cases.
Fixed a problem in inmem NSEC lookup which caused returning an
incorrect NSEC record or (in rare cases) assert failures
when a non-existent domain was queried, which was a sub-domain of
a domain that existed.
(Trac #2504, git 835553eb309d100b062051f7ef18422d2e8e3ae4)
518. [func] stephen
......
......@@ -903,11 +903,12 @@ AC_SUBST(MULTITHREADING_FLAG)
#
GTEST_LDFLAGS=
GTEST_LDADD=
# TODO: set DISTCHECK_GTEST_CONFIGURE_FLAG for --with-gtest too
DISTCHECK_GTEST_CONFIGURE_FLAG=
if test "x$enable_gtest" = "xyes" ; then
DISTCHECK_GTEST_CONFIGURE_FLAG="--with-gtest=$gtest_path"
if test -n "$with_gtest_source" ; then
if test "x$GTEST_SOURCE" = "xyes" ; then
......@@ -1375,6 +1376,7 @@ AC_OUTPUT([doc/version.ent
src/lib/log/tests/console_test.sh
src/lib/log/tests/destination_test.sh
src/lib/log/tests/init_logger_test.sh
src/lib/log/tests/buffer_logger_test.sh
src/lib/log/tests/local_file_test.sh
src/lib/log/tests/logger_lock_test.sh
src/lib/log/tests/severity_test.sh
......
......@@ -20,9 +20,11 @@
* - @subpage DataScrubbing
*
* @section DHCP
* - @subpage dhcpv4
* - @subpage dhcp4
* - @subpage dhcpv4Session
* - @subpage dhcpv6
* - @subpage dhcpv4ConfigParser
* - @subpage dhcpv4ConfigInherit
* - @subpage dhcp6
* - @subpage dhcpv6Session
* - @subpage dhcpv6ConfigParser
* - @subpage dhcpv6ConfigInherit
......@@ -33,7 +35,7 @@
* - @subpage leasemgr
* - @subpage cfgmgr
* - @subpage allocengine
* - @subpage dhcp-database-backends
* - @subpage dhcpDatabaseBackends
* - @subpage perfdhcpInternals
*
* @section misc Miscellaneous topics
......
......@@ -758,7 +758,7 @@ as a dependency earlier -->
If the configure fails, it may be due to missing or old
dependencies.
</para>
<note>
<para>For notes on configuring and building DHCPv6 with MySQL see <xref linkend="dhcp6-install">.</xref></para>
</note>
......@@ -1841,10 +1841,8 @@ config set /Boss/components/b10-zonemgr/kind dispensable
<para>
The key ring lives in the configuration in "tsig_keys/keys". Most of
the system uses the keys from there &mdash; ACLs, authoritative server to
sign responses to signed queries, and <command>b10-xfrout</command>
to sign transfers. The <command>b10-xfrin</command> uses its own
configuration for keys, but that will be fixed in Trac ticket
<ulink url="http://bind10.isc.org/ticket/1351">#1351</ulink>.
sign responses to signed queries, and <command>b10-xfrin</command>
and <command>b10-xfrout</command> to sign transfers.
</para>
<para>
......@@ -2721,6 +2719,15 @@ TODO
</para>
</section>
<section>
<title>TSIG</title>
If you want to use TSIG for incoming transfers, a system wide TSIG
key ring must be configured (see <xref linkend="tsig-key-ring"/>).
To specify a key to use, set tsig_key value to the name of the key
to use from the key ring.
&gt; <userinput>config set Xfrin/zones[0]/tsig_key "<option>example.key</option>"</userinput>
</section>
<section>
<title>Enabling IXFR</title>
<para>
......@@ -3397,16 +3404,94 @@ then change those defaults with config set Resolver/forward_addresses[0]/address
<section id="dhcp4-config">
<title>DHCPv4 Server Configuration</title>
<para>
The DHCPv4 server does not have a lease database implemented yet
nor any support for configuration, so the same set
of configuration options (including the same fixed address)
will be assigned every time.
Once the server is started, it can be configured. To view the
current configuration, use the following command in <command>bindctl</command>:
<screen>
&gt; <userinput>config show Dhcp4</userinput></screen>
When starting Dhcp4 daemon for the first time, the default configuration
will be available. It will look similar to this:
<screen>
&gt; <userinput>config show Dhcp4</userinput>
Dhcp4/interface/ list (default)
Dhcp4/renew-timer 1000 integer (default)
Dhcp4/rebind-timer 2000 integer (default)
Dhcp4/preferred-lifetime 3000 integer (default)
Dhcp4/valid-lifetime 4000 integer (default)
Dhcp4/subnet4 [] list (default)</screen>
</para>
<para>
To change one of the parameters, simply follow
the usual <command>bindctl</command> procedure. For example, to make the
leases longer, change their valid-lifetime parameter:
<screen>
&gt; <userinput>config set Dhcp4/valid-lifetime 7200</userinput>
&gt; <userinput>config commit</userinput></screen>
Please note that most Dhcp4 parameters are of global scope
and apply to all defined subnets, unless they are overridden on a
per-subnet basis.
</para>
<para>
The essential role of DHCPv4 server is address assignment. The server
has to be configured with at least one subnet and one pool of dynamic
addresses to be managed. For example, assume that the server
is connected to a network segment that uses the 192.0.2.0/24
prefix. The Administrator of that network has decided that addresses from range
192.0.2.10 to 192.0.2.20 are going to be managed by the Dhcp4
server. Such a configuration can be achieved in the following way:
<screen>
&gt; <userinput>config add Dhcp4/subnet4</userinput>
&gt; <userinput>config set Dhcp4/subnet4[0]/subnet "192.0.2.0/24"</userinput>
&gt; <userinput>config set Dhcp4/subnet4[0]/pool [ "192.0.2.10 - 192.0.2.20" ]</userinput>
&gt; <userinput>config commit</userinput></screen>
Note that subnet is defined as a simple string, but the pool parameter
is actually a list of pools: for this reason, the pool definition is
enclosed in square brackets, even though only one range of addresses
is specified.</para>
<para>It is possible to define more than one pool in a
subnet: continuing the previous example, further assume that
192.0.2.64/26 should be also be managed by the server. It could be written as
192.0.2.64 to 192.0.2.127. Alternatively, it can be expressed more simply as
192.0.2.64/26. Both formats are supported by Dhcp4 and can be mixed in the pool list.
For example, one could define the following pools:
<screen>
&gt; <userinput>config set Dhcp4/subnet4[0]/pool [ "192.0.2.10-192.0.2.20", "192.0.2.64/26" ]</userinput>
&gt; <userinput>config commit</userinput></screen>
The number of pools is not limited, but for performance reasons it is recommended to
use as few as possible. Space and tabulations in pool definitions are ignored, so
spaces before and after hyphen are optional. They can be used to improve readability.
</para>
<para>
The server may be configured to serve more than one subnet. To add a second subnet,
use a command similar to the following:
<screen>
&gt; <userinput>config add Dhcp4/subnet4</userinput>
&gt; <userinput>config set Dhcp4/subnet4[1]/subnet "192.0.3.0/24"</userinput>
&gt; <userinput>config set Dhcp4/subnet4[1]/pool [ "192.0.3.0/24" ]</userinput>
&gt; <userinput>config commit</userinput></screen>
Arrays are counted from 0. subnet[0] refers to the subnet defined in the
previous example. The <command>config add Dhcp4/subnet4</command> adds
another (second) subnet. It can be referred to as
<command>Dhcp4/subnet4[1]</command>. In this example, we allow server to
dynamically assign all addresses available in the whole subnet.
</para>
<para>
When configuring a DHCPv4 server using prefix/length notation, please pay
attention to the boundary values. When specifying that the server should use
a given pool, it will be able to allocate also first (typically network
address) and the last (typically broadcast address) address from that pool.
In the aforementioned example of pool 192.0.3.0/24, both 192.0.3.0 and
192.0.3.255 addresses may be assigned as well. This may be invalid in some
network configurations. If you want to avoid this, please use min-max notation.
</para>
<para>
At this stage of development, the only way to alter the server
configuration is to modify its source code. To do so, please
edit src/bin/dhcp4/dhcp4_srv.cc file and modify following
parameters and recompile:
Note: Although configuration is now accepted, it is not internally used
by they server yet. At this stage of development, the only way to alter
server configuration is to modify its source code. To do so, please edit
src/bin/dhcp6/dhcp4_srv.cc file, modify the following parameters and
recompile:
<screen>
const std::string HARDCODED_LEASE = "192.0.2.222"; // assigned lease
const std::string HARDCODED_NETMASK = "255.255.255.0";
......@@ -3416,7 +3501,7 @@ const std::string HARDCODED_DNS_SERVER = "192.0.2.2";
const std::string HARDCODED_DOMAIN_NAME = "isc.example.com";
const std::string HARDCODED_SERVER_ID = "192.0.2.1";</screen>
Lease database and configuration support is planned for 2012.
Lease database and configuration support is planned for end of 2012.
</para>
</section>
......
......@@ -147,7 +147,7 @@ main(int argc, char* argv[]) {
// Initialize logging. If verbose, we'll use maximum verbosity.
isc::log::initLogger(AUTH_NAME,
(verbose ? isc::log::DEBUG : isc::log::INFO),
isc::log::MAX_DEBUG_LEVEL, NULL);
isc::log::MAX_DEBUG_LEVEL, NULL, true);
int ret = 0;
......@@ -256,7 +256,9 @@ main(int argc, char* argv[]) {
// If we haven't registered callback for data sources, this will be just
// no-op.
config_session->removeRemoteConfig("data_sources");
if (config_session != NULL) {
config_session->removeRemoteConfig("data_sources");
}
delete xfrin_session;
delete config_session;
......
......@@ -48,7 +48,7 @@ else:
PREFIX = "@prefix@"
DATAROOTDIR = "@datarootdir@"
SPECFILE_LOCATION = "@datadir@/@PACKAGE@/bob.spec".replace("${datarootdir}", DATAROOTDIR).replace("${prefix}", PREFIX)
import subprocess
import signal
import re
......@@ -76,7 +76,7 @@ import isc.bind10.socket_cache
import libutil_io_python
import tempfile
isc.log.init("b10-boss")
isc.log.init("b10-boss", buffer=True)
logger = isc.log.Logger("boss")
# Pending system-wide debug level definitions, the ones we
......@@ -166,14 +166,14 @@ class ProcessStartError(Exception): pass
class BoB:
"""Boss of BIND class."""
def __init__(self, msgq_socket_file=None, data_path=None,
config_filename=None, clear_config=False,
verbose=False, nokill=False, setuid=None, setgid=None,
username=None, cmdctl_port=None, wait_time=10):
"""
Initialize the Boss of BIND. This is a singleton (only one can run).
The msgq_socket_file specifies the UNIX domain socket file that the
msgq process listens on. If verbose is True, then the boss reports
what it is doing.
......@@ -216,6 +216,12 @@ class BoB:
self.clear_config = clear_config
self.cmdctl_port = cmdctl_port
self.wait_time = wait_time
self.msgq_timeout = 5
# _run_under_unittests is only meant to be used when testing. It
# bypasses execution of some code to help with testing.
self._run_under_unittests = False
self._component_configurator = isc.bind10.component.Configurator(self,
isc.bind10.special_component.get_specials())
# The priorities here make them start in the correct order. First
......@@ -332,6 +338,7 @@ class BoB:
"""
logger.info(BIND10_KILLING_ALL_PROCESSES)
self.__kill_children(True)
self.components = {}
def _read_bind10_config(self):
"""
......@@ -400,7 +407,7 @@ class BoB:
logger.error(BIND10_STARTUP_UNEXPECTED_MESSAGE, msg)
except:
logger.error(BIND10_STARTUP_UNRECOGNISED_MESSAGE, msg)
return False
# The next few methods start the individual processes of BIND-10. They
......@@ -408,21 +415,34 @@ class BoB:
# raised which is caught by the caller of start_all_processes(); this kills
# processes started up to that point before terminating the program.
def _make_process_info(self, name, args, env,
dev_null_stdout=False, dev_null_stderr=False):
"""
Wrapper around ProcessInfo(), useful to override
ProcessInfo() creation during testing.
"""
return ProcessInfo(name, args, env, dev_null_stdout, dev_null_stderr)
def start_msgq(self):
"""
Start the message queue and connect to the command channel.
"""
self.log_starting("b10-msgq")
msgq_proc = ProcessInfo("b10-msgq", ["b10-msgq"], self.c_channel_env,
True, not self.verbose)
msgq_proc = self._make_process_info("b10-msgq", ["b10-msgq"],
self.c_channel_env,
True, not self.verbose)
msgq_proc.spawn()
self.log_started(msgq_proc.pid)
# Now connect to the c-channel
cc_connect_start = time.time()
while self.cc_session is None:
# if we are run under unittests, break
if self._run_under_unittests:
break
# if we have been trying for "a while" give up
if (time.time() - cc_connect_start) > 5:
if (time.time() - cc_connect_start) > self.msgq_timeout:
logger.error(BIND10_CONNECTING_TO_CC_FAIL)
raise CChannelConnectError("Unable to connect to c-channel after 5 seconds")
......@@ -434,7 +454,8 @@ class BoB:
# Subscribe to the message queue. The only messages we expect to receive
# on this channel are once relating to process startup.
self.cc_session.group_subscribe("Boss")
if self.cc_session is not None:
self.cc_session.group_subscribe("Boss")
return msgq_proc
......@@ -450,13 +471,14 @@ class BoB:
args.append("--config-filename=" + self.config_filename)
if self.clear_config:
args.append("--clear-config")
bind_cfgd = ProcessInfo("b10-cfgmgr", args,
self.c_channel_env)
bind_cfgd = self._make_process_info("b10-cfgmgr", args,
self.c_channel_env)
bind_cfgd.spawn()
self.log_started(bind_cfgd.pid)
# Wait for the configuration manager to start up as subsequent initialization
# cannot proceed without it. The time to wait can be set on the command line.
# Wait for the configuration manager to start up as
# subsequent initialization cannot proceed without it. The
# time to wait can be set on the command line.
time_remaining = self.wait_time
msg, env = self.cc_session.group_recvmsg()
while time_remaining > 0 and not self.process_running(msg, "ConfigManager"):
......@@ -464,7 +486,7 @@ class BoB:
time.sleep(1)
time_remaining = time_remaining - 1
msg, env = self.cc_session.group_recvmsg()
if not self.process_running(msg, "ConfigManager"):
raise ProcessStartError("Configuration manager process has not started")
......@@ -481,7 +503,7 @@ class BoB:
process, the log_starting/log_started methods are not used.
"""
logger.info(BIND10_STARTING_CC)
self.ccs = isc.config.ModuleCCSession(SPECFILE_LOCATION,
self.ccs = isc.config.ModuleCCSession(SPECFILE_LOCATION,
self.config_handler,
self.command_handler,
socket_file = self.msgq_socket_file)
......@@ -499,7 +521,7 @@ class BoB:
The port and address arguments are for log messages only.
"""
self.log_starting(name, port, address)
newproc = ProcessInfo(name, args, c_channel_env)
newproc = self._make_process_info(name, args, c_channel_env)
newproc.spawn()
self.log_started(newproc.pid)
return newproc
......@@ -611,7 +633,6 @@ class BoB:
if self.msgq_socket_file is not None:
c_channel_env["BIND10_MSGQ_SOCKET_FILE"] = self.msgq_socket_file
logger.debug(DBG_PROCESS, BIND10_CHECK_MSGQ_ALREADY_RUNNING)
# try to connect, and if we can't wait a short while
try:
self.cc_session = isc.cc.Session(self.msgq_socket_file)
logger.fatal(BIND10_MSGQ_ALREADY_RUNNING)
......@@ -679,7 +700,7 @@ class BoB:
except:
pass
# XXX: some delay probably useful... how much is uncertain
# I have changed the delay from 0.5 to 1, but sometime it's
# I have changed the delay from 0.5 to 1, but sometime it's
# still not enough.
time.sleep(1)
self.reap_children()
......@@ -728,17 +749,19 @@ class BoB:
return os.waitpid(-1, os.WNOHANG)
def reap_children(self):
"""Check to see if any of our child processes have exited,
and note this for later handling.
"""Check to see if any of our child processes have exited,
and note this for later handling.
"""
while True:
try:
(pid, exit_status) = self._get_process_exit_status()
except OSError as o:
if o.errno == errno.ECHILD: break
if o.errno == errno.ECHILD:
break
# XXX: should be impossible to get any other error here
raise
if pid == 0: break
if pid == 0:
break
if pid in self.components:
# One of the components we know about. Get information on it.
component = self.components.pop(pid)
......@@ -760,11 +783,11 @@ class BoB:
"""
Restart any dead processes:
* Returns the time when the next process is ready to be restarted.
* Returns the time when the next process is ready to be restarted.
* If the server is shutting down, returns 0.
* If there are no processes, returns None.
The values returned can be safely passed into select() as the
The values returned can be safely passed into select() as the
timeout value.
"""
......@@ -909,8 +932,10 @@ class BoB:
"""
if self._srv_socket is not None:
self._srv_socket.close()
os.remove(self._socket_path)
os.rmdir(self._tmpdir)
if os.path.exists(self._socket_path):
os.remove(self._socket_path)
if os.path.isdir(self._tmpdir):
os.rmdir(self._tmpdir)
def _srv_accept(self):
"""
......@@ -1006,7 +1031,7 @@ boss_of_bind = None
def reaper(signal_number, stack_frame):
"""A child process has died (SIGCHLD received)."""
# don't do anything...
# don't do anything...
# the Python signal handler has been set up to write
# down a pipe, waking up our select() bit
pass
......@@ -1173,7 +1198,7 @@ and the created lock file must be writable for that user.
except KeyError:
pass
# Next try getting information about the user, assuming user name
# Next try getting information about the user, assuming user name
# passed.
# If the information is both a valid user name and user number, we
# prefer the name because we try it second. A minor point, hopefully.
......
This diff is collapsed.
......@@ -27,7 +27,7 @@ import glob
import os.path
import imp
import isc.log
isc.log.init("b10-cfgmgr")
isc.log.init("b10-cfgmgr", buffer=True)
from isc.config.cfgmgr import ConfigManager, ConfigManagerDataReadError, logger
from isc.log_messages.cfgmgr_messages import *
......
......@@ -49,7 +49,7 @@ from hashlib import sha1
from isc.util import socketserver_mixin
from isc.log_messages.cmdctl_messages import *
isc.log.init("b10-cmdctl")
isc.log.init("b10-cmdctl", buffer=True)
logger = isc.log.Logger("cmdctl")
# Debug level for communication with BIND10
......
......@@ -45,7 +45,7 @@ import os.path
import signal
import socket
isc.log.init("b10-ddns")
isc.log.init("b10-ddns", buffer=True)
logger = isc.log.Logger("ddns")
TRACE_BASIC = logger.DBGLVL_TRACE_BASIC
......
......@@ -44,6 +44,7 @@ pkglibexec_PROGRAMS = b10-dhcp4
b10_dhcp4_SOURCES = main.cc
b10_dhcp4_SOURCES += ctrl_dhcp4_srv.cc ctrl_dhcp4_srv.h
b10_dhcp4_SOURCES += config_parser.cc config_parser.h
b10_dhcp4_SOURCES += dhcp4_log.cc dhcp4_log.h
b10_dhcp4_SOURCES += dhcp4_srv.cc dhcp4_srv.h
......@@ -57,6 +58,7 @@ b10_dhcp4_CXXFLAGS = -Wno-unused-parameter
endif
b10_dhcp4_LDADD = $(top_builddir)/src/lib/dhcp/libb10-dhcp++.la
b10_dhcp4_LDADD += $(top_builddir)/src/lib/dhcpsrv/libb10-dhcpsrv.la
b10_dhcp4_LDADD += $(top_builddir)/src/lib/exceptions/libb10-exceptions.la
b10_dhcp4_LDADD += $(top_builddir)/src/lib/asiolink/libb10-asiolink.la
b10_dhcp4_LDADD += $(top_builddir)/src/lib/log/libb10-log.la
......
This diff is collapsed.
// Copyright (C) 2012 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 <exceptions/exceptions.h>
#include <cc/data.h>
#include <string>
#ifndef DHCP4_CONFIG_PARSER_H
#define DHCP4_CONFIG_PARSER_H
/// @todo: This header file and its .cc counterpart are very similar between
/// DHCPv4 and DHCPv6. They should be merged. A ticket #2355.
namespace isc {
namespace dhcp {
class Dhcpv4Srv;
/// @brief a collection of elements that store uint32 values (e.g. renew-timer = 900)
typedef std::map<std::string, uint32_t> Uint32Storage;
/// @brief a collection of elements that store string values
typedef std::map<std::string, std::string> StringStorage;
/// An exception that is thrown if an error occurs while configuring an
/// \c Dhcpv4Srv object.
class Dhcp4ConfigError : public isc::Exception {
public:
/// @brief constructor
///
/// @param file name of the file, where exception occurred
/// @param line line of the file, where exception occurred
/// @param what text description of the issue that caused exception
Dhcp4ConfigError(const char* file, size_t line, const char* what)
: isc::Exception(file, line, what) {}
};
/// @brief Base abstract class for all DHCPv4 parsers
///
/// Each instance of a class derived from this class parses one specific config
/// element. Sometimes elements are simple (e.g. a string) and sometimes quite
/// complex (e.g. a subnet). In such case, it is likely that a parser will
/// spawn child parsers to parse child elements in the configuration.
/// @todo: Merge this class with DhcpConfigParser in src/bin/dhcp6
class Dhcp4ConfigParser {
///
/// \name Constructors and Destructor
///
/// Note: The copy constructor and the assignment operator are
/// intentionally defined as private to make it explicit that this is a
/// pure base class.
//@{
private:
// Private construtor and assignment operator assures that nobody
// will be able to copy or assign a parser. There are no defined
// bodies for them.
Dhcp4ConfigParser(const Dhcp4ConfigParser& source);
Dhcp4ConfigParser& operator=(const Dhcp4ConfigParser& source);
protected:
/// \brief The default constructor.
///
/// This is intentionally defined as \c protected as this base class should
/// never be instantiated (except as part of a derived class).
Dhcp4ConfigParser() {}
public:
/// The destructor.
virtual ~Dhcp4ConfigParser() {}
//@}
/// \brief Prepare configuration value.
///