blob: d293823e20a87aa018ef5e8d0db9ba3af9f0a0e0 [file] [log] [blame]
// Copyright 2017 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef GARNET_LIB_WLAN_COMMON_INCLUDE_WLAN_COMMON_MACADDR_H_
#define GARNET_LIB_WLAN_COMMON_INCLUDE_WLAN_COMMON_MACADDR_H_
#include <lib/fidl/cpp/array.h>
#include <zircon/compiler.h>
#include <zircon/types.h>
#include <algorithm>
#include <cstddef>
#include <string>
namespace wlan {
namespace common {
// This macro provides memory safe C-style string.
#define MACSTR(mac_addr) (mac_addr).ToString().c_str()
// ISO/IEC 10039
// See http://standards.ieee.org/develop/regauth/tut/macgrp.pdf
constexpr size_t kMacAddrLen = 6; // bytes
struct MacAddr {
// Consider if this should be private. Pay attention to byte alignment.
uint8_t byte[kMacAddrLen];
MacAddr() {}
MacAddr(const MacAddr& addr) { Set(addr); }
explicit MacAddr(const std::string& addr) { Set(addr); }
explicit MacAddr(const uint8_t addr[kMacAddrLen]) { Set(addr); }
explicit MacAddr(::fidl::Array<uint8_t, 6> addr) { Set(addr.data()); }
explicit MacAddr(std::initializer_list<uint8_t> addr) { Set(addr); }
explicit MacAddr(uint64_t val) {
for (size_t i = 0; i < kMacAddrLen; i++) {
byte[kMacAddrLen - 1 - i] = val & 0xff;
val >>= 8;
}
}
std::string ToString() const {
char buf[17 + 1];
std::snprintf(buf, 17 + 1, "%02x:%02x:%02x:%02x:%02x:%02x", byte[0], byte[1], byte[2],
byte[3], byte[4], byte[5]);
return std::string(buf);
}
void Reset() { std::memset(byte, 0x00, kMacAddrLen); }
int Cmp(const MacAddr& addr) const { return memcmp(byte, addr.byte, kMacAddrLen); }
// TODO(porce): inline
bool operator==(const MacAddr& addr) const { return Cmp(addr) == 0; }
bool operator!=(const MacAddr& addr) const { return !(*this == addr); }
bool operator>(const MacAddr& addr) const { return Cmp(addr) > 0; }
bool operator<(const MacAddr& addr) const { return Cmp(addr) < 0; }
bool IsZero() const {
// Note kZeroMac not used here. struct forward declaration can't be used.
for (size_t idx = 0; idx < kMacAddrLen; idx++) {
if (byte[idx] != 0x00) return false;
}
return true;
}
bool IsBcast() const {
// Note kBcastMac not used here. struct forward declaration can't be used.
for (size_t idx = 0; idx < kMacAddrLen; idx++) {
if (byte[idx] != 0xff) return false;
}
return true;
}
bool IsUcast() const { return (byte[0] & 0x01) == 0; }
bool IsMcast() const { return !IsUcast(); }
bool IsLocalAdmin() const { return byte[0] & 0x02; }
bool IsStdGroupAddr() const {
// IEEE 802.1D MAC bridge Standard MAC Group Addresses
// IEEE range: 01:80:c2:00:00:00 - 01:80:c2:ff:ff:ff
if (byte[0] == 0x01 && byte[1] == 0x80 && byte[2] == 0xc2) { return true; }
// ISO 9542 MAC Group Addresses
if (byte[0] == 0x09 && byte[1] == 0x00 && byte[2] == 0x2b && byte[3] == 0x00 &&
byte[4] == 0x00 && (byte[5] == 0x04 || byte[5] == 0x05)) {
return true;
}
// TokenRing functional addresses not honored.
return false;
}
// IEEE 802.11-2016, 9.2.4.3.3
bool IsGroupAddr() const { return IsMcast() || IsBcast(); }
// Overloaded initializers.
void Set(const MacAddr& addr) { std::memcpy(byte, addr.byte, kMacAddrLen); }
void Set(const std::string& addr) { FromStr(addr); }
void Set(const uint8_t addr[kMacAddrLen]) { std::memcpy(byte, addr, kMacAddrLen); }
void Set(std::initializer_list<uint8_t> addr) {
if (addr.size() == kMacAddrLen) std::copy(addr.begin(), addr.end(), byte);
}
bool FromStr(const std::string& str) {
// Accepted format: xx:xx:xx:xx:xx:xx
// TODO(porce): Support xx-xx-xx-xx-xx-xx, xxxx.xxxx.xxxx, xxxxxxxxxxxx
if (str.length() != 17) { return false; }
unsigned int tmp[kMacAddrLen];
int result = std::sscanf(str.c_str(), "%02x:%02x:%02x:%02x:%02x:%02x", &tmp[0], &tmp[1],
&tmp[2], &tmp[3], &tmp[4], &tmp[5]);
if (kMacAddrLen != static_cast<size_t>(result)) { return false; }
for (size_t idx = 0; idx < kMacAddrLen; idx++) {
byte[idx] = (uint8_t)tmp[idx];
}
return true;
}
uint64_t ToU64() const {
uint64_t m = 0;
for (size_t idx = 0; idx < kMacAddrLen; idx++) {
m <<= 8;
m |= byte[idx];
}
return m;
}
inline void* CopyTo(void* dst) const { return memcpy(dst, byte, kMacAddrLen); }
} __PACKED;
struct MacAddrHasher {
std::size_t operator()(const MacAddr& addr) const {
return std::hash<uint64_t>()(addr.ToU64());
}
};
// Defined in macaddr.cpp
extern const MacAddr kZeroMac;
extern const MacAddr kBcastMac;
} // namespace common
} // namespace wlan
#endif // GARNET_LIB_WLAN_COMMON_INCLUDE_WLAN_COMMON_MACADDR_H_