0

I am trying to convert a group of IP ranges that can start and end on any given address, but not necessarily on a .0, .127, or .255, etc. I have code that is mostly working; however, it can be slow for large ranges.

For example find_range("1.40.0.0","1.44.255.255") will take over a minute to return the correct result of 1.40.0.0/14 and 1.44.0.0/16.

Also, I am have trouble when the starting range does not end with a .0. How can I fix these 2 issues: slowness on large IP ranges and when the starting range does not end in .0?

For the slowness problem, I tried skipping more than 1 address at a time, but then this would miss smaller ranges.

import ipaddress, socket, struct
def ip2int(addr): 
 return struct.unpack("!I", socket.inet_aton(addr))[0] 
def int2ip(addr): 
 return socket.inet_ntoa(struct.pack("!I", addr)) 
def ipminus(ip, amount=1):
 tmp = ip2int(ip)
 return int2ip(tmp - amount)
def ipplus(ip):
 tmp = ip2int(ip)
 return int2ip(tmp + 1)
def cidr_notation(a,b):
 for mask in range(32, 6, -1):
 test = "%s/%s" % (a,mask)
 try:
 n = ipaddress.IPv4Network(test,False)
 if b == "%s" % (n.broadcast_address):
 return test
 except:
 pass
 return None
def split_range(a,b):
 a1 = ip2int(a)
 b1 = ip2int(b)
 needed = 1
 while needed:
 result = cidr_notation(a,b)
 if result:
 print( "* %16s\t%16s\t%16s" % (result, a, b))
 if ip2int(b) > b1:
 needed = 0
 else:
 a = ipplus(b)
 b = int2ip(b1)
 else:
 b = ipminus(b)
 return result
def find_range(x,y):
 result = cidr_notation(x,y)
 if result:
 print( "# %16s\t%16s\t%16s" % (result, x, y))
 else:
 split_range(x,y)
# main...
print("%16s\t%16s\t%16s" % ("mask","start","end"))
print("%16s\t%16s\t%16s" % ("----","-----","---"))
find_range("128.191.0.0","128.191.255.255") #fast
find_range("10.55.96.106","10.55.96.106") #fast
find_range("5.135.14.0","5.135.61.11") #slow
find_range("4.31.64.72","4.59.175.255") #does not work, how to fix?
find_range("1.40.0.0","1.44.255.255") #very slow
# 5000 more find_range() calls...
asked Jul 15, 2013 at 20:50
1

1 Answer 1

1

Based on bsdlp's comment, this code got a lot simpler and faster!

 def find_range(x,y,c_code="",c_name=""):
 print()
 print("%29s\t%23s" % (x,y))
 print("%16s\t%16s\t%16s\t%4s\t%s" % ("mask","start","end","code","name"))
 print("%16s\t%16s\t%16s\t%4s\t%s" % ("----","-----","---","----","----"))
 result = ipaddress.summarize_address_range( ipaddress.IPv4Address(x), ipaddress.IPv4Address(y) )
 for entry in result:
 net = str( entry.network_address )
 bcast = str( entry.broadcast_address )
 print( "%16s\t%16s\t%16s\t%4s\t%s" % (entry, net, bcast,c_code,c_name))
answered Jul 16, 2013 at 13:32
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.