-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsubcalc
executable file
·224 lines (195 loc) · 8.88 KB
/
subcalc
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
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
#!/usr/bin/env python3
import argparse
import sys
import ipaddress
try:
import readline # This enables arrow keys, history, and line editing
except ImportError:
# readline is not available on all platforms (like Windows without additional packages)
pass
from vlsm import get_subnet_info as get_vlsm_subnet_info, display_subnet_info as display_vlsm_subnet_info, print_table
from flsm import get_subnet_info as get_flsm_subnet_info, get_subnet_info_by_prefix as get_flsm_subnet_info_by_prefix, display_subnet_info as display_flsm_subnet_info
def display_network_summary(network):
"""Display summary information about a network"""
try:
network_obj = ipaddress.ip_network(network, strict=False)
print(f"\nNetwork Summary for {network_obj}:")
print(f"Network Address: {network_obj.network_address}")
print(f"Broadcast Address: {network_obj.broadcast_address}")
print(f"Netmask: {network_obj.netmask}")
print(f"Prefix Length: /{network_obj.prefixlen}")
print(f"Number of Addresses: {network_obj.num_addresses}")
print(f"Usable Hosts: {network_obj.num_addresses - 2}")
print(f"First Usable Host: {network_obj.network_address + 1}")
print(f"Last Usable Host: {network_obj.broadcast_address - 1}")
except ValueError as e:
print(f"Error: {e}")
def run_vlsm_tool(network=None, hosts_required=None):
"""Run the Variable Length Subnet Mask calculator tool"""
try:
if network is None:
network = input("Enter the base subnet address (e.g., 192.168.0.0/24): ")
if hosts_required is None or len(hosts_required) == 0:
hosts_input = input("Enter the required number of hosts for multiple subnets, separated by commas (e.g., 50,40,10,30,60): ")
try:
hosts_required = list(map(int, hosts_input.split(',')))
except ValueError:
print("Invalid input for hosts required. Please provide a comma-separated list of integers.")
return
try:
subnets = get_vlsm_subnet_info(network, hosts_required)
except ValueError as e:
print(e)
return
table_data = [
["Subnet", "Subnet Mask", "Network ID", "Broadcast ID", "First Host IP", "Last Host IP", "Needed Hosts", "Total Hosts"]
]
for subnet_info in subnets:
table_data.append(display_vlsm_subnet_info(subnet_info))
print_table(table_data)
except KeyboardInterrupt:
print("\nOperation cancelled by user.")
return
def run_flsm_tool(network=None, subnet_input=None):
"""Run the Fixed Length Subnet Mask calculator tool"""
try:
if network is None:
network = input("Enter the base subnet address (e.g., 192.168.0.0/24): ")
if subnet_input is None:
subnet_input = input("Enter the number of subnets to create OR prefix length (e.g., 16 or /28): ")
# Process the input to determine if it's a number of subnets or a prefix length
by_prefix = False
if isinstance(subnet_input, str) and subnet_input.startswith('/'):
try:
prefix_length = int(subnet_input[1:])
by_prefix = True
except ValueError:
print("Invalid prefix length. Please provide a number after the '/' character.")
return
else:
try:
num_subnets = int(subnet_input)
if num_subnets <= 0:
print("Number of subnets must be greater than 0.")
return
except ValueError:
print("Invalid input. Please provide either a number of subnets or a prefix length (e.g., /28).")
return
try:
# Get subnets based on either number of subnets or prefix length
if by_prefix:
subnets = get_flsm_subnet_info_by_prefix(network, prefix_length)
num_subnets = len(subnets) # For the summary info
else:
subnets = get_flsm_subnet_info(network, num_subnets)
# Calculate the summary information
if not subnets:
print("No subnets created.")
return
# Extract information from the first subnet
network_obj = ipaddress.ip_network(network, strict=False)
subnet_obj = subnets[0][0]
subnet_bits = subnet_obj.prefixlen - network_obj.prefixlen
actual_subnets = len(subnets)
hosts_per_subnet = subnets[0][2] # From the tuple (subnet, index, total_hosts)
# Calculate max possible subnets with this prefix length
max_subnets = 2 ** subnet_bits
unused_subnets = max_subnets - actual_subnets if by_prefix else max_subnets - num_subnets
# Print summary
print("\nFLSM Summary:")
print(f"Base Network: {network_obj}")
print(f"Subnet Bits: {subnet_bits}")
print(f"New Prefix Length: /{subnet_obj.prefixlen}")
print(f"Subnet Mask: {subnet_obj.netmask}")
print(f"Hosts per Subnet: {hosts_per_subnet}")
if by_prefix:
print(f"Specified Prefix: /{prefix_length}")
print(f"Maximum Subnets: {max_subnets}")
print(f"Created Subnets: {actual_subnets}")
else:
print(f"Requested Subnets: {num_subnets}")
print(f"Actual Subnets: {actual_subnets}")
print(f"Unused Subnets: {unused_subnets}")
print()
except ValueError as e:
print(e)
return
# Generate the table data
table_data = [
["Subnet", "CIDR Notation", "Subnet Mask", "Network ID", "Broadcast ID", "First Host IP", "Last Host IP", "Hosts"]
]
for subnet_info in subnets:
table_data.append(display_flsm_subnet_info(subnet_info))
print_table(table_data)
except KeyboardInterrupt:
print("\nOperation cancelled by user.")
return
def main():
"""Main entry point for the subcalc tool"""
parser = argparse.ArgumentParser(
description="Subnet Calculator Tool - Calculate and display subnet information",
epilog="""
Examples:
./subcalc --network 192.168.0.0/24 # Display network summary
./subcalc --network 192.168.0.0/24 --flsm 16 # Create 16 equal-sized subnets
./subcalc --network 192.168.0.0/24 --flsm /28 # Create subnets with prefix /28
./subcalc --network 192.168.0.0/24 --vlsm 20 40 50 # Create subnets with specified host capacities
./subcalc --flsm # Run FLSM in interactive mode
./subcalc --vlsm # Run VLSM in interactive mode
""",
formatter_class=argparse.RawDescriptionHelpFormatter # This preserves formatting in the epilog
)
parser.add_argument(
"--network",
type=str,
help="Base network address in CIDR notation (e.g., 192.168.0.0/24)"
)
parser.add_argument(
"--vlsm",
nargs='*',
type=int,
help="Run Variable Length Subnet Mask calculator with specified host requirements (e.g., --vlsm 20 40 80)"
)
parser.add_argument(
"--flsm",
nargs='?',
const='interactive',
help="Run Fixed Length Subnet Mask calculator with either number of subnets (e.g., --flsm 4) or target prefix length (e.g., --flsm /28)"
)
args = parser.parse_args()
# Network summary only
if args.network and args.vlsm is None and args.flsm is None:
display_network_summary(args.network)
return
# VLSM mode
if args.vlsm is not None:
if args.network:
run_vlsm_tool(args.network, args.vlsm)
else:
run_vlsm_tool(hosts_required=args.vlsm)
return
# FLSM mode
if args.flsm:
if args.flsm == 'interactive':
# Fully interactive if neither arg is provided
if args.network:
run_flsm_tool(args.network)
else:
run_flsm_tool()
else:
# Semi-interactive if only one arg is provided
if args.network:
run_flsm_tool(args.network, args.flsm)
else:
run_flsm_tool(subnet_input=args.flsm)
return
# No recognized arguments provided
parser.print_help()
print("\nError: Please specify at least one option")
sys.exit(1)
if __name__ == "__main__":
try:
main()
except KeyboardInterrupt:
print("\nOperation cancelled by user.")
sys.exit(0)