From: Tomek Mrugalski Date: Tue, 14 Oct 2014 12:29:31 +0000 (+0200) Subject: [3549] Changes after review: X-Git-Tag: trac3629a_base~8^2~3 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=d4a2bd9fbaea34d1a0decc160ab4ab9e91d3eddf;p=thirdparty%2Fkea.git [3549] Changes after review: - It's called getMACFromIPv6() now - Tests for u,g bits added. - u bit is now flipped properly. - Unit tests updated to reflect above changes. --- diff --git a/src/lib/dhcp/pkt.cc b/src/lib/dhcp/pkt.cc index b9f0287d2c..0dc77b4cfd 100644 --- a/src/lib/dhcp/pkt.cc +++ b/src/lib/dhcp/pkt.cc @@ -169,7 +169,7 @@ Pkt::getMAC(uint32_t hw_addr_src) { } HWAddrPtr -Pkt::getMACfromIPv6(const isc::asiolink::IOAddress& addr) { +Pkt::getMACFromIPv6(const isc::asiolink::IOAddress& addr) { if (!addr.isV6LinkLocal()) { return (HWAddrPtr()); @@ -183,6 +183,10 @@ Pkt::getMACfromIPv6(const isc::asiolink::IOAddress& addr) { // Check that it's link-local (starts with fe80). (bin[0] != 0xfe) || (bin[1] != 0x80) || + // Check that u bit is set and g is clear. See Section 2.5.1 of RFC2373 + // for details. + ( (bin[0] & 3) != 2) || + // And that the IID is of EUI-64 type. (bin[11] != 0xff) || (bin[12] != 0xfe)) { return (HWAddrPtr()); @@ -194,6 +198,10 @@ Pkt::getMACfromIPv6(const isc::asiolink::IOAddress& addr) { // Ok, we're down to EUI-64 only now: XX:XX:XX:ff:fe:XX:XX:XX bin.erase(bin.begin() + 3, bin.begin() + 5); + // MAC-48 to EUI-64 involves inverting u bit (see explanation in Section + // 2.5.1 of RFC2373). We need to revert that. + bin[0] = bin[0] ^ 2; + // Let's get the interface this packet was received on. We need it to get // hardware type Iface* iface = IfaceMgr::instance().getIface(iface_); diff --git a/src/lib/dhcp/pkt.h b/src/lib/dhcp/pkt.h index 48106dfa38..98a9b802eb 100644 --- a/src/lib/dhcp/pkt.h +++ b/src/lib/dhcp/pkt.h @@ -536,7 +536,7 @@ protected: /// @param addr IPv6 address to be converted /// @return hardware address (or NULL) HWAddrPtr - getMACfromIPv6(const isc::asiolink::IOAddress& addr); + getMACFromIPv6(const isc::asiolink::IOAddress& addr); /// Transaction-id (32 bits for v4, 24 bits for v6) uint32_t transid_; diff --git a/src/lib/dhcp/pkt6.cc b/src/lib/dhcp/pkt6.cc index 8ba9360205..72a2ea5617 100644 --- a/src/lib/dhcp/pkt6.cc +++ b/src/lib/dhcp/pkt6.cc @@ -546,11 +546,11 @@ HWAddrPtr Pkt6::getMACFromSrcLinkLocalAddr() { if (relay_info_.empty()) { // This is a direct message, use source address - return (getMACfromIPv6(remote_addr_)); + return (getMACFromIPv6(remote_addr_)); } // This is a relayed message, get the peer-addr from the first relay-forw - return (getMACfromIPv6(relay_info_[relay_info_.size() - 1].peeraddr_)); + return (getMACFromIPv6(relay_info_[relay_info_.size() - 1].peeraddr_)); } diff --git a/src/lib/dhcp/tests/pkt6_unittest.cc b/src/lib/dhcp/tests/pkt6_unittest.cc index 0eb1b47962..141fa07caa 100644 --- a/src/lib/dhcp/tests/pkt6_unittest.cc +++ b/src/lib/dhcp/tests/pkt6_unittest.cc @@ -923,9 +923,12 @@ TEST_F(Pkt6Test, getMACFromIPv6LinkLocal_direct) { pkt.setIface(iface->getName()); pkt.setIndex(iface->getIndex()); + // Note that u and g bits (the least significant ones of the most significant + // byte) have special meaning and must not be set in MAC. u bit is always set + // in EUI-64. g is always cleared. IOAddress global("2001:db8::204:06ff:fe08:0a:0c"); - IOAddress linklocal_eui64("fe80::204:06ff:fe08:0a0c"); - IOAddress linklocal_noneui64("fe80::0204:0608:0a0c:0e10"); + IOAddress linklocal_eui64("fe80::f204:06ff:fe08:0a0c"); + IOAddress linklocal_noneui64("fe80::f204:0608:0a0c:0e10"); // If received from a global address, this method should fail pkt.setRemoteAddr(global); @@ -937,7 +940,7 @@ TEST_F(Pkt6Test, getMACFromIPv6LinkLocal_direct) { ASSERT_TRUE(found); stringstream tmp; - tmp << "hwtype=" << (int)iface->getHWType() << " 02:04:06:08:0a:0c"; + tmp << "hwtype=" << (int)iface->getHWType() << " f0:04:06:08:0a:0c"; EXPECT_EQ(tmp.str(), found->toText(true)); } @@ -963,8 +966,8 @@ TEST_F(Pkt6Test, getMACFromIPv6LinkLocal_singleRelay) { pkt.setIndex(iface->getIndex()); IOAddress global("2001:db8::204:06ff:fe08:0a:0c"); // global address - IOAddress linklocal_noneui64("fe80::0204:0608:0a0c:0e10"); // no fffe - IOAddress linklocal_eui64("fe80::204:06ff:fe08:0a0c"); // valid EUI-64 + IOAddress linklocal_noneui64("fe80::f204:0608:0a0c:0e10"); // no fffe + IOAddress linklocal_eui64("fe80::f204:06ff:fe08:0a0c"); // valid EUI-64 // If received from a global address, this method should fail pkt.relay_info_[0].peeraddr_ = global; @@ -980,7 +983,7 @@ TEST_F(Pkt6Test, getMACFromIPv6LinkLocal_singleRelay) { ASSERT_TRUE(found); stringstream tmp; - tmp << "hwtype=" << (int)iface->getHWType() << " 02:04:06:08:0a:0c"; + tmp << "hwtype=" << (int)iface->getHWType() << " f0:04:06:08:0a:0c"; EXPECT_EQ(tmp.str(), found->toText(true)); } @@ -995,9 +998,9 @@ TEST_F(Pkt6Test, getMACFromIPv6LinkLocal_multiRelay) { // are stored in relay_info_ in the encapsulation order rather than in // traverse order. The following simulates: // client --- relay1 --- relay2 --- relay3 --- server - IOAddress linklocal1("fe80::ff:fe00:1"); // valid EUI-64 - IOAddress linklocal2("fe80::ff:fe00:2"); // valid EUI-64 - IOAddress linklocal3("fe80::ff:fe00:3"); // valid EUI-64 + IOAddress linklocal1("fe80::200:ff:fe00:1"); // valid EUI-64 + IOAddress linklocal2("fe80::200:ff:fe00:2"); // valid EUI-64 + IOAddress linklocal3("fe80::200:ff:fe00:3"); // valid EUI-64 // Let's add info about relay3. This was the last relay, so it added the // outermost encapsulation layer, so it was parsed first during reception.