Convert dotted-quad IP addresses to long integer and back, get network and host portions from an IP address, all nice and fast thanks to the builtin socket module (with a little help from the builtin struct module, too).
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
# IP address manipulation functions, dressed up a bit import socket, struct def dottedQuadToNum(ip): "convert decimal dotted quad string to long integer" return struct.unpack('L',socket.inet_aton(ip)) def numToDottedQuad(n): "convert long int to dotted quad string" return socket.inet_ntoa(struct.pack('L',n)) def makeMask(n): "return a mask of n bits as a long integer" return (2L<<n-1)-1 def ipToNetAndHost(ip, maskbits): "returns tuple (network, host) dotted-quad addresses given IP and mask size" # (by Greg Jorgensen) n = dottedQuadToNum(ip) m = makeMask(maskbits) host = n & m net = n - host return numToDottedQuad(net), numToDottedQuad(host)
As per http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/65219, but Python "comes with batteries included", and thus offers excellent, fast and simple ways to perform many such tasks -- socket.inet_aton and .inet_ntoa to convert between dotted quads and packed strings, struct.pack and .unpack to convert between packed strings and other forms of data (here, longs).
It's generally better to use Python-supplied functionality -- it's most likely going to be faster than what one can recode oneself, and most likely also faster to code and requiring less maintenance.
Careful: byte-order -> example is not correct on usual (PC) platforms. Hi!
The interpretation via the struct-module is not correct on most platforms. You have to force interpretation in network (= big-endian) byte order, i.e. "!L" as format string, not just "L".
makeMask fails with argument of 0. Yes, obviously there's not much point to calling with 0, as it's a no-op, but "it's easier to ask forgiveness than permission."
Here's a version that works with the (valid) input of 0:
IPv6? Is there a similar lib for IPv6 addresses?