prettified, changed exercise generator for more diverse exercise parameters, changed printDotted to use IP as input instead of octets, changed comments to mirror the actual program, changed solution algorithm

This commit is contained in:
Neko 2023-09-07 10:10:32 +02:00
parent 0c4b095ab3
commit b76ba78beb

157
main.py
View File

@ -3,64 +3,56 @@ import random
def intToDotted(ip): def intToDotted(ip):
# input: ip # input: ip
# determins dotted decimal format for given ip as int # determins dotted decimal format for given ip as int
# returns list octets
# returns list: octets
octets = [] octets = []
while ip != 0: while ip != 0:
octets.append(ip % 256) octets.append(ip % 256)
ip = math.floor(ip / 256) ip = math.floor(ip / 256)
octets.reverse() octets.reverse()
return octets return octets
def printDotted(octets): def printDotted(ip):
# input: list containing octets # input: ip as integer
# returns the dotted decimal format
# returns out the dotted decimal format
# hint: use '.'.join() # hint: use '.'.join()
#returns prettyfied DD format as string # returns prettyfied dotted decimal format as string
octets = intToDotted(ip)
return ".".join(str(x) for x in octets) return ".".join(str(x) for x in octets)
def generateNetwork(): def generateNetwork():
# input: none # input: none
# generates a random ip and prefix # generates a random ip and prefix
# the generated prefix should be in the range [8, 30] # the generated prefix should be in the range [8, 29]
# to avoid getting too large and too small networks # to avoid getting too large and too small networks
# returns dict: {ip:int, prefix:int} # returns dict: {"ip":ip, "prefix":prefix}
ip = random.randint(0, 2**32-1) ip = random.randint(0, 2**32-1)
prefix = random.randint(8, 31) #max prefix generated is prefix = random.randint(8, 29) #max prefix generated is
# 30, allowing for at least 1 bit to be subnetted and still have hostbits left # 29, allowing for at least 1 bit to be subnetted and still have valid hosts left
ipandprefix = {"ip":ip, "prefix":prefix} ipandprefix = {"ip":ip, "prefix":prefix}
return ipandprefix return ipandprefix
def getNetId(ip, prefix):
snm=(2**prefix-1)<<(32-prefix)
netid = ip&snm
return netid
def analyseSubnet(ip, prefix): def analyseSubnet(ip, prefix):
# input: ip as int, prefix as int # input: ip as int, prefix as int
# returns net id, broadcast address
# returns dict: {"nid":netid, "bc":bc}
snm=(2**prefix-1)<<(32-prefix)
# prints out net id, broadcast address, netid = ip&snm
# and amount of addresses and amount of
# usable adresses for a given subnet
wmask = 0xffffffff >> prefix wmask = 0xffffffff >> prefix
bid = ip|wmask bc = ip|wmask
hostbits = 32 - prefix return {"nid":netid, "bc":bc}
hosts = 2**hostbits-2
print("Useable Hosts: {}".format(hosts))
ids = {"bid":bid}
return ids
# returns dict: {netid:int, bc:int}
def newSubnetExercises(ip, prefix): def newSubnetExercises(ip, prefix):
# input: a subnet, consisting of an ip # input: a subnet, consisting of an ip
@ -79,58 +71,85 @@ def newSubnetExercises(ip, prefix):
# "split the given network into...." # "split the given network into...."
# depending on the type of exercise # depending on the type of exercise
# returns dict: {ip: int, prefix:int, newprefix:int} # returns dict: {"ip":ip, "prefix":prefix, "newprefix":newprefix}
# newprefx contains the new subnet mask that solves the exercise # newprefix contains the new subnet mask that solves the exercise
aufgabentyp = random.randint(0,1) nid = analyseSubnet(ip, prefix).get("nid")
bonusaufgabe = random.randint(0,10) newprefix = random.randint(prefix+1, 30) # max 30 to leave 2 hostbits (no empty nets)
newprefix = random.randint(prefix+1, prefix+5) listnetwork = -1 #set this to -1, meaning "exercise did not appear"
print("Network: {}/{}".format(printDotted(intToDotted(ip)), prefix)) print("Exercise:\n")
print("newprefix: {}".format(newprefix)) print("Given Network: {}/{}\n".format(printDotted(nid), prefix))
if aufgabentyp == 0:
print("Split the Network into {} subnets".format(2**(newprefix-prefix))) # sanity assertions
assert(prefix<newprefix) #no supernetting, only subnetting, at least 1 bit difference
# (otherwise no subnets!)
assert(32-newprefix > 1) #must allow for more than 1 hostbit (no usable hosts otherwise)
if random.random() > 0.5:
#ask user to split into networks, but make sure the amount of networks
#requires to use the specific prefix generated by the exercise
#start is set to at least as much subnets as 1 bit less, but plus one so
#you cannot use one fewer bits for the new prefix
#end is set to exactly the amount of subnets possible with the newprefix
print("Split the Network into {} subnets".format(random.randint(2**(newprefix-prefix-1)+1,2**(newprefix-prefix))))
else: else:
print("Split the network into subnets with {} Hosts".format(2**(32-newprefix))) #ask user to split into hosts, but make sure the amount of hosts required
#requires the user to use at least the new prefix generated
#-1 at the start means it's at least enough hosts as 1 hostbit less
# -> since 2 hosts are left, using 1 less hostbit is not allowed
#-2 at the end makes sure the required amount of hosts still fit
# within the specific new prefix
print("Split the network into subnets with {} Hosts".format(random.randint(2**(32-newprefix-1),2**(32-newprefix)-2)))
if random.random() > 0.5:
listnetwork = random.randint(0, 2^(newprefix-prefix)-1) # user may list this network
#make the user list a specific network between 0 and the last
print("\nList the start and end of Subnet {}".format(listnetwork))
if bonusaufgabe > 5: return {"ip":ip, "prefix":prefix, "newprefix":newprefix, "listnetwork":listnetwork}
print("What is the Net ID of the given subnet?")
print("What is the start and end of the Subnet")
if bonusaufgabe > 8:
print("What is the Adress of the next subnet?")
subnetdic = {"ip":ip, "prefix":prefix, "newprefix":newprefix}
return subnetdic
def listSubnets(ip, prefix, newprefix): def listSubnets(ip, prefix, newprefix):
# input: a network range and a subnet prefix to split into DONE # input: a network range and a subnet prefix, a new prefix for subnetting
# note: sanity check with: assert newprefix > prefix
# this function prints out every possible network
# within the given range, showing net id and bc
# as well as amount of adresses and usable hosts per network
# returns: nothing, this just prints all possible subnets
# note: sanity check with: assert newprefix > prefix DONE
# this function prints out every possible network ???
# within the given range, showing net id and bc DONE
# as well as amount of adresses and usable hosts per network DONE
# returns: nothing, this just prints all possible subnets DONE
nid = getNetId(ip, prefix)
print(newprefix)
hostbits = 32-newprefix hostbits = 32-newprefix
newnetbits = newprefix - prefix newnets = 2**(newprefix-prefix)
newnetbits = 2**newnetbits nid = analyseSubnet(ip, prefix).get("nid")
for i in range(0,newnetbits):
print("subnet", i,":", printDotted(intToDotted(nid +i*2**hostbits))) for i in range(0,newnets):
if i > 25: print("Network", i,":", printDotted(nid+i*2**hostbits))
print("and many many more...") if i > 8:
#-10 -> we list network 0 to 9 (larger than 8), which is 10 already listed
print("and {} more...".format(newnets-10))
break break
if __name__ == '__main__': if __name__ == '__main__':
ipdic = generateNetwork()
ip = ipdic.get("ip")
prefix = ipdic.get("prefix")
newprefixdic = newSubnetExercises(ip=ip, prefix=prefix)
if input("Press Space and enter to continue") != "":
listSubnets(ip, prefix, newprefixdic.get("newprefix"))
# 1. Generate new exercise # 1. Generate new exercise
# 2. wait for user input, noting that the solution # 2. wait for user input, noting that the solution
# will be shown after after pressing any key # will be shown after after pressing any key
# 3. print the solution # 3. print the solution
# 4. exit # 4. exit
network = generateNetwork()
ip = network.get("ip")
prefix = network.get("prefix")
net = analyseSubnet(ip, prefix)
exercise = newSubnetExercises(ip=ip, prefix=prefix)
newprefix = exercise.get("newprefix")
listnetwork = exercise.get("listnetwork")
#wait for an enter to continue
input("\nPress Enter to show solution\n")
print("The original network starts at {} and ends at {}.".format(printDotted(net.get("nid")), printDotted(net.get("bc"))))
print("The new prefix is {}, allowing for {} subnets with {} Hosts each".format(newprefix, 2**(newprefix-prefix), 2**(32-newprefix)-2))
if(listnetwork >= 0):
subnet=analyseSubnet(net.get("nid")+listnetwork*2**(32-newprefix), newprefix)
print("Network {}: NID: {} BC: {}".format(listnetwork, printDotted(subnet.get("nid")), printDotted(subnet.get("bc"))))
print("\nSubnets:")
listSubnets(ip, prefix, newprefix)