okay. let's give this a shot.

This commit is contained in:
2020-05-18 04:59:00 -04:00
parent 4df9287abd
commit 80765e58ed
10 changed files with 203 additions and 81 deletions

View File

@@ -1,10 +1,11 @@
import ipaddress
import socket
##
import netaddr
from pyroute2 import IPRoute
##
from . import utils
from . import ra
from . import utils
class IP(object):
@@ -51,14 +52,28 @@ class IP6(IP):
class Assignment(object):
def __init__(self, assign_xml, ra = False, dns = False, ra_provider = 'dnsmasq'):
def __init__(self,
assign_xml,
ra_dns = False,
ra_dhcp = False,
ra_other = False,
ra_tag = None,
ra_domains = None):
self.xml = assign_xml
self.ra = ra
self.dns = dns
self.ra_dns = ra_dns
self.ra_tag = ra_tag
self.ra_other = ra_other
self.ra_domains = set()
if isinstance(ra_domains, list):
self.ra_domains.update(ra_domains)
elif isinstance(ra_domains, str):
self.ra_domains.update([i.lower().strip() for i in ra_domains if i.strip() != ''])
self.ra_dhcp = ra_dhcp
self.iface = None
self.iface_ll = None
self.iface_idx = None
self.iface_addrs = []
self.iface_blocks = []
self.dhcp6_ranges = []
self.alloc = None # This must be set externally to a mapped Allocation instance
self.alloc_id = None
self.prefix = None
@@ -74,6 +89,16 @@ class Assignment(object):
self.iface = _iface_txt.strip()
ipr = IPRoute()
self.iface_idx = ipr.link_lookup(ifname = self.iface)[0]
# Link-Local address
ll = ipr.get_addr(index = self.iface_idx,
family = socket.AF_INET6,
scope = 253)[0]['attrs']
addrs = dict(ll)['IFA_ADDRESS']
if isinstance(addrs, (list, tuple)):
addr = addrs[0]
else:
addr = addrs
self.iface_ll = addr
ipr.close()
return(None)
@@ -92,7 +117,11 @@ class Assignment(object):
# NOT AN IP6 OBJECT!
self.iface_blocks = self.alloc_block.extract_subnet(self.prefix, count = 1)
for i in self.iface_blocks:
self.iface_addrs.append(IP6(str(next(i.iter_hosts())), 128))
# DHCPv6 range.
_base = str(i.ip).rstrip(':')
start = '{0}:dead:beef:cafe:0'.format(_base)
stop = '{0}:dead:beef:cafe:ffff'.format(_base)
self.dhcp6_ranges.append((start, stop))
return(None)
@@ -114,11 +143,8 @@ class Tunnel(object):
self.client = None
self.server = None
self.endpoint = None
self.ra = False
self.ra_provider = None
self.ra_dns = False
self.ra_dhcp = False
self.allocations = {} # This is a dict of {}[alloc.id] = Allocation obj
self.allocations = {} # This is a dict of {}[alloc.id] = Allocation obj (as provided by HE)
self.assignments = [] # This is a list of Assignment objs
self.parse()
@@ -128,11 +154,27 @@ class Tunnel(object):
def _assignments(self):
_assigns_xml = self.xml.find('assignments')
self.enable_ra = utils.xml2bool(_assigns_xml.attrib.get('radvd', 'false'))
self.ra_dns = utils.xml2bool(_assigns_xml.attrib.get('radvdDns', 'false'))
self.ra_provider = _assigns_xml.attrib.get('raProvider')
for _assign_xml in _assigns_xml.findall('assign'):
assign = Assignment(_assign_xml, ra = self.enable_ra, dns = self.ra_dns)
do_dns = False
domains = []
do_dhcp = False
ra_other = False
tag = _assign_xml.attrib.get('tag', None)
dns = _assign_xml.find('dns')
if dns and self.ra_provider:
do_dns = utils.xml2bool(dns.text.strip())
domains = [i.strip() for i in dns.attrib.get('domains', '').split() if i.strip() != '']
dhcp = _assign_xml.find('dhcpv6')
if dhcp and self.ra_provider:
do_dhcp = utils.xml2bool(dhcp.text.strip())
ra_other = utils.xml2bool(dhcp.attrib.get('advOther', 'false').strip())
assign = Assignment(_assign_xml,
ra_dns = do_dns,
ra_dhcp = do_dhcp,
ra_other = ra_other,
ra_tag = tag,
ra_domains = domains)
assign.alloc = self.allocations[assign.alloc_id]
assign.parse_alloc()
self.assignments.append(assign)
@@ -154,9 +196,13 @@ class Tunnel(object):
self.id = int(self.xml.attrib['id'].strip())
return(None)
def _radvd(self):
self.radvd.conf.generate(self.assignments)
def _ra(self):
# TODO: support conf path override via config XML?
if self.ra_provider.strip().lower() == 'dnsmasq':
self.ra = ra.DNSMasq()
elif self.ra_provider.strip().lower() == 'radvd':
self.ra = ra.RADVD()
self.ra.conf.generate(self.assignments)
return(None)
def _server(self):
@@ -171,5 +217,5 @@ class Tunnel(object):
self._endpoint()
self._allocations()
self._assignments()
self._radvd()
self._ra()
return(None)