Commit be15d120 authored by Tomek Mrugalski's avatar Tomek Mrugalski 🛰
Browse files

[3177] Merge branch 'trac3177' b10-dhcp6 relay traffic UDP port fix.

Conflicts:
	ChangeLog
parents 9b7cc4af 6b33de4b
686. [bug] tomek
b10-dhcp6 now sends back relayed traffic to proper port.
(Trac #3177, git 6b33de4bea92eecb64b6c673bf1b8ae51f8edcf1)
685. [func] tomek 685. [func] tomek
libdhcpsrv: Allocation Engine is now able to handle IPv6 prefixes. libdhcpsrv: Allocation Engine is now able to handle IPv6 prefixes.
This will be used in Prefix Delegation. This will be used in Prefix Delegation.
...@@ -24,10 +28,10 @@ ...@@ -24,10 +28,10 @@
show Xfrin" via bindctl when b10-xfrin is running. show Xfrin" via bindctl when b10-xfrin is running.
(Trac #2274, git ca691626a2be16f08754177bb27983a9f4984702) (Trac #2274, git ca691626a2be16f08754177bb27983a9f4984702)
681. [func] tmark 681. [func] tmark
Added support for prefix delegation configuration to b10-dhcp6 Added support for prefix delegation configuration to b10-dhcp6
subnets. subnets.
(Trac# 3151 git 79a22be33825bafa1a0cdfa24d5cb751ab1ae2d3) (Trac# 3151, git 79a22be33825bafa1a0cdfa24d5cb751ab1ae2d3)
680. [func] marcin 680. [func] marcin
perfdhcp: Added support for requesting IPv6 prefixes using IA_PD perfdhcp: Added support for requesting IPv6 prefixes using IA_PD
...@@ -37,12 +41,12 @@ ...@@ -37,12 +41,12 @@
679. [func] tmark 679. [func] tmark
b10-dhcp-ddns Finite state machine logic was refactored into its own class, b10-dhcp-ddns Finite state machine logic was refactored into its own class,
StateModel. StateModel.
(Trac# 3156, git 6e9227b1b15448e834d1f60dd655e5633ff9745c) (Trac# 3156, git 6e9227b1b15448e834d1f60dd655e5633ff9745c)
678. [func] tmark 678. [func] tmark
MySQL backend used by b10-dhcp6 now uses lease type as a MySQL backend used by b10-dhcp6 now uses lease type as a
filtering parameter in all IPv6 lease queries. filtering parameter in all IPv6 lease queries.
(Trac# 3147, git 65b6372b783cb1361fd56efe2b3247bfdbdc47ea) (Trac# 3147, git 65b6372b783cb1361fd56efe2b3247bfdbdc47ea)
677. [func] tomek 677. [func] tomek
libdhcpsrv: CfgMgr is now able to store IA, TA and PD pools in libdhcpsrv: CfgMgr is now able to store IA, TA and PD pools in
......
...@@ -369,7 +369,15 @@ bool Dhcpv6Srv::run() { ...@@ -369,7 +369,15 @@ bool Dhcpv6Srv::run() {
if (rsp) { if (rsp) {
rsp->setRemoteAddr(query->getRemoteAddr()); rsp->setRemoteAddr(query->getRemoteAddr());
rsp->setLocalAddr(query->getLocalAddr()); rsp->setLocalAddr(query->getLocalAddr());
rsp->setRemotePort(DHCP6_CLIENT_PORT);
if (rsp->relay_info_.empty()) {
// Direct traffic, send back to the client directly
rsp->setRemotePort(DHCP6_CLIENT_PORT);
} else {
// Relayed traffic, send back to the relay agent
rsp->setRemotePort(DHCP6_SERVER_PORT);
}
rsp->setLocalPort(DHCP6_SERVER_PORT); rsp->setLocalPort(DHCP6_SERVER_PORT);
rsp->setIndex(query->getIndex()); rsp->setIndex(query->getIndex());
rsp->setIface(query->getIface()); rsp->setIface(query->getIface());
...@@ -433,10 +441,10 @@ bool Dhcpv6Srv::run() { ...@@ -433,10 +441,10 @@ bool Dhcpv6Srv::run() {
// Pass incoming packet as argument // Pass incoming packet as argument
callout_handle->setArgument("response6", rsp); callout_handle->setArgument("response6", rsp);
// Call callouts // Call callouts
HooksManager::callCallouts(Hooks.hook_index_buffer6_send_, *callout_handle); HooksManager::callCallouts(Hooks.hook_index_buffer6_send_, *callout_handle);
// Callouts decided to skip the next processing step. The next // Callouts decided to skip the next processing step. The next
// processing step would to parse the packet, so skip at this // processing step would to parse the packet, so skip at this
// stage means drop. // stage means drop.
...@@ -444,7 +452,7 @@ bool Dhcpv6Srv::run() { ...@@ -444,7 +452,7 @@ bool Dhcpv6Srv::run() {
LOG_DEBUG(dhcp6_logger, DBG_DHCP6_HOOKS, DHCP6_HOOK_BUFFER_SEND_SKIP); LOG_DEBUG(dhcp6_logger, DBG_DHCP6_HOOKS, DHCP6_HOOK_BUFFER_SEND_SKIP);
continue; continue;
} }
callout_handle->getArgument("response6", rsp); callout_handle->getArgument("response6", rsp);
} }
......
...@@ -78,6 +78,7 @@ dhcp6_unittests_SOURCES += ../dhcp6_srv.h ../dhcp6_srv.cc ...@@ -78,6 +78,7 @@ dhcp6_unittests_SOURCES += ../dhcp6_srv.h ../dhcp6_srv.cc
dhcp6_unittests_SOURCES += ../dhcp6_log.h ../dhcp6_log.cc dhcp6_unittests_SOURCES += ../dhcp6_log.h ../dhcp6_log.cc
dhcp6_unittests_SOURCES += ../ctrl_dhcp6_srv.cc dhcp6_unittests_SOURCES += ../ctrl_dhcp6_srv.cc
dhcp6_unittests_SOURCES += ../config_parser.cc ../config_parser.h dhcp6_unittests_SOURCES += ../config_parser.cc ../config_parser.h
dhcp6_unittests_SOURCES += wireshark.cc
nodist_dhcp6_unittests_SOURCES = ../dhcp6_messages.h ../dhcp6_messages.cc nodist_dhcp6_unittests_SOURCES = ../dhcp6_messages.h ../dhcp6_messages.cc
nodist_dhcp6_unittests_SOURCES += marker_file.h test_libraries.h nodist_dhcp6_unittests_SOURCES += marker_file.h test_libraries.h
......
...@@ -2116,6 +2116,82 @@ TEST_F(FqdnDhcpv6SrvTest, processRequestRelease) { ...@@ -2116,6 +2116,82 @@ TEST_F(FqdnDhcpv6SrvTest, processRequestRelease) {
} }
// Checks if server responses are sent to the proper port.
TEST_F(Dhcpv6SrvTest, portsDirectTraffic) {
NakedDhcpv6Srv srv(0);
// Let's create a simple SOLICIT
Pkt6Ptr sol = captureSimpleSolicit();
// Simulate that we have received that traffic
srv.fakeReceive(sol);
// Server will now process to run its normal loop, but instead of calling
// IfaceMgr::receive6(), it will read all packets from the list set by
// fakeReceive()
srv.run();
// Get Advertise...
ASSERT_FALSE(srv.fake_sent_.empty());
Pkt6Ptr adv = srv.fake_sent_.front();
ASSERT_TRUE(adv);
// This is sent back to client directly, should be port 546
EXPECT_EQ(DHCP6_CLIENT_PORT, adv->getRemotePort());
}
// Checks if server responses are sent to the proper port.
TEST_F(Dhcpv6SrvTest, portsRelayedTraffic) {
NakedDhcpv6Srv srv(0);
// Let's create a simple SOLICIT
Pkt6Ptr sol = captureRelayedSolicit();
// Simulate that we have received that traffic
srv.fakeReceive(sol);
// Server will now process to run its normal loop, but instead of calling
// IfaceMgr::receive6(), it will read all packets from the list set by
// fakeReceive()
srv.run();
// Get Advertise...
ASSERT_FALSE(srv.fake_sent_.empty());
Pkt6Ptr adv = srv.fake_sent_.front();
ASSERT_TRUE(adv);
// This is sent back to relay, so port is 547
EXPECT_EQ(DHCP6_SERVER_PORT, adv->getRemotePort());
}
// Checks if server is able to handle a relayed traffic from DOCSIS3.0 modems
// @todo Uncomment this test as part of #3180 work.
// Kea code currently fails to handle docsis traffic.
TEST_F(Dhcpv6SrvTest, DISABLED_docsisTraffic) {
NakedDhcpv6Srv srv(0);
// Let's get a traffic capture from DOCSIS3.0 modem
Pkt6Ptr sol = captureDocsisRelayedSolicit();
// Simulate that we have received that traffic
srv.fakeReceive(sol);
// Server will now process to run its normal loop, but instead of calling
// IfaceMgr::receive6(), it will read all packets from the list set by
// fakeReceive()
srv.run();
// We should have an Advertise in response
ASSERT_FALSE(srv.fake_sent_.empty());
Pkt6Ptr adv = srv.fake_sent_.front();
ASSERT_TRUE(adv);
/// @todo Check that the ADVERTISE is ok, that it includes all options,
/// that is relayed properly, etc.
}
/// @todo: Add more negative tests for processX(), e.g. extend sanityCheck() test /// @todo: Add more negative tests for processX(), e.g. extend sanityCheck() test
/// to call processX() methods. /// to call processX() methods.
......
...@@ -394,6 +394,21 @@ public: ...@@ -394,6 +394,21 @@ public:
return (lease); return (lease);
} }
// see wireshark.cc for descriptions
// The descriptions are too large and too closely related to the
// code, so it is kept in .cc rather than traditionally in .h
Pkt6Ptr captureSimpleSolicit();
Pkt6Ptr captureRelayedSolicit();
Pkt6Ptr captureDocsisRelayedSolicit();
/// @brief Auxiliary method that sets Pkt6 fields
///
/// Used to reconstruct captured packets. Sets UDP ports, interface names,
/// and other fields to some believable values.
/// @param pkt packet that will have its fields set
void captureSetDefaultFields(const Pkt6Ptr& pkt);
~Dhcpv6SrvTest() { ~Dhcpv6SrvTest() {
CfgMgr::instance().deleteSubnets6(); CfgMgr::instance().deleteSubnets6();
}; };
......
...@@ -85,33 +85,6 @@ TEST_F(Dhcpv6SrvTest, Hooks) { ...@@ -85,33 +85,6 @@ TEST_F(Dhcpv6SrvTest, Hooks) {
EXPECT_TRUE(hook_index_lease6_release > 0); EXPECT_TRUE(hook_index_lease6_release > 0);
} }
// This function returns buffer for very simple Solicit
Pkt6* captureSimpleSolicit() {
Pkt6* pkt;
uint8_t data[] = {
1, // type 1 = SOLICIT
0xca, 0xfe, 0x01, // trans-id = 0xcafe01
0, 1, // option type 1 (client-id)
0, 10, // option lenth 10
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, // DUID
0, 3, // option type 3 (IA_NA)
0, 12, // option length 12
0, 0, 0, 1, // iaid = 1
0, 0, 0, 0, // T1 = 0
0, 0, 0, 0 // T2 = 0
};
pkt = new Pkt6(data, sizeof(data));
pkt->setRemotePort(546);
pkt->setRemoteAddr(IOAddress("fe80::1"));
pkt->setLocalPort(0);
pkt->setLocalAddr(IOAddress("ff02::1:2"));
pkt->setIndex(2);
pkt->setIface("eth0");
return (pkt);
}
/// @brief a class dedicated to Hooks testing in DHCPv6 server /// @brief a class dedicated to Hooks testing in DHCPv6 server
/// ///
/// This class has a number of static members, because each non-static /// This class has a number of static members, because each non-static
......
// Copyright (C) 2013 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 <dhcp6/tests/dhcp6_test_utils.h>
#include <string>
/// @file wireshark.cc
///
/// @brief contains packet captures imported from Wireshark
///
/// These are actual packets captured over wire. They are used in various
/// tests.
///
/// The procedure to export Wireshark -> unit-tests is manual, but rather
/// easy to follow:
/// 1. Open a file in wireshark
/// 2. Find the packet you want to export
/// 3. There's a protocol stack (Frame, Ethernet, IPv6, UDP, DHCPv6, ...)
/// 4. Right click on DHCPv6 -> Copy -> Bytes -> Hex Stream
/// 5. Paste it as: string hex_string="[paste here]";
/// 6. Coding guidelines line restrictions apply, so wrap your code as necessary
/// 7. Make sure you decribe the capture appropriately
/// 8. Follow whatever rest of the methods are doing (set ports, ifaces etc.)
using namespace std;
namespace isc {
namespace test {
void Dhcpv6SrvTest::captureSetDefaultFields(const Pkt6Ptr& pkt) {
pkt->setRemotePort(546);
pkt->setRemoteAddr(IOAddress("fe80::1"));
pkt->setLocalPort(0);
pkt->setLocalAddr(IOAddress("ff02::1:2"));
pkt->setIndex(2);
pkt->setIface("eth0");
}
// This function returns buffer for very simple Solicit
Pkt6Ptr Dhcpv6SrvTest::captureSimpleSolicit() {
uint8_t data[] = {
1, // type 1 = SOLICIT
0xca, 0xfe, 0x01, // trans-id = 0xcafe01
0, 1, // option type 1 (client-id)
0, 10, // option lenth 10
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, // DUID
0, 3, // option type 3 (IA_NA)
0, 12, // option length 12
0, 0, 0, 1, // iaid = 1
0, 0, 0, 0, // T1 = 0
0, 0, 0, 0 // T2 = 0
};
Pkt6Ptr pkt(new Pkt6(data, sizeof(data)));
captureSetDefaultFields(pkt);
return (pkt);
}
Pkt6Ptr Dhcpv6SrvTest::captureRelayedSolicit() {
// This is a very simple relayed SOLICIT message:
// RELAY-FORW
// - interface-id
// - relay-message
// - SOLICIT
// - client-id
// - IA_NA (iaid=1, t1=0, t2=0)
// - ORO (7)
// string exported from Wireshark
string hex_string =
"0c0500000000000000000000000000000000fc00000000000000000000000000000900"
"12000231350009002c010517100001000e0001000151b5e46208002758f1e80003000c"
"000000010000000000000000000600020007";
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);
Pkt6Ptr pkt(new Pkt6(&bin[0], bin.size()));
captureSetDefaultFields(pkt);
return (pkt);
}
/// returns a buffer with relayed SOLICIT (from DOCSIS3.0 cable modem)
Pkt6Ptr isc::test::Dhcpv6SrvTest::captureDocsisRelayedSolicit() {
// This is an actual DOCSIS packet
// RELAY-FORW (12)
// - Relay Message
// - SOLICIT (1)
// - client-id
// - IA_NA (iaid=7f000788, t2=0, t2=0)
// - IAAddress (::, pref=0,valid=0)
// - rapid-commit
// - ORO
// - Reconfigure-accept
// - Vendor-Class ("docsis3.0")
// - Vendor-specific Info
// - subopt 1: Option request = 32,33,34,37,38
// - subopt 36: Device identifier
// - subopt 35: TLV5
// - subopt 2: Device type = ECM
// - subopt 3: Embedded components
// - subopt 4: Serial Number
// - subopt 5: Hardware version
// - subopt 6: Software version
// - subopt 7: Boot ROM Version
// - subopt 8: Organization Unique Identifier
// - subopt 9: Model Number
// - subopt 10: Vendor Name (Netgear)
// - subopt 15: unknown
// - Interface-Id
// - Vendor-specific Information
// - Suboption 1025: CMTS capabilities
// - Suboption 1026: Cable Modem MAC addr = 10:0d:7f:00:07:88
// string exported from Wireshark
string hex_string =
"0c002a0288fe00fe00015a8d09fffe7af955fe80000000000000120d7ffffe00078800"
"090189010d397f0001000a00030001100d7f000788000300287f000788000000000000"
"000000050018000000000000000000000000000000000000000000000000000e000000"
"0800020000000600020011001400000010000f0000118b0009646f63736973332e3000"
"1101200000118b0001000a0020002100220025002600240006100d7f00078800230081"
"0101010201030301010401010501010601010701180801080901000a01010b01180c01"
"010d0200400e0200100f01011004000000021101011301011401001501381601011701"
"011801041901041a01041b01281c01021d01081e01201f011020011821010222010123"
"010124011825010126020040270101120701100d7f00078a0002000345434d0003000b"
"45434d3a45524f555445520004000d3335463132395550303030353200050004332e31"
"310006000956312e30312e31315400070013505350552d426f6f7420312e302e31362e"
"323200080006303030393542000900084347343030305444000a00074e657467656172"
"000f000745524f5554455200120012427531264361312f3000100d7f00078800000011"
"00160000118b040100040102030004020006100d7f000788";
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);
Pkt6Ptr pkt(new Pkt6(&bin[0], bin.size()));
captureSetDefaultFields(pkt);
return (pkt);
}
}; // end of isc::test namespace
}; // end of isc namespace
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment