Welcome, guest | Sign In | My Account | Store | Cart
# Simple module for handling IPv4 addresses.

# Many thanks to Steve Holden (http://www.holdenweb.com/) for method
# min_container() and other helpful advice.

import struct
from socket import inet_aton, inet_ntoa, error as socket_error

MAX_IPV4_ADDR = 0xFFFFFFFFL

def len_to_bitmask(mask):
    """Return mask length as bitmask"""
    assert 0 <= mask <= 32
    
    return ((2L << mask - 1) - 1) << (32 - mask)
       	
def bit_to_lenmask(bitmask):
    """Convert bitmask to mask length."""

    mask = 32
    while bitmask % 2 == 0:
        bitmask = bitmask >> 1
        mask -= 1
    return mask

def quad_to_dec(addr):
    """Return dotted ip address string as long integer

    Raise IPv4AddrTypeError if address is illegal.
    """

    try:
        return struct.unpack('>L', inet_aton(addr))[0]
    except socket_error:
        raise IPv4AddrTypeError(addr)

def dec_to_quad(num):
    """Return integer ip address in dotted format

    Raise OverflowError if num is too large.
    
    >>> dec_to_quad(2**24+2**16+2**8)
    '1.1.1.0'
    >>> dec_to_quad(3243242652)
    '193.79.244.156'
    """

    return inet_ntoa(struct.pack('>L', num))

class IPv4AddrTypeError(TypeError):
    def __init__(self, addr):
        self.addr = addr
    def __str__(self):
        return "Illegal IPv4 address '%s'" % self.addr
        
class IPv4Addr:
    """Class for representing IPv4 addresses"""

    def __init__(self, addr):
        """Instantiate object.

        @param addr: dotted-quad ip address string
        """
        
        self.mask = 32                  # to help uniform handling of subnets
        self._binmask = MAX_IPV4_ADDR

        self.numeric = quad_to_dec(addr)
        self.string = addr
                     
    def mask_with(self, mask):
        """Return dotted-quad address masked with mask"""
        return dec_to_quad(self.numeric & len_to_bitmask(mask))

History