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
Adam Osuchowski
Kea
Commits
4c2bed01
Commit
4c2bed01
authored
Jan 14, 2013
by
Tomek Mrugalski
🛰
Browse files
[2597] Server-ID is now stored and read from a file.
parent
8e5e30b8
Changes
8
Hide whitespace changes
Inline
Side-by-side
src/bin/dhcp6/ctrl_dhcp6_srv.cc
View file @
4c2bed01
...
...
@@ -41,7 +41,6 @@ using namespace std;
namespace
isc
{
namespace
dhcp
{
ControlledDhcpv6Srv
*
ControlledDhcpv6Srv
::
server_
=
NULL
;
ConstElementPtr
...
...
src/bin/dhcp6/dhcp6_messages.mes
View file @
4c2bed01
...
...
@@ -194,6 +194,29 @@ A debug message listing the data returned to the client.
The IPv6 DHCP server has encountered a fatal error and is terminating.
The reason for the failure is included in the message.
% DHCP6_SERVERID_GENERATED Server-id %1 has been generated and will be stored in %2
This informational messages indicates that the server was not able to read
its server identifier (DUID) and has generated a new one. This server-id will
be stored in a file and will be read and used during next restart. It is normal
behavior when the server is started for the first time. If this message is printed
every start, please check that the server have sufficient permission to write its
duid file and that the duid file is not corrupted. Changing server identifier in
a production environment is not desired as clients will not recognize the server
and may go through rebind phase. They still should be able to recover without loosing
their leases.
% DHCP6_SERVERID_LOADED Server-id %1 has been loaded from file %2
This debug message indicates that the server loaded its server identifier.
That value is sent in all server responses and clients use it to discriminate
between servers. This is a part of normal startup or reconfiguration procedure.
% DHCP6_SERVERID_WRITE_FAIL server was not able to write its duid to file %1
This warning message indicates that server was not able to write its server identifier
(DUID) to a file. This likely indicates lack of write permission to a given
file or directory. This is not cricital and the server will continue to operate,
but server will generate different DUID during every start and clients will
need to go through rebind phase to recover.
% DHCP6_SESSION_FAIL failed to establish BIND 10 session (%1), running stand-alone
The server has failed to establish communication with the rest of BIND
10 and is running in stand-alone mode. (This behavior will change once
...
...
src/bin/dhcp6/dhcp6_srv.cc
View file @
4c2bed01
...
...
@@ -36,11 +36,16 @@
#include
<exceptions/exceptions.h>
#include
<util/io_utilities.h>
#include
<util/range_utilities.h>
#include
<util/encode/hex.h>
#include
<boost/foreach.hpp>
#include
<boost/tokenizer.hpp>
#include
<boost/algorithm/string/erase.hpp>
#include
<stdlib.h>
#include
<time.h>
#include
<iomanip>
#include
<fstream>
using
namespace
isc
;
using
namespace
isc
::
asiolink
;
...
...
@@ -70,7 +75,22 @@ Dhcpv6Srv::Dhcpv6Srv(uint16_t port, const char* dbconfig)
IfaceMgr
::
instance
().
openSockets6
(
port
);
}
setServerID
();
string
duid_file
=
CfgMgr
::
instance
().
getDataDir
()
+
"/"
+
string
(
SERVER_DUID_FILE
);
if
(
loadServerID
(
duid_file
))
{
LOG_DEBUG
(
dhcp6_logger
,
DBG_DHCP6_START
,
DHCP6_SERVERID_LOADED
)
.
arg
(
duid_file
);
}
else
{
generateServerID
();
LOG_INFO
(
dhcp6_logger
,
DHCP6_SERVERID_GENERATED
)
.
arg
(
duidToString
(
getServerID
()))
.
arg
(
duid_file
);
if
(
!
writeServerID
(
duid_file
))
{
LOG_WARN
(
dhcp6_logger
,
DHCP6_SERVERID_WRITE_FAIL
)
.
arg
(
duid_file
);
}
}
// Instantiate LeaseMgr
LeaseMgrFactory
::
create
(
dbconfig
);
...
...
@@ -209,10 +229,67 @@ bool Dhcpv6Srv::run() {
return
(
true
);
}
void
Dhcpv6Srv
::
setServerID
()
{
bool
Dhcpv6Srv
::
loadServerID
(
const
std
::
string
&
file_name
)
{
// load content of the file into a string
fstream
f
(
file_name
.
c_str
(),
ios
::
in
);
if
(
!
f
.
is_open
())
{
return
(
false
);
}
string
hex_string
;
f
>>
hex_string
;
f
.
close
();
// remove any spaces
boost
::
algorithm
::
erase_all
(
hex_string
,
" "
);
// now remove :
/// @todo: We should check first if the format is sane.
/// Otherwise 1:2:3:4 will be converted to 0x12, 0x34
boost
::
algorithm
::
erase_all
(
hex_string
,
":"
);
std
::
vector
<
uint8_t
>
bin
;
// Decode the hex string and store it in bin (which happens
// to be OptionBuffer format)
isc
::
util
::
encode
::
decodeHex
(
hex_string
,
bin
);
// Now create server-id option
serverid_
.
reset
(
new
Option
(
Option
::
V6
,
D6O_SERVERID
,
bin
));
return
(
true
);
}
std
::
string
Dhcpv6Srv
::
duidToString
(
const
OptionPtr
&
opt
)
{
stringstream
tmp
;
OptionBuffer
data
=
opt
->
getData
();
bool
colon
=
false
;
for
(
OptionBufferConstIter
it
=
data
.
begin
();
it
!=
data
.
end
();
++
it
)
{
if
(
colon
)
{
tmp
<<
":"
;
}
tmp
<<
hex
<<
setw
(
2
)
<<
setfill
(
'0'
)
<<
static_cast
<
uint16_t
>
(
*
it
);
if
(
!
colon
)
{
colon
=
true
;
}
}
return
tmp
.
str
();
}
bool
Dhcpv6Srv
::
writeServerID
(
const
std
::
string
&
file_name
)
{
fstream
f
(
file_name
.
c_str
(),
ios
::
out
|
ios
::
trunc
);
if
(
!
f
.
good
())
{
return
(
false
);
}
f
<<
duidToString
(
getServerID
());
f
.
close
();
}
/// @todo: DUID should be generated once and then stored, rather
/// than generated each time
void
Dhcpv6Srv
::
generateServerID
()
{
/// @todo: This code implements support for DUID-LLT (the recommended one).
/// We should eventually add support for other DUID types: DUID-LL, DUID-EN
...
...
src/bin/dhcp6/dhcp6_srv.h
View file @
4c2bed01
...
...
@@ -31,6 +31,16 @@
namespace
isc
{
namespace
dhcp
{
/// @brief file name of a server-id file
///
/// Server must store its duid in persistent storage that must not change
/// between restarts. This is name of the file that is created in dataDir
/// (see isc::dhcp::CfgMgr::getDataDir()). It is a text file that uses
/// double digit hex values separated by colons format, e.g.
/// 01:ff:02:03:06:80:90:ab:cd:ef. Server will create it during first
/// run and then use it afterwards.
static
const
char
*
SERVER_DUID_FILE
=
"b10-dhcp6-serverid"
;
/// @brief DHCPv6 server service.
///
/// This class represents DHCPv6 server. It contains all
...
...
@@ -290,15 +300,39 @@ protected:
/// @brief Sets server-identifier.
///
/// This method attempts to set server-identifier DUID. It loads it
/// from a file. If file load fails, it generates new DUID using
/// interface link-layer addresses (EUI-64) + timestamp (DUID type
/// duid-llt, see RFC3315, section 9.2). If there are no suitable
/// This method attempts to generate server-identifier DUID. It generates a
/// new DUID using interface link-layer addresses (EUI-64) + timestamp (DUID
/// type duid-llt, see RFC3315, section 9.2). If there are no suitable
/// interfaces present, exception it thrown
///
/// @throws isc::Unexpected Failed to read DUID file and no suitable
/// interfaces for new DUID generation are detected.
void
setServerID
();
void
generateServerID
();
/// @brief attempts to load DUID from a file
///
/// Tries to load duid from a text file. If the load is successful,
/// it creates server-id option and stores it in serverid_ (to be used
/// later by getServerID()).
///
/// @param file_name name of the DUID file to load
/// @return true if load was successful, false otherwise
bool
loadServerID
(
const
std
::
string
&
file_name
);
/// @brief attempts to write DUID to a file
/// Tries to write duid content (stored in serverid_) to a text file.
///
/// @param file_name name of the DUID file to write
/// @return true if write was successful, false otherwise
bool
writeServerID
(
const
std
::
string
&
file_name
);
/// @brief converts DUID to text
/// Converts content of DUID option to a text representation, e.g.
/// 01:ff:02:03:06:80:90:ab:cd:ef
///
/// @param opt option that contains DUID
/// @return string representation
static
std
::
string
duidToString
(
const
OptionPtr
&
opt
);
private:
/// @brief Allocation Engine.
...
...
src/bin/dhcp6/tests/dhcp6_srv_unittest.cc
View file @
4c2bed01
...
...
@@ -35,7 +35,7 @@
#include
<boost/scoped_ptr.hpp>
#include
<gtest/gtest.h>
#include
<unistd.h>
#include
<fstream>
#include
<iostream>
#include
<sstream>
...
...
@@ -64,10 +64,16 @@ public:
using
Dhcpv6Srv
::
createStatusCode
;
using
Dhcpv6Srv
::
selectSubnet
;
using
Dhcpv6Srv
::
sanityCheck
;
using
Dhcpv6Srv
::
loadServerID
;
using
Dhcpv6Srv
::
writeServerID
;
};
static
const
char
*
DUID_FILE
=
"server-id-test.txt"
;
class
Dhcpv6SrvTest
:
public
::
testing
::
Test
{
public:
/// Name of the server-id file (used in server-id tests)
// these are empty for now, but let's keep them around
Dhcpv6SrvTest
()
:
rcode_
(
-
1
)
{
subnet_
=
Subnet6Ptr
(
new
Subnet6
(
IOAddress
(
"2001:db8:1::"
),
48
,
1000
,
...
...
@@ -77,6 +83,9 @@ public:
CfgMgr
::
instance
().
deleteSubnets6
();
CfgMgr
::
instance
().
addSubnet6
(
subnet_
);
// it's ok if that fails. There should not be such a file anyway
unlink
(
DUID_FILE
);
}
// Generate IA_NA option with specified parameters
...
...
@@ -246,6 +255,9 @@ public:
~
Dhcpv6SrvTest
()
{
CfgMgr
::
instance
().
deleteSubnets6
();
// Let's clean up if there is such a file.
unlink
(
DUID_FILE
);
};
// A subnet used in most tests
...
...
@@ -1294,6 +1306,38 @@ TEST_F(Dhcpv6SrvTest, sanityCheck) {
RFCViolation
);
}
// This test verifies if the server-id disk operations (read, write) are
// working properly.
TEST_F
(
Dhcpv6SrvTest
,
ServerID
)
{
NakedDhcpv6Srv
srv
(
0
);
string
duid1_text
=
"01:ff:02:03:06:80:90:ab:cd:ef"
;
uint8_t
duid1
[]
=
{
0x01
,
0xff
,
2
,
3
,
6
,
0x80
,
0x90
,
0xab
,
0xcd
,
0xef
};
OptionBuffer
expected_duid1
(
duid1
,
duid1
+
sizeof
(
duid1
));
fstream
file1
(
DUID_FILE
,
ios
::
out
|
ios
::
trunc
);
file1
<<
duid1_text
;
file1
.
close
();
// Test reading from a file
EXPECT_TRUE
(
srv
.
loadServerID
(
DUID_FILE
));
ASSERT_TRUE
(
srv
.
getServerID
());
ASSERT_EQ
(
sizeof
(
duid1
)
+
Option
::
OPTION6_HDR_LEN
,
srv
.
getServerID
()
->
len
());
ASSERT_TRUE
(
expected_duid1
==
srv
.
getServerID
()
->
getData
());
// Now test writing to a file
EXPECT_EQ
(
0
,
unlink
(
DUID_FILE
));
EXPECT_NO_THROW
(
srv
.
writeServerID
(
DUID_FILE
));
fstream
file2
(
DUID_FILE
,
ios
::
in
);
ASSERT_TRUE
(
file2
.
good
());
string
text
;
file2
>>
text
;
file2
.
close
();
EXPECT_EQ
(
duid1_text
,
text
);
}
/// @todo: Add more negative tests for processX(), e.g. extend sanityCheck() test
/// to call processX() methods.
...
...
src/lib/dhcpsrv/Makefile.am
View file @
4c2bed01
SUBDIRS
=
.
tests
AM_CPPFLAGS
=
-I
$(top_builddir)
/src/lib
-I
$(top_srcdir)
/src/lib
AM_CPPFLAGS
=
-I
$(top_builddir)
/src/lib
-I
$(top_srcdir)
/src/lib
-DDHCP_DATA_DIR
=
"
\"
$(localstatedir)
\"
"
AM_CPPFLAGS
+=
$(BOOST_INCLUDES)
if
HAVE_MYSQL
AM_CPPFLAGS
+=
$(MYSQL_CPPFLAGS)
...
...
src/lib/dhcpsrv/cfgmgr.cc
View file @
4c2bed01
...
...
@@ -242,7 +242,14 @@ void CfgMgr::deleteSubnets6() {
subnets6_
.
clear
();
}
CfgMgr
::
CfgMgr
()
{
std
::
string
CfgMgr
::
getDataDir
()
{
return
(
datadir_
);
}
CfgMgr
::
CfgMgr
()
:
datadir_
(
DHCP_DATA_DIR
)
{
// DHCP_DATA_DIR is set with -DDHCP_DATA_DIR in Makefile.am
}
CfgMgr
::~
CfgMgr
()
{
...
...
src/lib/dhcpsrv/cfgmgr.h
View file @
4c2bed01
...
...
@@ -219,6 +219,14 @@ public:
/// completely new?
void
deleteSubnets4
();
/// @brief returns path do the data directory
///
/// This method returns a path to writeable directory that DHCP servers
/// can store data in.
/// @return data directory
std
::
string
getDataDir
();
protected:
/// @brief Protected constructor.
...
...
@@ -266,6 +274,8 @@ private:
/// @brief Container for defined DHCPv4 option spaces.
OptionSpaceCollection
spaces4_
;
/// @brief directory where data files (e.g. server-id) are stored
std
::
string
datadir_
;
};
}
// namespace isc::dhcp
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment