From: Andrii Kryzhyk Date: Thu, 24 Aug 2017 19:08:18 +0000 (-0700) Subject: Create generic method to extract mac address from EUI-64 constructed addresses X-Git-Tag: v2017.08.28.00~8 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=de75bdc4d39c3983ff8b1d09c4eddab415bc893b;hp=f2d4ac87c2a6c1903e181f4bc76ce6e7b13620c1;p=folly.git Create generic method to extract mac address from EUI-64 constructed addresses 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 --- diff --git a/folly/IPAddressV6.cpp b/folly/IPAddressV6.cpp index 70f5c883..45391b40 100644 --- a/folly/IPAddressV6.cpp +++ b/folly/IPAddressV6.cpp @@ -138,20 +138,23 @@ IPAddressV6::AddressStorage::AddressStorage(MacAddress mac) { Optional 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 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 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] diff --git a/folly/IPAddressV6.h b/folly/IPAddressV6.h index 05cc5bdc..23c19e50 100644 --- a/folly/IPAddressV6.h +++ b/folly/IPAddressV6.h @@ -231,6 +231,16 @@ class IPAddressV6 { */ Optional getMacAddressFromLinkLocal() const; + /** + * Return the mac address if this is an auto-configured IPv6 address based on + * EUI-64 + * + * @return an Optional 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 getMacAddressFromEUI64() const; + /** * Return true if this is a multicast address. */ diff --git a/folly/test/IPAddressTest.cpp b/folly/test/IPAddressTest.cpp index cc108184..11ebac5f 100644 --- a/folly/test/IPAddressTest.cpp +++ b/folly/test/IPAddressTest.cpp @@ -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");