Source code for dhcp_types.mac

# -*- encoding: utf-8 -*-
"""
libpydhcpserver.dhcp_types.mac
==============================
Defines a standard way of representing MACs within the library.

Legal
-----
This file is part of libpydhcpserver.
libpydhcpserver is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.

(C) Neil Tallim, 2014 <flan@uguu.ca>
(C) Mathieu Ignacio, 2008 <mignacio@april.org>
"""
try:
    from types import StringTypes
except ImportError: #py3k
    StringTypes = (str,)
    
IntegerTypes = (int,)
try:
    IntegerTypes = (int, long)
except ImportError: #py3k
    pass
    
from conversion import (listToNumber)

[docs]class MAC(object): """ Provides a standardised way of representing MACs. """ _mac = None #: The MAC encapsulated by this object, as a tuple of bytes. _mac_integer = None #: The MAC as an integer. _mac_string = None #: The MAC as a colon-delimited, lower-case string. def __init__(self, address): """ Constructs a MAC abstraction from a concrete representation. :param address: A MAC, which may be a string of twelve hex digits, optionally separated by non-hex characters, like ':', '.', or '-', a sequence of six bytes, or an unsigned integer. :except ValueError: The address could not be processed. """ if isinstance(address, IntegerTypes): if not 0 <= address <= 281474976710655: raise ValueError("'%(ip)i' is not a valid IP: not a 32-bit unsigned integer" % { 'ip': address, }) self._mac_integer = int(address) self._mac = ( self._mac_integer >> 40 & 0xFF, self._mac_integer >> 32 & 0xFF, self._mac_integer >> 24 & 0xFF, self._mac_integer >> 16 & 0xFF, self._mac_integer >> 8 & 0xFF, self._mac_integer & 0xFF, ) elif isinstance(address, StringTypes): address = [c for c in address.lower() if c.isdigit() or 'a' <= c <= 'f'] if len(address) != 12: raise ValueError("Expected twelve hex digits as a MAC identifier; received " + str(len(address))) mac = [] while address: mac.append(int(address.pop(0), 16) * 16 + int(address.pop(0), 16)) self._mac = tuple(mac) else: self._mac = tuple(address) if len(self._mac) != 6 or any((type(d) is not int or d < 0 or d > 255) for d in self._mac): raise ValueError("Expected a sequence of six bytes as a MAC identifier; received " + repr(self._mac)) def __cmp__(self, other): if not other and not isinstance(other, MAC): return 1 if isinstance(other, IntegerTypes): return cmp(int(self), other) if isinstance(other, StringTypes): other = MAC(other) return cmp(self._mac, tuple(other)) def __hash__(self): return hash(self._mac) def __getitem__(self, index): return self._mac[index] def __nonzero__(self): return any(self._mac) def __int__(self): if self._mac_integer is None: self._mac_integer = listToNumber(self._mac) return self._mac_integer def __long__(self): return long(int(self)) def __repr__(self): return "MAC(%r)" % (str(self)) def __str__(self): if self._mac_string is None: self._mac_string = "%02x:%02x:%02x:%02x:%02x:%02x" % self._mac return self._mac_string