21#include <boost/foreach.hpp>
43 <<
"), hop-count=" <<
static_cast<int>(hop_count_) <<
"," << endl
44 <<
"link-address=" << linkaddr_.toText()
45 <<
", peer-address=" << peeraddr_.toText() <<
", "
46 <<
options_.size() <<
" option(s)" << endl;
47 for (
auto const& option :
options_) {
48 tmp << option.second->toText() << endl;
76Pkt6::prepareGetAnyRelayOption(
const RelaySearchOrder& order,
77 int& start,
int& end,
int& direction)
const {
117 prepareGetAnyRelayOption(order, start, end, direction);
125 for (
int i = start; i != end + direction; i += direction) {
150 prepareGetAnyRelayOption(order, start, end, direction);
158 for (
int i = start; i != end + direction; i += direction) {
182 prepareGetAnyRelayOption(order, start, end, direction);
191 for (
int i = start; i != end + direction; i += direction) {
192 std::pair<OptionCollection::const_iterator,
193 OptionCollection::const_iterator> range =
195 opts.insert(range.first, range.second);
213 prepareGetAnyRelayOption(order, start, end, direction);
222 for (
int i = start; i != end + direction; i += direction) {
223 std::pair<OptionCollection::iterator,
224 OptionCollection::iterator> range =
230 BOOST_FOREACH(
auto& opt_it, range) {
231 OptionPtr option_copy = opt_it.second->clone();
232 opt_it.second = option_copy;
235 opts.insert(range.first, range.second);
242 const uint8_t relay_level)
const {
246 <<
" There is no info about "
247 << relay_level + 1 <<
" relay.");
250 OptionCollection::const_iterator x =
relay_info_[relay_level].options_.find(opt_type);
263 <<
" There is no info about "
264 << relay_level + 1 <<
" relay.");
267 OptionCollection::iterator x =
relay_info_[relay_level].options_.find(opt_type);
270 OptionPtr relay_option_copy = x->second->clone();
271 x->second = relay_option_copy;
281 const uint8_t relay_level)
const {
285 <<
" There is no info about "
286 << relay_level + 1 <<
" relay.");
289 std::pair<OptionCollection::const_iterator,
290 OptionCollection::const_iterator> range =
291 relay_info_[relay_level].options_.equal_range(opt_type);
297 const uint8_t relay_level) {
301 <<
" There is no info about "
302 << relay_level + 1 <<
" relay.");
307 std::pair<OptionCollection::iterator,
308 OptionCollection::iterator> range =
309 relay_info_[relay_level].options_.equal_range(opt_type);
314 BOOST_FOREACH(
auto& opt_it, range) {
315 OptionPtr option_copy = opt_it.second->clone();
316 opt_it.second = option_copy;
327 <<
" There is no info about " << relay_level + 1 <<
" relay.");
337 <<
" There is no info about " << relay_level + 1 <<
" relay.");
347 for (
auto const& opt : relay.
options_) {
348 len += (opt.second)->
len();
358 for (
int relay_index =
relay_info_.size(); relay_index > 0; --relay_index) {
370 length += it.second->len();
413 isc::asiolink::V6ADDRESS_LEN);
415 isc::asiolink::V6ADDRESS_LEN);
422 for (
auto const& opt : relay.options_) {
456 " not implemented yet.");
473 if (
data_.size() < 4) {
475 <<
data_.size() <<
", DHCPv6 header alone has 4 bytes.");
503 OptionBuffer::const_iterator end) {
504 size_t size = std::distance(begin, end);
508 <<
data_.size() <<
", DHCPv6 header alone has 4 bytes.");
514 ((*begin++) << 8) + (*begin++);
552 size_t bufsize =
data_.size();
559 size_t relay_msg_offset = 0;
560 size_t relay_msg_len = 0;
566 offset += isc::asiolink::V6ADDRESS_LEN;
568 offset += isc::asiolink::V6ADDRESS_LEN;
577 &relay_msg_offset, &relay_msg_len);
584 if (relay_msg_offset == 0 || relay_msg_len == 0) {
593 if (relay_msg_len >= bufsize) {
597 uint8_t inner_type =
data_[offset + relay_msg_offset];
598 offset += relay_msg_offset;
599 bufsize = relay_msg_len;
614 if ( (offset ==
data_.size()) && (bufsize == 0) ) {
635 "not implemented yet.");
646 uint8_t hlen = opt_duid->getData().size();
650 vector<uint8_t> hw_addr(hlen, 0);
651 std::vector<unsigned char> duid_data = opt_duid->getData();
661 if (duid_data.size() >= 5) {
663 duid_data.size() - 2);
664 mac.reset(
new HWAddr(&duid_data[4], duid_data.size() - 4, hwtype));
672 if (duid_data.size() >= 9) {
674 duid_data.size() - 2);
675 mac.reset(
new HWAddr(&duid_data[8], duid_data.size() - 8, hwtype));
694 std::stringstream label;
698 label <<
", tid=0x" << std::hex << transid << std::dec;
700 return (label.str());
705 std::stringstream label;
711 label <<
"duid=[" << (duid ? duid->toText() :
"no info")
712 <<
"], [" << (hwaddr ? hwaddr->toText() :
"no hwaddr info") <<
"]";
714 return (label.str());
734 tmp <<
", trans_id=0x" << hex <<
transid_ << dec;
737 tmp <<
"," << endl <<
"options:";
740 tmp << endl << opt.second->toText(2);
742 tmp <<
"(unknown)" << endl;
747 tmp <<
"," << endl <<
"message contains no options";
752 tmp << endl <<
relay_info_.size() <<
" relay(s):" << endl;
755 tmp <<
"relay[" << cnt++ <<
"]: " << relay.toText();
758 tmp << endl <<
"No relays traversed." << endl;
783 static const char* ADVERTISE =
"ADVERTISE";
784 static const char* CONFIRM =
"CONFIRM";
785 static const char* DECLINE =
"DECLINE";
786 static const char* INFORMATION_REQUEST =
"INFORMATION_REQUEST";
787 static const char* LEASEQUERY =
"LEASEQUERY";
788 static const char* LEASEQUERY_DATA =
"LEASEQUERY_DATA";
789 static const char* LEASEQUERY_DONE =
"LEASEQUERY_DONE";
790 static const char* LEASEQUERY_REPLY =
"LEASEQUERY_REPLY";
791 static const char* REBIND =
"REBIND";
792 static const char* RECONFIGURE =
"RECONFIGURE";
793 static const char* RELAY_FORW =
"RELAY_FORWARD";
794 static const char* RELAY_REPL =
"RELAY_REPLY";
795 static const char* RELEASE =
"RELEASE";
796 static const char* RENEW =
"RENEW";
797 static const char* REPLY =
"REPLY";
798 static const char* REQUEST =
"REQUEST";
799 static const char* SOLICIT =
"SOLICIT";
800 static const char* DHCPV4_QUERY =
"DHCPV4_QUERY";
801 static const char* DHCPV4_RESPONSE =
"DHCPV4_RESPONSE";
802 static const char* UNKNOWN =
"UNKNOWN";
815 return (INFORMATION_REQUEST);
821 return (LEASEQUERY_DATA);
824 return (LEASEQUERY_DONE);
827 return (LEASEQUERY_REPLY);
833 return (RECONFIGURE);
857 return (DHCPV4_QUERY);
860 return (DHCPV4_RESPONSE);
876 for (
size_t i = 0; i < question->relay_info_.size(); ++i) {
879 info.hop_count_ = question->relay_info_[i].hop_count_;
880 info.linkaddr_ = question->relay_info_[i].linkaddr_;
881 info.peeraddr_ = question->relay_info_[i].peeraddr_;
888 info.options_.insert(make_pair(opt->getType(), opt));
894 info.options_.insert(make_pair(opt->getType(), opt));
930 if (data.size() >= 3) {
933 mac.reset(
new HWAddr(&data[0] + 2, data.size() - 2,
952 vendor = boost::dynamic_pointer_cast< OptionVendor>(opt.second);
961 if (!device_id->getData().empty()) {
987 vendor = boost::dynamic_pointer_cast< OptionVendor>(opt.second);
996 if (cm_mac && !cm_mac->getData().empty()) {
1018 if (data.size() >= 5) {
1022 uint16_t hwtype = 0;
1027 hwtype = iface->getHWType();
1030 size_t len = data.size() - 4;
1037 mac.reset(
new HWAddr(&data[0] + 4,
len, hwtype));
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
This is a base class for exceptions thrown from the DNS library module.
virtual const char * what() const
Returns a C-style character string of the cause of the exception.
A generic exception that is thrown if a function is called in a prohibited way.
A generic exception that is thrown when a function is not implemented.
A generic exception that is thrown if a parameter given to a method would refer to or modify out-of-r...
A generic exception that is thrown when an unexpected error condition occurs.
The IOAddress class represents an IP addresses (version agnostic)
static IOAddress fromBytes(short family, const uint8_t *data)
Creates an address from over wire data.
Holds DUID (DHCPv6 Unique Identifier)
@ DUID_LL
link-layer, see RFC3315, section 11.4
@ DUID_LLT
link-layer + time, see RFC3315, section 11.2
IfacePtr getIface(const unsigned int ifindex)
Returns interface specified interface index.
static IfaceMgr & instance()
IfaceMgr is a singleton class.
static size_t unpackOptions6(const OptionBuffer &buf, const std::string &option_space, isc::dhcp::OptionCollection &options, size_t *relay_msg_offset=0, size_t *relay_msg_len=0)
Parses provided buffer as DHCPv6 options and creates Option objects.
static void packOptions6(isc::util::OutputBuffer &buf, const isc::dhcp::OptionCollection &options)
Stores DHCPv6 options in a buffer.
static const size_t OPTION6_HDR_LEN
length of any DHCPv6 option header
virtual std::string toText() const
Returns text representation of the packet.
uint16_t calculateRelaySizes()
Calculates overhead for all relays defined for this message.
virtual HWAddrPtr getMACFromIPv6RelayOpt()
Extract MAC/Hardware address from client link-layer address.
DHCPv6Proto
DHCPv6 transport protocol.
virtual std::string getLabel() const
Returns text representation of the primary packet identifiers.
OptionCollection getRelayOptions(uint16_t option_code, uint8_t nesting_level)
Returns options inserted by relay.
static const size_t DHCPV6_PKT_HDR_LEN
specifies non-relayed DHCPv6 packet header length (over UDP)
virtual size_t len()
Returns length of the packet.
virtual void pack()
Prepares on-wire format.
OptionPtr getRelayOption(uint16_t option_code, uint8_t nesting_level)
Returns option inserted by relay.
virtual HWAddrPtr getMACFromRemoteIdRelayOption()
Attempts to obtain MAC address from remote-id relay option.
void unpackTCP()
Parses on-wire form of TCP DHCPv6 packet.
const char * getName() const
Returns name of the DHCPv6 message.
virtual HWAddrPtr getMACFromSrcLinkLocalAddr()
Attempts to generate MAC/Hardware address from IPv6 link-local address.
OptionPtr getNonCopiedRelayOption(const uint16_t opt_type, const uint8_t relay_level) const
Returns pointer to an option inserted by relay agent.
void unpackRelayMsg()
Unpacks relayed message (RELAY-FORW or RELAY-REPL).
RelaySearchOrder
defines relay search pattern
@ RELAY_SEARCH_FROM_CLIENT
@ RELAY_SEARCH_FROM_SERVER
static std::string makeLabel(const DuidPtr duid, const uint32_t transid, const HWAddrPtr &hwaddr)
Returns text representation of the given packet identifiers.
OptionPtr getAnyRelayOption(const uint16_t option_code, const RelaySearchOrder &order)
Return first instance of a specified option.
DuidPtr getClientId() const
Retrieves the DUID from the Client Identifier option.
void packTCP()
Builds on wire packet for TCP transmission.
OptionPtr getNonCopiedAnyRelayOption(const uint16_t option_code, const RelaySearchOrder &order) const
Returns pointer to an instance of specified option.
void copyRelayInfo(const Pkt6Ptr &question)
copies relay information from client's packet to server's response
DHCPv6Proto proto_
UDP (usually) or TCP (bulk leasequery or failover)
const isc::asiolink::IOAddress & getRelay6PeerAddress(uint8_t relay_level) const
return the peer address field from a relay option
virtual void unpack()
Dispatch method that handles binary packet parsing.
OptionCollection getAllRelayOptions(const uint16_t option_code, const RelaySearchOrder &order)
Return first instances of a specified option.
virtual HWAddrPtr getMACFromDUID()
Extract MAC/Hardware address from client-id.
virtual HWAddrPtr getMACFromDocsisCMTS()
Attempts to extract MAC/Hardware address from DOCSIS options.
const isc::asiolink::IOAddress & getRelay6LinkAddress(uint8_t relay_level) const
return the link address field from a relay option
OptionCollection getNonCopiedAllRelayOptions(const uint16_t option_code, const RelaySearchOrder &order) const
Returns pointers to instances of specified option.
std::vector< RelayInfo > relay_info_
Relay information.
uint8_t msg_type_
DHCPv6 message type.
Pkt6(uint8_t msg_type, uint32_t transid, DHCPv6Proto proto=UDP)
Constructor, used in replying to a message.
void addRelayInfo(const RelayInfo &relay)
add information about one traversed relay
virtual HWAddrPtr getMACFromDocsisModem()
Attempts to extract MAC/Hardware address from DOCSIS options inserted by the modem itself.
OptionCollection getNonCopiedRelayOptions(const uint16_t opt_type, const uint8_t relay_level) const
Returns all option instances inserted by relay agent.
void packUDP()
Builds on wire packet for UDP transmission.
void unpackUDP()
Parses on-wire form of UDP DHCPv6 packet.
void unpackMsg(OptionBuffer::const_iterator begin, OptionBuffer::const_iterator end)
Unpacks direct (non-relayed) message.
uint16_t directLen() const
Calculates size of the message as if it was not relayed at all.
uint16_t getRelayOverhead(const RelayInfo &relay) const
Calculates overhead introduced in specified relay.
virtual uint8_t getType() const
Returns message type (e.g.
static const size_t DHCPV6_RELAY_HDR_LEN
specifies relay DHCPv6 packet header length (over UDP)
Base class for classes representing DHCP messages.
isc::asiolink::IOAddress remote_addr_
Remote IP address.
uint16_t local_port_
local TDP or UDP port
uint32_t transid_
Transaction-id (32 bits for v4, 24 bits for v6)
isc::asiolink::IOAddress local_addr_
Local IP (v4 or v6) address.
OptionBuffer data_
Unparsed data (in received packets).
uint16_t remote_port_
remote TCP or UDP port
uint32_t getTransid() const
Returns value of transaction-id field.
isc::dhcp::OptionCollection options_
Collection of options present in this message.
isc::util::OutputBuffer buffer_out_
Output buffer (used during message transmission)
OptionCollection getNonCopiedOptions(const uint16_t opt_type) const
Returns all option instances of specified type without copying.
bool copy_retrieved_options_
Indicates if a copy of the retrieved option should be returned when Pkt::getOption is called.
std::string iface_
Name of the network interface the packet was received/to be sent over.
OptionPtr getNonCopiedOption(const uint16_t type) const
Returns the first option of specified type without copying.
HWAddrPtr getMACFromIPv6(const isc::asiolink::IOAddress &addr)
Attempts to convert IPv6 address into MAC.
void writeUint8(uint8_t data)
Write an unsigned 8-bit integer into the buffer.
void writeUint16(uint16_t data)
Write an unsigned 16-bit integer in host byte order into the buffer in network byte order.
void writeData(const void *data, size_t len)
Copy an arbitrary length of data into the buffer.
void clear()
Clear buffer content.
@ D6O_CLIENT_LINKLAYER_ADDR
@ DHCPV6_INFORMATION_REQUEST
@ DHCPV6_LEASEQUERY_REPLY
#define VENDOR_ID_CABLE_LABS
#define DOCSIS3_V6_CMTS_CM_MAC
#define DOCSIS3_V6_DEVICE_ID
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
static const uint32_t HWADDR_SOURCE_REMOTE_ID
A relay can insert remote-id.
static const uint32_t HWADDR_SOURCE_CLIENT_ADDR_RELAY_OPTION
Get it from RFC6939 option.
static const uint32_t HWADDR_SOURCE_DOCSIS_MODEM
A cable modem (acting as DHCP client) that supports DOCSIS standard can insert DOCSIS options that co...
static const uint32_t HWADDR_SOURCE_DUID
Extracted from DUID-LL or DUID-LLT (not 100% reliable as the client can send fake DUID).
static const uint32_t HWADDR_SOURCE_DOCSIS_CMTS
A CMTS (acting as DHCP relay agent) that supports DOCSIS standard can insert DOCSIS options that cont...
boost::shared_ptr< OptionVendor > OptionVendorPtr
Pointer to a vendor option.
boost::shared_ptr< Iface > IfacePtr
Type definition for the pointer to an Iface object.
boost::shared_ptr< DUID > DuidPtr
std::multimap< unsigned int, OptionPtr > OptionCollection
A collection of DHCP (v4 or v6) options.
boost::shared_ptr< HWAddr > HWAddrPtr
Shared pointer to a hardware address structure.
boost::shared_ptr< Pkt6 > Pkt6Ptr
A pointer to Pkt6 packet.
std::vector< uint8_t > OptionBuffer
buffer types used in DHCP code.
@ HTYPE_DOCSIS
The traffic captures we have from cable modems as well as this list by IANA: http://www....
boost::shared_ptr< Option > OptionPtr
uint16_t readUint16(void const *const buffer, size_t const length)
uint16_t wrapper over readUint.
Defines the logger used by the top-level component of kea-lfc.
const IOAddress DEFAULT_ADDRESS6("::")
Default address used in Pkt6 constructor.
#define DHCP6_OPTION_SPACE
Hardware type that represents information from DHCPv4 packet.
static const size_t MAX_HWADDR_LEN
Maximum size of a hardware address.
structure that describes a single relay information
RelayInfo()
default constructor
isc::dhcp::OptionCollection options_
options received from a specified relay, except relay-msg option
uint8_t msg_type_
message type (RELAY-FORW oro RELAY-REPL)
std::string toText() const
Returns printable representation of the relay information.
isc::asiolink::IOAddress linkaddr_
fixed field in relay-forw/relay-reply
uint8_t hop_count_
number of traversed relays (up to 32)
isc::asiolink::IOAddress peeraddr_
fixed field in relay-forw/relay-reply