/* * © Copyright 2014 – Urheberrechtshinweis * Alle Rechte vorbehalten / All Rights Reserved * * Programmcode ist urheberrechtlich geschuetzt. * Das Urheberrecht liegt, soweit nicht ausdruecklich anders gekennzeichnet, bei Frank Ebner. * Keine Verwendung ohne explizite Genehmigung. * (vgl. § 106 ff UrhG / § 97 UrhG) */ #ifndef MACADDRESS_H #define MACADDRESS_H #include #include #include "../Exception.h" /** * describes a MAC-Address as 64-bit integer. * provides 8-bit access to all 6 values */ union MACAddress { private: /** fieldwise access */ struct { uint8_t h5; uint8_t h4; uint8_t h3; uint8_t h2; uint8_t h1; uint8_t h0; } fields; /** store as 64-bit integer */ uint64_t mac = 0; public: /** empty ctor */ MACAddress() { ; } /** copy ctor */ MACAddress(const MACAddress& o) : mac(o.mac) { ; } /** ctor form long */ MACAddress(const uint64_t mac) : mac(mac) { ; } /** ctor form string (e.g. "xx:xx:xx:xx:xx:xx") */ MACAddress(const std::string& str) { // sanity check if (str.size() == 17 ){ mac = 0; // all zeros fields.h5 = hexWordToInt(str[ 0], str[ 1]); fields.h4 = hexWordToInt(str[ 3], str[ 4]); fields.h3 = hexWordToInt(str[ 6], str[ 7]); fields.h2 = hexWordToInt(str[ 9], str[10]); fields.h1 = hexWordToInt(str[12], str[13]); fields.h0 = hexWordToInt(str[15], str[16]); } else if (str.size() == 12){ mac = 0; // all zeros fields.h5 = hexWordToInt(str[ 0], str[ 1]); fields.h4 = hexWordToInt(str[ 2], str[ 3]); fields.h3 = hexWordToInt(str[ 4], str[ 5]); fields.h2 = hexWordToInt(str[ 6], str[ 7]); fields.h1 = hexWordToInt(str[ 8], str[ 9]); fields.h0 = hexWordToInt(str[10], str[11]); } else{ throw Exception("invalid hex string length. must be 17 or 12 (without :)"); } } uint8_t getField(const int idx) const { switch(idx) { case 0: return fields.h0; case 1: return fields.h1; case 2: return fields.h2; case 3: return fields.h3; case 4: return fields.h4; case 5: return fields.h5; } throw Exception("field-idx out of bounds"); } /** convert to lower-case hex-string ("xx:xx:xx:xx:xx:xx") */ std::string asString() const { std::string str = ":::::::::::::::::"; intToHexStr(fields.h5, &str[ 0]); intToHexStr(fields.h4, &str[ 3]); intToHexStr(fields.h3, &str[ 6]); intToHexStr(fields.h2, &str[ 9]); intToHexStr(fields.h1, &str[12]); intToHexStr(fields.h0, &str[15]); return str; } /** get the mac address as a long-int value */ uint64_t asLong() const { // even if we initialized all 8 bytes with zero // we mask the 2 unsued bytes to be absolutely safe return mac & 0x0000FFFFFFFFFFFF; } /** equal? */ bool operator == (const MACAddress& o) const { return o.asLong() == asLong(); } /** not equal? */ bool operator != (const MACAddress& o) const { return o.asLong() != asLong(); } private: /** convert the given hex char [0-F] to an integer [0-15] */ static uint8_t hexCharToInt(const char hex) { // convert if (hex >= '0' && hex <= '9') { // digits return (hex - '0'); } else if (hex >= 'a' && hex <= 'f') { // lower case return (hex - 'a' + 10); } else if (hex >= 'A' && hex <= 'F') { // upper case return (hex - 'A' + 10); } // found an invalid character throw Exception("invalid character within MAC address"); } /** convert the given hex-word to an integer */ static uint8_t hexWordToInt(const char hi, const char lo) { return hexCharToInt(hi) << 4 | hexCharToInt(lo); } /** conver the given integer [0-15] to a hex char [0-F] */ static char intToHexChar(const uint8_t val) { return (val < 10) ? ('0' + val) : ('A' - 10 + val); } /** insert two hex chars into the provided string buffer */ static void intToHexStr(const uint8_t val, char* dst) { dst[0] = intToHexChar((val >> 4) & 0xF); dst[1] = intToHexChar((val >> 0) & 0xF); } }; /** hash-method for MAC-Addresses */ namespace std { template <> struct hash { std::size_t operator() (const MACAddress& mac) const { return std::hash()(mac.asLong()); } }; } #endif // MACADDRESS_H