// Method 4: From client link-layer address option inserted by a relay
if (hw_addr_src & HWADDR_SOURCE_CLIENT_ADDR_RELAY_OPTION) {
- mac = getMACFromIPv6RelayOpt();
- if (mac) {
- return (mac);
- } else if (hw_addr_src == HWADDR_SOURCE_CLIENT_ADDR_RELAY_OPTION) {
+ mac = getMACFromIPv6RelayOpt();
+ if (mac) {
+ return (mac);
+ } else if (hw_addr_src == 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());
///
/// This method is called from getMAC(HWADDR_SOURCE_CLIENT_ADDR_RELAY_OPTION)
/// and should not be called directly. It will extract the client's
- // MAC/Hardware address from option client_linklayer_addr (RFC6939)
- // inserted by the relay agent closest to the client.
+ /// MAC/Hardware address from option client_linklayer_addr (RFC6939)
+ /// inserted by the relay agent closest to the client.
/// If this method fails, it will return NULL.
///
/// @note This is a pure virtual method and must be implemented in
#include <dhcp/libdhcp++.h>
#include <dhcp/option.h>
#include <dhcp/pkt6.h>
+#include <util/io_utilities.h>
#include <exceptions/exceptions.h>
#include <iostream>
HWAddrPtr
Pkt6::getMACFromIPv6RelayOpt() {
if (relay_info_.empty()) {
- // This is a direct message
+ // This is a direct message
return (HWAddrPtr());
}
// RFC6969 Section 6: Look for the client_linklayer_addr option on the
// relay agent closest to the client
OptionPtr opt = getAnyRelayOption(D6O_CLIENT_LINKLAYER_ADDR, RELAY_GET_FIRST);
if (opt) {
- return (HWAddrPtr(new HWAddr(&(opt->getData())[2], (opt->len()-opt->getHeaderLen()-2),
- opt->getUint16())));
+ const OptionBuffer data = opt->getData();
+ if (data.size() < 3) {
+ // This client link address option is trucnated. It's supposed to be
+ // 2 bytes of link-layer type followed by link-layer address.
+ return (HWAddrPtr());
+ }
+
+ // +2, -2 means to skip the initial 2 bytes which are hwaddress type
+ return (HWAddrPtr(new HWAddr(&data[0] + 2, data.size() - 2,
+ opt->getUint16())));
}
else {
- return (HWAddrPtr());
+ return (HWAddrPtr());
}
}
Pkt6::RelayInfo info;
// generate options with code 79 and client link layer address
- const char opt_data[] = {
+ const uint8_t opt_data[] = {
0x00, 0x01, // Ethertype
0x0a, 0x1b, 0x0b, 0x01, 0xca, 0xfe // MAC
};
// Now pretend it was relayed two times. The relay closest to the server
// adds link-layer-address information against the RFC, the process fails.
Pkt6::RelayInfo info1;
- char opt_data[] = {
+ uint8_t opt_data[] = {
0x00, 0x01, // Ethertype
0x1a, 0x30, 0x0b, 0xfa, 0xc0, 0xfe // MAC
};
- OptionPtr relay_opt1(new Option(Option::V6, 79,
+ OptionPtr relay_opt1(new Option(Option::V6, D6O_CLIENT_LINKLAYER_ADDR,
OptionBuffer(opt_data, opt_data + sizeof(opt_data))));
info1.options_.insert(make_pair(relay_opt1->getType(), relay_opt1));
// Let's envolve the packet with a third relay (now the closest to the client)
// that inserts the correct client_linklayer_addr option.
Pkt6::RelayInfo info3;
+
// We reuse the option and modify the MAC to be sure we get the right address
opt_data[2] = 0xfa;
- OptionPtr relay_opt3(new Option(Option::V6, 79,
+ OptionPtr relay_opt3(new Option(Option::V6, D6O_CLIENT_LINKLAYER_ADDR,
OptionBuffer(opt_data, opt_data + sizeof(opt_data))));
info3.options_.insert(make_pair(relay_opt3->getType(), relay_opt3));
pkt.addRelayInfo(info3);