import math import random print("Made by VitaAeterna and NekoSilvertail https://github.com/VitaAetaerna/SubnetExerciseGenerator/") def intToDotted(ip): # input: ip # determins dotted decimal format for given ip as int # returns list octets octets = [] while ip != 0: octets.append(ip % 256) ip = math.floor(ip / 256) octets.reverse() return octets def printDotted(ip): # input: ip as integer # returns the dotted decimal format # hint: use '.'.join() # 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, 29] # to avoid getting too large and too small networks # returns dict: {"ip":ip, "prefix":prefix} 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} snm=(2**prefix-1)<<(32-prefix) netid = ip&snm wmask = 0xffffffff >> prefix bc = ip|wmask return {"nid":netid, "bc":bc} def newSubnetExercises(ip, prefix): # input: a subnet, consisting of an ip # and a given prefix # generates a new subnet exercise # 1. determine the type of exercise # types: split into x subnets # split into subnets with x hosts # 2. print out the given subnet # 3. determine if there is optional exercises # like determining a specific subnet (start, end), etc # think of new types of exercises to add into this # output logic # 4. print out the exercise: # "split the given network into...." # depending on the type of exercise # returns dict: {"ip":ip, "prefix":prefix, "newprefix":newprefix} # newprefix contains the new subnet mask that solves the exercise 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" print("Exercise:\n") print("Given Network: {}/{}\n".format(printDotted(nid), prefix)) # sanity assertions assert(prefix 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, 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") 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__': # 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) input("\nPress enter to exit\n")