1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
|
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))
|