]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[3549] Changes after review:
authorTomek Mrugalski <tomasz@isc.org>
Tue, 14 Oct 2014 12:29:31 +0000 (14:29 +0200)
committerTomek Mrugalski <tomasz@isc.org>
Tue, 14 Oct 2014 12:29:31 +0000 (14:29 +0200)
 - It's called getMACFromIPv6() now
 - Tests for u,g bits added.
 - u bit is now flipped properly.
 - Unit tests updated to reflect above changes.

src/lib/dhcp/pkt.cc
src/lib/dhcp/pkt.h
src/lib/dhcp/pkt6.cc
src/lib/dhcp/tests/pkt6_unittest.cc

index b9f0287d2cd74916cde771a94c7bc4412ce8eecc..0dc77b4cfdeb08bd06ea420f3e45a26553a30f7c 100644 (file)
@@ -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_);
index 48106dfa38acf8391578f74f7287782470f012fe..98a9b802ebe54e6279595072452ad1b28b53ff3f 100644 (file)
@@ -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_;
index 8ba936020541f89b0e99c4de85716d5d5a7370ba..72a2ea56177c953934ea6b8cea82630a5f3ee503 100644 (file)
@@ -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_));
 }
 
 
index 0eb1b479621240d53bc3be6581f76ececa9eb31a..141fa07caac56d44a9abf1c1a82c47838df9a3f5 100644 (file)
@@ -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.