Skip to content

Commit 2c41b28

Browse files
committed
Initial commit
0 parents  commit 2c41b28

File tree

4 files changed

+181
-0
lines changed

4 files changed

+181
-0
lines changed

README.md

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
# `python-hexroute`
2+
3+
4+
## Summary
5+
6+
This is a python version of the original bash `hexroute` script (availble [here](http://www.xrx.ca/hexroute.htm)).
7+
8+
9+
## Installation
10+
11+
Just download and run the script:
12+
13+
wget https://raw.githubusercontent.com/musashiXXX/python-hexroute/main/hexroute.py
14+
chmod 755 hexroute.py
15+
./hexroute.py
16+
17+
18+
Or install it via `pipenv` to be used as a module:
19+
20+
pipenv install -e git+https://github.com/musashiXXX/python-hexroute.git#egg=python-hexroute
21+
22+
23+
## Usage
24+
25+
usage: hexroute.py [-h] (-r 192.168.0.0/16 192.168.0.1 | -R 18:C0:A8:64:C0:A8:64:01)
26+
27+
Generate or parse a DHCP option 249 hexadecimal string
28+
29+
optional arguments:
30+
-h, --help show this help message and exit
31+
-r 192.168.0.0/16 192.168.0.1, --route 192.168.0.0/16 192.168.0.1
32+
Specify a network/gateway pair
33+
-R 18:C0:A8:64:C0:A8:64:01, --reverse 18:C0:A8:64:C0:A8:64:01
34+
Convert an option 121/249 hex string into IPv4 network/route pairs
35+
36+
37+
Generate a hex string:
38+
39+
./hexroute.py -r 10.10.10.0/24 192.168.0.1 -r 172.16.0.0/12 192.168.0.1
40+
18:0A:0A:0A:C0:A8:00:01:0C:AC:10:C0:A8:00:01
41+
42+
43+
Parse a hex string:
44+
45+
./hexroute.py -R '18:0A:0A:0A:C0:A8:00:01:0C:AC:10:C0:A8:00:01'
46+
[(IPv4Network('10.10.10.0/24'), IPv4Address('192.168.0.1')), (IPv4Network('172.16.0.0/12'), IPv4Address('192.168.0.1'))]
47+

hexroute.py

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
#!/usr/bin/env python
2+
3+
import ipaddress, argparse, itertools
4+
5+
def hexroute(routes: list, uppercase=True) -> str:
6+
'''
7+
Takes a list of lists or tuples in the form ('network/prefix', 'gateway_ip')
8+
and returns a DHCP option 121/249 hex string
9+
10+
>>> hexroute([('192.168.100.0/24','192.168.100.1')])
11+
'18:C0:A8:64:C0:A8:64:01'
12+
>>> hexroute([('172.16.0.0/24', '172.16.0.1')])
13+
'18:AC:10:00:AC:10:00:01'
14+
>>> hexroute([('10.1.1.10/8', '10.254.254.1')])
15+
'08:0A:0A:FE:FE:01'
16+
>>> hexroute([('192.168.1.0/23','192.168.0.1'), ('192.168.0.0/23', '192.168.0.1')])
17+
'17:C0:A8:00:C0:A8:00:01'
18+
'''
19+
20+
hex = []
21+
networks = []
22+
for route in routes:
23+
net = ipaddress.IPv4Network(route[0], strict=False)
24+
if net in networks:
25+
continue
26+
prefix = net.prefixlen
27+
net_address = [int(i) for i in str(net.network_address).split('.')]
28+
gateway_address = [int(i) for i in str(route[1]).split('.')]
29+
octets = []
30+
if prefix > 0:
31+
octets.append(net_address[0])
32+
if prefix > 8:
33+
octets.append(net_address[1])
34+
if prefix > 16:
35+
octets.append(net_address[2])
36+
if prefix > 24:
37+
octets.append(net_address[3])
38+
container = [prefix]
39+
container += octets
40+
container += gateway_address
41+
hex += ['{:02X}'.format(i) for i in container]
42+
networks.append(net)
43+
44+
opt249str = ':'.join(hex)
45+
if not uppercase:
46+
return opt249str.lower()
47+
return opt249str
48+
49+
def hexroute_reverse(hex_string):
50+
'''
51+
Takes a hexadecimal DHCP option 249 string and returns the IPv4 networks and their gateways
52+
53+
>>> hexroute_reverse('18:C0:A8:64:C0:A8:64:01')
54+
[(IPv4Network('192.168.100.0/24'), IPv4Address('192.168.100.1'))]
55+
>>> hexroute_reverse('18:AC:10:00:AC:10:00:01')
56+
[(IPv4Network('172.16.0.0/24'), IPv4Address('172.16.0.1'))]
57+
>>> hexroute_reverse('08:0A:0A:FE:FE:01')
58+
[(IPv4Network('10.0.0.0/8'), IPv4Address('10.254.254.1'))]
59+
>>> hexroute_reverse('17:C0:A8:00:C0:A8:00:01')
60+
[(IPv4Network('192.168.0.0/23'), IPv4Address('192.168.0.1'))]
61+
'''
62+
63+
decimal_vals = [int(i, 16) for i in hex_string.split(':')]
64+
routes = []
65+
while len(decimal_vals):
66+
next = 0
67+
subnet = decimal_vals.pop(0)
68+
for i in (0, 8, 16, 24):
69+
if subnet > i:
70+
next += 1
71+
subnet_octets = decimal_vals[:next]
72+
while len(subnet_octets) < 4:
73+
subnet_octets.append(0)
74+
network = ipaddress.IPv4Network('.'.join([str(i) for i in subnet_octets]) + '/{}'.format(subnet), strict=False)
75+
del decimal_vals[:next]
76+
gateway_address = decimal_vals[:4]
77+
gateway = ipaddress.IPv4Address('.'.join([str(i) for i in gateway_address]))
78+
del decimal_vals[:4]
79+
routes.append((network, gateway))
80+
return routes
81+
82+
if __name__ == '__main__':
83+
parser = argparse.ArgumentParser(description = 'Generate or parse a DHCP option 249 hexadecimal string')
84+
group = parser.add_mutually_exclusive_group(required=True)
85+
group.add_argument(
86+
'-r',
87+
'--route',
88+
help='Specify a network/gateway pair',
89+
metavar=('192.168.0.0/16', '192.168.0.1'),
90+
nargs=2,
91+
action='append'
92+
)
93+
group.add_argument(
94+
'-R',
95+
'--reverse',
96+
help='Convert an option 121/249 hex string into IPv4 network/route pairs',
97+
metavar='18:C0:A8:64:C0:A8:64:01'
98+
)
99+
args = parser.parse_args()
100+
if args.route:
101+
print(hexroute(args.route))
102+
if args.reverse:
103+
print(hexroute_reverse(args.reverse))

pyproject.toml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
[project]
2+
name = "python-hexroute"
3+
version = "0.1"
4+
5+
readme = "README.md"
6+
keywords = ["dhcp", "249", "121"]
7+
requires-python = ">3.7"

setup.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#!/usr/bin/env python
2+
# -*- coding: utf8 -*-
3+
4+
import sys
5+
6+
try:
7+
from setuptools import setup
8+
except ImportError:
9+
from distutils.core import setup
10+
11+
setup(
12+
name='hexroute',
13+
version='0.1',
14+
url='https://github.com/musashiXXX/python-hexroute',
15+
license='GNU GPLv3',
16+
author='Charles Hamilton',
17+
author_email='chamilton@nefaria.com',
18+
keywords='249 121 dhcp hexroute',
19+
description='Generate a hex string for use with DHCP options 121/249',
20+
long_description='',
21+
classifiers=['Programming Language :: Python :: 3'],
22+
py_modules=['hexroute']
23+
)
24+

0 commit comments

Comments
 (0)