bytes_[15] = macBytes[5];
}
+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)) {
+ return folly::none;
+ }
+ // The link-local 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 2: invert the universal/local (U/L) flag (bit 7)
+ bytes[0] = addr_.bytes_[8] ^ 0x02;
+ // Step 3: copy thhese bytes are they are
+ bytes[1] = addr_.bytes_[9];
+ bytes[2] = addr_.bytes_[10];
+ // Step 4: strip bytes (0xfffe), which are bytes_[11] and bytes_[12]
+ // Step 5: copy the rest.
+ bytes[3] = addr_.bytes_[13];
+ bytes[4] = addr_.bytes_[14];
+ bytes[5] = addr_.bytes_[15];
+ return Optional<MacAddress>(MacAddress::fromBinary(range(bytes)));
+}
+
void IPAddressV6::setFromBinary(ByteRange bytes) {
if (bytes.size() != 16) {
throw IPAddressFormatException(to<std::string>(
#include <stdexcept>
#include <folly/Hash.h>
+#include <folly/Optional.h>
#include <folly/Range.h>
#include <folly/detail/IPAddress.h>
*/
bool isLinkLocal() const;
+ /**
+ * Return the mac address if this is a link-local IPv6 address.
+ *
+ * @return an Optional<MacAddress> union representing the mac address.
+ *
+ * If the address is not a link-local one it will return an empty Optional.
+ * You can use Optional::value() to check whether the mac address is not null.
+ */
+ Optional<MacAddress> getMacAddressFromLinkLocal() const;
+
/**
* Return true if this is a multicast address.
*/
EXPECT_EQ("1.2.3.4", detail::fastIpv4ToString(a4));
}
+TEST(IPAddress, getMacAddressFromLinkLocal) {
+ IPAddressV6 ip6("fe80::f652:14ff:fec5:74d8");
+ EXPECT_TRUE(ip6.getMacAddressFromLinkLocal().hasValue());
+ EXPECT_EQ("f4:52:14:c5:74:d8", ip6.getMacAddressFromLinkLocal()->toString());
+}
+
+TEST(IPAddress, getMacAddressFromLinkLocal_Negative) {
+ IPAddressV6 no_link_local_ip6("2803:6082:a2:4447::1");
+ EXPECT_FALSE(no_link_local_ip6.getMacAddressFromLinkLocal().hasValue());
+ no_link_local_ip6 = IPAddressV6("fe80::f652:14ff:ccc5:74d8");
+ EXPECT_FALSE(no_link_local_ip6.getMacAddressFromLinkLocal().hasValue());
+ no_link_local_ip6 = IPAddressV6("fe80::f652:14ff:ffc5:74d8");
+ EXPECT_FALSE(no_link_local_ip6.getMacAddressFromLinkLocal().hasValue());
+ no_link_local_ip6 = IPAddressV6("fe81::f652:14ff:ffc5:74d8");
+ EXPECT_FALSE(no_link_local_ip6.getMacAddressFromLinkLocal().hasValue());
+}
+
TEST(IPAddress, LongestCommonPrefix) {
IPAddress ip10("10.0.0.0");
IPAddress ip11("11.0.0.0");