Welcome, guest | Sign In | My Account | Store | Cart

Two simple classes for IPv4 addresses and networks. Features include checking if network contains another, returning ip/mask in normalized form, conversions from/to numeric/string, enumerating all contained ip addresses etc.

Python, 73 lines
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
# 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))

For example, to see all addresses in given net:

for ia in IPv4Network('192.168.1.192/26'): print ia

Also, you can do stuff like

net = IPv4Network('192.168.1.192/26') net.contains('192.168.1.123')

and IPv4Addr('192.168.1.192').next() # IPv4Addr('192.168.1.193')

etc.

2 comments

William McVey 18 years, 6 months ago  # | flag

IPy is an alternative. IPy is a package that fits a similar niche, with many more capabilities, not the least of which is IPv6 support. IPy is at http://c0re.23.nu/c0de/IPy/

Christos Georgiou 18 years, 6 months ago  # | flag

...and another implementation... ...is IPv4_Utils at PyPI