Created
December 4, 2020 12:41
-
-
Save maxried/61f4a422c9c1b2f5698f02f43c3d5159 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
from ipaddress import IPv4Network, collapse_addresses | |
from argparse import ArgumentParser, RawDescriptionHelpFormatter | |
from typing import List | |
def main(): | |
parser = ArgumentParser(description='Create excluding IPv4 routing tables, and simplify IPv4 routing tables.', | |
formatter_class=RawDescriptionHelpFormatter, | |
epilog='Examples:\n' | |
'198.51.100.0/25, and 198.51.100.128/25 will be merged to 198.51.100.0/24:\n' | |
'\troute-tool -s 198.51.100.0/25 198.51.100.128/25\n' | |
'\n' | |
'Create a set of routes which are nearly default, but exclude two subnets:\n' | |
'\troute-tool -e 198.51.100.0/24 203.0.113.0/24\n' | |
'\n' | |
'Route your network through a VPN, but exclude the VPN server at 192.0.2.62:\n' | |
'\troute-tool -i 192.0.2.0/24 -e 192.0.2.62') | |
parser.add_argument('--include', '-i', type=IPv4Network, nargs='*', default=[IPv4Network('0.0.0.0/0')], | |
help='The positive routing table. Defaults to 0.0.0.0/0.') | |
parser.add_argument('--exclude', '-e', type=IPv4Network, nargs='*', default=[], | |
help='The negative routing table, i. e. the list of networks to exclude from the positive ' | |
'routing table. Defaults to empty list.') | |
parser.add_argument('--simplify', '-s', action='store_const', default=False, const=True, | |
help='Simplify the resulting routing table by merging adjacent networks.') | |
args = parser.parse_args() | |
result: List[IPv4Network] = [] | |
include: IPv4Network | |
for include in args.include: | |
to_add = [include] | |
exclude: IPv4Network | |
something_changed = True | |
while something_changed: | |
something_changed = False | |
for exclude in args.exclude: | |
for net in to_add: | |
if net.subnet_of(exclude): | |
to_add = [] | |
something_changed = True | |
break | |
elif exclude.subnet_of(net): | |
to_add.remove(net) | |
to_add.extend(net.address_exclude(exclude)) | |
something_changed = True | |
break | |
if something_changed: | |
break | |
result.extend(to_add) | |
if args.simplify: | |
result = list(collapse_addresses(result)) | |
for i in result: | |
print(f'{i.network_address}/{i.prefixlen}') | |
if __name__ == '__main__': | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment