Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
Sebastian Schrader
Kea
Commits
0764a74e
Commit
0764a74e
authored
Oct 22, 2013
by
Marcin Siodelski
Browse files
[3194] Implemented basic vendor options support.
parent
78cb0f4f
Changes
25
Hide whitespace changes
Inline
Side-by-side
src/bin/dhcp4/config_parser.cc
View file @
0764a74e
...
...
@@ -96,6 +96,13 @@ protected:
<<
" for DHCPv6 server"
);
}
// Check if this is a vendor-option. If it is, get vendor-specific
// definition.
uint32_t
vendor_id
=
SubnetConfigParser
::
optionSpaceToVendorId
(
option_space
);
if
(
vendor_id
)
{
def
=
LibDHCP
::
getVendorOptionDef
(
Option
::
V4
,
vendor_id
,
option_code
);
}
return
(
def
);
}
};
...
...
src/bin/dhcp4/dhcp4_srv.cc
View file @
0764a74e
...
...
@@ -20,7 +20,9 @@
#include <dhcp/option4_addrlst.h>
#include <dhcp/option_int.h>
#include <dhcp/option_int_array.h>
#include <dhcp/option_vendor.h>
#include <dhcp/pkt4.h>
#include <dhcp/docsis3_option_defs.h>
#include <dhcp4/dhcp4_log.h>
#include <dhcp4/dhcp4_srv.h>
#include <dhcpsrv/addr_utilities.h>
...
...
@@ -36,6 +38,7 @@
#include <boost/algorithm/string/erase.hpp>
#include <boost/bind.hpp>
#include <boost/foreach.hpp>
#include <iomanip>
#include <fstream>
...
...
@@ -643,6 +646,62 @@ Dhcpv4Srv::appendRequestedOptions(const Pkt4Ptr& question, Pkt4Ptr& msg) {
}
}
void
Dhcpv4Srv
::
appendRequestedVendorOptions
(
const
Pkt4Ptr
&
question
,
Pkt4Ptr
&
answer
)
{
// Get the configured subnet suitable for the incoming packet.
Subnet4Ptr
subnet
=
selectSubnet
(
question
);
// Leave if there is no subnet matching the incoming packet.
// There is no need to log the error message here because
// it will be logged in the assignLease() when it fails to
// pick the suitable subnet. We don't want to duplicate
// error messages in such case.
if
(
!
subnet
)
{
return
;
}
// Try to get the vendor option
boost
::
shared_ptr
<
OptionVendor
>
vendor_req
=
boost
::
dynamic_pointer_cast
<
OptionVendor
>
(
question
->
getOption
(
DHO_VIVSO_SUBOPTIONS
));
if
(
!
vendor_req
)
{
return
;
}
uint32_t
vendor_id
=
vendor_req
->
getVendorId
();
// Let's try to get ORO within that vendor-option
/// @todo This is very specific to vendor-id=4491 (Cable Labs). Other vendors
/// may have different policies.
OptionPtr
oro
=
vendor_req
->
getOption
(
DOCSIS3_V4_ORO
);
/// @todo: see OPT_UINT8_TYPE definition in OptionDefinition::optionFactory().
/// I think it should be OptionUint8Array, not OptionGeneric
// Option ORO not found. Don't do anything then.
if
(
!
oro
)
{
return
;
}
boost
::
shared_ptr
<
OptionVendor
>
vendor_rsp
(
new
OptionVendor
(
Option
::
V4
,
vendor_id
));
// Get the list of options that client requested.
bool
added
=
false
;
const
OptionBuffer
&
requested_opts
=
oro
->
getData
();
for
(
OptionBuffer
::
const_iterator
code
=
requested_opts
.
begin
();
code
!=
requested_opts
.
end
();
++
code
)
{
Subnet
::
OptionDescriptor
desc
=
subnet
->
getVendorOptionDescriptor
(
vendor_id
,
*
code
);
if
(
desc
.
option
)
{
vendor_rsp
->
addOption
(
desc
.
option
);
added
=
true
;
}
}
if
(
added
)
{
answer
->
addOption
(
vendor_rsp
);
}
}
void
Dhcpv4Srv
::
appendBasicOptions
(
const
Pkt4Ptr
&
question
,
Pkt4Ptr
&
msg
)
{
// Identify options that we always want to send to the
...
...
@@ -858,6 +917,7 @@ Dhcpv4Srv::processDiscover(Pkt4Ptr& discover) {
copyDefaultFields
(
discover
,
offer
);
appendDefaultOptions
(
offer
,
DHCPOFFER
);
appendRequestedOptions
(
discover
,
offer
);
appendRequestedVendorOptions
(
discover
,
offer
);
assignLease
(
discover
,
offer
);
...
...
@@ -881,6 +941,7 @@ Dhcpv4Srv::processRequest(Pkt4Ptr& request) {
copyDefaultFields
(
request
,
ack
);
appendDefaultOptions
(
ack
,
DHCPACK
);
appendRequestedOptions
(
request
,
ack
);
appendRequestedVendorOptions
(
request
,
ack
);
// Note that we treat REQUEST message uniformly, regardless if this is a
// first request (requesting for new address), renewing existing address
...
...
@@ -1226,6 +1287,25 @@ Dhcpv4Srv::unpackOptions(const OptionBuffer& buf,
<<
"-byte long buffer."
);
}
/// @todo: Not sure if this is needed. Perhaps it would be better to extend
/// DHO_VIVSO_SUBOPTIONS definitions in std_option_defs.h to cover
/// OptionVendor class?
if
(
opt_type
==
DHO_VIVSO_SUBOPTIONS
)
{
if
(
offset
+
4
>
buf
.
size
())
{
// Truncated vendor-option. There is expected at least 4 bytes
// long enterprise-id field
return
(
offset
);
}
// Parse this as vendor option
OptionPtr
vendor_opt
(
new
OptionVendor
(
Option
::
V4
,
buf
.
begin
()
+
offset
,
buf
.
begin
()
+
offset
+
opt_len
));
options
.
insert
(
std
::
make_pair
(
opt_type
,
vendor_opt
));
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
...
...
src/bin/dhcp4/dhcp4_srv.h
View file @
0764a74e
...
...
@@ -227,6 +227,18 @@ protected:
/// @param msg outgoing message (options will be added here)
void
appendRequestedOptions
(
const
Pkt4Ptr
&
question
,
Pkt4Ptr
&
msg
);
/// @brief Appends requested vendor options as requested by client.
///
/// This method is similar to \ref appendRequestedOptions(), but uses
/// vendor options. The major difference is that vendor-options use
/// its own option spaces (there may be more than one distinct set of vendor
/// options, each with unique vendor-id). Vendor options are requested
/// using separate options within their respective vendor-option spaces.
///
/// @param question DISCOVER or REQUEST message from a client.
/// @param msg outgoing message (options will be added here)
void
appendRequestedVendorOptions
(
const
Pkt4Ptr
&
question
,
Pkt4Ptr
&
answer
);
/// @brief Assigns a lease and appends corresponding options
///
/// This method chooses the most appropriate lease for reqesting
...
...
src/bin/dhcp4/tests/dhcp4_srv_unittest.cc
View file @
0764a74e
...
...
@@ -25,8 +25,10 @@
#include <dhcp/option4_addrlst.h>
#include <dhcp/option_custom.h>
#include <dhcp/option_int_array.h>
#include <dhcp/option_vendor.h>
#include <dhcp/pkt_filter.h>
#include <dhcp/pkt_filter_inet.h>
#include <dhcp/docsis3_option_defs.h>
#include <dhcp4/dhcp4_srv.h>
#include <dhcp4/dhcp4_log.h>
#include <dhcp4/config_parser.h>
...
...
@@ -1138,11 +1140,7 @@ TEST_F(Dhcpv4SrvTest, ServerID) {
EXPECT_EQ
(
srvid_text
,
text
);
}
// Checks if callouts installed on pkt4_receive are indeed called and the
// all necessary parameters are passed.
//
// Note that the test name does not follow test naming convention,
// but the proper hook name is "buffer4_receive".
// Checks if received relay agent info option is echoed back to the client
TEST_F
(
Dhcpv4SrvTest
,
relayAgentInfoEcho
)
{
NakedDhcpv4Srv
srv
(
0
);
...
...
@@ -1180,6 +1178,87 @@ TEST_F(Dhcpv4SrvTest, relayAgentInfoEcho) {
EXPECT_TRUE
(
rai_response
->
equal
(
rai_query
));
}
// Checks if vendor options are parsed correctly and requested vendor options
// are echoed back.
TEST_F
(
Dhcpv4SrvTest
,
vendorOptionsDocsis
)
{
NakedDhcpv4Srv
srv
(
0
);
string
config
=
"{
\"
interfaces
\"
: [
\"
*
\"
],"
"
\"
rebind-timer
\"
: 2000, "
"
\"
renew-timer
\"
: 1000, "
"
\"
option-data
\"
: [ {"
"
\"
name
\"
:
\"
tftp-servers
\"
,"
"
\"
space
\"
:
\"
vendor-4491
\"
,"
"
\"
code
\"
: 2,"
"
\"
data
\"
:
\"
10.253.175.16
\"
,"
"
\"
csv-format
\"
: True"
" }],"
"
\"
subnet4
\"
: [ { "
"
\"
pool
\"
: [
\"
10.254.226.0/25
\"
],"
"
\"
subnet
\"
:
\"
10.254.226.0/24
\"
, "
"
\"
interface
\"
:
\"
"
+
valid_iface_
+
"
\"
"
" }, {"
"
\"
pool
\"
: [
\"
192.0.3.0/25
\"
],"
"
\"
subnet
\"
:
\"
192.0.3.0/24
\"
"
" } ],"
"
\"
valid-lifetime
\"
: 4000 }"
;
ElementPtr
json
=
Element
::
fromJSON
(
config
);
ConstElementPtr
status
;
// Configure the server and make sure the config is accepted
EXPECT_NO_THROW
(
status
=
configureDhcp4Server
(
srv
,
json
));
ASSERT_TRUE
(
status
);
comment_
=
config
::
parseAnswer
(
rcode_
,
status
);
ASSERT_EQ
(
0
,
rcode_
);
// Let's create a relayed DISCOVER. This particular relayed DISCOVER has
// added option 82 (relay agent info) with 3 suboptions. The server
// is supposed to echo it back in its response.
Pkt4Ptr
dis
;
ASSERT_NO_THROW
(
dis
=
captureRelayedDiscover
());
// Simulate that we have received that traffic
srv
.
fakeReceive
(
dis
);
// Server will now process to run its normal loop, but instead of calling
// IfaceMgr::receive4(), it will read all packets from the list set by
// fakeReceive()
// In particular, it should call registered buffer4_receive callback.
srv
.
run
();
// Check that the server did send a reposonse
ASSERT_EQ
(
1
,
srv
.
fake_sent_
.
size
());
// Make sure that we received a response
Pkt4Ptr
offer
=
srv
.
fake_sent_
.
front
();
ASSERT_TRUE
(
offer
);
// Get Relay Agent Info from query...
OptionPtr
vendor_opt_response
=
offer
->
getOption
(
DHO_VIVSO_SUBOPTIONS
);
ASSERT_TRUE
(
vendor_opt_response
);
// Check if it's of a correct type
boost
::
shared_ptr
<
OptionVendor
>
vendor_opt
=
boost
::
dynamic_pointer_cast
<
OptionVendor
>
(
vendor_opt_response
);
ASSERT_TRUE
(
vendor_opt
);
// Get Relay Agent Info from response...
OptionPtr
tftp_servers_generic
=
vendor_opt
->
getOption
(
DOCSIS3_V4_TFTP_SERVERS
);
ASSERT_TRUE
(
tftp_servers_generic
);
Option4AddrLstPtr
tftp_servers
=
boost
::
dynamic_pointer_cast
<
Option4AddrLst
>
(
tftp_servers_generic
);
ASSERT_TRUE
(
tftp_servers
);
Option4AddrLst
::
AddressContainer
addrs
=
tftp_servers
->
getAddresses
();
ASSERT_EQ
(
1
,
addrs
.
size
());
EXPECT_EQ
(
"10.253.175.16"
,
addrs
[
0
].
toText
());
}
/// @todo Implement tests for subnetSelect See tests in dhcp6_srv_unittest.cc:
/// selectSubnetAddr, selectSubnetIface, selectSubnetRelayLinkaddr,
/// selectSubnetRelayInterfaceId. Note that the concept of interface-id is not
...
...
src/bin/dhcp4/tests/wireshark.cc
View file @
0764a74e
...
...
@@ -100,6 +100,8 @@ Bootstrap Protocol
Option: (55) Parameter Request List
Option: (60) Vendor class identifier
Option: (125) V-I Vendor-specific Information
- suboption 1 (Option Request): requesting option 2
- suboption 5 (Modem Caps): 117 bytes
Option: (43) Vendor-Specific Information (CableLabs)
Option: (61) Client identifier
Option: (57) Maximum DHCP Message Size
...
...
src/bin/dhcp6/config_parser.cc
View file @
0764a74e
...
...
@@ -111,6 +111,13 @@ protected:
<<
" for DHCPv4 server"
);
}
// Check if this is a vendor-option. If it is, get vendor-specific
// definition.
uint32_t
vendor_id
=
SubnetConfigParser
::
optionSpaceToVendorId
(
option_space
);
if
(
vendor_id
)
{
def
=
LibDHCP
::
getVendorOptionDef
(
Option
::
V6
,
vendor_id
,
option_code
);
}
return
def
;
}
};
...
...
src/bin/dhcp6/dhcp6_srv.cc
View file @
0764a74e
...
...
@@ -17,6 +17,7 @@
#include <asiolink/io_address.h>
#include <dhcp_ddns/ncr_msg.h>
#include <dhcp/dhcp6.h>
#include <dhcp/docsis3_option_defs.h>
#include <dhcp/duid.h>
#include <dhcp/iface_mgr.h>
#include <dhcp/libdhcp++.h>
...
...
@@ -26,6 +27,7 @@
#include <dhcp/option6_iaaddr.h>
#include <dhcp/option6_iaprefix.h>
#include <dhcp/option_custom.h>
#include <dhcp/option_vendor.h>
#include <dhcp/option_int_array.h>
#include <dhcp/pkt6.h>
#include <dhcp6/dhcp6_log.h>
...
...
@@ -683,6 +685,57 @@ Dhcpv6Srv::appendRequestedOptions(const Pkt6Ptr& question, Pkt6Ptr& answer) {
}
}
void
Dhcpv6Srv
::
appendRequestedVendorOptions
(
const
Pkt6Ptr
&
question
,
Pkt6Ptr
&
answer
)
{
// Get the configured subnet suitable for the incoming packet.
Subnet6Ptr
subnet
=
selectSubnet
(
question
);
// Leave if there is no subnet matching the incoming packet.
// There is no need to log the error message here because
// it will be logged in the assignLease() when it fails to
// pick the suitable subnet. We don't want to duplicate
// error messages in such case.
if
(
!
subnet
)
{
return
;
}
// Try to get the vendor option
boost
::
shared_ptr
<
OptionVendor
>
vendor_req
=
boost
::
dynamic_pointer_cast
<
OptionVendor
>
(
question
->
getOption
(
D6O_VENDOR_OPTS
));
if
(
!
vendor_req
)
{
return
;
}
uint32_t
vendor_id
=
vendor_req
->
getVendorId
();
// Let's try to get ORO within that vendor-option
/// @todo This is very specific to vendor-id=4491 (Cable Labs). Other vendors
/// may have different policies.
boost
::
shared_ptr
<
OptionUint16Array
>
oro
=
boost
::
dynamic_pointer_cast
<
OptionUint16Array
>
(
vendor_req
->
getOption
(
DOCSIS3_V6_ORO
));
// Option ORO not found. Don't do anything then.
if
(
!
oro
)
{
return
;
}
boost
::
shared_ptr
<
OptionVendor
>
vendor_rsp
(
new
OptionVendor
(
Option
::
V6
,
vendor_id
));
// Get the list of options that client requested.
bool
added
=
false
;
const
std
::
vector
<
uint16_t
>&
requested_opts
=
oro
->
getValues
();
BOOST_FOREACH
(
uint16_t
opt
,
requested_opts
)
{
Subnet
::
OptionDescriptor
desc
=
subnet
->
getVendorOptionDescriptor
(
vendor_id
,
opt
);
if
(
desc
.
option
)
{
vendor_rsp
->
addOption
(
desc
.
option
);
added
=
true
;
}
}
if
(
added
)
{
answer
->
addOption
(
vendor_rsp
);
}
}
OptionPtr
Dhcpv6Srv
::
createStatusCode
(
uint16_t
code
,
const
std
::
string
&
text
)
{
// @todo This function uses OptionCustom class to manage contents
...
...
@@ -2114,6 +2167,7 @@ Dhcpv6Srv::processSolicit(const Pkt6Ptr& solicit) {
copyDefaultOptions
(
solicit
,
advertise
);
appendDefaultOptions
(
solicit
,
advertise
);
appendRequestedOptions
(
solicit
,
advertise
);
appendRequestedVendorOptions
(
solicit
,
advertise
);
Option6ClientFqdnPtr
fqdn
=
processClientFqdn
(
solicit
);
assignLeases
(
solicit
,
advertise
,
fqdn
);
...
...
@@ -2135,6 +2189,7 @@ Dhcpv6Srv::processRequest(const Pkt6Ptr& request) {
copyDefaultOptions
(
request
,
reply
);
appendDefaultOptions
(
request
,
reply
);
appendRequestedOptions
(
request
,
reply
);
appendRequestedVendorOptions
(
request
,
reply
);
Option6ClientFqdnPtr
fqdn
=
processClientFqdn
(
request
);
assignLeases
(
request
,
reply
,
fqdn
);
...
...
@@ -2301,6 +2356,22 @@ Dhcpv6Srv::unpackOptions(const OptionBuffer& buf,
continue
;
}
if
(
opt_type
==
D6O_VENDOR_OPTS
)
{
if
(
offset
+
4
>
length
)
{
// Truncated vendor-option. There is expected at least 4 bytes
// long enterprise-id field
return
(
offset
);
}
// Parse this as vendor option
OptionPtr
vendor_opt
(
new
OptionVendor
(
Option
::
V6
,
buf
.
begin
()
+
offset
,
buf
.
begin
()
+
offset
+
opt_len
));
options
.
insert
(
std
::
make_pair
(
opt_type
,
vendor_opt
));
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
...
...
src/bin/dhcp6/dhcp6_srv.h
View file @
0764a74e
...
...
@@ -336,6 +336,15 @@ protected:
/// @param answer server's message (options will be added here)
void
appendRequestedOptions
(
const
Pkt6Ptr
&
question
,
Pkt6Ptr
&
answer
);
/// @brief Appends requested vendor options to server's answer.
///
/// This is mostly useful for Cable Labs options for now, but the method
/// is easily extensible to other vendors.
///
/// @param question client's message
/// @param answer server's message (vendor options will be added here)
void
appendRequestedVendorOptions
(
const
Pkt6Ptr
&
question
,
Pkt6Ptr
&
answer
);
/// @brief Assigns leases.
///
/// It supports addresses (IA_NA) only. It does NOT support temporary
...
...
src/bin/dhcp6/tests/config_parser_unittest.cc
View file @
0764a74e
...
...
@@ -2049,6 +2049,118 @@ TEST_F(Dhcp6ParserTest, stdOptionData) {
EXPECT_EQ
(
1516
,
optionIA
->
getT2
());
}
// This test checks if vendor options can be specified in the config file
// (in hex format), and later retrieved from configured subnet
TEST_F
(
Dhcp6ParserTest
,
vendorOptionsHex
)
{
// This configuration string is to configure two options
// sharing the code 1 and belonging to the different vendor spaces.
// (different vendor-id values).
string
config
=
"{
\"
interfaces
\"
: [
\"
*
\"
],"
"
\"
rebind-timer
\"
: 2000,"
"
\"
renew-timer
\"
: 1000,"
"
\"
option-data
\"
: [ {"
"
\"
name
\"
:
\"
option-one
\"
,"
"
\"
space
\"
:
\"
vendor-4491
\"
,"
"
\"
code
\"
: 100,"
"
\"
data
\"
:
\"
AB CDEF0105
\"
,"
"
\"
csv-format
\"
: False"
" },"
" {"
"
\"
name
\"
:
\"
option-two
\"
,"
"
\"
space
\"
:
\"
vendor-1234
\"
,"
"
\"
code
\"
: 100,"
"
\"
data
\"
:
\"
1234
\"
,"
"
\"
csv-format
\"
: False"
" } ],"
"
\"
subnet6
\"
: [ { "
"
\"
pool
\"
: [
\"
2001:db8:1::/80
\"
],"
"
\"
subnet
\"
:
\"
2001:db8:1::/64
\"
"
" } ]"
"}"
;
ConstElementPtr
status
;
ElementPtr
json
=
Element
::
fromJSON
(
config
);
EXPECT_NO_THROW
(
status
=
configureDhcp6Server
(
srv_
,
json
));
ASSERT_TRUE
(
status
);
checkResult
(
status
,
0
);
// Options should be now available for the subnet.
Subnet6Ptr
subnet
=
CfgMgr
::
instance
().
getSubnet6
(
IOAddress
(
"2001:db8:1::5"
));
ASSERT_TRUE
(
subnet
);
// Try to get the option from the vendor space 4491
Subnet
::
OptionDescriptor
desc1
=
subnet
->
getVendorOptionDescriptor
(
4491
,
100
);
ASSERT_TRUE
(
desc1
.
option
);
EXPECT_EQ
(
100
,
desc1
.
option
->
getType
());
// Try to get the option from the vendor space 1234
Subnet
::
OptionDescriptor
desc2
=
subnet
->
getVendorOptionDescriptor
(
1234
,
100
);
ASSERT_TRUE
(
desc2
.
option
);
EXPECT_EQ
(
100
,
desc1
.
option
->
getType
());
// Try to get the non-existing option from the non-existing
// option space and expect that option is not returned.
Subnet
::
OptionDescriptor
desc3
=
subnet
->
getVendorOptionDescriptor
(
5678
,
38
);
ASSERT_FALSE
(
desc3
.
option
);
}
// This test checks if vendor options can be specified in the config file,
// (in csv format), and later retrieved from configured subnet
TEST_F
(
Dhcp6ParserTest
,
vendorOptionsCsv
)
{
// This configuration string is to configure two options
// sharing the code 1 and belonging to the different vendor spaces.
// (different vendor-id values).
string
config
=
"{
\"
interfaces
\"
: [
\"
*
\"
],"
"
\"
rebind-timer
\"
: 2000,"
"
\"
renew-timer
\"
: 1000,"
"
\"
option-data
\"
: [ {"
"
\"
name
\"
:
\"
foo
\"
,"
"
\"
space
\"
:
\"
vendor-4491
\"
,"
"
\"
code
\"
: 100,"
"
\"
data
\"
:
\"
this is a string vendor-opt
\"
,"
"
\"
csv-format
\"
: True"
" } ],"
"
\"
option-def
\"
: [ {"
"
\"
name
\"
:
\"
foo
\"
,"
"
\"
code
\"
: 100,"
"
\"
type
\"
:
\"
string
\"
,"
"
\"
array
\"
: False,"
"
\"
record-types
\"
:
\"\"
,"
"
\"
space
\"
:
\"
vendor-4491
\"
,"
"
\"
encapsulate
\"
:
\"\"
"
" } ],"
"
\"
subnet6
\"
: [ { "
"
\"
pool
\"
: [
\"
2001:db8:1::/80
\"
],"
"
\"
subnet
\"
:
\"
2001:db8:1::/64
\"
"
" } ]"
"}"
;
ConstElementPtr
status
;
ElementPtr
json
=
Element
::
fromJSON
(
config
);
EXPECT_NO_THROW
(
status
=
configureDhcp6Server
(
srv_
,
json
));
ASSERT_TRUE
(
status
);
checkResult
(
status
,
0
);
// Options should be now available for the subnet.
Subnet6Ptr
subnet
=
CfgMgr
::
instance
().
getSubnet6
(
IOAddress
(
"2001:db8:1::5"
));
ASSERT_TRUE
(
subnet
);
// Try to get the option from the vendor space 4491
Subnet
::
OptionDescriptor
desc1
=
subnet
->
getVendorOptionDescriptor
(
4491
,
100
);
ASSERT_TRUE
(
desc1
.
option
);
EXPECT_EQ
(
100
,
desc1
.
option
->
getType
());
// Try to get the non-existing option from the non-existing
// option space and expect that option is not returned.
Subnet
::
OptionDescriptor
desc2
=
subnet
->
getVendorOptionDescriptor
(
5678
,
38
);
ASSERT_FALSE
(
desc2
.
option
);
}
// The goal of this test is to verify that the standard option can
// be configured to encapsulate multiple other options.
TEST_F
(
Dhcp6ParserTest
,
stdOptionDataEncapsulate
)
{
...
...
src/bin/dhcp6/tests/dhcp6_srv_unittest.cc
View file @
0764a74e
...
...
@@ -25,10 +25,13 @@
#include <dhcp/option6_ia.h>
#include <dhcp/option6_iaaddr.h>
#include <dhcp/option_int.h>
#include <dhcp/option_vendor.h>
#include <dhcp/option_int_array.h>
#include <dhcp/option_string.h>
#include <dhcp/iface_mgr.h>
#include <dhcp6/config_parser.h>
#include <dhcp/dhcp6.h>
#include <dhcp/docsis3_option_defs.h>
#include <dhcpsrv/cfgmgr.h>
#include <dhcpsrv/lease_mgr.h>
#include <dhcpsrv/lease_mgr_factory.h>
...
...
@@ -2014,9 +2017,210 @@ TEST_F(Dhcpv6SrvTest, docsisTraffic) {
ASSERT_FALSE
(
srv
.
fake_sent_
.
empty
());
Pkt6Ptr
adv
=
srv
.
fake_sent_
.
front
();
ASSERT_TRUE
(
adv
);
}
// Checks if server is able to handle a relayed traffic from DOCSIS3.0 modems
TEST_F
(
Dhcpv6SrvTest
,
docsisVendorOptionsParse
)
{
NakedDhcpv6Srv
srv
(
0
);
// Let's get a traffic capture from DOCSIS3.0 modem
Pkt6Ptr
sol
=
captureDocsisRelayedSolicit
();
EXPECT_NO_THROW
(
sol
->
unpack
());
// Check if the packet contain
OptionPtr
opt
=
sol
->
getOption
(
D6O_VENDOR_OPTS
);
ASSERT_TRUE
(
opt
);
boost
::
shared_ptr
<
OptionVendor
>
vendor
=
boost
::
dynamic_pointer_cast
<
OptionVendor
>
(
opt
);
ASSERT_TRUE
(
vendor
);
EXPECT_TRUE
(
vendor
->
getOption
(
1
));
EXPECT_TRUE
(
vendor
->
getOption
(
36
));
EXPECT_TRUE
(
vendor
->
getOption
(
35
));
EXPECT_TRUE
(
vendor
->
getOption
(
2
));
EXPECT_TRUE
(
vendor
->
getOption
(
3
));
EXPECT_TRUE
(
vendor
->
getOption
(
4
));
EXPECT_TRUE
(
vendor
->
getOption
(
5
));
EXPECT_TRUE
(
vendor
->
getOption
(
6
));
EXPECT_TRUE
(
vendor
->
getOption
(
7
));
EXPECT_TRUE
(
vendor
->
getOption
(
8
));
EXPECT_TRUE
(
vendor
->
getOption
(
9
));
EXPECT_TRUE
(
vendor
->
getOption
(
10
));
EXPECT_TRUE
(
vendor
->
getOption
(
15
));
EXPECT_FALSE
(
vendor
->
getOption
(
20
));
EXPECT_FALSE
(
vendor
->
getOption
(
11
));
EXPECT_FALSE
(
vendor
->
getOption
(
17
));
}
// Checks if server is able to parse incoming docsis option and extract suboption 1 (docsis ORO)
TEST_F
(
Dhcpv6SrvTest
,
docsisVendorORO
)
{
NakedDhcpv6Srv
srv
(
0
);
// Let's get a traffic capture from DOCSIS3.0 modem
Pkt6Ptr
sol
=
captureDocsisRelayedSolicit
();
EXPECT_NO_THROW
(
sol
->
unpack
());
// Check if the packet contain
OptionPtr
opt
=
sol
->
getOption
(
D6O_VENDOR_OPTS
);
ASSERT_TRUE
(
opt
);
boost
::
shared_ptr
<
OptionVendor
>
vendor
=
boost
::
dynamic_pointer_cast
<
OptionVendor
>
(
opt
);
ASSERT_TRUE
(
vendor
);