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
14716853
Commit
14716853
authored
Jun 10, 2016
by
Marcin Siodelski
Browse files
[master] Merge branch 'trac4498'
parents
3f6b5678
aa0bfc57
Changes
24
Expand all
Hide whitespace changes
Inline
Side-by-side
src/bin/dhcp4/dhcp4_srv.cc
View file @
14716853
...
...
@@ -654,15 +654,6 @@ Dhcpv4Srv::processPacket(Pkt4Ptr& query, Pkt4Ptr& rsp) {
isc
::
stats
::
StatsMgr
::
instance
().
addValue
(
"pkt4-received"
,
static_cast
<
int64_t
>
(
1
));
// In order to parse the DHCP options, the server needs to use some
// configuration information such as: existing option spaces, option
// definitions etc. This is the kind of information which is not
// available in the libdhcp, so we need to supply our own implementation
// of the option parsing function here, which would rely on the
// configuration data.
query
->
setCallback
(
boost
::
bind
(
&
Dhcpv4Srv
::
unpackOptions
,
this
,
_1
,
_2
,
_3
));
bool
skip_unpack
=
false
;
// The packet has just been received so contains the uninterpreted wire
...
...
@@ -2355,102 +2346,6 @@ Dhcpv4Srv::sanityCheck(const Pkt4Ptr& query, RequirementLevel serverid) {
}
}
size_t
Dhcpv4Srv
::
unpackOptions
(
const
OptionBuffer
&
buf
,
const
std
::
string
&
option_space
,
isc
::
dhcp
::
OptionCollection
&
options
)
{
size_t
offset
=
0
;
OptionDefContainer
option_defs
;
if
(
option_space
==
"dhcp4"
)
{
// Get the list of standard option definitions.
option_defs
=
LibDHCP
::
getOptionDefs
(
Option
::
V4
);
}
else
if
(
!
option_space
.
empty
())
{
OptionDefContainerPtr
option_defs_ptr
=
CfgMgr
::
instance
()
.
getCurrentCfg
()
->
getCfgOptionDef
()
->
getAll
(
option_space
);
if
(
option_defs_ptr
!=
NULL
)
{
option_defs
=
*
option_defs_ptr
;
}
}
// Get the search index #1. It allows to search for option definitions
// using option code.
const
OptionDefContainerTypeIndex
&
idx
=
option_defs
.
get
<
1
>
();
// The buffer being read comprises a set of options, each starting with
// a one-byte type code and a one-byte length field.
while
(
offset
+
1
<=
buf
.
size
())
{
uint8_t
opt_type
=
buf
[
offset
++
];
// DHO_END is a special, one octet long option
if
(
opt_type
==
DHO_END
)
return
(
offset
);
// just return. Don't need to add DHO_END option
// DHO_PAD is just a padding after DHO_END. Let's continue parsing
// in case we receive a message without DHO_END.
if
(
opt_type
==
DHO_PAD
)
continue
;
if
(
offset
+
1
>
buf
.
size
())
{
// opt_type must be cast to integer so as it is not treated as
// unsigned char value (a number is presented in error message).
isc_throw
(
OutOfRange
,
"Attempt to parse truncated option "
<<
static_cast
<
int
>
(
opt_type
));
}
uint8_t
opt_len
=
buf
[
offset
++
];
if
(
offset
+
opt_len
>
buf
.
size
())
{
// We peeked at the option header of the next option, but discovered
// that it would end up beyond buffer end, so the option is
// truncated. Hence we can't parse it. Therefore we revert
// back by two bytes (as if we never parsed them).
return
(
offset
-
2
);
// isc_throw(OutOfRange, "Option parse failed. Tried to parse "
// << offset + opt_len << " bytes from " << buf.size()
// << "-byte long buffer.");
}
// Get all definitions with the particular option code. Note that option code
// is non-unique within this container however at this point we expect
// to get one option definition with the particular code. If more are
// returned we report an error.
const
OptionDefContainerTypeRange
&
range
=
idx
.
equal_range
(
opt_type
);
// Get the number of returned option definitions for the option code.
size_t
num_defs
=
distance
(
range
.
first
,
range
.
second
);
OptionPtr
opt
;
if
(
num_defs
>
1
)
{
// Multiple options of the same code are not supported right now!
isc_throw
(
isc
::
Unexpected
,
"Internal error: multiple option definitions"
" for option type "
<<
static_cast
<
int
>
(
opt_type
)
<<
" returned. Currently it is not supported to initialize"
<<
" multiple option definitions for the same option code."
<<
" This will be supported once support for option spaces"
<<
" is implemented"
);
}
else
if
(
num_defs
==
0
)
{
opt
=
OptionPtr
(
new
Option
(
Option
::
V4
,
opt_type
,
buf
.
begin
()
+
offset
,
buf
.
begin
()
+
offset
+
opt_len
));
opt
->
setEncapsulatedSpace
(
"dhcp4"
);
}
else
{
// The option definition has been found. Use it to create
// the option instance from the provided buffer chunk.
const
OptionDefinitionPtr
&
def
=
*
(
range
.
first
);
assert
(
def
);
opt
=
def
->
optionFactory
(
Option
::
V4
,
opt_type
,
buf
.
begin
()
+
offset
,
buf
.
begin
()
+
offset
+
opt_len
,
boost
::
bind
(
&
Dhcpv4Srv
::
unpackOptions
,
this
,
_1
,
_2
,
_3
));
}
options
.
insert
(
std
::
make_pair
(
opt_type
,
opt
));
offset
+=
opt_len
;
}
return
(
offset
);
}
void
Dhcpv4Srv
::
classifyByVendor
(
const
Pkt4Ptr
&
pkt
,
std
::
string
&
classes
)
{
// Built-in vendor class processing
boost
::
shared_ptr
<
OptionString
>
vendor_class
=
...
...
src/bin/dhcp4/dhcp4_srv.h
View file @
14716853
...
...
@@ -729,18 +729,6 @@ protected:
/// simulates transmission of a packet. For that purpose it is protected.
virtual
void
sendPacket
(
const
Pkt4Ptr
&
pkt
);
/// @brief Implements a callback function to parse options in the message.
///
/// @param buf a A buffer holding options in on-wire format.
/// @param option_space A name of the option space which holds definitions
/// of to be used to parse options in the packets.
/// @param [out] options A reference to the collection where parsed options
/// will be stored.
/// @return An offset to the first byte after last parsed option.
size_t
unpackOptions
(
const
OptionBuffer
&
buf
,
const
std
::
string
&
option_space
,
isc
::
dhcp
::
OptionCollection
&
options
);
/// @brief Assigns incoming packet to zero or more classes.
///
/// @note This is done in two phases: first the content of the
...
...
src/bin/dhcp4/tests/dhcp4_srv_unittest.cc
View file @
14716853
// Copyright (C) 2011-201
5
Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2011-201
6
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
...
...
@@ -15,6 +15,7 @@
#include
<dhcp/tests/pkt_captures.h>
#include
<dhcp/dhcp4.h>
#include
<dhcp/iface_mgr.h>
#include
<dhcp/libdhcp++.h>
#include
<dhcp/option.h>
#include
<dhcp/option_int.h>
#include
<dhcp/option4_addrlst.h>
...
...
@@ -1142,187 +1143,6 @@ TEST_F(Dhcpv4SrvTest, vendorOptionsDocsis) {
/// See ticket #3057
// This test verifies that the following option structure can be parsed:
// - option (option space 'foobar')
// - sub option (option space 'foo')
// - sub option (option space 'bar')
// @todo Add more thorough unit tests for unpackOptions.
TEST_F
(
Dhcpv4SrvTest
,
unpackSubOptions
)
{
// Create option definition for each level of encapsulation. Each option
// definition is for the option code 1. Options may have the same
// option code because they belong to different option spaces.
// Top level option encapsulates options which belong to 'space-foo'.
OptionDefinitionPtr
opt_def
(
new
OptionDefinition
(
"option-foobar"
,
1
,
"uint32"
,
"space-foo"
));
\
// Middle option encapsulates options which belong to 'space-bar'
OptionDefinitionPtr
opt_def2
(
new
OptionDefinition
(
"option-foo"
,
1
,
"uint16"
,
"space-bar"
));
// Low level option doesn't encapsulate any option space.
OptionDefinitionPtr
opt_def3
(
new
OptionDefinition
(
"option-bar"
,
1
,
"uint8"
));
// Add option definitions to the Configuration Manager. Each goes under
// different option space.
CfgOptionDefPtr
cfg_option_def
=
CfgMgr
::
instance
().
getStagingCfg
()
->
getCfgOptionDef
();
ASSERT_NO_THROW
(
cfg_option_def
->
add
(
opt_def
,
"space-foobar"
));
ASSERT_NO_THROW
(
cfg_option_def
->
add
(
opt_def2
,
"space-foo"
));
ASSERT_NO_THROW
(
cfg_option_def
->
add
(
opt_def3
,
"space-bar"
));
CfgMgr
::
instance
().
commit
();
// Create the buffer holding the structure of options.
const
uint8_t
raw_data
[]
=
{
// First option starts here.
0x01
,
// option code = 1
0x0B
,
// option length = 11
0x00
,
0x01
,
0x02
,
0x03
,
// This option carries uint32 value
// Sub option starts here.
0x01
,
// option code = 1
0x05
,
// option length = 5
0x01
,
0x02
,
// this option carries uint16 value
// Last option starts here.
0x01
,
// option code = 1
0x01
,
// option length = 1
0x00
// This option carries a single uint8
// value and has no sub options.
};
size_t
raw_data_len
=
sizeof
(
raw_data
)
/
sizeof
(
uint8_t
);
OptionBuffer
buf
(
raw_data
,
raw_data
+
raw_data_len
);
// Parse options.
NakedDhcpv4Srv
srv
(
0
);
OptionCollection
options
;
ASSERT_NO_THROW
(
srv
.
unpackOptions
(
buf
,
"space-foobar"
,
options
));
// There should be one top level option.
ASSERT_EQ
(
1
,
options
.
size
());
boost
::
shared_ptr
<
OptionInt
<
uint32_t
>
>
option_foobar
=
boost
::
dynamic_pointer_cast
<
OptionInt
<
uint32_t
>
>
(
options
.
begin
()
->
second
);
ASSERT_TRUE
(
option_foobar
);
EXPECT_EQ
(
1
,
option_foobar
->
getType
());
EXPECT_EQ
(
0x00010203
,
option_foobar
->
getValue
());
// There should be a middle level option held in option_foobar.
boost
::
shared_ptr
<
OptionInt
<
uint16_t
>
>
option_foo
=
boost
::
dynamic_pointer_cast
<
OptionInt
<
uint16_t
>
>
(
option_foobar
->
getOption
(
1
));
ASSERT_TRUE
(
option_foo
);
EXPECT_EQ
(
1
,
option_foo
->
getType
());
EXPECT_EQ
(
0x0102
,
option_foo
->
getValue
());
// Finally, there should be a low level option under option_foo.
boost
::
shared_ptr
<
OptionInt
<
uint8_t
>
>
option_bar
=
boost
::
dynamic_pointer_cast
<
OptionInt
<
uint8_t
>
>
(
option_foo
->
getOption
(
1
));
ASSERT_TRUE
(
option_bar
);
EXPECT_EQ
(
1
,
option_bar
->
getType
());
EXPECT_EQ
(
0x0
,
option_bar
->
getValue
());
}
// Check parsing of an empty option
TEST_F
(
Dhcpv4SrvTest
,
unpackEmptyOption
)
{
// Create option definition for the option code 1 without fields.
OptionDefinitionPtr
opt_def
(
new
OptionDefinition
(
"option-empty"
,
1
,
"empty"
,
false
));
// Add it to the Configuration Manager.
CfgOptionDefPtr
cfg_option_def
=
CfgMgr
::
instance
().
getStagingCfg
()
->
getCfgOptionDef
();
ASSERT_NO_THROW
(
cfg_option_def
->
add
(
opt_def
,
"space-empty"
));
CfgMgr
::
instance
().
commit
();
// Create the buffer holding the structure of the empty option.
const
uint8_t
raw_data
[]
=
{
0x01
,
// option code = 1
0x00
// option length = 0
};
size_t
raw_data_len
=
sizeof
(
raw_data
)
/
sizeof
(
uint8_t
);
OptionBuffer
buf
(
raw_data
,
raw_data
+
raw_data_len
);
// Parse options.
NakedDhcpv4Srv
srv
(
0
);
OptionCollection
options
;
ASSERT_NO_THROW
(
srv
.
unpackOptions
(
buf
,
"space-empty"
,
options
));
// There should be one option.
ASSERT_EQ
(
1
,
options
.
size
());
OptionPtr
option_empty
=
options
.
begin
()
->
second
;
ASSERT_TRUE
(
option_empty
);
EXPECT_EQ
(
1
,
option_empty
->
getType
());
EXPECT_EQ
(
2
,
option_empty
->
len
());
}
// Check parsing of an empty VSI sub option
TEST_F
(
Dhcpv4SrvTest
,
unpackVSIOption
)
{
// Create the buffer holding the structure of the Vendor-Specific Info
const
uint8_t
raw_data
[]
=
{
43
,
// option code = DHO_VENDOR_ENCAPSULATED_OPTIONS
2
,
// option length
0xdc
,
// suboption code
0
// suboption length
};
size_t
raw_data_len
=
sizeof
(
raw_data
)
/
sizeof
(
uint8_t
);
OptionBuffer
buf
(
raw_data
,
raw_data
+
raw_data_len
);
// Parse options.
NakedDhcpv4Srv
srv
(
0
);
OptionCollection
options
;
ASSERT_NO_THROW
(
srv
.
unpackOptions
(
buf
,
"dhcp4"
,
options
));
// There should be one option: the VSI
ASSERT_EQ
(
1
,
options
.
size
());
OptionPtr
vsi
=
options
.
begin
()
->
second
;
ASSERT_TRUE
(
vsi
);
EXPECT_EQ
(
DHO_VENDOR_ENCAPSULATED_OPTIONS
,
vsi
->
getType
());
OptionCollection
suboptions
=
vsi
->
getOptions
();
// There should be one suboption
ASSERT_EQ
(
1
,
suboptions
.
size
());
OptionPtr
eso
=
suboptions
.
begin
()
->
second
;
ASSERT_TRUE
(
eso
);
EXPECT_EQ
(
0xdc
,
eso
->
getType
());
EXPECT_EQ
(
2
,
eso
->
len
());
}
// Check parsing of an empty VIVSI sub option
TEST_F
(
Dhcpv4SrvTest
,
unpackVIVSIOption
)
{
// Create the buffer holding the structure of the Vendor-Identifying
// Vendor-Specific Info
const
uint8_t
raw_data
[]
=
{
125
,
// option code = DHO_VIVSO_SUBOPTIONS
7
,
// option length
0
,
0
,
9
,
0xbf
,
// ISC enterprise number (2495)
2
,
// option data length
0xdc
,
// suboption code
0
// suboption length
};
size_t
raw_data_len
=
sizeof
(
raw_data
)
/
sizeof
(
uint8_t
);
OptionBuffer
buf
(
raw_data
,
raw_data
+
raw_data_len
);
// Parse options.
NakedDhcpv4Srv
srv
(
0
);
OptionCollection
options
;
ASSERT_NO_THROW
(
srv
.
unpackOptions
(
buf
,
"dhcp4"
,
options
));
// There should be one option: the VIVSI
ASSERT_EQ
(
1
,
options
.
size
());
OptionPtr
vivsi
=
options
.
begin
()
->
second
;
ASSERT_TRUE
(
vivsi
);
EXPECT_EQ
(
DHO_VIVSO_SUBOPTIONS
,
vivsi
->
getType
());
// Cast to OptionVendor
OptionVendorPtr
vsi
=
boost
::
dynamic_pointer_cast
<
OptionVendor
>
(
vivsi
);
ASSERT_TRUE
(
vsi
);
EXPECT_EQ
(
2495
,
vsi
->
getVendorId
());
OptionCollection
suboptions
=
vsi
->
getOptions
();
// There should be one suboption
ASSERT_EQ
(
1
,
suboptions
.
size
());
OptionPtr
eso
=
suboptions
.
begin
()
->
second
;
ASSERT_TRUE
(
eso
);
EXPECT_EQ
(
0xdc
,
eso
->
getType
());
EXPECT_EQ
(
2
,
eso
->
len
());
}
// Checks whether the server uses default (0.0.0.0) siaddr value, unless
// explicitly specified
TEST_F
(
Dhcpv4SrvTest
,
siaddrDefault
)
{
...
...
src/bin/dhcp4/tests/dhcp4_test_utils.cc
View file @
14716853
...
...
@@ -11,6 +11,7 @@
#include
<cc/command_interpreter.h>
#include
<dhcp4/json_config_parser.h>
#include
<dhcp4/tests/dhcp4_test_utils.h>
#include
<dhcp/libdhcp++.h>
#include
<dhcp/option4_addrlst.h>
#include
<dhcp/option_int.h>
#include
<dhcp/option_int_array.h>
...
...
@@ -67,6 +68,8 @@ Dhcpv4SrvTest::Dhcpv4SrvTest()
CfgMgr
::
instance
().
getStagingCfg
()
->
getCfgSubnets4
()
->
add
(
subnet_
);
CfgMgr
::
instance
().
commit
();
LibDHCP
::
clearRuntimeOptionDefs
();
// Let's wipe all existing statistics.
isc
::
stats
::
StatsMgr
::
instance
().
removeAll
();
}
...
...
@@ -77,6 +80,8 @@ Dhcpv4SrvTest::~Dhcpv4SrvTest() {
CfgMgr
::
instance
().
clear
();
CfgMgr
::
instance
().
echoClientId
(
true
);
LibDHCP
::
clearRuntimeOptionDefs
();
// Let's wipe all existing statistics.
isc
::
stats
::
StatsMgr
::
instance
().
removeAll
();
}
...
...
src/bin/dhcp4/tests/dhcp4_test_utils.h
View file @
14716853
...
...
@@ -194,7 +194,6 @@ public:
using
Dhcpv4Srv
::
acceptServerId
;
using
Dhcpv4Srv
::
sanityCheck
;
using
Dhcpv4Srv
::
srvidToString
;
using
Dhcpv4Srv
::
unpackOptions
;
using
Dhcpv4Srv
::
classifyPacket
;
using
Dhcpv4Srv
::
accept
;
using
Dhcpv4Srv
::
acceptMessageType
;
...
...
src/bin/dhcp6/dhcp6_srv.cc
View file @
14716853
...
...
@@ -469,15 +469,6 @@ void Dhcpv6Srv::run_one() {
void
Dhcpv6Srv
::
processPacket
(
Pkt6Ptr
&
query
,
Pkt6Ptr
&
rsp
)
{
// In order to parse the DHCP options, the server needs to use some
// configuration information such as: existing option spaces, option
// definitions etc. This is the kind of information which is not
// available in the libdhcp, so we need to supply our own implementation
// of the option parsing function here, which would rely on the
// configuration data.
query
->
setCallback
(
boost
::
bind
(
&
Dhcpv6Srv
::
unpackOptions
,
this
,
_1
,
_2
,
_3
,
_4
,
_5
));
bool
skip_unpack
=
false
;
// The packet has just been received so contains the uninterpreted wire
...
...
@@ -1604,11 +1595,9 @@ Dhcpv6Srv::extendIA_NA(const Pkt6Ptr& query, const Pkt6Ptr& answer,
Option6IAAddrPtr
iaaddr
=
boost
::
dynamic_pointer_cast
<
Option6IAAddr
>
(
it
->
second
);
if
(
!
iaaddr
)
{
// That's weird. Option code was ok, but the object type was not.
// As we use Dhcpv6Srv::unpackOptions() that is guaranteed to use
// Option6IAAddr for D6O_IAADDR, this should never happen. The only
// case would be with badly mis-implemented hook libraries that
// insert invalid option objects. There's no way to protect against
// this.
// This should never happen. The only case would be with badly
// mis-implemented hook libraries that insert invalid option objects.
// There's no way to protect against this.
continue
;
}
ctx
.
hints_
.
push_back
(
make_pair
(
iaaddr
->
getAddress
(),
128
));
...
...
@@ -1758,11 +1747,9 @@ Dhcpv6Srv::extendIA_PD(const Pkt6Ptr& query,
Option6IAPrefixPtr
prf
=
boost
::
dynamic_pointer_cast
<
Option6IAPrefix
>
(
it
->
second
);
if
(
!
prf
)
{
// That's weird. Option code was ok, but the object type was not.
// As we use Dhcpv6Srv::unpackOptions() that is guaranteed to use
// Option6IAPrefix for D6O_IAPREFIX, this should never happen. The only
// case would be with badly mis-implemented hook libraries that
// insert invalid option objects. There's no way to protect against
// this.
// This should never happen. The only case would be with badly
// mis-implemented hook libraries that insert invalid option objects.
// There's no way to protect against this.
continue
;
}
...
...
@@ -2779,108 +2766,6 @@ Dhcpv6Srv::processInfRequest(const Pkt6Ptr& inf_request) {
return
(
reply
);
}
size_t
Dhcpv6Srv
::
unpackOptions
(
const
OptionBuffer
&
buf
,
const
std
::
string
&
option_space
,
isc
::
dhcp
::
OptionCollection
&
options
,
size_t
*
relay_msg_offset
,
size_t
*
relay_msg_len
)
{
size_t
offset
=
0
;
size_t
length
=
buf
.
size
();
OptionDefContainer
option_defs
;
if
(
option_space
==
"dhcp6"
)
{
// Get the list of standard option definitions.
option_defs
=
LibDHCP
::
getOptionDefs
(
Option
::
V6
);
}
else
if
(
!
option_space
.
empty
())
{
OptionDefContainerPtr
option_defs_ptr
=
CfgMgr
::
instance
().
getCurrentCfg
()
->
getCfgOptionDef
()
->
getAll
(
option_space
);
if
(
option_defs_ptr
!=
NULL
)
{
option_defs
=
*
option_defs_ptr
;
}
}
// Get the search index #1. It allows to search for option definitions
// using option code.
const
OptionDefContainerTypeIndex
&
idx
=
option_defs
.
get
<
1
>
();
// The buffer being read comprises a set of options, each starting with
// a two-byte type code and a two-byte length field.
while
(
offset
+
4
<=
length
)
{
// At this point, from the while condition, we know that there
// are at least 4 bytes available following offset in the
// buffer.
uint16_t
opt_type
=
isc
::
util
::
readUint16
(
&
buf
[
offset
],
2
);
offset
+=
2
;
uint16_t
opt_len
=
isc
::
util
::
readUint16
(
&
buf
[
offset
],
2
);
offset
+=
2
;
if
(
offset
+
opt_len
>
length
)
{
// @todo: consider throwing exception here.
// We peeked at the option header of the next option, but discovered
// that it would end up beyond buffer end, so the option is
// truncated. Hence we can't parse it. Therefore we revert
// by by those four bytes (as if we never parsed them).
return
(
offset
-
4
);
}
if
(
opt_type
==
D6O_RELAY_MSG
&&
relay_msg_offset
&&
relay_msg_len
)
{
// remember offset of the beginning of the relay-msg option
*
relay_msg_offset
=
offset
;
*
relay_msg_len
=
opt_len
;
// do not create that relay-msg option
offset
+=
opt_len
;
continue
;
}
// Get all definitions with the particular option code. Note that option
// code is non-unique within this container however at this point we
// expect to get one option definition with the particular code. If more
// are returned we report an error.
const
OptionDefContainerTypeRange
&
range
=
idx
.
equal_range
(
opt_type
);
// Get the number of returned option definitions for the option code.
size_t
num_defs
=
distance
(
range
.
first
,
range
.
second
);
OptionPtr
opt
;
if
(
num_defs
>
1
)
{
// Multiple options of the same code are not supported right now!
isc_throw
(
isc
::
Unexpected
,
"Internal error: multiple option definitions"
" for option type "
<<
opt_type
<<
" returned. Currently it is not"
" supported to initialize multiple option definitions"
" for the same option code. This will be supported once"
" support for option spaces is implemented"
);
}
else
if
(
num_defs
==
0
)
{
// @todo Don't crash if definition does not exist because only a few
// option definitions are initialized right now. In the future
// we will initialize definitions for all options and we will
// remove this elseif. For now, return generic option.
opt
=
OptionPtr
(
new
Option
(
Option
::
V6
,
opt_type
,
buf
.
begin
()
+
offset
,
buf
.
begin
()
+
offset
+
opt_len
));
opt
->
setEncapsulatedSpace
(
"dhcp6"
);
}
else
{
// The option definition has been found. Use it to create
// the option instance from the provided buffer chunk.
const
OptionDefinitionPtr
&
def
=
*
(
range
.
first
);
assert
(
def
);
opt
=
def
->
optionFactory
(
Option
::
V6
,
opt_type
,
buf
.
begin
()
+
offset
,
buf
.
begin
()
+
offset
+
opt_len
,
boost
::
bind
(
&
Dhcpv6Srv
::
unpackOptions
,
this
,
_1
,
_2
,
_3
,
_4
,
_5
));
}
// add option to options
options
.
insert
(
std
::
make_pair
(
opt_type
,
opt
));
offset
+=
opt_len
;
}
return
(
offset
);
}
void
Dhcpv6Srv
::
classifyByVendor
(
const
Pkt6Ptr
&
pkt
,
std
::
string
&
classes
)
{
OptionVendorClassPtr
vclass
=
boost
::
dynamic_pointer_cast
<
OptionVendorClass
>
(
pkt
->
getOption
(
D6O_VENDOR_CLASS
));
...
...
src/bin/dhcp6/dhcp6_srv.h
View file @
14716853
...
...
@@ -607,24 +607,6 @@ protected:
/// simulates transmission of a packet. For that purpose it is protected.
virtual
void
sendPacket
(
const
Pkt6Ptr
&
pkt
);
/// @brief Implements a callback function to parse options in the message.
///
/// @param buf a A buffer holding options in on-wire format.
/// @param option_space A name of the option space which holds definitions
/// of to be used to parse options in the packets.
/// @param [out] options A reference to the collection where parsed options
/// will be stored.
/// @param relay_msg_offset Reference to a size_t structure. If specified,
/// offset to beginning of relay_msg option will be stored in it.
/// @param relay_msg_len reference to a size_t structure. If specified,
/// length of the relay_msg option will be stored in it.
/// @return An offset to the first byte after last parsed option.
size_t
unpackOptions
(
const
OptionBuffer
&
buf
,
const
std
::
string
&
option_space
,
isc
::
dhcp
::
OptionCollection
&
options
,
size_t
*
relay_msg_offset
,
size_t
*
relay_msg_len
);
/// @brief Assigns incoming packet to zero or more classes.
///
/// @note This is done in two phases: first the content of the
...
...
src/bin/dhcp6/tests/dhcp6_srv_unittest.cc
View file @
14716853
// Copyright (C) 2011-201
5
Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2011-201
6
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
...
...
@@ -1721,79 +1721,6 @@ TEST_F(Dhcpv6SrvTest, vendorOptionsDocsisDefinitions) {
ASSERT_EQ
(
0
,
rcode_
);
}
// This test verifies that the following option structure can be parsed:
// - option (option space 'foobar')
// - sub option (option space 'foo')
// - sub option (option space 'bar')
TEST_F
(
Dhcpv6SrvTest
,
unpackOptions
)
{
// Create option definition for each level of encapsulation. Each option
// definition is for the option code 1. Options may have the same
// option code because they belong to different option spaces.
// Top level option encapsulates options which belong to 'space-foo'.
OptionDefinitionPtr
opt_def
(
new
OptionDefinition
(
"option-foobar"
,
1
,
"uint32"
,
"space-foo"
));
\
// Middle option encapsulates options which belong to 'space-bar'
OptionDefinitionPtr
opt_def2
(
new
OptionDefinition
(
"option-foo"
,
1
,
"uint16"
,
"space-bar"
));
// Low level option doesn't encapsulate any option space.
OptionDefinitionPtr
opt_def3
(
new
OptionDefinition
(
"option-bar"
,
1
,
"uint8"
));
// Add option definitions to the Configuration Manager. Each goes under
// different option space.
CfgOptionDefPtr
cfg_option_def
=
CfgMgr
::
instance
().
getStagingCfg
()
->
getCfgOptionDef
();
ASSERT_NO_THROW
(
cfg_option_def
->
add
(
opt_def
,
"space-foobar"
));
ASSERT_NO_THROW
(
cfg_option_def
->
add
(
opt_def2
,
"space-foo"
));
ASSERT_NO_THROW
(
cfg_option_def
->
add
(
opt_def3
,
"space-bar"
));
CfgMgr
::
instance
().
commit
();
// Create the buffer holding the structure of options.
const
char
raw_data
[]
=
{
// First option starts here.
0x00
,
0x01
,
// option code = 1
0x00
,
0x0F
,
// option length = 15
0x00
,
0x01
,
0x02
,
0x03
,
// This option carries uint32 value
// Sub option starts here.