diff --git a/utils/he_ipv6/config.py b/utils/he_ipv6/config.py
index 6ebd174..0567b59 100644
--- a/utils/he_ipv6/config.py
+++ b/utils/he_ipv6/config.py
@@ -6,6 +6,7 @@ import re
##
import netaddr
import requests
+import requests.auth
from lxml import etree
from pyroute2 import IPRoute
##
@@ -182,7 +183,7 @@ class Allocation(object):
class Tunnel(object):
- def __init__(self, tun_xml):
+ def __init__(self, tun_xml, he_config):
self.xml = tun_xml
self.id = None
self.client = None
@@ -194,6 +195,7 @@ class Tunnel(object):
self.radvd_dns = None
self.allocations = {} # This is a dict of {}[alloc.id] = Allocation obj
self.assignments = [] # This is a list of Assignment objs
+ self.heconf = he_config
self.parse()
def _allocations(self):
@@ -251,39 +253,19 @@ class Tunnel(object):
return(None)
-class Config(object):
- default_xsd = 'http://schema.xml.r00t2.io/projects/he_ipv6.xsd'
+class BaseConfig(object):
+ default_xsd = None
- def __init__(self, xml_path, *args, **kwargs):
- self.xml_path = os.path.abspath(os.path.expanduser(xml_path))
- if not os.path.isfile(self.xml_path):
- raise ValueError('xml_path does not exist')
+ def __init__(self, xml_raw, *args, **kwargs):
+ self.raw = xml_raw
self.tree = None
self.ns_tree = None
self.xml = None
self.ns_xml = None
- self.raw = None
self.xsd = None
self.defaults_parser = None
self.obj = None
- self.tunnels = collections.OrderedDict()
- self.creds = {}
- self.parse()
-
- def _creds(self):
- creds_xml = self.xml.find('creds')
- for cred_xml in creds_xml.findall('cred'):
- cred = Credential(cred_xml)
- self.creds[cred.id] = cred
- return(None)
-
- def _tunnels(self):
- tunnels_xml = self.xml.find('tunnels')
- for tun_xml in tunnels_xml.findall('tunnel'):
- tun = Tunnel(tun_xml)
- tun.creds = self.creds.get(tun.creds_id)
- self.tunnels[tun.id] = tun
- return(None)
+ self.parse_xml()
def get_xsd(self):
raw_xsd = None
@@ -310,18 +292,14 @@ class Config(object):
self.xsd = etree.XMLSchema(etree.XML(raw_xsd, base_url = base_url))
return(None)
- def parse(self):
+ def parse_xml(self):
self.parse_raw()
self.get_xsd()
self.populate_defaults()
self.validate()
- self.subparse()
return(None)
def parse_raw(self, parser = None):
- if not self.raw:
- with open(self.xml_path, 'rb') as fh:
- self.raw = fh.read()
self.xml = etree.fromstring(self.raw, parser = parser)
self.ns_xml = etree.fromstring(self.raw, parser = parser)
self.tree = self.xml.getroottree()
@@ -359,13 +337,88 @@ class Config(object):
raise ValueError('Did not know how to parse obj parameter')
return(None)
- def subparse(self):
- self._creds()
- self._tunnels()
- return(None)
-
def validate(self):
if not self.xsd:
self.get_xsd()
self.xsd.assertValid(self.ns_tree)
return(None)
+
+
+class Config(BaseConfig):
+ default_xsd = 'http://schema.xml.r00t2.io/projects/he_ipv6.xsd'
+
+ def __init__(self, xml_path, *args, **kwargs):
+ self.xml_path = os.path.abspath(os.path.expanduser(xml_path))
+ if not os.path.isfile(self.xml_path):
+ raise ValueError('xml_path does not exist')
+ else:
+ with open(xml_path, 'rb') as fh:
+ raw_xml = fh.read()
+ super().__init__(raw_xml, *args, **kwargs)
+ self.heconf = None
+ self.creds = {}
+ self.tunnels = collections.OrderedDict()
+ self.subparse()
+
+ def _creds(self):
+ creds_xml = self.xml.find('creds')
+ for cred_xml in creds_xml.findall('cred'):
+ cred = Credential(cred_xml)
+ self.creds[cred.id] = cred
+ return(None)
+
+ def _heconf(self):
+ self.heconf = HEConfig(self.creds)
+ return(None)
+
+ def _tunnels(self):
+ tunnels_xml = self.xml.find('tunnels')
+ for tun_xml in tunnels_xml.findall('tunnel'):
+ tun_id = int(tun_xml.attrib['id'].strip())
+ tun = Tunnel(tun_xml, self.heconf.tunnels[tun_id])
+ tun.creds = self.creds.get(tun.creds_id)
+ self.tunnels[tun_id] = tun
+ return(None)
+
+ def subparse(self):
+ self._creds()
+ self._heconf()
+ self._tunnels()
+ return(None)
+
+
+class HEConfig(BaseConfig):
+ default_xsd = 'http://schema.xml.r00t2.io/projects/tunnelbroker.xsd'
+ nsmap = {None: 'https://tunelbroker.net/tunnelInfo.php',
+ 'xsi': 'http://www.w3.org/2001/XMLSchema-instance'}
+ attr_qname = etree.QName('http://www.w3.org/2001/XMLSchema-instance', 'schemaLocation')
+ schema_loc = 'https://tunnelbroker.net/tunnelInfo.php {0}'.format(default_xsd)
+
+ def __init__(self, creds, xml_url = 'https://tunnelbroker.net/tunnelInfo.php', *args, **kwargs):
+ self.creds = creds
+ self.url = xml_url
+ req = requests.get(self.url,
+ auth = requests.auth.HTTPBasicAuth(self.creds.user, self.creds.password))
+ if not req.ok:
+ raise RuntimeError('Could not fetch remote tunnel information')
+ raw_xml = self._add_ns(req.content)
+ super().__init__(raw_xml, *args, **kwargs)
+ self.tunnels = collections.OrderedDict()
+ self.subparse()
+
+ def subparse(self):
+ pass
+
+ def _add_ns(self, raw_xml):
+ # https://mailman-mail5.webfaction.com/pipermail/lxml/20100323/013260.html
+ _xml = etree.fromstring(raw_xml)
+ _nsmap = copy.deepcopy(_xml.nsmap)
+ _nsmap.update(self.nsmap)
+ mod_xml = etree.Element(_xml.tag, {self.attr_qname: self.schema_loc}, nsmap = _nsmap)
+ mod_xml[:] = _xml[:]
+ return(etree.tostring(mod_xml,
+ encoding = 'UTF-8',
+ xml_declaration = True,
+ pretty_print = True,
+ with_tail = True,
+ with_comments = True))
diff --git a/utils/he_ipv6/example.tunnelbroker.xml b/utils/he_ipv6/example.tunnelbroker.xml
index 1a13420..34dbfe1 100644
--- a/utils/he_ipv6/example.tunnelbroker.xml
+++ b/utils/he_ipv6/example.tunnelbroker.xml
@@ -12,15 +12,16 @@
ipv6user
+ someSecretPassword
xXxXxXxXxXxXxXXX
someotheruser
+ anotherPassword
0000000000000000
@@ -28,14 +29,11 @@