Create generic method to extract mac address from EUI-64 constructed addresses
authorAndrii Kryzhyk <kandrew@fb.com>
Thu, 24 Aug 2017 19:08:18 +0000 (12:08 -0700)
committerFacebook Github Bot <facebook-github-bot@users.noreply.github.com>
Thu, 24 Aug 2017 19:30:03 +0000 (12:30 -0700)
Summary: Link local is not the only type of address that is based on mac address, therefore create generic function to extract mac address from EUI-64 autoconfigured addresses using the same logic as for getMacAddressFromLinkLocal

Reviewed By: pallotron

Differential Revision: D5697781

fbshipit-source-id: 4d69085a1d8f08e06496b8a9b638ac7ff31c6c3a

folly/IPAddressV6.cpp
folly/IPAddressV6.h
folly/test/IPAddressTest.cpp

index 70f5c883c2b5a238dca7d190822c2d9d7527a7fc..45391b40232ccc4fef193184b892a00d65b65b61 100644 (file)
@@ -138,20 +138,23 @@ IPAddressV6::AddressStorage::AddressStorage(MacAddress mac) {
 
 Optional<MacAddress> IPAddressV6::getMacAddressFromLinkLocal() const {
   // Returned MacAddress must be constructed from a link-local IPv6 address.
-  if (!(addr_.bytes_[0] == 0xfe && addr_.bytes_[1] == 0x80 &&
-        addr_.bytes_[2] == 0x00 && addr_.bytes_[3] == 0x00 &&
-        addr_.bytes_[4] == 0x00 && addr_.bytes_[5] == 0x00 &&
-        addr_.bytes_[6] == 0x00 && addr_.bytes_[7] == 0x00 &&
-        addr_.bytes_[11] == 0xff && addr_.bytes_[12] == 0xfe)) {
+  if (!isLinkLocal()) {
     return folly::none;
   }
-  // The link-local address uses modified EUI-64 format,
+  return getMacAddressFromEUI64();
+}
+
+Optional<MacAddress> IPAddressV6::getMacAddressFromEUI64() const {
+  if (!(addr_.bytes_[11] == 0xff && addr_.bytes_[12] == 0xfe)) {
+    return folly::none;
+  }
+  // The auto configured address uses modified EUI-64 format,
   // See RFC 4291 sections 2.5.1, 2.5.6, and Appendix A
   std::array<uint8_t, MacAddress::SIZE> bytes;
-  // Step 1: first 8 bytes are fe:80:00:00:00:00:00:00, and can be stripped
+  // Step 1: first 8 bytes are network prefix, and can be stripped
   // Step 2: invert the universal/local (U/L) flag (bit 7)
   bytes[0] = addr_.bytes_[8] ^ 0x02;
-  // Step 3: copy thhese bytes are they are
+  // Step 3: copy these bytes as they are
   bytes[1] = addr_.bytes_[9];
   bytes[2] = addr_.bytes_[10];
   // Step 4: strip bytes (0xfffe), which are bytes_[11] and bytes_[12]
index 05cc5bdc4b2dff7bd10e24bb2789553fecbd7537..23c19e50c011ac7dd85136532d7f613e5061217c 100644 (file)
@@ -231,6 +231,16 @@ class IPAddressV6 {
    */
   Optional<MacAddress> getMacAddressFromLinkLocal() const;
 
+  /**
+   * Return the mac address if this is an auto-configured IPv6 address based on
+   * EUI-64
+   *
+   * @return an Optional<MacAddress> union representing the mac address.
+   * If the address is not based on EUI-64 it will return an empty Optional.
+   * You can use Optional::value() to check whether the mac address is not null.
+   */
+  Optional<MacAddress> getMacAddressFromEUI64() const;
+
   /**
    * Return true if this is a multicast address.
    */
index cc108184b52773794ce9f5cf381ae59739fa57d1..11ebac5f4f523def6423d5448d12f1ffc1442306 100644 (file)
@@ -1140,6 +1140,20 @@ TEST(IPAddress, getMacAddressFromLinkLocal_Negative) {
   EXPECT_FALSE(no_link_local_ip6.getMacAddressFromLinkLocal().hasValue());
 }
 
+TEST(IPAddress, getMacAddressFromEUI64) {
+  IPAddressV6 ip6("2401:db00:3020:51dc:4a57:ddff:fe04:5643");
+  EXPECT_TRUE(ip6.getMacAddressFromEUI64().hasValue());
+  EXPECT_EQ("48:57:dd:04:56:43", ip6.getMacAddressFromEUI64()->toString());
+  ip6 = IPAddressV6("fe80::4a57:ddff:fe04:5643");
+  EXPECT_TRUE(ip6.getMacAddressFromEUI64().hasValue());
+  EXPECT_EQ("48:57:dd:04:56:43", ip6.getMacAddressFromEUI64()->toString());
+}
+
+TEST(IPAddress, getMacAddressFromEUI64_Negative) {
+  IPAddressV6 not_eui64_ip6("2401:db00:3020:51dc:face:0000:009a:0000");
+  EXPECT_FALSE(not_eui64_ip6.getMacAddressFromEUI64().hasValue());
+}
+
 TEST(IPAddress, LongestCommonPrefix) {
   IPAddress ip10("10.0.0.0");
   IPAddress ip11("11.0.0.0");