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
Sebastian Schrader
Kea
Commits
9f05a29c
Commit
9f05a29c
authored
Oct 15, 2014
by
Marcin Siodelski
Browse files
[master] Merge branch 'trac3367'
parents
f71e34d4
a3ee7a21
Changes
8
Hide whitespace changes
Inline
Side-by-side
src/bin/dhcp4/dhcp4_srv.cc
View file @
9f05a29c
...
...
@@ -504,9 +504,11 @@ void
Dhcpv4Srv
::
copyDefaultFields
(
const
Pkt4Ptr
&
question
,
Pkt4Ptr
&
answer
)
{
answer
->
setIface
(
question
->
getIface
());
answer
->
setIndex
(
question
->
getIndex
());
answer
->
setCiaddr
(
question
->
getCiaddr
());
answer
->
setSiaddr
(
IOAddress
(
"0.0.0.0"
));
// explicitly set this to 0
// ciaddr is always 0, except for the Renew/Rebind state when it may
// be set to the ciaddr sent by the client.
answer
->
setCiaddr
(
IOAddress
(
"0.0.0.0"
));
answer
->
setHops
(
question
->
getHops
());
// copy MAC address
...
...
@@ -1050,6 +1052,18 @@ Dhcpv4Srv::assignLease(const Pkt4Ptr& question, Pkt4Ptr& answer) {
answer
->
setYiaddr
(
lease
->
addr_
);
/// @todo The server should check what ciaddr the client has supplied
/// in ciaddr. Currently the ciaddr is ignored except for the subnet
/// selection. If the client supplied an invalid address, the server
/// will also return an invalid address here.
if
(
!
fake_allocation
)
{
// If this is a renewing client it will set a ciaddr which the
// server may include in the response. If this is a new allocation
// the client will set ciaddr to 0 and this will also be propagated
// to the server's answer.
answer
->
setCiaddr
(
question
->
getCiaddr
());
}
// If there has been Client FQDN or Hostname option sent, but the
// hostname is empty, it means that server is responsible for
// generating the entire hostname for the client. The example of the
...
...
src/bin/dhcp4/tests/dhcp4_client.cc
View file @
9f05a29c
...
...
@@ -45,6 +45,7 @@ Dhcp4Client::Configuration::reset() {
Dhcp4Client
::
Dhcp4Client
(
const
Dhcp4Client
::
State
&
state
)
:
config_
(),
ciaddr_
(
IOAddress
(
"0.0.0.0"
)),
curr_transid_
(
0
),
dest_addr_
(
"255.255.255.255"
),
hwaddr_
(
generateHWAddr
()),
...
...
@@ -59,6 +60,7 @@ Dhcp4Client::Dhcp4Client(const Dhcp4Client::State& state) :
Dhcp4Client
::
Dhcp4Client
(
boost
::
shared_ptr
<
NakedDhcpv4Srv
>&
srv
,
const
Dhcp4Client
::
State
&
state
)
:
config_
(),
ciaddr_
(
IOAddress
(
"0.0.0.0"
)),
curr_transid_
(
0
),
dest_addr_
(
"255.255.255.255"
),
hwaddr_
(
generateHWAddr
()),
...
...
@@ -151,6 +153,10 @@ Dhcp4Client::doDiscover(const boost::shared_ptr<IOAddress>& requested_addr) {
if
(
requested_addr
)
{
addRequestedAddress
(
*
requested_addr
);
}
// Override the default ciaddr if specified by a test.
if
(
ciaddr_
.
isSpecified
())
{
context_
.
query_
->
setCiaddr
(
ciaddr_
.
get
());
}
// Send the message to the server.
sendMsg
(
context_
.
query_
);
// Expect response.
...
...
@@ -195,8 +201,10 @@ void
Dhcp4Client
::
doRequest
()
{
context_
.
query_
=
createMsg
(
DHCPREQUEST
);
// Set ciaddr.
if
((
state_
==
SELECTING
)
||
(
state_
==
INIT_REBOOT
))
{
// Override the default ciaddr if specified by a test.
if
(
ciaddr_
.
isSpecified
())
{
context_
.
query_
->
setCiaddr
(
ciaddr_
.
get
());
}
else
if
((
state_
==
SELECTING
)
||
(
state_
==
INIT_REBOOT
))
{
context_
.
query_
->
setCiaddr
(
IOAddress
(
"0.0.0.0"
));
}
else
{
context_
.
query_
->
setCiaddr
(
IOAddress
(
config_
.
lease_
.
addr_
));
...
...
src/bin/dhcp4/tests/dhcp4_client.h
View file @
9f05a29c
...
...
@@ -19,6 +19,7 @@
#include
<dhcp/hwaddr.h>
#include
<dhcp/pkt4.h>
#include
<dhcp4/tests/dhcp4_test_utils.h>
#include
<util/optional_value.h>
#include
<boost/noncopyable.hpp>
#include
<boost/shared_ptr.hpp>
#include
<set>
...
...
@@ -294,6 +295,13 @@ public:
/// @brief Current client's configuration obtained from the server.
Configuration
config_
;
/// @brief Specific ciaddr to be used in client's messages.
///
/// If this value is "unspecified" the default values will be used
/// by the client. If this value is specified, it will override ciaddr
/// in the client's messages.
isc
::
util
::
OptionalValue
<
asiolink
::
IOAddress
>
ciaddr_
;
private:
/// @brief Creates and adds Requested IP Address option to the client's
...
...
@@ -373,6 +381,7 @@ private:
/// @brief Enable relaying messages to the server.
bool
use_relay_
;
};
}
// end of namespace isc::dhcp::test
...
...
src/bin/dhcp4/tests/dora_unittest.cc
View file @
9f05a29c
...
...
@@ -302,7 +302,7 @@ TEST_F(DORATest, selectingRequestNonMatchingAddress) {
// Test that the client in the INIT-REBOOT state can request the IP
// address it has and the address is returned. Also, check that if
// if the client requests in valid address the server sends a DHCPNAK.
TEST_F
(
DORATest
,
I
nitRebootRequest
)
{
TEST_F
(
DORATest
,
i
nitRebootRequest
)
{
Dhcp4Client
client
(
Dhcp4Client
::
SELECTING
);
// Configure DHCP server.
configure
(
DORA_CONFIGS
[
0
],
*
client
.
getServer
());
...
...
@@ -349,4 +349,57 @@ TEST_F(DORATest, InitRebootRequest) {
EXPECT_EQ
(
DHCPNAK
,
static_cast
<
int
>
(
resp
->
getType
()));
}
// Check that the ciaddr returned by the server is correct for DHCPOFFER and
// DHCPNAK according to RFC2131, section 4.3.1.
TEST_F
(
DORATest
,
ciaddr
)
{
Dhcp4Client
client
(
Dhcp4Client
::
SELECTING
);
// Configure DHCP server.
configure
(
DORA_CONFIGS
[
0
],
*
client
.
getServer
());
// Force ciaddr of Discover message to be non-zero.
client
.
ciaddr_
.
specify
(
IOAddress
(
"10.0.0.50"
));
// Obtain a lease from the server using the 4-way exchange.
ASSERT_NO_THROW
(
client
.
doDiscover
(
boost
::
shared_ptr
<
IOAddress
>
(
new
IOAddress
(
"10.0.0.50"
))));
// Make sure that the server responded.
ASSERT_TRUE
(
client
.
getContext
().
response_
);
Pkt4Ptr
resp
=
client
.
getContext
().
response_
;
// Make sure that the server has responded with DHCPOFFER.
ASSERT_EQ
(
DHCPOFFER
,
static_cast
<
int
>
(
resp
->
getType
()));
// Make sure ciaddr is not set for DHCPOFFER.
EXPECT_EQ
(
"0.0.0.0"
,
resp
->
getCiaddr
().
toText
());
// Obtain a lease from the server using the 4-way exchange.
ASSERT_NO_THROW
(
client
.
doRequest
());
// Make sure that the server responded.
ASSERT_TRUE
(
client
.
getContext
().
response_
);
resp
=
client
.
getContext
().
response_
;
// Make sure that the server has responded with DHCPACK.
ASSERT_EQ
(
DHCPACK
,
static_cast
<
int
>
(
resp
->
getType
()));
// Let's transition the client to Renewing state.
client
.
setState
(
Dhcp4Client
::
RENEWING
);
// Set the unicast destination address to indicate that it is a renewal.
client
.
setDestAddress
(
IOAddress
(
"10.0.0.1"
));
ASSERT_NO_THROW
(
client
.
doRequest
());
// The client is sending invalid ciaddr so the server should send a NAK.
resp
=
client
.
getContext
().
response_
;
ASSERT_EQ
(
DHCPACK
,
static_cast
<
int
>
(
resp
->
getType
()));
// For DHCPACK the ciaddr may be 0 or may be set to the ciaddr value
// from the client's message. Kea sets it to the latter.
EXPECT_EQ
(
"10.0.0.50"
,
resp
->
getCiaddr
().
toText
());
// Replace the address held by the client. The client will request
// the assignment of this address but the server has a different
// address for this client.
client
.
ciaddr_
.
specify
(
IOAddress
(
"192.168.0.30"
));
ASSERT_NO_THROW
(
client
.
doRequest
());
// The client is sending invalid ciaddr so the server should send a NAK.
resp
=
client
.
getContext
().
response_
;
ASSERT_EQ
(
DHCPNAK
,
static_cast
<
int
>
(
resp
->
getType
()));
// For DHCPNAK the ciaddr is always 0 (should not be copied) from the
// client's message.
EXPECT_EQ
(
"0.0.0.0"
,
resp
->
getCiaddr
().
toText
());
}
}
// end of anonymous namespace
src/lib/util/Makefile.am
View file @
9f05a29c
...
...
@@ -30,6 +30,7 @@ libkea_util_la_SOURCES += memory_segment_local.h memory_segment_local.cc
if
USE_SHARED_MEMORY
libkea_util_la_SOURCES
+=
memory_segment_mapped.h memory_segment_mapped.cc
endif
libkea_util_la_SOURCES
+=
optional_value.h
libkea_util_la_SOURCES
+=
range_utilities.h
libkea_util_la_SOURCES
+=
signal_set.cc signal_set.h
libkea_util_la_SOURCES
+=
encode/base16_from_binary.h
...
...
src/lib/util/optional_value.h
0 → 100644
View file @
9f05a29c
// Copyright (C) 2014 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.
#ifndef OPTIONAL_VALUE_H
#define OPTIONAL_VALUE_H
namespace
isc
{
namespace
util
{
/// @brief Simple class representing an optional value.
///
/// This template class encapsulates a value of any type. An additional flag
/// held by this class indicates if the value is "specified" or "unspecified".
/// For example, a configuration parser for DHCP server may use this class
/// to represent the value of the configuration parameter which may appear
/// in the configuration file, but is not mandatory. The value of the
/// @c OptionalValue may be initialized to "unspecified" initially. When the
/// configuration parser finds that the appropriate parameter exists in the
/// configuration file, the default value can be overriden and the value may
/// be marked as "specified". If the parameter is not found, the value remains
/// "unspecified" and the appropriate actions may be taken, e.g. the default
/// value may be used.
///
/// This is a generic class and may be used in all cases when there is a need
/// for the additional information to be carried along with the value.
/// Alternative approach is to use a pointer which is only initialized if the
/// actual value needs to be specified, but this may not be feasible in all
/// cases.
///
/// @tparam Type of the encapsulated value.
template
<
typename
T
>
class
OptionalValue
{
public:
/// @brief Constructor
///
/// Creates optional value. The value defaults to "unspecified".
///
/// @param value Default explicit value.
/// @param specified Boolean value which determines if the value is
/// initially specified or not (default is false).
OptionalValue
(
const
T
&
value
,
const
bool
specified
=
false
)
:
value_
(
value
),
specified_
(
specified
)
{
}
/// @brief Retrieves the actual value.
T
get
()
const
{
return
(
value_
);
}
/// @brief Sets the actual value.
///
/// @param value New value.
void
set
(
const
T
&
value
)
{
value_
=
value
;
}
/// @brief Sets the new value and marks it specified.
///
/// @param value New actual value.
void
specify
(
const
T
&
value
)
{
set
(
value
);
specify
(
true
);
}
/// @brief Sets the value to "specified" or "unspecified".
///
/// It does not alter the actual value. It only marks it "specified" or
/// "unspecified".
/// @param specified boolean that determined if a value is specified or not
void
specify
(
const
bool
specified
)
{
specified_
=
specified
;
}
/// @brief Checks if the value is specified or unspecified.
///
/// @return true if the value is specified, false otherwise.
bool
isSpecified
()
const
{
return
(
specified_
);
}
private:
T
value_
;
///< Encapsulated value.
bool
specified_
;
///< Flag which indicates if the value is specified.
};
}
// end of namespace isc::util
}
// end of namespace isc
#endif // OPTIONAL_VALUE_H
src/lib/util/tests/Makefile.am
View file @
9f05a29c
...
...
@@ -40,6 +40,7 @@ run_unittests_SOURCES += memory_segment_mapped_unittest.cc
endif
run_unittests_SOURCES
+=
memory_segment_common_unittest.h
run_unittests_SOURCES
+=
memory_segment_common_unittest.cc
run_unittests_SOURCES
+=
optional_value_unittest.cc
run_unittests_SOURCES
+=
qid_gen_unittest.cc
run_unittests_SOURCES
+=
random_number_generator_unittest.cc
run_unittests_SOURCES
+=
socketsession_unittest.cc
...
...
src/lib/util/tests/optional_value_unittest.cc
0 → 100644
View file @
9f05a29c
// Copyright (C) 2014 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
<config.h>
#include
<util/optional_value.h>
#include
<gtest/gtest.h>
namespace
{
using
namespace
isc
::
util
;
// This test checks that the constructor sets the values passed as arguments.
TEST
(
OptionalValueTest
,
constructor
)
{
// Do not specify the second parameter. The default should be that
// the value is "unspecified".
OptionalValue
<
int
>
value1
(
10
);
EXPECT_EQ
(
10
,
value1
.
get
());
EXPECT_FALSE
(
value1
.
isSpecified
());
// Use the non-default value for second parameter.
OptionalValue
<
int
>
value2
(
2
,
true
);
EXPECT_EQ
(
2
,
value2
.
get
());
EXPECT_TRUE
(
value2
.
isSpecified
());
}
// This test checks that the OptionalValue::set and OptionalValue::specify
// set the values as expected.
TEST
(
OptionalValueTest
,
set
)
{
OptionalValue
<
int
>
value
(
10
);
ASSERT_EQ
(
10
,
value
.
get
());
ASSERT_FALSE
(
value
.
isSpecified
());
// Set new value. This should not change the "specified" flag.
value
.
set
(
100
);
ASSERT_EQ
(
100
,
value
.
get
());
ASSERT_FALSE
(
value
.
isSpecified
());
// Mark value "specified". The value itself should not change.
value
.
specify
(
true
);
ASSERT_EQ
(
100
,
value
.
get
());
ASSERT_TRUE
(
value
.
isSpecified
());
// Once it is "specified", set the new value. It should remain specified.
value
.
set
(
5
);
ASSERT_EQ
(
5
,
value
.
get
());
ASSERT_TRUE
(
value
.
isSpecified
());
// Mark it "unspecified". The value should remain the same.
value
.
specify
(
false
);
ASSERT_EQ
(
5
,
value
.
get
());
ASSERT_FALSE
(
value
.
isSpecified
());
}
// This test checks that the OptionalValue::specify functions may be used
// to set the new value and to mark value specified.
TEST
(
OptionalValueTest
,
specifyValue
)
{
OptionalValue
<
int
>
value
(
10
);
ASSERT_EQ
(
10
,
value
.
get
());
ASSERT_FALSE
(
value
.
isSpecified
());
// Set the new value and mark it "specified".
value
.
specify
(
123
);
ASSERT_EQ
(
123
,
value
.
get
());
ASSERT_TRUE
(
value
.
isSpecified
());
// Specify another value. The value should be still "specified".
value
.
specify
(
1000
);
ASSERT_EQ
(
1000
,
value
.
get
());
ASSERT_TRUE
(
value
.
isSpecified
());
}
}
// end of anonymous namespace
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