Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
ISC Open Source Projects
Kea
Commits
a2924fcc
Commit
a2924fcc
authored
Jul 14, 2017
by
Tomek Mrugalski
🛰
Browse files
[5272] lease_cmds in progress
parent
63e8df70
Changes
12
Hide whitespace changes
Inline
Side-by-side
configure.ac
View file @
a2924fcc
...
...
@@ -1630,6 +1630,8 @@ AC_CONFIG_FILES([Makefile
src/bin/shell/tests/shell_unittest.py
src/hooks/Makefile
src/hooks/dhcp/Makefile
src/hooks/dhcp/lease_cmds/Makefile
src/hooks/dhcp/lease_cmds/tests/Makefile
src/hooks/dhcp/user_chk/Makefile
src/hooks/dhcp/user_chk/tests/Makefile
src/hooks/dhcp/user_chk/tests/test_data_files_config.h
...
...
src/hooks/dhcp/Makefile.am
View file @
a2924fcc
SUBDIRS
=
user_chk
SUBDIRS
=
user_chk
lease_cmds
src/hooks/dhcp/lease_cmds/Makefile.am
0 → 100644
View file @
a2924fcc
SUBDIRS
=
.
tests
AM_CPPFLAGS
=
-I
$(top_builddir)
/src/lib
-I
$(top_srcdir)
/src/lib
AM_CPPFLAGS
+=
$(BOOST_INCLUDES)
AM_CXXFLAGS
=
$(KEA_CXXFLAGS)
# Define rule to build logging source files from message file
lease_cmds_messages.h lease_cmds_messages.cc
:
s-messages
s-messages
:
lease_cmds_messages.mes
$(top_builddir)
/src/lib/log/compiler/kea-msg-compiler
$(top_srcdir)
/src/hooks/dhcp/lease_cmds/lease_cmds_messages.mes
touch
$@
# Tell automake that the message files are built as part of the build process
# (so that they are built before the main library is built).
BUILT_SOURCES
=
lease_cmds_messages.h lease_cmds_messages.cc
# Ensure that the message file is included in the distribution
EXTRA_DIST
=
lease_cmds_messages.mes
# Get rid of generated message files on a clean
CLEANFILES
=
*
.gcno
*
.gcda lease_cmds_messages.h lease_cmds_messages.cc s-messages
# convenience archive
noinst_LTLIBRARIES
=
liblease_cmds.la
liblease_cmds_la_SOURCES
=
lease_cmds.cc lease_cmds.h
liblease_cmds_la_SOURCES
+=
lease_parser.h lease_parser.cc
liblease_cmds_la_SOURCES
+=
lease_cmds_log.cc lease_cmds_log.h
liblease_cmds_la_SOURCES
+=
load_unload.cc
liblease_cmds_la_SOURCES
+=
version.cc
nodist_liblease_cmds_la_SOURCES
=
lease_cmds_messages.cc lease_cmds_messages.h
liblease_cmds_la_CXXFLAGS
=
$(AM_CXXFLAGS)
liblease_cmds_la_CPPFLAGS
=
$(AM_CPPFLAGS)
# install the shared object into $(libdir)/hooks
lib_hooksdir
=
$(libdir)
/hooks
lib_hooks_LTLIBRARIES
=
libdhcp_lease_cmds.la
libdhcp_lease_cmds_la_SOURCES
=
libdhcp_lease_cmds_la_LDFLAGS
=
$(AM_LDFLAGS)
libdhcp_lease_cmds_la_LDFLAGS
+=
-avoid-version
-export-dynamic
-module
libdhcp_lease_cmds_la_LIBADD
=
liblease_cmds.la
libdhcp_lease_cmds_la_LIBADD
+=
$(top_builddir)
/src/lib/cc/libkea-cc.la
libdhcp_lease_cmds_la_LIBADD
+=
$(top_builddir)
/src/lib/config/libkea-cfgclient.la
libdhcp_lease_cmds_la_LIBADD
+=
$(top_builddir)
/src/lib/dhcpsrv/libkea-dhcpsrv.la
libdhcp_lease_cmds_la_LIBADD
+=
$(top_builddir)
/src/lib/hooks/libkea-hooks.la
libdhcp_lease_cmds_la_LIBADD
+=
$(top_builddir)
/src/lib/asiolink/libkea-asiolink.la
libdhcp_lease_cmds_la_LIBADD
+=
$(top_builddir)
/src/lib/dhcp/libkea-dhcp++.la
libdhcp_lease_cmds_la_LIBADD
+=
$(top_builddir)
/src/lib/eval/libkea-eval.la
libdhcp_lease_cmds_la_LIBADD
+=
$(top_builddir)
/src/lib/dhcp_ddns/libkea-dhcp_ddns.la
libdhcp_lease_cmds_la_LIBADD
+=
$(top_builddir)
/src/lib/stats/libkea-stats.la
libdhcp_lease_cmds_la_LIBADD
+=
$(top_builddir)
/src/lib/dns/libkea-dns++.la
libdhcp_lease_cmds_la_LIBADD
+=
$(top_builddir)
/src/lib/cryptolink/libkea-cryptolink.la
libdhcp_lease_cmds_la_LIBADD
+=
$(top_builddir)
/src/lib/log/libkea-log.la
libdhcp_lease_cmds_la_LIBADD
+=
$(top_builddir)
/src/lib/util/threads/libkea-threads.la
libdhcp_lease_cmds_la_LIBADD
+=
$(top_builddir)
/src/lib/util/libkea-util.la
libdhcp_lease_cmds_la_LIBADD
+=
$(top_builddir)
/src/lib/exceptions/libkea-exceptions.la
EXTRA_DIST
+=
lease_cmds.dox
src/hooks/dhcp/lease_cmds/lease_cmds.cc
0 → 100644
View file @
a2924fcc
// Copyright (C) 2017 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
<config.h>
#include
<lease_cmds.h>
#include
<config/command_mgr.h>
#include
<lease_parser.h>
#include
<cc/command_interpreter.h>
#include
<cc/data.h>
#include
<asiolink/io_address.h>
#include
<lease_cmds_log.h>
#include
<dhcpsrv/cfgmgr.h>
#include
<dhcpsrv/lease_mgr.h>
#include
<dhcpsrv/lease_mgr_factory.h>
#include
<dhcpsrv/subnet_id.h>
#include
<dhcp/duid.h>
#include
<util/encode/hex.h>
#include
<util/strutil.h>
#include
<exceptions/exceptions.h>
#include
<boost/bind.hpp>
#include
<string>
using
namespace
isc
::
dhcp
;
using
namespace
isc
::
data
;
using
namespace
isc
::
config
;
using
namespace
isc
::
asiolink
;
using
namespace
std
;
namespace
isc
{
namespace
lease_cmds
{
/// @brief Wrapper class around reservation command handlers.
class
LeaseCmdsImpl
{
public:
LeaseCmdsImpl
();
~
LeaseCmdsImpl
();
/// @brief Parameters specified for reservation-get and reservation-del
///
/// As both call types (get and delete) need specify which reservation to
/// act on, they have the same set of parameters. In particular, those
/// two call types support the following sets of parameters:
/// - subnet-id, address
/// - subnet-id, identifier type, identifier value
///
/// This class stores those parameters and is used to pass them around.
class
Parameters
{
public:
/// @brief specifies type of query (by IP addr, by hwaddr, by DUID)
typedef
enum
{
TYPE_ADDR
,
///< query by IP address (either v4 or v6)
TYPE_HWADDR
,
///< query by hardware address (v4 only)
TYPE_DUID
///< query by DUID (v6 only)
}
Type
;
/// @brief Specifies subnet-id (always used)
SubnetID
subnet_id
;
/// @brief Specifies IPv4 or IPv6 address (used when query_by_addr is true)
IOAddress
addr
;
/// @brief Specifies identifier type (usually FLEX_ID, used when
/// query_by_addr is false)
HWAddrPtr
hwaddr
;
/// @brief Specifies identifier value (used when query_by_addr is false)
isc
::
dhcp
::
DuidPtr
duid
;
/// @brief specifies parameter types (true = query by address, false =
/// query by indetifier-type,identifier)
Type
query_type
;
/// @brief Default contstructor.
Parameters
()
:
addr
(
"::"
),
query_type
(
TYPE_ADDR
)
{
}
};
private:
/// @brief Registers commands:
///
/// Registers:
/// - lease4-add
/// - lease6-add
/// - lease4-get
/// - lease6-get
/// - lease4-del
/// - lease6-del
/// - lease4-update
/// - lease6-update
/// - lease4-del-all
/// - lease6-del-all
/// @throw Unexpected if CommandMgr is not available (should not happen)
void
registerCommands
();
/// @brief Dergisters commands:
///
/// Deregisters:
/// - lease4-add
/// - lease6-add
/// - lease4-get
/// - lease6-get
/// - lease4-del
/// - lease6-del
/// - lease4-update
/// - lease6-update
/// - lease4-del-all
/// - lease6-del-all
///
/// @throw Unexpected if CommandMgr is not available (should not happen)
void
deregisterCommands
();
/// @brief reservation-add command handler
///
/// This command attempts to add a lease.
///
/// An example full command looks as follows. Note that the args
/// parameter is expected to contain the "arguments" portion of it.
/// This function covers v4 lease only.
///
/// Example command
/// {
/// "command": "lease4-add",
/// "parameters": {
/// "address": "192.0.2.1",
/// "hwaddr": "00:01:02:03:04:05",
/// "client-id": "this-is-a-client",
/// "valid-lft": 3600,
/// "expire": 1499282530,
/// "subnet-id": 1,
/// "fdqn_fwd": true,
/// "fqdn_rev": true,
/// "hostname": "myhost.example.org",
/// "state": 0
/// }
/// }
///
/// @param command should be 'reservation-add' (but it's ignored)
/// @param args must contain host reservation definition.
/// @return result of the operation
static
ConstElementPtr
leaseAddHandler
(
const
string
&
command
,
ConstElementPtr
args
);
/// @brief reservation-get command handler
///
/// This command attempts to retrieve a host that match selected criteria.
/// Two types of parameters are supported: (subnet-id, address) or
/// (subnet-id, identifier-type, identifier).
///
/// Example command for query by (subnet-id, address):
/// {
/// "command": "reservation-get",
/// "arguments": {
/// "subnet-id": 1,
/// "ip-address": "192.0.2.202"
/// }
/// }
///
/// Example command for query by (subnet-id, identifier-type, identifier)
/// {
/// "command": "reservation-get",
/// "arguments": {
/// "subnet-id": 1,
/// "identifier-type": "hw-address",
/// "identifier": "00:01:02:03:04:05"
/// }
/// }";
/// @param command should be 'reservation-get' (but it's ignored)
/// @param args must contain host reservation definition.
/// @return result of the operation (host will be included as parameters, if found)
static
ConstElementPtr
leaseGetHandler
(
const
string
&
command
,
ConstElementPtr
args
);
/// @brief reservation-del command handler
///
/// This command attempts to delete a host that match selected criteria.
/// Two types of parameters are supported: (subnet-id, address) or
/// (subnet-id, identifier-type, identifier).
///
/// Note: for this operation to work, hosts-database must be specified
/// in your configuration file (or from code point of view, alternate_source_
/// must be set in HostMgr).
///
/// Example command for query by (subnet-id, address):
/// {
/// "command": "reservation-get",
/// "arguments": {
/// "subnet-id": 1,
/// "ip-address": "192.0.2.202"
/// }
/// }
///
/// Example command for query by (subnet-id, identifier-type, identifier)
/// {
/// "command": "reservation-get",
/// "arguments": {
/// "subnet-id": 1,
/// "identifier-type": "hw-address",
/// "identifier": "00:01:02:03:04:05"
/// }
/// }";
/// @param command should be 'reservation-add' (but it's ignored)
/// @param args must contain host reservation definition.
/// @return result of the operation (host will be included as parameters, if found)
static
ConstElementPtr
leaseDelHandler
(
const
string
&
command
,
ConstElementPtr
args
);
static
ConstElementPtr
leaseUpdateHandler
(
const
string
&
command
,
ConstElementPtr
args
);
static
ConstElementPtr
leaseWipeHandler
(
const
string
&
command
,
ConstElementPtr
args
);
/// @brief Extracts parameters required for reservation-get and reservation-del
///
/// See @ref Parameters class for detailed description of what is expected
/// in the args structure.
///
/// @param args - arguments passed to command
/// @return parsed parameters
/// @throw BadValue if input arguments don't make sense.
static
Parameters
getParameters
(
const
ConstElementPtr
&
args
);
/// @brief Covenience pointer used to access database storage
static
HostDataSourcePtr
db_storage_
;
/// @brief Protocol family (IPv4 or IPv6)
static
uint16_t
family_
;
};
LeaseCmdsImpl
::
LeaseCmdsImpl
()
{
family_
=
CfgMgr
::
instance
().
getFamily
();
registerCommands
();
}
LeaseCmdsImpl
::~
LeaseCmdsImpl
()
{
deregisterCommands
();
}
void
LeaseCmdsImpl
::
registerCommands
()
{
/// @todo: Use registration mechanism once #5321 discussion is done
CommandMgr
::
instance
().
registerCommand
(
"lease4-add"
,
boost
::
bind
(
&
LeaseCmdsImpl
::
leaseAddHandler
,
_1
,
_2
));
CommandMgr
::
instance
().
registerCommand
(
"lease6-add"
,
boost
::
bind
(
&
LeaseCmdsImpl
::
leaseAddHandler
,
_1
,
_2
));
CommandMgr
::
instance
().
registerCommand
(
"lease4-get"
,
boost
::
bind
(
&
LeaseCmdsImpl
::
leaseGetHandler
,
_1
,
_2
));
CommandMgr
::
instance
().
registerCommand
(
"lease6-get"
,
boost
::
bind
(
&
LeaseCmdsImpl
::
leaseGetHandler
,
_1
,
_2
));
CommandMgr
::
instance
().
registerCommand
(
"lease4-del"
,
boost
::
bind
(
&
LeaseCmdsImpl
::
leaseDelHandler
,
_1
,
_2
));
CommandMgr
::
instance
().
registerCommand
(
"lease6-del"
,
boost
::
bind
(
&
LeaseCmdsImpl
::
leaseDelHandler
,
_1
,
_2
));
CommandMgr
::
instance
().
registerCommand
(
"lease4-update"
,
boost
::
bind
(
&
LeaseCmdsImpl
::
leaseUpdateHandler
,
_1
,
_2
));
CommandMgr
::
instance
().
registerCommand
(
"lease6-update"
,
boost
::
bind
(
&
LeaseCmdsImpl
::
leaseUpdateHandler
,
_1
,
_2
));
CommandMgr
::
instance
().
registerCommand
(
"lease4-del-all"
,
boost
::
bind
(
&
LeaseCmdsImpl
::
leaseWipeHandler
,
_1
,
_2
));
CommandMgr
::
instance
().
registerCommand
(
"lease6-del-all"
,
boost
::
bind
(
&
LeaseCmdsImpl
::
leaseWipeHandler
,
_1
,
_2
));
}
void
LeaseCmdsImpl
::
deregisterCommands
()
{
/// @todo: Use deregistration mechanism once #5321 discussion is done
CommandMgr
::
instance
().
deregisterCommand
(
"lease4-add"
);
CommandMgr
::
instance
().
deregisterCommand
(
"lease6-add"
);
CommandMgr
::
instance
().
deregisterCommand
(
"lease4-get"
);
CommandMgr
::
instance
().
deregisterCommand
(
"lease6-get"
);
CommandMgr
::
instance
().
deregisterCommand
(
"lease4-del"
);
CommandMgr
::
instance
().
deregisterCommand
(
"lease6-del"
);
CommandMgr
::
instance
().
deregisterCommand
(
"lease4-update"
);
CommandMgr
::
instance
().
deregisterCommand
(
"lease6-update"
);
CommandMgr
::
instance
().
deregisterCommand
(
"lease4-del-all"
);
CommandMgr
::
instance
().
deregisterCommand
(
"lease6-del-all"
);
}
ConstElementPtr
LeaseCmdsImpl
::
leaseAddHandler
(
const
std
::
string
&
name
,
ConstElementPtr
params
)
{
bool
v4
=
(
name
==
"lease4-add"
);
string
txt
=
"(missing parameters)"
;
if
(
params
)
{
txt
=
params
->
str
();
}
try
{
if
(
!
params
)
{
isc_throw
(
isc
::
BadValue
,
"no parameters specified for the command"
);
}
ConstElementPtr
lease_data
=
params
->
get
(
"lease"
);
if
(
!
lease_data
)
{
isc_throw
(
isc
::
BadValue
,
"'lease' parameters must be specified"
);
}
Lease4Ptr
lease4
;
Lease6Ptr
lease6
;
if
(
v4
)
{
LeaseDataParser4
parser
;
lease4
=
parser
.
parse
(
lease_data
);
checkLeaseIntegrity
(
lease4
);
if
(
lease4
)
{
LeaseMgrFactory
::
instance
().
add
(
lease4
);
}
}
else
{
LeaseDataParser6
parser
;
lease6
=
parser
.
parse
(
lease_data
);
checkLeaseIntegrity
(
lease6
);
if
(
lease6
)
{
LeaseMgrFactory
::
instance
().
add
(
lease6
);
}
}
}
catch
(
const
std
::
exception
&
ex
)
{
LOG_ERROR
(
lease_cmds_logger
,
LEASE_CMDS_RESERV_ADD_FAILED
)
.
arg
(
txt
)
.
arg
(
ex
.
what
());
return
(
createAnswer
(
CONTROL_RESULT_ERROR
,
ex
.
what
()));
}
LOG_INFO
(
lease_cmds_logger
,
v4
?
LEASE_CMDS_ADD4
:
LEASE_CMDS_ADD6
).
arg
(
txt
);
return
(
createAnswer
(
CONTROL_RESULT_SUCCESS
,
"Lease added."
));
}
LeaseCmdsImpl
::
Parameters
LeaseCmdsImpl
::
getParameters
(
const
ConstElementPtr
&
params
)
{
Parameters
x
;
if
(
!
params
||
params
->
getType
()
!=
Element
::
map
)
{
isc_throw
(
BadValue
,
"Parameters missing or are not a map."
);
}
// We support 2 sets of parameters for lease-get/lease-del:
// lease-get(subnet-id, address)
// lease-get(subnet-id, interifier-type, identifier)
ConstElementPtr
tmp
=
params
->
get
(
"subnet-id"
);
if
(
!
tmp
)
{
isc_throw
(
BadValue
,
"Mandatory 'subnet-id' parameter missing."
);
}
if
(
tmp
->
getType
()
!=
Element
::
integer
)
{
isc_throw
(
BadValue
,
"'subnet-id' parameter is not integer."
);
}
x
.
subnet_id
=
tmp
->
intValue
();
tmp
=
params
->
get
(
"ip-address"
);
ConstLeasePtr
host
;
if
(
tmp
)
{
if
(
tmp
->
getType
()
!=
Element
::
string
)
{
isc_throw
(
BadValue
,
"'ip-address' is not a string."
);
}
x
.
addr
=
IOAddress
(
tmp
->
stringValue
());
x
.
query_by_addr
=
true
;
return
(
x
);
}
// No address specified. Ok, so it must be identifier based query.
// "identifier-type": "duid",
// "identifier": "aa:bb:cc:dd:ee:..."
ConstElementPtr
type
=
params
->
get
(
"identifier-type"
);
ConstElementPtr
ident
=
params
->
get
(
"identifier"
);
if
(
!
type
||
type
->
getType
()
!=
Element
::
string
)
{
isc_throw
(
BadValue
,
"No 'ip-address' provided"
" and 'identifier-type' is either missing or not a string."
);
}
if
(
!
ident
||
ident
->
getType
()
!=
Element
::
string
)
{
isc_throw
(
BadValue
,
"No 'ip-address' provided"
" and 'identifier' is either missing or not a string."
);
}
// Got the parameters. Let's see if their values make sense.
// Try to parse the identifier value first.
try
{
x
.
ident
=
util
::
str
::
quotedStringToBinary
(
ident
->
stringValue
());
if
(
x
.
ident
.
empty
())
{
util
::
str
::
decodeFormattedHexString
(
ident
->
stringValue
(),
x
.
ident
);
}
}
catch
(...)
{
// The string doesn't match any known pattern, so we have to
// report an error at this point.
isc_throw
(
BadValue
,
"Unable to parse 'identifier' value."
);
}
if
(
x
.
ident
.
empty
())
{
isc_throw
(
BadValue
,
"Unable to query for empty 'identifier'."
);
}
// Next, try to convert identifier-type
try
{
x
.
type
=
Lease
::
getIdentifierType
(
type
->
stringValue
());
}
catch
(
const
std
::
exception
&
ex
)
{
isc_throw
(
BadValue
,
"Value of 'identifier-type' was not recognized."
);
}
x
.
query_by_addr
=
false
;
return
(
x
);
}
ConstElementPtr
LeaseCmdsImpl
::
leaseGetHandler
(
const
std
::
string
&
name
,
ConstElementPtr
params
)
{
Parameters
p
;
Lease4Ptr
lease4
;
Lease6Ptr
lease6
;
bool
v4
=
(
name
==
"lease4-get"
);
try
{
p
=
getParameters
(
params
);
switch
(
p
.
query_type
)
{
case
TYPE_ADDR
:
{
// Query by address
if
(
v4
)
{
lease4
=
LeaseMgr
::
instance
().
getLease4
(
p
.
subnet_id
,
p
.
addr
);
}
else
{
lease6
=
LeaseMgr
::
instance
().
getLease6
(
p
.
subnet_id
,
p
.
addr
);
}
break
;
}
case
TYPE_HWADDR
:
if
(
v4
)
{
lease4
=
LeaseMgr
::
instance
().
getLease4
(
p
.
subnet_id
,
p
.
hwaddr
);
}
else
{
return
(
createAnswer
(
CONTROL_RESULT_ERROR
,
"Query by hw-address is not allowed in v6."
));
}
case
TYPE_DUID
:
if
(
v6
)
{
lease6
=
LeaseMgr
::
instance
().
getLease6
(
p
.
subnet_id
,
p
.
duid
);
}
else
{
return
(
createAnswer
(
CONTROL_RESULT_ERROR
,
"Query by duid is not allowed in v4."
));
}
default:
return
(
createAnswer
(
CONTROL_RESULT_ERROR
,
"Unknown query type: "
<<
static_cast
<
int
>
(
p
.
query_type
)));
}
}
catch
(
const
std
::
exception
&
ex
)
{
return
(
createAnswer
(
CONTROL_RESULT_ERROR
,
"Failure during leaseX-get: "
<<
ex
.
what
()));
}
ElementPtr
lease_json
;
if
(
v4
&&
lease4
)
{
lease_json
=
lease4
->
toElement4
();
}
if
(
!
v4
&&
lease6
)
{
lease_json
=
lease6
->
toElement6
();
}
if
(
lease
)
{
return
(
createAnswer
(
CONTROL_RESULT_SUCCESS
,
"Lease found."
,
lease_json
));
}
else
{
return
(
createAnswer
(
CONTROL_RESULT_SUCCESS
,
"Lease not found."
));
}
}
ConstElementPtr
LeaseCmdsImpl
::
reservationDelHandler
(
const
std
::
string
&
/*name*/
,
ConstElementPtr
params
)
{
Parameters
p
;
bool
deleted
;
try
{
p
=
getParameters
(
params
);
if
(
p
.
query_by_addr
)
{
// try to delete by address
deleted
=
LeaseMgr
::
instance
().
del
(
p
.
subnet_id
,
p
.
addr
);
}
else
{
// try to delete by identifier
if
(
family_
==
AF_INET
)
{
deleted
=
LeaseMgr
::
instance
().
del4
(
p
.
subnet_id
,
p
.
type
,
&
p
.
ident
[
0
],
p
.
ident
.
size
());
}
else
{
deleted
=
LeaseMgr
::
instance
().
del6
(
p
.
subnet_id
,
p
.
type
,
&
p
.
ident
[
0
],
p
.
ident
.
size
());
}
}
}
catch
(
const
std
::
exception
&
ex
)
{
return
(
createAnswer
(
CONTROL_RESULT_ERROR
,
ex
.
what
()));
}
if
(
deleted
)
{
return
(
createAnswer
(
CONTROL_RESULT_SUCCESS
,
"Lease deleted."
));
}
else
{
return
(
createAnswer
(
CONTROL_RESULT_ERROR
,
"Lease not deleted (not found)."
));
}
}
uint16_t
LeaseCmdsImpl
::
family_
=
AF_INET
;
LeaseDataSourcePtr
LeaseCmdsImpl
::
db_storage_
;
LeaseCmds
::
LeaseCmds
()
:
impl_
(
new
LeaseCmdsImpl
())
{
}
LeaseCmds
::~
LeaseCmds
()
{
impl_
.
reset
();
}
};
};
src/hooks/dhcp/lease_cmds/lease_cmds.h
0 → 100644
View file @
a2924fcc
// Copyright (C) 2017 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/.
#ifndef LEASE_CMDS_H