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

[master] Merge branch 'trac3553' (MAC address from docsis options)

parents 69393d44 bd9f0c66
......@@ -1921,7 +1921,7 @@ should include options from the isc option space:
</simpara>
</listitem>
<listitem>
<simpara><command>remote-id</command> <ulink
<simpara><command>remote-id</command> - <ulink
url="http://tools.ietf.org/html/rfc4649">RFC 4649</ulink>
defines remote-id option that is inserted by a relay agent. Depending
on the relay agent configuration, the inserted option may convey client's
......@@ -1941,10 +1941,20 @@ should include options from the isc option space:
</simpara>
</listitem>
<listitem>
<simpara><command>docsis</command> - Yet another possible source of MAC
<simpara><command>docsis-cmts</command> - Yet another possible source of MAC
address information are DOCSIS options inserted by a CMTS that acts
as a DHCPv6 relay agent in cable networks. This method is
currently not implemented.
as a DHCPv6 relay agent in cable networks. This method attempts to extract
MAC address information from suboption 1026 (cm mac) of the vendor specific option
with vendor-id=4491. This vendor option is extracted from the relay-forward message,
not the original client's message.
</simpara>
</listitem>
<listitem>
<simpara><command>docsis-modem</command> - Yet another possible source of MAC
address information are DOCSIS options inserted by the cable modem itself.
This method attempts to extract MAC address information from suboption 36 (device id)
of the vendor specific option with vendor-id=4491. This vendor option is extracted from
the original client's message, not from any relay options.
</simpara>
</listitem>
</itemizedlist>
......
......@@ -80,7 +80,6 @@ dhcp4_unittests_SOURCES += dhcp4_unittests.cc
dhcp4_unittests_SOURCES += dhcp4_srv_unittest.cc
dhcp4_unittests_SOURCES += dhcp4_test_utils.cc dhcp4_test_utils.h
dhcp4_unittests_SOURCES += direct_client_unittest.cc
dhcp4_unittests_SOURCES += wireshark.cc
dhcp4_unittests_SOURCES += ctrl_dhcp4_srv_unittest.cc
dhcp4_unittests_SOURCES += config_parser_unittest.cc
dhcp4_unittests_SOURCES += fqdn_unittest.cc
......
......@@ -18,6 +18,7 @@
#include <asiolink/io_address.h>
#include <config/ccsession.h>
#include <dhcp4/tests/dhcp4_test_utils.h>
#include <dhcp/tests/pkt_captures.h>
#include <dhcp/dhcp4.h>
#include <dhcp/iface_mgr.h>
#include <dhcp/option.h>
......@@ -56,6 +57,7 @@ using namespace isc::data;
using namespace isc::asiolink;
using namespace isc::hooks;
using namespace isc::dhcp::test;
using namespace isc::test;
namespace {
......@@ -1159,7 +1161,7 @@ TEST_F(Dhcpv4SrvTest, relayAgentInfoEcho) {
// 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());
ASSERT_NO_THROW(dis = PktCaptures::captureRelayedDiscover());
// Simulate that we have received that traffic
srv.fakeReceive(dis);
......@@ -1235,7 +1237,7 @@ TEST_F(Dhcpv4SrvTest, vendorOptionsDocsis) {
// 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());
ASSERT_NO_THROW(dis = PktCaptures::captureRelayedDiscover());
// Simulate that we have received that traffic
srv.fakeReceive(dis);
......@@ -2935,7 +2937,7 @@ TEST_F(HooksDhcpv4SrvTest, lease4ReleaseSkip) {
TEST_F(Dhcpv4SrvTest, docsisVendorOptionsParse) {
// Let's get a traffic capture from DOCSIS3.0 modem
Pkt4Ptr dis = captureRelayedDiscover();
Pkt4Ptr dis = PktCaptures::captureRelayedDiscover();
ASSERT_NO_THROW(dis->unpack());
// Check if the packet contain
......@@ -2959,7 +2961,7 @@ TEST_F(Dhcpv4SrvTest, docsisVendorOptionsParse) {
TEST_F(Dhcpv4SrvTest, docsisVendorORO) {
// Let's get a traffic capture from DOCSIS3.0 modem
Pkt4Ptr dis = captureRelayedDiscover();
Pkt4Ptr dis = PktCaptures::captureRelayedDiscover();
EXPECT_NO_THROW(dis->unpack());
// Check if the packet contains vendor specific information option
......@@ -3127,7 +3129,7 @@ TEST_F(Dhcpv4SrvTest, clientClassification) {
// Let's create a relayed DISCOVER. This particular relayed DISCOVER has
// vendor-class set to docsis3.0
Pkt4Ptr dis1;
ASSERT_NO_THROW(dis1 = captureRelayedDiscover());
ASSERT_NO_THROW(dis1 = PktCaptures::captureRelayedDiscover());
ASSERT_NO_THROW(dis1->unpack());
srv.classifyPacket(dis1);
......@@ -3138,7 +3140,7 @@ TEST_F(Dhcpv4SrvTest, clientClassification) {
// Let's create a relayed DISCOVER. This particular relayed DISCOVER has
// vendor-class set to eRouter1.0
Pkt4Ptr dis2;
ASSERT_NO_THROW(dis2 = captureRelayedDiscover2());
ASSERT_NO_THROW(dis2 = PktCaptures::captureRelayedDiscover2());
ASSERT_NO_THROW(dis2->unpack());
srv.classifyPacket(dis2);
......
......@@ -335,21 +335,6 @@ public:
/// @param expected_clientid expected value of client-id
void checkClientId(const Pkt4Ptr& rsp, const OptionPtr& expected_clientid);
/// @brief sets default fields in a captured packet
///
/// Sets UDP ports, addresses and interface.
///
/// @param pkt packet to have default fields set
void captureSetDefaultFields(const Pkt4Ptr& pkt);
/// @brief returns captured DISCOVER that went through a relay
///
/// See method code for a detailed explanation. This is a discover from
/// docsis3.0 device (Cable Modem)
///
/// @return relayed DISCOVER
Pkt4Ptr captureRelayedDiscover();
/// @brief Create packet from output buffer of another packet.
///
/// This function creates a packet using an output buffer from another
......@@ -373,21 +358,8 @@ public:
/// @return assertion result indicating if a function completed with
/// success or failure.
static ::testing::AssertionResult
createPacketFromBuffer(const Pkt4Ptr& src_pkt,
Pkt4Ptr& dst_pkt);
/// @brief returns captured DISCOVER that went through a relay
///
/// See method code for a detailed explanation. This is a discover from
/// eRouter1.0 device (CPE device integrated with cable modem)
///
/// @return relayed DISCOVER
Pkt4Ptr captureRelayedDiscover2();
/// @brief generates a DHCPv4 packet based on provided hex string
///
/// @return created packet
Pkt4Ptr packetFromCapture(const std::string& hex_string);
createPacketFromBuffer(const isc::dhcp::Pkt4Ptr& src_pkt,
isc::dhcp::Pkt4Ptr& dst_pkt);
/// @brief Tests if Discover or Request message is processed correctly
///
......
......@@ -79,7 +79,6 @@ dhcp6_unittests_SOURCES += dhcp6_test_utils.cc dhcp6_test_utils.h
dhcp6_unittests_SOURCES += d2_unittest.cc d2_unittest.h
dhcp6_unittests_SOURCES += marker_file.cc
dhcp6_unittests_SOURCES += ctrl_dhcp6_srv_unittest.cc
dhcp6_unittests_SOURCES += wireshark.cc
dhcp6_unittests_SOURCES += dhcp6_client.cc dhcp6_client.h
dhcp6_unittests_SOURCES += rebind_unittest.cc
dhcp6_unittests_SOURCES += sarr_unittest.cc
......
// Copyright (C) 2011-2014 Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2011-2015 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
......@@ -40,6 +40,8 @@
#include <hooks/server_hooks.h>
#include <dhcp6/tests/dhcp6_test_utils.h>
#include <dhcp/tests/pkt_captures.h>
#include <config/ccsession.h>
#include <boost/pointer_cast.hpp>
#include <boost/scoped_ptr.hpp>
#include <gtest/gtest.h>
......@@ -50,7 +52,6 @@
using namespace isc;
using namespace isc::data;
using namespace isc::config;
using namespace isc::test;
using namespace isc::asiolink;
using namespace isc::dhcp;
......@@ -1443,7 +1444,7 @@ TEST_F(Dhcpv6SrvTest, portsDirectTraffic) {
NakedDhcpv6Srv srv(0);
// Let's create a simple SOLICIT
Pkt6Ptr sol = captureSimpleSolicit();
Pkt6Ptr sol = PktCaptures::captureSimpleSolicit();
// Simulate that we have received that traffic
srv.fakeReceive(sol);
......@@ -1468,7 +1469,7 @@ TEST_F(Dhcpv6SrvTest, portsRelayedTraffic) {
NakedDhcpv6Srv srv(0);
// Let's create a simple SOLICIT
Pkt6Ptr sol = captureRelayedSolicit();
Pkt6Ptr sol = PktCaptures::captureRelayedSolicit();
// Simulate that we have received that traffic
srv.fakeReceive(sol);
......@@ -1495,7 +1496,7 @@ TEST_F(Dhcpv6SrvTest, docsisTraffic) {
NakedDhcpv6Srv srv(0);
// Let's get a traffic capture from DOCSIS3.0 modem
Pkt6Ptr sol = captureDocsisRelayedSolicit();
Pkt6Ptr sol = PktCaptures::captureDocsisRelayedSolicit();
// Simulate that we have received that traffic
srv.fakeReceive(sol);
......@@ -1515,7 +1516,7 @@ TEST_F(Dhcpv6SrvTest, docsisTraffic) {
TEST_F(Dhcpv6SrvTest, docsisVendorOptionsParse) {
// Let's get a traffic capture from DOCSIS3.0 modem
Pkt6Ptr sol = captureDocsisRelayedSolicit();
Pkt6Ptr sol = PktCaptures::captureDocsisRelayedSolicit();
EXPECT_NO_THROW(sol->unpack());
// Check if the packet contain
......@@ -1550,7 +1551,7 @@ TEST_F(Dhcpv6SrvTest, docsisVendorORO) {
NakedDhcpv6Srv srv(0);
// Let's get a traffic capture from DOCSIS3.0 modem
Pkt6Ptr sol = captureDocsisRelayedSolicit();
Pkt6Ptr sol = PktCaptures::captureDocsisRelayedSolicit();
ASSERT_NO_THROW(sol->unpack());
// Check if the packet contains vendor options option
......@@ -1698,13 +1699,13 @@ TEST_F(Dhcpv6SrvTest, vendorOptionsDocsisDefinitions) {
// This should fail (missing option definition)
EXPECT_NO_THROW(x = configureDhcp6Server(srv, json_bogus));
ASSERT_TRUE(x);
comment_ = parseAnswer(rcode_, x);
comment_ = isc::config::parseAnswer(rcode_, x);
ASSERT_EQ(1, rcode_);
// This should work (option definition present)
EXPECT_NO_THROW(x = configureDhcp6Server(srv, json_valid));
ASSERT_TRUE(x);
comment_ = parseAnswer(rcode_, x);
comment_ = isc::config::parseAnswer(rcode_, x);
ASSERT_EQ(0, rcode_);
}
......@@ -1789,7 +1790,7 @@ TEST_F(Dhcpv6SrvTest, clientClassification) {
// Let's create a relayed SOLICIT. This particular relayed SOLICIT has
// vendor-class set to docsis3.0
Pkt6Ptr sol1;
ASSERT_NO_THROW(sol1 = captureDocsisRelayedSolicit());
ASSERT_NO_THROW(sol1 = PktCaptures::captureDocsisRelayedSolicit());
ASSERT_NO_THROW(sol1->unpack());
srv.classifyPacket(sol1);
......@@ -1801,7 +1802,7 @@ TEST_F(Dhcpv6SrvTest, clientClassification) {
// Let's get a relayed SOLICIT. This particular relayed SOLICIT has
// vendor-class set to eRouter1.0
Pkt6Ptr sol2;
ASSERT_NO_THROW(sol2 = captureeRouterRelayedSolicit());
ASSERT_NO_THROW(sol2 = PktCaptures::captureeRouterRelayedSolicit());
ASSERT_NO_THROW(sol2->unpack());
srv.classifyPacket(sol2);
......@@ -1902,7 +1903,7 @@ TEST_F(Dhcpv6SrvTest, cableLabsShortVendorClass) {
NakedDhcpv6Srv srv(0);
// Create a simple Solicit with the 4-byte long vendor class option.
Pkt6Ptr sol = captureCableLabsShortVendorClass();
Pkt6Ptr sol = PktCaptures::captureCableLabsShortVendorClass();
// Simulate that we have received that traffic
srv.fakeReceive(sol);
......
......@@ -15,6 +15,7 @@
#include <gtest/gtest.h>
#include <dhcp6/tests/dhcp6_test_utils.h>
#include <dhcp6/json_config_parser.h>
#include <config/ccsession.h>
using namespace isc::data;
using namespace isc::dhcp;
......@@ -603,7 +604,7 @@ Dhcpv6SrvTest::configure(const std::string& config, NakedDhcpv6Srv& srv) {
EXPECT_NO_THROW(status = configureDhcp6Server(srv, json));
ASSERT_TRUE(status);
int rcode;
ConstElementPtr comment = config::parseAnswer(rcode, status);
ConstElementPtr comment = isc::config::parseAnswer(rcode, status);
ASSERT_EQ(0, rcode);
CfgMgr::instance().commit();
......
......@@ -33,7 +33,6 @@
#include <dhcpsrv/lease_mgr_factory.h>
#include <dhcp6/dhcp6_srv.h>
#include <hooks/hooks_manager.h>
#include <config/ccsession.h>
#include <list>
......@@ -521,22 +520,6 @@ public:
testReleaseReject(isc::dhcp::Lease::Type type,
const isc::asiolink::IOAddress& addr);
// 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
isc::dhcp::Pkt6Ptr captureSimpleSolicit();
isc::dhcp::Pkt6Ptr captureRelayedSolicit();
isc::dhcp::Pkt6Ptr captureDocsisRelayedSolicit();
isc::dhcp::Pkt6Ptr captureeRouterRelayedSolicit();
isc::dhcp::Pkt6Ptr captureCableLabsShortVendorClass();
/// @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 isc::dhcp::Pkt6Ptr& pkt);
/// A subnet used in most tests
isc::dhcp::Subnet6Ptr subnet_;
......
// Copyright (C) 2013-2014 Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2013-2015 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
......@@ -28,6 +28,8 @@
#include <hooks/server_hooks.h>
#include <dhcp6/tests/dhcp6_test_utils.h>
#include <dhcp/tests/pkt_captures.h>
#include <config/ccsession.h>
#include <boost/scoped_ptr.hpp>
#include <gtest/gtest.h>
#include <unistd.h>
......@@ -37,7 +39,6 @@
using namespace isc;
using namespace isc::data;
using namespace isc::config;
using namespace isc::test;
using namespace isc::asiolink;
using namespace isc::dhcp;
......@@ -524,7 +525,7 @@ TEST_F(HooksDhcpv6SrvTest, simple_buffer6_receive) {
"buffer6_receive", buffer6_receive_callout));
// Let's create a simple SOLICIT
Pkt6Ptr sol = Pkt6Ptr(captureSimpleSolicit());
Pkt6Ptr sol = Pkt6Ptr(PktCaptures::captureSimpleSolicit());
// Simulate that we have received that traffic
srv_->fakeReceive(sol);
......@@ -557,7 +558,7 @@ TEST_F(HooksDhcpv6SrvTest, valueChange_buffer6_receive) {
"buffer6_receive", buffer6_receive_change_clientid));
// Let's create a simple SOLICIT
Pkt6Ptr sol = Pkt6Ptr(captureSimpleSolicit());
Pkt6Ptr sol = Pkt6Ptr(PktCaptures::captureSimpleSolicit());
// Simulate that we have received that traffic
srv_->fakeReceive(sol);
......@@ -594,7 +595,7 @@ TEST_F(HooksDhcpv6SrvTest, deleteClientId_buffer6_receive) {
"buffer6_receive", buffer6_receive_delete_clientid));
// Let's create a simple SOLICIT
Pkt6Ptr sol = Pkt6Ptr(captureSimpleSolicit());
Pkt6Ptr sol = Pkt6Ptr(PktCaptures::captureSimpleSolicit());
// Simulate that we have received that traffic
srv_->fakeReceive(sol);
......@@ -618,7 +619,7 @@ TEST_F(HooksDhcpv6SrvTest, skip_buffer6_receive) {
"buffer6_receive", buffer6_receive_skip));
// Let's create a simple SOLICIT
Pkt6Ptr sol = Pkt6Ptr(captureSimpleSolicit());
Pkt6Ptr sol = Pkt6Ptr(PktCaptures::captureSimpleSolicit());
// Simulate that we have received that traffic
srv_->fakeReceive(sol);
......@@ -645,7 +646,7 @@ TEST_F(HooksDhcpv6SrvTest, simple_pkt6_receive) {
"pkt6_receive", pkt6_receive_callout));
// Let's create a simple SOLICIT
Pkt6Ptr sol = Pkt6Ptr(captureSimpleSolicit());
Pkt6Ptr sol = Pkt6Ptr(PktCaptures::captureSimpleSolicit());
// Simulate that we have received that traffic
srv_->fakeReceive(sol);
......@@ -678,7 +679,7 @@ TEST_F(HooksDhcpv6SrvTest, valueChange_pkt6_receive) {
"pkt6_receive", pkt6_receive_change_clientid));
// Let's create a simple SOLICIT
Pkt6Ptr sol = Pkt6Ptr(captureSimpleSolicit());
Pkt6Ptr sol = Pkt6Ptr(PktCaptures::captureSimpleSolicit());
// Simulate that we have received that traffic
srv_->fakeReceive(sol);
......@@ -714,7 +715,7 @@ TEST_F(HooksDhcpv6SrvTest, deleteClientId_pkt6_receive) {
"pkt6_receive", pkt6_receive_delete_clientid));
// Let's create a simple SOLICIT
Pkt6Ptr sol = Pkt6Ptr(captureSimpleSolicit());
Pkt6Ptr sol = Pkt6Ptr(PktCaptures::captureSimpleSolicit());
// Simulate that we have received that traffic
srv_->fakeReceive(sol);
......@@ -738,7 +739,7 @@ TEST_F(HooksDhcpv6SrvTest, skip_pkt6_receive) {
"pkt6_receive", pkt6_receive_skip));
// Let's create a simple SOLICIT
Pkt6Ptr sol = Pkt6Ptr(captureSimpleSolicit());
Pkt6Ptr sol = Pkt6Ptr(PktCaptures::captureSimpleSolicit());
// Simulate that we have received that traffic
srv_->fakeReceive(sol);
......@@ -763,7 +764,7 @@ TEST_F(HooksDhcpv6SrvTest, simple_pkt6_send) {
"pkt6_send", pkt6_send_callout));
// Let's create a simple SOLICIT
Pkt6Ptr sol = Pkt6Ptr(captureSimpleSolicit());
Pkt6Ptr sol = Pkt6Ptr(PktCaptures::captureSimpleSolicit());
// Simulate that we have received that traffic
srv_->fakeReceive(sol);
......@@ -799,7 +800,7 @@ TEST_F(HooksDhcpv6SrvTest, valueChange_pkt6_send) {
"pkt6_send", pkt6_send_change_serverid));
// Let's create a simple SOLICIT
Pkt6Ptr sol = Pkt6Ptr(captureSimpleSolicit());
Pkt6Ptr sol = Pkt6Ptr(PktCaptures::captureSimpleSolicit());
// Simulate that we have received that traffic
srv_->fakeReceive(sol);
......@@ -836,7 +837,7 @@ TEST_F(HooksDhcpv6SrvTest, deleteServerId_pkt6_send) {
"pkt6_send", pkt6_send_delete_serverid));
// Let's create a simple SOLICIT
Pkt6Ptr sol = Pkt6Ptr(captureSimpleSolicit());
Pkt6Ptr sol = Pkt6Ptr(PktCaptures::captureSimpleSolicit());
// Simulate that we have received that traffic
srv_->fakeReceive(sol);
......@@ -867,7 +868,7 @@ TEST_F(HooksDhcpv6SrvTest, skip_pkt6_send) {
"pkt6_send", pkt6_send_skip));
// Let's create a simple REQUEST
Pkt6Ptr sol = Pkt6Ptr(captureSimpleSolicit());
Pkt6Ptr sol = Pkt6Ptr(PktCaptures::captureSimpleSolicit());
// Simulate that we have received that traffic
srv_->fakeReceive(sol);
......@@ -919,7 +920,7 @@ TEST_F(HooksDhcpv6SrvTest, subnet6_select) {
// Configure the server and make sure the config is accepted
EXPECT_NO_THROW(status = configureDhcp6Server(*srv_, json));
ASSERT_TRUE(status);
comment_ = parseAnswer(rcode_, status);
comment_ = isc::config::parseAnswer(rcode_, status);
ASSERT_EQ(0, rcode_);
CfgMgr::instance().commit();
......@@ -990,7 +991,7 @@ TEST_F(HooksDhcpv6SrvTest, subnet_select_change) {
// Configure the server and make sure the config is accepted
EXPECT_NO_THROW(status = configureDhcp6Server(*srv_, json));
ASSERT_TRUE(status);
comment_ = parseAnswer(rcode_, status);
comment_ = isc::config::parseAnswer(rcode_, status);
ASSERT_EQ(0, rcode_);
CfgMgr::instance().commit();
......
/*
* Copyright (c) 2004-2011, 2014 by Internet Systems Consortium, Inc. ("ISC")
* Copyright (c) 2004-2011, 2014-2015 by Internet Systems Consortium, Inc. ("ISC")
* Copyright (c) 1995-2003 by Internet Software Consortium
*
* Permission to use, copy, modify, and distribute this software for any
......@@ -54,6 +54,10 @@ static const uint16_t BOOTP_BROADCAST = 32768L;
/* Possible values for hardware type (htype) field... */
enum HType {
HTYPE_ETHER = 1, /* Ethernet 10Mbps */
HTYPE_DOCSIS = 1, /* The traffic captures we have from cable modems as well
as this list by IANA: http://www.iana.org/assignments/
arp-parameters/arp-parameters.xhtml suggest that
Ethernet (1) should be used in DOCSIS environment. */
HTYPE_IEEE802 = 6, /* IEEE 802.2 Token Ring */
HTYPE_FDDI = 8 /* FDDI */
/// TODO Add infiniband here
......
......@@ -42,9 +42,14 @@ const int DOCSIS3_V4_DEFS_SIZE = sizeof(DOCSIS3_V4_DEFS) / sizeof(OptionDefPara
#define DOCSIS3_V6_TFTP_SERVERS 32
#define DOCSIS3_V6_CONFIG_FILE 33
#define DOCSIS3_V6_SYSLOG_SERVERS 34
#define DOCSIS3_V6_DEVICE_ID 36
#define DOCSIS3_V6_TIME_SERVERS 37
#define DOCSIS3_V6_TIME_OFFSET 38
// The following DOCSIS3 options are inserted by the CMTS (which acts as
// a relay agent)
#define DOCSIS3_V6_CMTS_CM_MAC 1026
/// @brief Definitions of standard DHCPv6 options.
const OptionDefParams DOCSIS3_V6_DEFS[] = {
{ "oro", DOCSIS3_V6_ORO, OPT_UINT16_TYPE, true, NO_RECORD_DEF, "" },
......@@ -54,7 +59,9 @@ const OptionDefParams DOCSIS3_V6_DEFS[] = {
{ "time-servers", DOCSIS3_V6_TIME_SERVERS, OPT_IPV6_ADDRESS_TYPE, true, NO_RECORD_DEF, "" },
{ "config-file", DOCSIS3_V6_CONFIG_FILE, OPT_STRING_TYPE, false, NO_RECORD_DEF, "" },
{ "syslog-servers", DOCSIS3_V6_SYSLOG_SERVERS, OPT_IPV6_ADDRESS_TYPE, true, NO_RECORD_DEF, "" },
{ "time-offset", DOCSIS3_V6_TIME_OFFSET, OPT_INT32_TYPE, false, NO_RECORD_DEF, "" }
{ "device-id", DOCSIS3_V6_DEVICE_ID, OPT_BINARY_TYPE, false, NO_RECORD_DEF, "" },
{ "time-offset", DOCSIS3_V6_TIME_OFFSET, OPT_INT32_TYPE, false, NO_RECORD_DEF, "" },
{ "cmts-cm-mac", DOCSIS3_V6_CMTS_CM_MAC, OPT_BINARY_TYPE, false, NO_RECORD_DEF, "" }
// @todo add definitions for all remaning options.
};
......
......@@ -35,7 +35,8 @@ const uint32_t HWAddr::HWADDR_SOURCE_IPV6_LINK_LOCAL = 0x00000004;
const uint32_t HWAddr::HWADDR_SOURCE_CLIENT_ADDR_RELAY_OPTION = 0x00000008;
const uint32_t HWAddr::HWADDR_SOURCE_REMOTE_ID = 0x00000010;
const uint32_t HWAddr::HWADDR_SOURCE_SUBSCRIBER_ID = 0x00000020;
const uint32_t HWAddr::HWADDR_SOURCE_DOCSIS = 0x00000040;
const uint32_t HWAddr::HWADDR_SOURCE_DOCSIS_CMTS = 0x00000040;
const uint32_t HWAddr::HWADDR_SOURCE_DOCSIS_MODEM = 0x00000080;
HWAddr::HWAddr()
:htype_(HTYPE_ETHER), source_(0) {
......
......@@ -76,8 +76,15 @@ public:
/// A CMTS (acting as DHCP relay agent) that supports DOCSIS standard
/// can insert DOCSIS options that contain client's MAC address.
/// Client in this context would be a cable modem.
static const uint32_t HWADDR_SOURCE_DOCSIS;
/// This specific option is suboption 1026 in vendor-class option with
/// vendor-id=4491. Client in this context would be a cable modem.
static const uint32_t HWADDR_SOURCE_DOCSIS_CMTS;
/// A cable modem (acting as DHCP client) that supports DOCSIS standard
/// can insert DOCSIS options that contain client's MAC address.
/// This specific option is suboption 36 in vendor-class option with
/// vendor-id=4491.
static const uint32_t HWADDR_SOURCE_DOCSIS_MODEM;
/// @}
......
// Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2014-2015 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
......@@ -129,6 +129,8 @@ HWAddrPtr
Pkt::getMAC(uint32_t hw_addr_src) {
HWAddrPtr mac;
/// @todo: Implement an array of method pointers instead of set of ifs
// Method 1: from raw sockets.
if (hw_addr_src & HWAddr::HWADDR_SOURCE_RAW) {
mac = getRemoteHWAddr();
......@@ -182,8 +184,28 @@ Pkt::getMAC(uint32_t hw_addr_src) {
// Method 6: From subscriber-id option inserted by a relay
// Method 7: From docsis options
if (hw_addr_src & HWAddr::HWADDR_SOURCE_DOCSIS_CMTS) {
mac = getMACFromDocsisCMTS();
if (mac) {
return (mac);
} else if (hw_addr_src == HWAddr::HWADDR_SOURCE_DOCSIS_CMTS) {
// If we're interested only in CMTS options as a source of that
// info, there's no point in trying other options.
return (HWAddrPtr());
}
}
/// @todo: add other MAC acquisition methods here
// Method 8: From docsis options
if (hw_addr_src & HWAddr::HWADDR_SOURCE_DOCSIS_MODEM) {
mac = getMACFromDocsisModem();
if (mac) {
return (mac);
} else if (hw_addr_src == HWAddr::HWADDR_SOURCE_DOCSIS_MODEM) {
// If we're interested only in CMTS options as a source of that
// info, there's no point in trying other options.
return (HWAddrPtr());
}
}
// Ok, none of the methods were suitable. Return NULL.
return (HWAddrPtr());
......
......@@ -523,6 +523,32 @@ protected:
HWAddrPtr
getMACFromIPv6(const isc::asiolink::IOAddress& addr);
/// @brief Attempts to extract MAC/Hardware address from DOCSIS options
/// inserted by the modem itself.
///
/// This is a generic mechanism for extracting hardware address from the
/// DOCSIS options.
///
/// @note This is a pure virtual method and must be implemented in
/// the derived classes. The @c Pkt6 class have respective implementation.
/// This method is currently not implemented in DHCPv4.
///
/// @return hardware address (if necessary DOCSIS suboptions are present)
virtual HWAddrPtr getMACFromDocsisModem() = 0;
/// @brief Attempts to extract MAC/Hardware address from DOCSIS options
/// inserted by the CMTS (the relay agent)
///
/// This is a generic mechanism for extracting hardware address from the
/// DOCSIS options.
///
/// @note This is a pure virtual method and must be implemented in
/// the derived classes. The @c Pkt6 class have respective implementation.
/// This method is currently not implemented in DHCPv4.
///
/// @return hardware address (if necessary DOCSIS suboptions are present)
virtual HWAddrPtr getMACFromDocsisCMTS() = 0;
/// Transaction-id (32 bits for v4, 24 bits for v6)
uint32_t transid_;
......
......@@ -414,6 +414,17 @@ protected:
return (HWAddrPtr());
}
/// @brief No-op
///
/// This is a DHCPv4 version of the function that attempts to extract
/// MAC address from the options inserted by a cable modem. It is currently
/// not implemented for v4.
///
/// @return always NULL