Reputation: 1845
I am asked to do an App to gives the total possible hosts for a subnet, Sadly I cannot use ipaddress
module provided from Python so I need to write my own methods to check and validate entered data
My Code is like this:
def IP_Validation(chk_IP_vaild):
if chk_IP_vaild.count(".") == 3 and all(isIP(i) for i in chk_IP_vaild.split(".")):
return True
return False
def isIP(IP_String):
try:
return str(int(IP_String)) == IP_String and 0 <= int(IP_String) <= 255
except:
return False
def Calc_Networks(IP_One , IP_Two):
if IP_Validation(IP_One) and IP_Validation(IP_Two):
print (IP_One,IP_Two)
else:
print ("There is an error")
Calc_Networks("172.11.254.1", "172.1.254.")
Calc_Networks("172.11.254.1", "172.1.254.0")
There is an error
172.11.254.1 172.1.254.0
but this only checks if entered IPs are IPv4, so I was googling and checking solutions over the Internet and I came across this:
import ipaddress
def calc_inclusive_subnet(ip1, ip2): #accepts 2 IP strings
#make IP Address objects
ip1_obj=ipaddress.IPv4Address(ip1)
ip2_obj=ipaddress.IPv4Address(ip2)
if ip1_obj<=ip2_obj:
min_ip=ip1_obj
max_ip=ip2_obj
else:
min_ip=ip2_obj
max_ip=ip1_obj
distance = int(max_ip)-int(min_ip) #**
return distance
print (calc_inclusive_subnet("192.168.1.0", "192.168.2.255"))
511
What I noticed that If I did a subtraction to two IPs declared with ipaddress
module it does it right with no problem so I went to the Docs in order to understand how this module handles IPs so I can use a similar method
Doing the subtraction using code 1 it gives the following error:
def Calc_Networks(IP_One , IP_Two):
if IP_Validation(IP_One) and IP_Validation(IP_Two):
dis = int(IP_Two) - int(IP_One)
return dis
The Output is:
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-154-9e53188ce6f1> in <module>
16
17
---> 18 print(Calc_Networks("172.11.254.1", "172.1.254.1"))
19 Calc_Networks("172.11.254.1", "172.1.254.")
<ipython-input-154-9e53188ce6f1> in Calc_Networks(IP_One, IP_Two)
12 def Calc_Networks(IP_One , IP_Two):
13 if IP_Validation(IP_One) and IP_Validation(IP_Two):
---> 14 dis = int(IP_Two) - int(IP_One)
15 return dis
16
ValueError: invalid literal for int() with base 10: '172.1.254.1'
also these posts 1 & 2 could not help me!
Thanks in advance
Upvotes: 1
Views: 95
Reputation: 1295
The reason that your Calc_Networks
code didn't work but the calc_inclusive_subnet
did is that in calc_inclusive_subnet
an ipaddress.IPv4Address
was passed to int
, which has an __int__
method, and gives you what you need. Your code, however, simply passes the string representation to int
, which tries to parse the IP address as a normal int, which "172.11.254.1"
isn't.
If you don't want to use ipaddress
you can still implement a function to parse the IP address into a single integer:
def parse_ip_to_int(ip_address):
octets = ip_address.split('.')
return int.from_bytes(map(int, octets), 'big')
The above function splits ip_address
into a list of strings, each string corresponding to one octet of the address (so for "172.11.254.1"
, ["172", "11", "254", "1"]
). We then use map
to convert those strings into int
s. Finally we use the useful int.from_bytes
, which allows us to convert that iterable of octets into one big integer. This could alternatively by achieved with a loop and bit shifting left by 8. The second argument of int.from_bytes
, 'big'
, indicates that the most significant octet is the first one, which is how IPv4 addresses are encoded.
From here we can now correctly implement your Calc_Networks
function. I have simplified it by using abs
to ensure the distance we obtain is positive, rather than finding the minimum and maximum like in the original calc_inclusive_subnet
.
def Calc_Networks(IP_One, IP_Two):
if IP_Validation(IP_One) and IP_Validation(IP_Two):
return abs(parse_ip_to_int(IP_One) - parse_ip_to_int(IP_Two))
Similar to your initial implementation, if the validation fails, then None
is returned. A final note, although what I've presented does produce the same results as the calc_inclusive_subnet
you've shown, all that function did was count the number of addresses from a starting address up to, but not including, an end address. Your desired behaviour may be different.
Upvotes: 1