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.
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.
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/
...and another implementation... ...is IPv4_Utils at PyPI