Commit 2662ac5f authored by Tomek Mrugalski's avatar Tomek Mrugalski 🛰

[3554] Changes after review:

 - Moved MAC operations to a new CfgMACSource class
 - Moved macros to HWaddr class
 - Added several unit-tests for MAC sources
 - MAC extraction code moved to separate function in Dhcpv6Srv
parent 33a90f02
......@@ -1184,6 +1184,21 @@ Dhcpv6Srv::createRemovalNameChangeRequest(const Lease6Ptr& lease) {
CfgMgr::instance().getD2ClientMgr().sendRequest(ncr);
}
HWAddrPtr
Dhcpv6Srv::getMAC(const Pkt6Ptr& pkt) {
CfgMACSources mac_sources = CfgMgr::instance().getCurrentCfg()->
getMACSources().get();
HWAddrPtr hwaddr;
for (CfgMACSources::const_iterator it = mac_sources.begin();
it != mac_sources.end(); ++it) {
hwaddr = pkt->getMAC(*it);
if (hwaddr) {
return (hwaddr);
}
}
return (hwaddr);
}
OptionPtr
Dhcpv6Srv::assignIA_NA(const Subnet6Ptr& subnet, const DuidPtr& duid,
const Pkt6Ptr& query, const Pkt6Ptr& answer,
......@@ -1255,16 +1270,7 @@ Dhcpv6Srv::assignIA_NA(const Subnet6Ptr& subnet, const DuidPtr& duid,
// Attempt to get MAC address using configured mechanisms.
// It's ok if there response is NULL. Hardware address is optional in Lease6.
std::vector<uint32_t> mac_sources = CfgMgr::instance().getCurrentCfg()->
getMACSources();
HWAddrPtr hwaddr;
for (std::vector<uint32_t>::const_iterator it = mac_sources.begin();
it != mac_sources.end(); ++it) {
hwaddr = query->getMAC(*it);
if (hwaddr) {
break;
}
}
HWAddrPtr hwaddr = getMAC(query);
// Use allocation engine to pick a lease for this client. Allocation engine
// will try to honour the hint, but it is just a hint - some other address
......@@ -1384,8 +1390,7 @@ Dhcpv6Srv::assignIA_PD(const Subnet6Ptr& subnet, const DuidPtr& duid,
// Attempt to get MAC address using any of available mechanisms.
// It's ok if there response is NULL. Hardware address is optional in Lease6
/// @todo: Make this configurable after trac 3554 is done.
HWAddrPtr hwaddr = query->getMAC(Pkt::HWADDR_SOURCE_ANY);
HWAddrPtr hwaddr = getMAC(query);
LOG_DEBUG(dhcp6_logger, DBG_DHCP6_DETAIL, DHCP6_PROCESS_IA_PD_REQUEST)
.arg(duid ? duid->toText() : "(no-duid)").arg(ia->getIAID())
......@@ -1577,6 +1582,9 @@ Dhcpv6Srv::extendIA_NA(const Subnet6Ptr& subnet, const DuidPtr& duid,
lease->fqdn_fwd_ = do_fwd;
lease->fqdn_rev_ = do_rev;
/// @todo: check if hardware address has changed since last update.
/// And modify lease->hwaddr_ if it did.
ia_rsp->setT1(subnet->getT1());
ia_rsp->setT2(subnet->getT2());
......
......@@ -597,6 +597,15 @@ protected:
void classifyPacket(const Pkt6Ptr& pkt);
/// @brief Attempts to get a MAC/hardware address using configred sources
///
/// Tries to extract MAC/hardware address information from the packet
/// using MAC sources configured in 'mac-sources' directive.
///
/// @param pkt will try to exact MAC address from this packet
/// @return HWaddr pointer (or NULL if configured methods fail)
HWAddrPtr getMAC(const Pkt6Ptr& pkt);
/// @brief this is a prefix added to the contend of vendor-class option
///
/// If incoming packet has a vendor class option, its content is
......
......@@ -3628,14 +3628,48 @@ TEST_F(Dhcp6ParserTest, reservationBogus) {
}
/// The goal of this test is to verify that configuration can include
/// MAC/Hardware sources.
/// MAC/Hardware sources. This test also checks if the aliases are
/// handled properly (rfc6939 = client-addr-relay, rfc4649 = remote-id,
/// rfc4580 = subscriber-id).
TEST_F(Dhcp6ParserTest, macSources) {
ConstElementPtr status;
EXPECT_NO_THROW(status = configureDhcp6Server(srv_,
Element::fromJSON("{ \"interfaces\": [ \"*\" ],"
"\"mac-sources\": [ \"rfc6939\", \"rfc4649\", \"rfc4580\","
"\"client-link-addr-option\", \"remote-id\", \"subscriber-id\"],"
"\"preferred-lifetime\": 3000,"
"\"rebind-timer\": 2000, "
"\"renew-timer\": 1000, "
"\"subnet6\": [ ], "
"\"valid-lifetime\": 4000 }")));
// returned value should be 0 (success)
checkResult(status, 0);
CfgMACSources mac_sources = CfgMgr::instance().getStagingCfg()->getMACSources().get();
ASSERT_EQ(6, mac_sources.size());
// Let's check the aliases. They should be recognized to their base methods.
EXPECT_EQ(HWAddr::HWADDR_SOURCE_CLIENT_ADDR_RELAY_OPTION, mac_sources[0]);
EXPECT_EQ(HWAddr::HWADDR_SOURCE_REMOTE_ID, mac_sources[1]);
EXPECT_EQ(HWAddr::HWADDR_SOURCE_SUBSCRIBER_ID, mac_sources[2]);
// Let's check if the actual methods are recognized properly.
EXPECT_EQ(HWAddr::HWADDR_SOURCE_CLIENT_ADDR_RELAY_OPTION, mac_sources[3]);
EXPECT_EQ(HWAddr::HWADDR_SOURCE_REMOTE_ID, mac_sources[4]);
EXPECT_EQ(HWAddr::HWADDR_SOURCE_SUBSCRIBER_ID, mac_sources[5]);
}
/// The goal of this test is to verify that MAC sources configuration can be
/// empty.
TEST_F(Dhcp6ParserTest, macSourcesEmpty) {
ConstElementPtr status;
EXPECT_NO_THROW(status = configureDhcp6Server(srv_,
Element::fromJSON("{ \"interfaces\": [ \"*\" ],"
"\"mac-sources\": [ \"rfc6939\", \"rfc4649\", \"rfc4580\" ],"
"\"mac-sources\": [ ],"
"\"preferred-lifetime\": 3000,"
"\"rebind-timer\": 2000, "
"\"renew-timer\": 1000, "
......@@ -3645,11 +3679,27 @@ TEST_F(Dhcp6ParserTest, macSources) {
// returned value should be 0 (success)
checkResult(status, 0);
vector<uint32_t> mac_sources = CfgMgr::instance().getStagingCfg()->getMACSources();
ASSERT_EQ(3, mac_sources.size());
EXPECT_EQ(Pkt::HWADDR_SOURCE_CLIENT_ADDR_RELAY_OPTION, mac_sources[0]);
EXPECT_EQ(Pkt::HWADDR_SOURCE_REMOTE_ID, mac_sources[1]);
EXPECT_EQ(Pkt::HWADDR_SOURCE_SUBSCRIBER_ID, mac_sources[2]);
CfgMACSources mac_sources = CfgMgr::instance().getStagingCfg()->getMACSources().get();
EXPECT_EQ(0, mac_sources.size());
}
/// The goal of this test is to verify that MAC sources configuration can
/// only use valid parameters.
TEST_F(Dhcp6ParserTest, macSourcesBogus) {
ConstElementPtr status;
EXPECT_NO_THROW(status = configureDhcp6Server(srv_,
Element::fromJSON("{ \"interfaces\": [ \"*\" ],"
"\"mac-sources\": [ \"from-wire\" ],"
"\"preferred-lifetime\": 3000,"
"\"rebind-timer\": 2000, "
"\"renew-timer\": 1000, "
"\"subnet6\": [ ], "
"\"valid-lifetime\": 4000 }")));
// returned value should be 1 (failure)
checkResult(status, 1);
}
};
......@@ -63,7 +63,7 @@ Dhcp6Client::applyRcvdConfiguration(const Pkt6Ptr& reply) {
Opts opts = reply->options_;
// Let's try to get a MAC
HWAddrPtr hwaddr = reply->getMAC(Pkt::HWADDR_SOURCE_ANY);
HWAddrPtr hwaddr = reply->getMAC(HWAddr::HWADDR_SOURCE_ANY);
// Set the global status code to default: success and not received.
config_.resetGlobalStatusCode();
......
......@@ -27,6 +27,16 @@
namespace isc {
namespace dhcp {
const uint32_t HWAddr::HWADDR_SOURCE_ANY = 0xffffffff;
const uint32_t HWAddr::HWADDR_SOURCE_UNKNOWN = 0x00000000;
const uint32_t HWAddr::HWADDR_SOURCE_RAW = 0x00000001;
const uint32_t HWAddr::HWADDR_SOURCE_DUID = 0x00000002;
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;
HWAddr::HWAddr()
:htype_(HTYPE_ETHER), source_(0) {
}
......
......@@ -34,6 +34,53 @@ public:
/// @brief Maximum size of a hardware address.
static const size_t MAX_HWADDR_LEN = 20;
/// @defgroup hw_sources Specifies where a given MAC/hardware address was
/// obtained.
///
/// @brief The list covers all possible MAC/hw address sources.
///
/// @{
/// Not really a type, only used in getMAC() calls.
static const uint32_t HWADDR_SOURCE_ANY;
/// Used when actual origin is not known, e.g. when reading from a
/// lease database that didn't store that information.
static const uint32_t HWADDR_SOURCE_UNKNOWN;
/// Obtained first hand from raw socket (100% reliable).
static const uint32_t HWADDR_SOURCE_RAW;
/// Extracted from DUID-LL or DUID-LLT (not 100% reliable as the client
/// can send fake DUID).
static const uint32_t HWADDR_SOURCE_DUID;
/// Extracted from IPv6 link-local address. Not 100% reliable, as the
/// client can use different IID other than EUI-64, e.g. Windows supports
/// RFC4941 and uses random values instead of EUI-64.
static const uint32_t HWADDR_SOURCE_IPV6_LINK_LOCAL;
/// Get it from RFC6939 option. (A relay agent can insert client link layer
/// address option). Note that a skilled attacker can fake that by sending
/// his request relayed, so the legitimate relay will think it's a second
/// relay.
static const uint32_t HWADDR_SOURCE_CLIENT_ADDR_RELAY_OPTION;
/// A relay can insert remote-id. In some deployments it contains a MAC
/// address (RFC4649).
static const uint32_t HWADDR_SOURCE_REMOTE_ID;
/// A relay can insert a subscriber-id option. In some deployments it
/// contains a MAC address (RFC4580).
static const uint32_t HWADDR_SOURCE_SUBSCRIBER_ID;
/// 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;
/// @}
/// @brief default constructor
HWAddr();
......
......@@ -15,21 +15,12 @@
#include <utility>
#include <dhcp/pkt.h>
#include <dhcp/iface_mgr.h>
#include <dhcp/hwaddr.h>
#include <vector>
namespace isc {
namespace dhcp {
const uint32_t Pkt::HWADDR_SOURCE_ANY = 0xffffffff;
const uint32_t Pkt::HWADDR_SOURCE_UNKNOWN = 0x00000000;
const uint32_t Pkt::HWADDR_SOURCE_RAW = 0x00000001;
const uint32_t Pkt::HWADDR_SOURCE_DUID = 0x00000002;
const uint32_t Pkt::HWADDR_SOURCE_IPV6_LINK_LOCAL = 0x00000004;
const uint32_t Pkt::HWADDR_SOURCE_CLIENT_ADDR_RELAY_OPTION = 0x00000008;
const uint32_t Pkt::HWADDR_SOURCE_REMOTE_ID = 0x00000010;
const uint32_t Pkt::HWADDR_SOURCE_SUBSCRIBER_ID = 0x00000020;
const uint32_t Pkt::HWADDR_SOURCE_DOCSIS = 0x00000040;
Pkt::Pkt(uint32_t transid, const isc::asiolink::IOAddress& local_addr,
const isc::asiolink::IOAddress& remote_addr, uint16_t local_port,
uint16_t remote_port)
......@@ -139,11 +130,11 @@ Pkt::getMAC(uint32_t hw_addr_src) {
HWAddrPtr mac;
// Method 1: from raw sockets.
if (hw_addr_src & HWADDR_SOURCE_RAW) {
if (hw_addr_src & HWAddr::HWADDR_SOURCE_RAW) {
mac = getRemoteHWAddr();
if (mac) {
return (mac);
} else if (hw_addr_src == HWADDR_SOURCE_RAW) {
} else if (hw_addr_src == HWAddr::HWADDR_SOURCE_RAW) {
// If we're interested only in RAW sockets as source of that info,
// there's no point in trying other options.
return (HWAddrPtr());
......@@ -153,11 +144,11 @@ Pkt::getMAC(uint32_t hw_addr_src) {
// Method 2: Extracted from DUID-LLT or DUID-LL
// Method 3: Extracted from source IPv6 link-local address
if (hw_addr_src & HWADDR_SOURCE_IPV6_LINK_LOCAL) {
if (hw_addr_src & HWAddr::HWADDR_SOURCE_IPV6_LINK_LOCAL) {
mac = getMACFromSrcLinkLocalAddr();
if (mac) {
return (mac);
} else if (hw_addr_src == HWADDR_SOURCE_IPV6_LINK_LOCAL) {
} else if (hw_addr_src == HWAddr::HWADDR_SOURCE_IPV6_LINK_LOCAL) {
// If we're interested only in link-local addr as source of that
// info, there's no point in trying other options.
return (HWAddrPtr());
......@@ -165,11 +156,11 @@ Pkt::getMAC(uint32_t hw_addr_src) {
}
// Method 4: From client link-layer address option inserted by a relay
if (hw_addr_src & HWADDR_SOURCE_CLIENT_ADDR_RELAY_OPTION) {
if (hw_addr_src & HWAddr::HWADDR_SOURCE_CLIENT_ADDR_RELAY_OPTION) {
mac = getMACFromIPv6RelayOpt();
if (mac) {
return (mac);
} else if (hw_addr_src == HWADDR_SOURCE_CLIENT_ADDR_RELAY_OPTION) {
} else if (hw_addr_src == HWAddr::HWADDR_SOURCE_CLIENT_ADDR_RELAY_OPTION) {
// If we're interested only in RFC6939 link layer address as source
// of that info, there's no point in trying other options.
return (HWAddrPtr());
......@@ -233,34 +224,5 @@ Pkt::getMACFromIPv6(const isc::asiolink::IOAddress& addr) {
return (HWAddrPtr(new HWAddr(bin, hwtype)));
}
uint32_t Pkt::MACSourceFromText(const std::string& name) {
struct {
const char * name;
uint32_t type;
} sources[] = {
{ "any", Pkt::HWADDR_SOURCE_ANY },
{ "raw", Pkt::HWADDR_SOURCE_RAW },
{ "duid", Pkt::HWADDR_SOURCE_DUID },
{ "ipv6-link-local", Pkt::HWADDR_SOURCE_IPV6_LINK_LOCAL },
{ "client-link-addr-option", Pkt::HWADDR_SOURCE_CLIENT_ADDR_RELAY_OPTION },
{ "rfc6939", Pkt::HWADDR_SOURCE_CLIENT_ADDR_RELAY_OPTION },
{ "remote-id", Pkt::HWADDR_SOURCE_REMOTE_ID },
{ "rfc4649", Pkt::HWADDR_SOURCE_REMOTE_ID },
{ "subscriber-id", Pkt::HWADDR_SOURCE_SUBSCRIBER_ID },
{ "rfc4580", Pkt::HWADDR_SOURCE_SUBSCRIBER_ID },
{ "docsis", Pkt::HWADDR_SOURCE_DOCSIS }
};
for (int i=0; i < sizeof(sources)/sizeof(sources[0]); ++i) {
if (name.compare(sources[i].name) == 0) {
return (sources[i].type);
}
}
isc_throw(BadValue, "Can't convert '" << name << "' to any known MAC source.");
}
};
};
......@@ -37,70 +37,6 @@ namespace dhcp {
/// @note This is abstract class. Please instantiate derived classes
/// such as @c Pkt4 or @c Pkt6.
class Pkt {
public:
/// @defgroup hw_sources Specifies where a given MAC/hardware address was
/// obtained.
///
/// @brief The list covers all possible MAC/hw address sources.
///
/// @{
/// Not really a type, only used in getMAC() calls.
static const uint32_t HWADDR_SOURCE_ANY;
/// Used when actual origin is not known, e.g. when reading from a
/// lease database that didn't store that information.
static const uint32_t HWADDR_SOURCE_UNKNOWN;
/// Obtained first hand from raw socket (100% reliable).
static const uint32_t HWADDR_SOURCE_RAW;
/// Extracted from DUID-LL or DUID-LLT (not 100% reliable as the client
/// can send fake DUID).
static const uint32_t HWADDR_SOURCE_DUID;
/// Extracted from IPv6 link-local address. Not 100% reliable, as the
/// client can use different IID other than EUI-64, e.g. Windows supports
/// RFC4941 and uses random values instead of EUI-64.
static const uint32_t HWADDR_SOURCE_IPV6_LINK_LOCAL;
/// Get it from RFC6939 option. (A relay agent can insert client link layer
/// address option). Note that a skilled attacker can fake that by sending
/// his request relayed, so the legitimate relay will think it's a second
/// relay.
static const uint32_t HWADDR_SOURCE_CLIENT_ADDR_RELAY_OPTION;
/// A relay can insert remote-id. In some deployments it contains a MAC
/// address (RFC4649).
static const uint32_t HWADDR_SOURCE_REMOTE_ID;
/// A relay can insert a subscriber-id option. In some deployments it
/// contains a MAC address (RFC4580).
static const uint32_t HWADDR_SOURCE_SUBSCRIBER_ID;
/// 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;
/// @}
/// @brief Attempts to convert known hardware address sources to uint32_t
///
/// Supported strings are: any => 0xffffffff
/// raw => 0x00000001
/// duid => 0x00000002
/// ipv6-link-local 0x00000004
/// client-link-addr-option, rfc6939 => 0x00000008
/// remote-id, rfc4649 => 0x00000010
/// subscriber-id, rfc4580 => 0x00000020
/// docsis => 0x00000040
///
/// @throw BadValue if specified string is unknown
/// @return bitmask version of a given method
static uint32_t MACSourceFromText(const std::string& name);
protected:
/// @brief Constructor.
......
......@@ -857,8 +857,8 @@ TEST_F(Pkt4Test, getMAC) {
Pkt4 pkt(DHCPOFFER, 1234);
// DHCPv4 packet by default doens't have MAC address specified.
EXPECT_FALSE(pkt.getMAC(Pkt::HWADDR_SOURCE_ANY));
EXPECT_FALSE(pkt.getMAC(Pkt::HWADDR_SOURCE_RAW));
EXPECT_FALSE(pkt.getMAC(HWAddr::HWADDR_SOURCE_ANY));
EXPECT_FALSE(pkt.getMAC(HWAddr::HWADDR_SOURCE_RAW));
// Let's invent a MAC
const uint8_t hw[] = { 2, 4, 6, 8, 10, 12 }; // MAC
......@@ -869,12 +869,12 @@ TEST_F(Pkt4Test, getMAC) {
pkt.setRemoteHWAddr(dummy_hwaddr);
// Now we should be able to get something
ASSERT_TRUE(pkt.getMAC(Pkt::HWADDR_SOURCE_ANY));
ASSERT_TRUE(pkt.getMAC(Pkt::HWADDR_SOURCE_RAW));
ASSERT_TRUE(pkt.getMAC(HWAddr::HWADDR_SOURCE_ANY));
ASSERT_TRUE(pkt.getMAC(HWAddr::HWADDR_SOURCE_RAW));
// Check that the returned MAC is indeed the expected one
ASSERT_TRUE(*dummy_hwaddr == *pkt.getMAC(Pkt::HWADDR_SOURCE_ANY));
ASSERT_TRUE(*dummy_hwaddr == *pkt.getMAC(Pkt::HWADDR_SOURCE_RAW));
ASSERT_TRUE(*dummy_hwaddr == *pkt.getMAC(HWAddr::HWADDR_SOURCE_ANY));
ASSERT_TRUE(*dummy_hwaddr == *pkt.getMAC(HWAddr::HWADDR_SOURCE_RAW));
}
} // end of anonymous namespace
......@@ -883,20 +883,20 @@ TEST_F(Pkt6Test, getMAC) {
Pkt6 pkt(DHCPV6_ADVERTISE, 1234);
// DHCPv6 packet by default doens't have MAC address specified.
EXPECT_FALSE(pkt.getMAC(Pkt::HWADDR_SOURCE_ANY));
EXPECT_FALSE(pkt.getMAC(Pkt::HWADDR_SOURCE_RAW));
EXPECT_FALSE(pkt.getMAC(HWAddr::HWADDR_SOURCE_ANY));
EXPECT_FALSE(pkt.getMAC(HWAddr::HWADDR_SOURCE_RAW));
// We haven't specified source IPv6 address, so this method should
// fail, too
EXPECT_FALSE(pkt.getMAC(Pkt::HWADDR_SOURCE_IPV6_LINK_LOCAL));
EXPECT_FALSE(pkt.getMAC(HWAddr::HWADDR_SOURCE_IPV6_LINK_LOCAL));
// Let's check if setting IPv6 address improves the situation.
IOAddress linklocal_eui64("fe80::204:06ff:fe08:0a0c");
pkt.setRemoteAddr(linklocal_eui64);
EXPECT_TRUE(pkt.getMAC(Pkt::HWADDR_SOURCE_ANY));
EXPECT_TRUE(pkt.getMAC(Pkt::HWADDR_SOURCE_IPV6_LINK_LOCAL));
EXPECT_TRUE(pkt.getMAC(Pkt::HWADDR_SOURCE_IPV6_LINK_LOCAL |
Pkt::HWADDR_SOURCE_RAW));
EXPECT_TRUE(pkt.getMAC(HWAddr::HWADDR_SOURCE_ANY));
EXPECT_TRUE(pkt.getMAC(HWAddr::HWADDR_SOURCE_IPV6_LINK_LOCAL));
EXPECT_TRUE(pkt.getMAC(HWAddr::HWADDR_SOURCE_IPV6_LINK_LOCAL |
HWAddr::HWADDR_SOURCE_RAW));
pkt.setRemoteAddr(IOAddress("::"));
// Let's invent a MAC
......@@ -908,14 +908,14 @@ TEST_F(Pkt6Test, getMAC) {
pkt.setRemoteHWAddr(dummy_hwaddr);
// Now we should be able to get something
ASSERT_TRUE(pkt.getMAC(Pkt::HWADDR_SOURCE_ANY));
ASSERT_TRUE(pkt.getMAC(Pkt::HWADDR_SOURCE_RAW));
EXPECT_TRUE(pkt.getMAC(Pkt::HWADDR_SOURCE_IPV6_LINK_LOCAL |
Pkt::HWADDR_SOURCE_RAW));
ASSERT_TRUE(pkt.getMAC(HWAddr::HWADDR_SOURCE_ANY));
ASSERT_TRUE(pkt.getMAC(HWAddr::HWADDR_SOURCE_RAW));
EXPECT_TRUE(pkt.getMAC(HWAddr::HWADDR_SOURCE_IPV6_LINK_LOCAL |
HWAddr::HWADDR_SOURCE_RAW));
// Check that the returned MAC is indeed the expected one
ASSERT_TRUE(*dummy_hwaddr == *pkt.getMAC(Pkt::HWADDR_SOURCE_ANY));
ASSERT_TRUE(*dummy_hwaddr == *pkt.getMAC(Pkt::HWADDR_SOURCE_RAW));
ASSERT_TRUE(*dummy_hwaddr == *pkt.getMAC(HWAddr::HWADDR_SOURCE_ANY));
ASSERT_TRUE(*dummy_hwaddr == *pkt.getMAC(HWAddr::HWADDR_SOURCE_RAW));
}
// Test checks whether getMACFromIPv6LinkLocal() returns the hardware (MAC)
......@@ -941,11 +941,11 @@ TEST_F(Pkt6Test, getMACFromIPv6LinkLocal_direct) {
// If received from a global address, this method should fail
pkt.setRemoteAddr(global);
EXPECT_FALSE(pkt.getMAC(Pkt::HWADDR_SOURCE_IPV6_LINK_LOCAL));
EXPECT_FALSE(pkt.getMAC(HWAddr::HWADDR_SOURCE_IPV6_LINK_LOCAL));
// If received from link-local that is EUI-64 based, it should succeed
pkt.setRemoteAddr(linklocal_eui64);
HWAddrPtr found = pkt.getMAC(Pkt::HWADDR_SOURCE_IPV6_LINK_LOCAL);
HWAddrPtr found = pkt.getMAC(HWAddr::HWADDR_SOURCE_IPV6_LINK_LOCAL);
ASSERT_TRUE(found);
stringstream tmp;
......@@ -980,15 +980,15 @@ TEST_F(Pkt6Test, getMACFromIPv6LinkLocal_singleRelay) {
// If received from a global address, this method should fail
pkt.relay_info_[0].peeraddr_ = global;
EXPECT_FALSE(pkt.getMAC(Pkt::HWADDR_SOURCE_IPV6_LINK_LOCAL));
EXPECT_FALSE(pkt.getMAC(HWAddr::HWADDR_SOURCE_IPV6_LINK_LOCAL));
// If received from a link-local that does not use EUI-64, it should fail
pkt.relay_info_[0].peeraddr_ = linklocal_noneui64;
EXPECT_FALSE(pkt.getMAC(Pkt::HWADDR_SOURCE_IPV6_LINK_LOCAL));
EXPECT_FALSE(pkt.getMAC(HWAddr::HWADDR_SOURCE_IPV6_LINK_LOCAL));
// If received from link-local that is EUI-64 based, it should succeed
pkt.relay_info_[0].peeraddr_ = linklocal_eui64;
HWAddrPtr found = pkt.getMAC(Pkt::HWADDR_SOURCE_IPV6_LINK_LOCAL);
HWAddrPtr found = pkt.getMAC(HWAddr::HWADDR_SOURCE_IPV6_LINK_LOCAL);
ASSERT_TRUE(found);
stringstream tmp;
......@@ -1041,7 +1041,7 @@ TEST_F(Pkt6Test, getMACFromIPv6LinkLocal_multiRelay) {
pkt.setIndex(iface->getIndex());
// The method should return MAC based on the first relay that was closest
HWAddrPtr found = pkt.getMAC(Pkt::HWADDR_SOURCE_IPV6_LINK_LOCAL);
HWAddrPtr found = pkt.getMAC(HWAddr::HWADDR_SOURCE_IPV6_LINK_LOCAL);
ASSERT_TRUE(found);
// Let's check the info now.
......@@ -1058,7 +1058,7 @@ TEST_F(Pkt6Test, getMACFromIPv6RelayOpt_singleRelay) {
Pkt6 pkt(DHCPV6_SOLICIT, 1234);
// Packets that are not relayed should fail
EXPECT_FALSE(pkt.getMAC(Pkt::HWADDR_SOURCE_CLIENT_ADDR_RELAY_OPTION));
EXPECT_FALSE(pkt.getMAC(HWAddr::HWADDR_SOURCE_CLIENT_ADDR_RELAY_OPTION));
// Now pretend it was relayed by a single relay.
Pkt6::RelayInfo info;
......@@ -1075,7 +1075,7 @@ TEST_F(Pkt6Test, getMACFromIPv6RelayOpt_singleRelay) {
pkt.addRelayInfo(info);
ASSERT_EQ(1, pkt.relay_info_.size());
HWAddrPtr found = pkt.getMAC(Pkt::HWADDR_SOURCE_CLIENT_ADDR_RELAY_OPTION);
HWAddrPtr found = pkt.getMAC(HWAddr::HWADDR_SOURCE_CLIENT_ADDR_RELAY_OPTION);
ASSERT_TRUE(found);
stringstream tmp;
......@@ -1108,7 +1108,7 @@ TEST_F(Pkt6Test, getMACFromIPv6RelayOpt_multipleRelay) {
pkt.addRelayInfo(info2);
ASSERT_EQ(2, pkt.relay_info_.size());
EXPECT_FALSE(pkt.getMAC(Pkt::HWADDR_SOURCE_CLIENT_ADDR_RELAY_OPTION));
EXPECT_FALSE(pkt.getMAC(HWAddr::HWADDR_SOURCE_CLIENT_ADDR_RELAY_OPTION));
// Let's envolve the packet with a third relay (now the closest to the client)
// that inserts the correct client_linklayer_addr option.
......@@ -1123,7 +1123,7 @@ TEST_F(Pkt6Test, getMACFromIPv6RelayOpt_multipleRelay) {
ASSERT_EQ(3, pkt.relay_info_.size());
// Now extract the MAC address from the relayed option
HWAddrPtr found = pkt.getMAC(Pkt::HWADDR_SOURCE_CLIENT_ADDR_RELAY_OPTION);
HWAddrPtr found = pkt.getMAC(HWAddr::HWADDR_SOURCE_CLIENT_ADDR_RELAY_OPTION);
ASSERT_TRUE(found);
stringstream tmp;
......@@ -1131,33 +1131,4 @@ TEST_F(Pkt6Test, getMACFromIPv6RelayOpt_multipleRelay) {
EXPECT_EQ(tmp.str(), found->toText(true));
}
// Checks whether Pkt::MACSourceFromText is working correctly.
// Technically, this is a Pkt, not Pkt6 test, but since there is no separate
// unit-tests for Pkt and it is abstract, so it would be tricky to test it
// directly. Hence test is being run in Pkt6.
TEST_F(Pkt6Test, MACSourceFromText) {
EXPECT_THROW(Pkt::MACSourceFromText("unknown"), BadValue);
EXPECT_EQ(Pkt::HWADDR_SOURCE_ANY, Pkt::MACSourceFromText("any"));
EXPECT_EQ(Pkt::HWADDR_SOURCE_RAW, Pkt::MACSourceFromText("raw"));
EXPECT_EQ(Pkt::HWADDR_SOURCE_DUID, Pkt::MACSourceFromText("duid"));
EXPECT_EQ(Pkt::HWADDR_SOURCE_IPV6_LINK_LOCAL,
Pkt::MACSourceFromText("ipv6-link-local"));
EXPECT_EQ(Pkt::HWADDR_SOURCE_CLIENT_ADDR_RELAY_OPTION,
Pkt::MACSourceFromText("client-link-addr-option"));
EXPECT_EQ(Pkt::HWADDR_SOURCE_CLIENT_ADDR_RELAY_OPTION,
Pkt::MACSourceFromText("rfc6939"));
EXPECT_EQ(Pkt::HWADDR_SOURCE_REMOTE_ID,
Pkt::MACSourceFromText("remote-id"));
EXPECT_EQ(Pkt::HWADDR_SOURCE_REMOTE_ID,
Pkt::MACSourceFromText("rfc4649"));
EXPECT_EQ(Pkt::HWADDR_SOURCE_SUBSCRIBER_ID,
Pkt::MACSourceFromText("subscriber-id"));
EXPECT_EQ(Pkt::HWADDR_SOURCE_SUBSCRIBER_ID,
Pkt::MACSourceFromText("rfc4580"));
EXPECT_EQ(Pkt::HWADDR_SOURCE_DOCSIS,
Pkt::MACSourceFromText("docsis"));
}
}
......@@ -69,6 +69,7 @@ libkea_dhcpsrv_la_SOURCES += cfg_option.cc cfg_option.h
libkea_dhcpsrv_la_SOURCES += cfg_option_def.cc cfg_option_def.h
libkea_dhcpsrv_la_SOURCES += cfg_subnets4.cc cfg_subnets4.h
libkea_dhcpsrv_la_SOURCES += cfg_subnets6.cc cfg_subnets6.h
libkea_dhcpsrv_la_SOURCES += cfg_mac_source.cc cfg_mac_source.h
libkea_dhcpsrv_la_SOURCES += cfgmgr.cc cfgmgr.h
libkea_dhcpsrv_la_SOURCES += csv_lease_file4.cc csv_lease_file4.h
libkea_dhcpsrv_la_SOURCES += csv_lease_file6.cc csv_lease_file6.h
......
// 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 <dhcpsrv/cfg_mac_source.h>
#include <exceptions/exceptions.h>
#include <dhcp/hwaddr.h>
namespace isc {
namespace dhcp {
CfgMACSource::CfgMACSource() {
// By default, use any hardware source that is available.
mac_sources_.push_back(HWAddr::HWADDR_SOURCE_ANY);
}
uint32_t CfgMACSource::MACSourceFromText(const std::string& name) {