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

167
main.py
View File

@ -3,64 +3,56 @@ import random
def intToDotted(ip):
# input: ip
# determins dotted decimal format for given ip as int
# returns list: octets
# returns list octets
octets = []
while ip != 0:
octets.append(ip % 256)
ip = math.floor(ip / 256)
octets.reverse()
return octets
def printDotted(octets):
# input: list containing octets
# returns out the dotted decimal format
def printDotted(ip):
# input: ip as integer
# returns the dotted decimal format
# 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)
def generateNetwork():
# input: none
# 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
# returns dict: {ip:int, prefix:int}
ip = random.randint(0, 2**32-1)
prefix = random.randint(8, 31) #max prefix generated is
# 30, allowing for at least 1 bit to be subnetted and still have hostbits left
ipandprefix = {"ip":ip, "prefix":prefix}
return ipandprefix
# returns dict: {"ip":ip, "prefix":prefix}
def getNetId(ip, prefix):
snm=(2**prefix-1)<<(32-prefix)
netid = ip&snm
return netid
ip = random.randint(0, 2**32-1)
prefix = random.randint(8, 29) #max prefix generated is
# 29, allowing for at least 1 bit to be subnetted and still have valid hosts left
ipandprefix = {"ip":ip, "prefix":prefix}
return ipandprefix
def analyseSubnet(ip, prefix):
# input: ip as int, prefix as int
# returns net id, broadcast address
# returns dict: {"nid":netid, "bc":bc}
# prints out net id, broadcast address,
# and amount of addresses and amount of
# usable adresses for a given subnet
snm=(2**prefix-1)<<(32-prefix)
netid = ip&snm
wmask = 0xffffffff >> prefix
bid = ip|wmask
bc = ip|wmask
hostbits = 32 - prefix
hosts = 2**hostbits-2
print("Useable Hosts: {}".format(hosts))
ids = {"bid":bid}
return ids
# returns dict: {netid:int, bc:int}
return {"nid":netid, "bc":bc}
def newSubnetExercises(ip, prefix):
# input: a subnet, consisting of an ip
@ -79,58 +71,85 @@ def newSubnetExercises(ip, prefix):
# "split the given network into...."
# depending on the type of exercise
# returns dict: {ip: int, prefix:int, newprefix:int}
# newprefx contains the new subnet mask that solves the exercise
# returns dict: {"ip":ip, "prefix":prefix, "newprefix":newprefix}
# newprefix contains the new subnet mask that solves the exercise
aufgabentyp = random.randint(0,1)
bonusaufgabe = random.randint(0,10)
newprefix = random.randint(prefix+1, prefix+5)
print("Network: {}/{}".format(printDotted(intToDotted(ip)), prefix))
print("newprefix: {}".format(newprefix))
if aufgabentyp == 0:
print("Split the Network into {} subnets".format(2**(newprefix-prefix)))
else:
print("Split the network into subnets with {} Hosts".format(2**(32-newprefix)))
nid = analyseSubnet(ip, prefix).get("nid")
newprefix = random.randint(prefix+1, 30) # max 30 to leave 2 hostbits (no empty nets)
listnetwork = -1 #set this to -1, meaning "exercise did not appear"
if bonusaufgabe > 5:
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?")
print("Exercise:\n")
print("Given Network: {}/{}\n".format(printDotted(nid), prefix))
subnetdic = {"ip":ip, "prefix":prefix, "newprefix":newprefix}
return subnetdic
# 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:
#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))
return {"ip":ip, "prefix":prefix, "newprefix":newprefix, "listnetwork":listnetwork}
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
hostbits = 32-newprefix
newnets = 2**(newprefix-prefix)
nid = analyseSubnet(ip, prefix).get("nid")
# 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
newnetbits = newprefix - prefix
newnetbits = 2**newnetbits
for i in range(0,newnetbits):
print("subnet", i,":", printDotted(intToDotted(nid +i*2**hostbits)))
if i > 25:
print("and many many more...")
for i in range(0,newnets):
print("Network", i,":", printDotted(nid+i*2**hostbits))
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
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
# 2. wait for user input, noting that the solution
# will be shown after after pressing any key
# 3. print the solution
# 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)