} ]
}
},
+
+ { "item_name": "mac-sources",
+ "item_type": "list",
+ "item_optional": true,
+ "item_default": [ "any" ],
+ "item_description": "Lists MAC/hardware address acquisition sources",
+ "list_item_spec":
+ {
+ "item_name": "source",
+ "item_type": "string",
+ "item_optional": true,
+ "item_default": "any"
+ }
+ } ,
+
{ "item_name": "dhcp-ddns",
"item_type": "map",
"item_optional": false,
hostname = fqdn->getDomainName();
}
- // 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);
+ // 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;
+ }
+ }
// 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
parser = new HooksLibrariesParser(config_id);
} else if (config_id.compare("dhcp-ddns") == 0) {
parser = new D2ClientConfigParser(config_id);
+ } else if (config_id.compare("mac-sources") == 0) {
+ parser = new MACSourcesListConfigParser(config_id,
+ globalContext());
} else {
isc_throw(DhcpConfigError,
"unsupported global configuration parameter: "
#ifndef DHCP6_CONFIG_PARSER_H
#define DHCP6_CONFIG_PARSER_H
-/// @todo: This header file and its .cc counterpart are very similar between
-/// DHCPv4 and DHCPv6. They should be merged. See ticket #2355.
-
#include <cc/data.h>
#include <dhcpsrv/parsers/dhcp_parsers.h>
#include <exceptions/exceptions.h>
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)
return (HWAddrPtr(new HWAddr(bin, hwtype)));
}
+uint16_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)) {
+ return (sources[i].type);
+ }
+ }
+
+ isc_throw(BadValue, "Can't convert '" << name << "' to any known MAC source.");
+}
+
};
};
///
/// @brief The list covers all possible MAC/hw address sources.
///
- /// @note The uncommented ones are currently supported. When you implement
- /// a new method, please uncomment appropriate line here.
- ///
/// @{
/// Not really a type, only used in getMAC() calls.
- static const uint32_t HWADDR_SOURCE_ANY = 0xffff;
+ 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 = 0x0000;
+ static const uint32_t HWADDR_SOURCE_UNKNOWN;
/// Obtained first hand from raw socket (100% reliable).
- static const uint32_t HWADDR_SOURCE_RAW = 0x0001;
+ 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 = 0x0002;
+ 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 = 0x0004;
+ 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 = 0x0008;
+ 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 = 0x0010;
+ 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 = 0x0020;
+ 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_OPTIONS = 0x0040;
+ 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 uint16_t MACSourceFromText(const std::string& name);
+
protected:
/// @brief Constructor.
void
InterfaceListConfigParser::build(ConstElementPtr value) {
CfgIface cfg_iface;
+
BOOST_FOREACH(ConstElementPtr iface, value->listValue()) {
std::string iface_name = iface->stringValue();
try {
// Nothing to do.
}
+// ******************** MACSourcesListConfigParser *************************
+
+MACSourcesListConfigParser::
+MACSourcesListConfigParser(const std::string& param_name,
+ ParserContextPtr global_context)
+ : param_name_(param_name), global_context_(global_context) {
+ if (param_name_ != "mac-sources") {
+ isc_throw(BadValue, "Internal error. MAC sources configuration "
+ "parser called for the wrong parameter: " << param_name);
+ }
+}
+
+void
+MACSourcesListConfigParser::build(ConstElementPtr value) {
+ CfgIface cfg_iface;
+ uint32_t source = 0;
+
+ // By default, there's only one source defined: ANY.
+ // If user specified anything, we need to get rid of that default.
+ CfgMgr::instance().getStagingCfg()->clearMACSources();
+
+ BOOST_FOREACH(ConstElementPtr source_elem, value->listValue()) {
+ std::string source_str = source_elem->stringValue();
+ try {
+ source = Pkt::MACSourceFromText(source_str);
+ CfgMgr::instance().getStagingCfg()->addMACSource(source);
+ } catch (const std::exception& ex) {
+ isc_throw(DhcpConfigError, "Failed to convert '"
+ << source_str << "' to any recognized MAC source:"
+ << ex.what() << " (" << value->getPosition() << ")");
+ }
+ }
+}
+
+void
+MACSourcesListConfigParser::commit() {
+ // Nothing to do.
+}
+
// ******************** HooksLibrariesParser *************************
HooksLibrariesParser::HooksLibrariesParser(const std::string& param_name)
/// @brief parser for interface list definition
///
-/// This parser handles Dhcp4/interface entry.
+/// This parser handles Dhcp4/interfaces and Dhcp6/interfaces entries.
/// It contains a list of network interfaces that the server listens on.
/// In particular, it can contain an entry called "all" or "any" that
/// designates all interfaces.
-///
-/// It is useful for parsing Dhcp4/interface parameter.
class InterfaceListConfigParser : public DhcpConfigParser {
public:
ParserContextPtr global_context_;
};
+
+/// @brief parser for MAC/hardware aquisition sources
+///
+/// This parser handles Dhcp6/mac-sources entry.
+/// It contains a list of MAC/hardware aquisition source, i.e. methods how
+/// MAC address can possibly by obtained in DHCPv6. For a currently supported
+/// methods, see @ref isc::dhcp::Pkt::getMAC.
+class MACSourcesListConfigParser : public DhcpConfigParser {
+public:
+
+ /// @brief constructor
+ ///
+ /// As this is a dedicated parser, it must be used to parse
+ /// "mac-sources" parameter only. All other types will throw exception.
+ ///
+ /// @param param_name name of the configuration parameter being parsed
+ /// @param global_context Global parser context.
+ /// @throw BadValue if supplied parameter name is not "mac-sources"
+ MACSourcesListConfigParser(const std::string& param_name,
+ ParserContextPtr global_context);
+
+ /// @brief parses parameters value
+ ///
+ /// Parses configuration entry (list of sources) and adds each element
+ /// to the sources list.
+ ///
+ /// @param value pointer to the content of parsed values
+ virtual void build(isc::data::ConstElementPtr value);
+
+ /// @brief Does nothing.
+ virtual void commit();
+
+private:
+
+ // Parsed parameter name
+ std::string param_name_;
+
+ /// Global parser context.
+ ParserContextPtr global_context_;
+};
+
+
/// @brief Parser for hooks library list
///
/// This parser handles the list of hooks libraries. This is an optional list,
}; // end of isc namespace
#endif // DHCP_PARSERS_H
-
#include <dhcpsrv/srv_config.h>
#include <log/logger_manager.h>
#include <log/logger_specification.h>
+#include <dhcp/pkt.h> // Needed for HWADDR_SOURCE_*
#include <list>
#include <sstream>
: sequence_(0), cfg_option_def_(new CfgOptionDef()),
cfg_option_(new CfgOption()), cfg_subnets4_(new CfgSubnets4()),
cfg_subnets6_(new CfgSubnets6()), cfg_hosts_(new CfgHosts()) {
+
+ // By default, use any hardware source that is available.
+ mac_sources_.push_back(Pkt::HWADDR_SOURCE_ANY);
}
SrvConfig::SrvConfig(const uint32_t sequence)
: sequence_(sequence), cfg_option_def_(new CfgOptionDef()),
cfg_option_(new CfgOption()), cfg_subnets4_(new CfgSubnets4()),
cfg_subnets6_(new CfgSubnets6()), cfg_hosts_(new CfgHosts()) {
+
+ // By default, use any hardware source that is available.
+ mac_sources_.push_back(Pkt::HWADDR_SOURCE_ANY);
}
std::string
return (cfg_hosts_);
}
+ /// @brief Adds additional MAC/hardware address aquisition.
+ ///
+ /// @param source MAC source (see constants in Pkt::HWADDR_SOURCE_*)
+ ///
+ /// Specified source is being added to the mac_sources_ array.
+ void addMACSource(uint32_t source) {
+ mac_sources_.push_back(source);
+ }
+
+ /// @brief Provides access to the configure MAC/Hardware address sources.
+ ///
+ /// @note The const reference returned is only valid as long as the
+ /// object that returned it.
+ const std::vector<uint32_t>& getMACSources() const {
+ return mac_sources_;
+ }
+
+ /// @brief Removes any configured MAC/Hardware address sources.
+ void clearMACSources() {
+ mac_sources_.clear();
+ }
+
//@}
/// @brief Copies the currnet configuration to a new configuration.
//@}
+
private:
/// @brief Sequence number identifying the configuration.
/// reservations for different IPv4 and IPv6 subnets.
CfgHostsPtr cfg_hosts_;
+ /// @brief A list of configured MAC sources.
+ std::vector<uint32_t> mac_sources_;
};
/// @name Pointers to the @c SrvConfig object.
libdhcpsrv_unittests_CXXFLAGS += -Wno-unused-variable -Wno-unused-parameter
endif
-libdhcpsrv_unittests_LDADD = $(top_builddir)/src/lib/dhcpsrv/libkea-dhcpsrv.la
+libdhcpsrv_unittests_LDADD = $(top_builddir)/src/lib/dhcp/libkea-dhcp++.la
+libdhcpsrv_unittests_LDADD += $(top_builddir)/src/lib/dhcpsrv/libkea-dhcpsrv.la
libdhcpsrv_unittests_LDADD += $(top_builddir)/src/lib/dhcpsrv/testutils/libdhcpsrvtest.la
libdhcpsrv_unittests_LDADD += $(top_builddir)/src/lib/dhcp/tests/libdhcptest.la
libdhcpsrv_unittests_LDADD += $(top_builddir)/src/lib/dhcp/libkea-dhcp++.la