-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsubnetter.py
More file actions
160 lines (128 loc) · 5.82 KB
/
subnetter.py
File metadata and controls
160 lines (128 loc) · 5.82 KB
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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
#!/usr/bin/env python3
import ipaddress
import argparse
# tabulate package import condition
try:
from tabulate import tabulate
TABULATE_AVAILABLE = True
except ImportError:
TABULATE_AVAILABLE = False
def calculate_vlsm(network, subnets):
network = ipaddress.IPv4Network(network)
subnets = sorted(subnets, reverse=True) # sort
allocated_subnets = []
current_address = network.network_address
for host_count in subnets:
needed_subnet = find_appropriate_subnet(current_address, host_count)
# fitting subnets in available spaces
if needed_subnet['network'] <= network.broadcast_address:
allocated_subnets.append(needed_subnet)
current_address = needed_subnet['broadcast'] + 1
else:
print(f"Insufficient address space for the host requirement of {host_count}.")
display_subnets(allocated_subnets, subnets)
return allocated_subnets # list of allocated subnets
def calculate_subnet(network):
network = ipaddress.IPv4Network(network)
subnet_info = {
'IP Address': str(network),
'Subnet Mask': str(network.netmask),
'Wildcard Mask': str(network.hostmask),
'Network Bits': network.prefixlen,
'Host Bits': 32 - network.prefixlen,
'Usable Hosts': network.num_addresses - 2,
'Network Address': str(network.network_address),
'First IP': str(network.network_address + 1),
'Last IP': str(network.broadcast_address - 1),
'Broadcast Address': str(network.broadcast_address)
}
return subnet_info
def find_appropriate_subnet(start_address, hosts_required):
# prefix_length adjustment
if hosts_required > 2:
prefix_length = 32 - (hosts_required + 2 - 1).bit_length()
else:
# minimum subnet size for small subnets needing only 2 hosts
prefix_length = 30
subnet = ipaddress.IPv4Network((start_address, prefix_length), strict=False)
return {
'network': subnet.network_address,
'mask': subnet.netmask,
'first_address': subnet.network_address + 1,
'last_address': subnet.broadcast_address - 1,
'broadcast': subnet.broadcast_address,
'available_hosts': (subnet.num_addresses - 2),
'cidr': subnet
}
def display_subnet(subnet_info):
for key, value in subnet_info.items():
print(f"{key}: {value}")
def display_subnets(subnets, required_hosts):
for i, subnet in enumerate(subnets):
print(f"Subnet {i + 1}:")
print(f" Network IP: {subnet['network']}")
print(f" Broadcast IP: {subnet['broadcast']}")
print(f" First Host IP: {subnet['first_address']}")
print(f" Last Host IP: {subnet['last_address']}")
print(f" Subnet Mask: {subnet['mask']}")
print(f" Subnet IP: {subnet['cidr']}")
print(f" Available Hosts: {subnet['available_hosts']}")
print(f" Needed Hosts: {required_hosts[i]}")
print("")
def display_subnets_table(subnets, required_hosts):
headers = ["Subnet", "Network IP", "Broadcast IP", "First Host IP", "Last Host IP",
"Subnet Mask", "Subnet IP", "Available Hosts", "Needed Hosts"]
table_data = []
for i, subnet in enumerate(subnets):
table_data.append([
i+1,
subnet['network'],
subnet['broadcast'],
subnet['first_address'],
subnet['last_address'],
subnet['mask'],
subnet['cidr'],
subnet['available_hosts'],
required_hosts[i]
])
print(tabulate(table_data, headers=headers, tablefmt="grid"))
def display_banner():
# ascii art banner
banner = """
_____ _ _ ____ _ _ ______ _______ _______ ______ _____
/ ____| | | | _ \| \ | | ____|__ __|__ __| ____| __ \
| (___ | | | | |_) | \| | |__ | | | | | |__ | |__) |
\___ \| | | | _ <| . ` | __| | | | | | __| | _ /
____) | |__| | |_) | |\ | |____ | | | | | |____| | \ \
|_____/ \____/|____/|_| \_|______| |_| |_| |______|_| \_\
Created by @0xShakhawat
"""
print(banner)
print("-" * 50)
print(" A powerful tool for subnet and VLSM calculations.")
print("-" * 50)
print("\n Also check out the SubNetter app on the Play Store:")
print(" https://play.google.com/store/apps/details?id=me.shakhawat.subnetter")
print(" - A user-friendly subnet calculator with additional tools and an Academy!\n")
def main():
display_banner()
parser = argparse.ArgumentParser(description="SubNetter - Subnetting Calculator Tool")
parser.add_argument('network', help="Network address in CIDR format (e.g., 192.168.1.0/24)")
parser.add_argument('-s', '--subnets', type=str, help="Comma-separated list of required subnets or host counts (for VLSM)")
parser.add_argument('-t', '--table', action='store_true', help="Display results in a table (requires 'tabulate' package)")
args = parser.parse_args()
if args.subnets:
subnets = [int(h) for h in args.subnets.split(',')]
calculated_subnets = calculate_vlsm(args.network, subnets) # storing calculated subnet info
# view table format if -t is used and tabulate is available
if args.table:
if TABULATE_AVAILABLE:
display_subnets_table(calculated_subnets, args.subnets) # passing calculated subnets
else:
print("Error: The 'tabulate' package is required for table output. "
"Please install it using 'pip install tabulate'.")
else:
subnet_info = calculate_subnet(args.network)
display_subnet(subnet_info)
if __name__ == "__main__":
main()