EvilZone
Programming and Scripting => Scripting Languages => : flowjob July 29, 2014, 10:31:55 PM
-
NetCalc Subnet Calculator
I wrote that commandline scripts some months ago for school, as I was to lazy to calculate all that stuff by myself again and again...
It calculates the most important stuff like
- netmask/cidr
- maschine part (= inversed netmask)
- max-number of possible hosts
- broadcast addresse
- default gateway
Usage:
Either pass an IP and a netmask or an IP and CIDR as arguments
Example:
python2 netcalc.py 10.0.0.3 255.255.255.0
python2 netcalc.py 10.0.0.3/24
Source Code:
#!/usr/bin/env python2
import sys
def calcIPValue(ipaddr):
"""
Calculates the binary
value of the ip addresse
"""
ipaddr = ipaddr.split('.')
value = 0
for i in range(len(ipaddr)):
value = value | (int(ipaddr[i]) << ( 8*(3-i) ))
return value
def calcIPNotation(value):
"""
Calculates the notation
of the ip addresse given its value
"""
notat = []
for i in range(4):
shift = 255 << ( 8*(3-i) )
part = value & shift
part = part >> ( 8*(3-i) )
notat.append(str(part))
notat = '.'.join(notat)
return notat
def calcSubnet(cidr):
"""
Calculates the Subnet
based on the CIDR
"""
subn = 4294967295 << (32-cidr) # 4294967295 = all bits set to 1
subn = subn % 4294967296 # round it back to be 4 bytes
subn = calcIPNotation(subn)
return subn
def calcCIDR(subnet):
"""
Calculates the CIDR
based on the SUbnet
"""
cidr = 0
subnet = calcIPValue(subnet)
while subnet != 0:
subnet = subnet << 1
subnet = subnet % 4294967296
cidr += 1
return cidr
def calcNetpart(ipaddr,subnet):
ipaddr = calcIPValue(ipaddr)
subnet = calcIPValue(subnet)
netpart = ipaddr & subnet
netpart = calcIPNotation(netpart)
return netpart
def calcMacpart(subnet):
macpart = ~calcIPValue(subnet)
macpart = calcIPNotation(macpart)
return macpart
def calcBroadcast(ipaddr,subnet):
netpart = calcNetpart(ipaddr,subnet)
macpart = calcMacpart(subnet)
netpart = calcIPValue(netpart)
macpart = calcIPValue(macpart)
broadcast = netpart | macpart
broadcast = calcIPNotation(broadcast)
return broadcast
def calcDefaultGate(ipaddr,subnet):
defaultgw = calcNetpart(ipaddr,subnet)
defaultgw = calcIPValue(defaultgw) + 1
defaultgw = calcIPNotation(defaultgw)
return defaultgw
def calcHostNum(subnet):
macpart = calcMacpart(subnet)
hostnum = calcIPValue(macpart) - 1
return hostnum
def main():
if (len(sys.argv) == 2 and '/' in sys.argv[1]): # IPAdresse/CIDR
ipaddr = sys.argv[1].split('/')[0]
cidr = sys.argv[1].split('/')[1]
subnet = calcSubnet(int(cidr))
elif (len(sys.argv) == 3): # IPAdresse Subnet
ipaddr = sys.argv[1]
subnet = sys.argv[2]
cidr = calcCIDR(subnet)
else:
args = ' '.join(sys.argv[1:])
sys.exit('"' + args + '" is no valid combination of an IP and a Subnet/CIDR!')
print '==============================='
print 'IPv4: ' + ipaddr
print 'Netmask: ' + subnet
print 'CIDR: ' + str(cidr)
macpart = calcMacpart(subnet)
print 'Inversed Netmask: ' + macpart
hostnum = calcHostNum(subnet)
print 'Hosts: ' + str(hostnum)
netpart = calcNetpart(ipaddr,subnet)
print 'Network: ' + netpart
broadcast = calcBroadcast(ipaddr,subnet)
print 'Broadcast: ' + broadcast
defaultgw = calcDefaultGate(ipaddr,subnet)
print 'Default Gateway: ' + defaultgw
print '==============================='
if __name__ == '__main__':
main()
I also ported that script to C++ >> netcalc.cpp (https://evilzone.org/c-c/(c)-subnet-calculator)
-
Hey there, I've modified your calcSubnet() function to use the proper decimal representation for "all bits set to 1". I didn't like the use of the number you provided, as I couldn't find a reason (except for, maybe it just worked that way) to use '4294967295'.
Maybe you can provide some insight into why your code was written the way it was?
I feel like mine is still a little sloppy, but I'm still learning quite a lot, so I'm keen to see what you think :)
cidr = 16
def calcSubnet(cidr):
#Cidr into Subnet
Bits2Zero = 32-cidr #How many bits we'll need to zero
Bits2Decimal = 2**Bits2Zero #The calculation of bits into a decimal
AllBits = 2**32 #All bits in a IPv4 Address
#Convert it
Subnet = AllBits - Bits2Decimal #Decimal Representation of the subnet address
Subnet = calcIPNotation(Subnet) #Pass the decimal subnet into the function
print Subnet #Print the subnet adress
calcSubnet(cidr)
And I just made it better :)
cidr = 29
def calcSubnet(cidr):
DecimalSubnet = ( (2**32) - (2**(32-cidr)) )
Subnet = calcIPNotation(DecimalSubnet)
return Subnet
InverseSubnet = ~DecimalSubnet
Inverse = calcIPNotation(InverseSubnet)
return Inverse
calcSubnet(cidr)
-
I will just take a cookie for this stupid nursery school error. It typically shows you didn't test your code and you just put it here and trust me, i have received enough beating for not testing my code that i know better now.
I am talking about the two return statements that make no sense at all what their significance is. Style up and clean it up.
-
Erm, you could just replace 'return' with 'print' and you'll see the result. You'll need the full code flowjob has provided so that it works.
Adding 'print' under each variable will also show the value it provides before it's converted into a subnet address.
Or just add this function;
def calcIPNotation(value):
"""
Calculates the notation
of the ip addresse given its value
"""
notat = []
for i in range(4):
shift = 255 << ( 8*(3-i) )
part = value & shift
part = part >> ( 8*(3-i) )
notat.append(str(part))
notat = '.'.join(notat)
return notat
~sourced from flowjob's code, to the script you're shoving together.
-
#!/usr/bin/env python2
def calcSubnet(cidr):
"""
Calculates the Subnet
based on the CIDR
"""
subn = 4294967295 << (32-cidr) # 4294967295 = all bits set to 1
subn = subn % 4294967296 # round it back to be 4 bytes
subn = calcIPNotation(subn)
return subn
As I work through this more, I think I understand how you found '4294967295 '. Although 2^32 = 4294967296, is no the same as this; ( (((2^(8*3))*255)+(((2^(8*2))*255)+(((2^(8*1))*255)+(((2^(8*0))*255))))) ) = 4294967295, which is "255.255.255.255" technically the same value. Still researching as to why that is, but at least that explains what's going on.
-
As I work through this more, I think I understand how you found '4294967295 '. Although 2^32 = 4294967296, is no the same as this; ( (((2^(8*3))*255)+(((2^(8*2))*255)+(((2^(8*1))*255)+(((2^(8*0))*255))))) ) = 4294967295, which is "255.255.255.255" technically the same value. Still researching as to why that is, but at least that explains what's going on.
2 ^ 32 in binary:
1 0000 0000 0000 0000 0000 0000 0000 0000
whereas you want to have 2 ^ 32 - 1:
0 1111 1111 1111 1111 1111 1111 1111 1111
-
This is nice, thanks for sharing. I'll play around with this later.
-
Erm, you could just replace 'return' with 'print' and you'll see the result. You'll need the full code flowjob has provided so that it works.
Adding 'print' under each variable will also show the value it provides before it's converted into a subnet address.
Or just add this function;
def calcIPNotation(value):
"""
Calculates the notation
of the ip addresse given its value
"""
notat = []
for i in range(4):
shift = 255 << ( 8*(3-i) )
part = value & shift
part = part >> ( 8*(3-i) )
notat.append(str(part))
notat = '.'.join(notat)
return notat
~sourced from flowjob's code, to the script you're shoving together.
I was waiting fot the part where you admit you made a stupid mistake because mind you, return isn't the same as print. I don't have enough time now to explain but google your SHIT.