Finding largest netmask for given set of hosts
Steve Holden
sholden at holdenweb.com
Fri Aug 9 09:13:35 EDT 2002
"Edvard Majakari" <edvard.majakari at staselog.com> wrote in message
news:873ctotgvw.fsf at titan.staselog.com...
>
> I'm trying to construct a class method which returns the smallest possible
> network (largest netmask) for given set of hosts.
>
> Now, I have list of ip addresses in object variable self._list. Each IP
> address is in binary format (32-bit long)
>
> The algorithm is below:
>
> def gen_mask(self):
>
> nw = self._list[0] # initialise network to first ip address
> nm = 0xFFFFFFFFL # initialise netmask to 255.255.255.255
(32)
>
> # for every other ip in the list
> for ip in self._list[1:]:
> nw = nw & nm # AND network with netmask
>
> # XOR the network with ip address. All differing bits
> # should be ones after XOR, and all bits that are same should
> # be ones
>
> x = nw ^ ip
>
> # now, if nw was 192.128.11.12 and first ip was 192.128.11.20,
> # result of x should be 24L, which is corresponds to bitmask
of
> # 00000000000000000000000000011000. However, this is
> # undesirable - we need a bitmask that has ones for the
> # constant parts of the ip addresses and zeroes for the rest.
> # by inverting x (~ x) we get
> # 11111111111111111111111111100111, which still contains
> # one at the end of the bitstring. We get rid of this bit
> # by calling a function that zeroes all the rest bits after
> # the first zero bit:
>
> nm = zero_after_first_zero(dec2bin(~x))
>
> # now nm (according to the example) is
> # 11111111111111111111111111100000. We use this to
> # to recalculate new network:
> nw = nw & nm
>
> # now nw should be 192.128.11.0 and netmask is 27
>
> return nw
>
>
> The problem is that in Python, it seems quite difficult to create a
> routine dec2bin that would handle binary digits. I also doubt the
> algorithm is the best for this kind of thing.
>
> I wonder is there any existing Python modules that would do this kind of
> thing? I searched one for days (using Google), but didn't find any..
>
The first thing to note is that (version 4) IP addresses are 32-bit numbers,
which means that most Python implementations can handle them as integers and
use the bit-wise operations on them. Consequently, if all addresses are
converted before use, you won't need dec2bin. A naiive implementation will
end up producing long integers for anything above the class A space,
however. Unless efficiency is *really* important I'd overlook this as long
as your Python is recent enough to implicitly convert. You could even
explicitly use longs if you wanted.
Here's a simple implementation using these ideas. I haven't tested it
thoroughly, and it certainly hasn't been written for efficiency, but it
should give you something to play with.
def iptonum(s):
l = s.split('.')
addr = 0
for byte in l:
addr = 256*addr+int(byte)
return long(addr)
def numtoip(a):
l = []
for i in range(4):
l.append(str(a & 0xFF))
a >>= 8
l.reverse()
return ".".join(l)
addlist = [iptonum(x) for x in
['192.168.10.23',
'192.168.10.15',
'192.168.14.15',
'192.168.12.25']
]
mask = iptonum('255.255.255.255')
net = addlist[0]
for add in addlist[1:]:
mask = net ^ ~add
net = net & mask
#
# Now set all bits to the right of
# the leftmost zero to zero for the correct
# netmask, and use the mask to derive the
# correct network number.
#
zeros = 0
for bit in range(32, 0, -1):
pos = bit -1
zeros = zeros | (~mask & (1<< pos))
if zeros:
mask = mask & ~(1 << pos)
net = net & mask
print "Mask: ", numtoip(mask)
print "Network:", numtoip(net)
regards
-----------------------------------------------------------------------
Steve Holden http://www.holdenweb.com/
Python Web Programming http://pydish.holdenweb.com/pwp/
-----------------------------------------------------------------------
More information about the Python-list
mailing list