import re import math import json from typing import no_type_check valid_ranges = [ { "ip": "00001010000000000000000000000000", # 10.0.0.0/8 "sub":"11111111000000000000000000000000" }, { "ip": "10101100000100000000000000000000", # 172.16.0.0/12 "sub":"11111111111100000000000000000000" }, { "ip": "11000000101010000000000000000000", # 192.168.0.0/16 "sub":"11111111111111110000000000000000" } ] SUBNETLENGTH = 32 ip_regex = re.compile("^([0-9]{1,3}\\.){3}[0-9]{1,3}/[0-9]{1,2}$") def compIpSub(ip1, ip2, sub): for i,ii,s in zip(ip1, ip2, sub): if s == '1': if i != ii: return False return True def convSubBin(sub): a = "1"*int(sub) return f'{a:0<32}' def convDecBin(dec): return "{:08b}".format(int(dec)) def convIpBin(ip): out_string = "" for seg in ip.split("."): out_string += convDecBin(seg) return out_string def convBinIp(ip): segemnts = [] # https://stackoverflow.com/questions/9475241/split-string-every-nth-character for seg in [ip[i:i+8] for i in range(0,len(ip), 8)][:4]: segemnts.append(str(int(seg, 2))) return ".".join(segemnts) while True: input_str = input("Entrez l'addresse réseau ").strip() # Strip remove newline char if not ip_regex.match(input_str): print("IP Invalide") continue ip_cleaned = input_str.split("/")[0] subnet_cleaned = input_str.split("/")[1] # Since we're converting into binary, we don't want anything bigger than 8bit integers for ip_seg in ip_cleaned.split("."): if int(ip_seg,10) > 255: print("IP Invalide") continue # Convert the ip and subnet into bin net_bin = convIpBin(ip_cleaned) sub_bin = convSubBin(subnet_cleaned) # Check if the ip is in one of the apropriate ranges for i in valid_ranges: if compIpSub(i["ip"], net_bin, i["sub"]): break else: print("L'IP n'est pas dans un range valid pour un réseau privé") continue # Get the desired subnet size input_str = input("Entrez le nombre d'addresses désirés: ").strip() # Strip to remove unwanted newline try: min_net_size = int(input_str) + 2 except: print("Nombre invalide") continue # Convert subnet into binary target_sub_bin = convSubBin(SUBNETLENGTH - len(str(bin(min_net_size))[2:])) sub_size_diff = target_sub_bin.count("1") - sub_bin.count("1") # ex: /28 - /24 == 4, but in binary so num of 1s if sub_size_diff <= 0: print("Sous réseau requis plus grand ou égal à celui du réseau") continue # Get all networks in between the subnets # WARNING, entering legacy i dont understand anymore code territory net_start = net_bin[:sub_bin.count("1")] net_size = int(math.pow(2, target_sub_bin.count("0"))) networks = [] current_net_offset = 0 while current_net_offset < math.pow(2, sub_size_diff)*net_size: #umm, math stuff, size diff how much room we have in binary for new nets, we gotta convert that room to int (pow) and offset by its position in the bin string (*) new_net_bin = net_start + str(bin(current_net_offset))[2:].zfill(sub_bin.count("0")) # we strip 2 first chars as it is the type identifier, we also zfill because they are right padded and we need the correct size, if we left pad we will get a no good data networks.append(convBinIp(new_net_bin)) current_net_offset += net_size print("\n".join(networks))