class ShellResolver(BaseResolver): """ Example dynamic resolver. Maps DNS labels to shell commands and returns result as TXT record (Note: No context is passed to the shell command) """ def __init__(self,routes,origin,ttl): self.origin = DNSLabel(origin) self.ttl = parse_time(ttl) self.routes = {} for r in routes: route,_,cmd = r.partition(":") if route.endswith('.'): route = DNSLabel(route) else: route = self.origin.add(route) self.routes[route] = cmd def resolve(self,request,handler): reply = request.reply() qname = request.q.qname cmd = self.routes.get(qname) if cmd: output = getoutput(cmd).encode() reply.add_answer(RR(qname,QTYPE.TXT,ttl=self.ttl, rdata=TXT(output[:254]))) else: reply.header.rcode = RCODE.NXDOMAIN return reply
class ShellResolver(BaseResolver): """ Example dynamic resolver. Maps DNS labels to shell commands and returns result as TXT record (Note: No context is passed to the shell command) Shell commands are passed in a a list in <label>:<cmd> format - eg: [ 'uptime.abc.com.:uptime', 'ls:ls' ] Would respond to requests to 'uptime.abc.com.' with the output of the 'uptime' command. For non-absolute labels the 'origin' parameter is prepended """ def __init__(self, routes, origin, ttl): self.origin = DNSLabel(origin) self.ttl = parse_time(ttl) self.routes = {} for r in routes: route, _, cmd = r.partition(":") if route.endswith('.'): route = DNSLabel(route) else: route = self.origin.add(route) self.routes[route] = cmd def resolve(self, request, handler): print("resolver:" + "-" * 40) reply = request.reply() qname = request.q.qname ia = ip_address(handler.client_address[0]) cmd = self.routes.get(qname) if cmd: output = getoutput(cmd).encode() reply.add_answer( RR(qname, QTYPE.TXT, ttl=self.ttl, rdata=TXT(output[:254]))) else: rqt = QTYPE.TXT rqd = TXT(f"{str(ia)}") if request.q.qtype in [QTYPE.A, QTYPE.AAAA, QTYPE.PTR]: QTR = {QTYPE.A: "A", QTYPE.AAAA: "AAAA", QTYPE.PTR: "PTR"} qt = QTR[request.q.qtype] if ia.version is 6 and request.q.qtype == QTYPE.AAAA: rqt = request.q.qtype rqd = AAAA(str(ia)) elif ia.version is 4 and request.q.qtype == QTYPE.A: rqt = request.q.qtype rqd = A(str(ia)) elif request.q.qtype == QTYPE.PTR: rqt = request.q.qtype rqd = PTR(str(ia.reverse_pointer)) else: rqt = QTYPE.TXT rqd = TXT( f"Your request for {qt} confuses me, but here is the IP as text {str(ia)}" ) reply.add_answer(RR(qname, rqt, ttl=self.ttl, rdata=rqd)) return reply
class ShellResolver(BaseResolver): """ Example dynamic resolver. Maps DNS labels to shell commands and returns result as TXT record (Note: No context is passed to the shell command) """ def __init__(self, routes, origin, ttl): self.origin = DNSLabel(origin) self.ttl = parse_time(ttl) self.routes = {} for r in routes: route, _, cmd = r.partition(":") if route.endswith('.'): route = DNSLabel(route) else: route = self.origin.add(route) self.routes[route] = cmd def resolve(self, request, handler): reply = request.reply() qname = request.q.qname cmd = self.routes.get(qname) if cmd: output = getoutput(cmd).encode() reply.add_answer( RR(qname, QTYPE.TXT, ttl=self.ttl, rdata=TXT(output[:254]))) else: reply.header.rcode = RCODE.NXDOMAIN return reply
def _generate_as_topo(self, topo_id, as_conf): dns_domain = DNSLabel(as_conf.get("dns_domain", DEFAULT_DNS_DOMAIN)) dns_domain = dns_domain.add("isd%s" % topo_id[0]).add("as%s" % topo_id[1]) mtu = as_conf.get('mtu', self.default_mtu) assert mtu >= SCION_MIN_MTU, mtu self.topo_dicts[topo_id] = { 'Core': as_conf.get('core', False), 'ISD_AS': str(topo_id), 'DnsDomain': str(dns_domain), 'Zookeepers': {}, 'MTU': mtu, } for i in SCION_SERVICE_NAMES: self.topo_dicts[topo_id][i] = {} self._gen_srv_entries(topo_id, as_conf, dns_domain) self._gen_er_entries(topo_id) self._gen_zk_entries(topo_id, as_conf)
class ShellResolver(BaseResolver): """ Example dynamic resolver. Maps DNS labels to shell commands and returns result as TXT record (Note: No context is passed to the shell command) Shell commands are passed in a a list in <label>:<cmd> format - eg: [ 'uptime.abc.com.:uptime', 'ls:ls' ] Would respond to requests to 'uptime.abc.com.' with the output of the 'uptime' command. For non-absolute labels the 'origin' parameter is prepended """ def __init__(self,routes,origin,ttl): self.origin = DNSLabel(origin) self.ttl = parse_time(ttl) self.routes = {} for r in routes: route,_,cmd = r.partition(":") if route.endswith('.'): route = DNSLabel(route) else: route = self.origin.add(route) self.routes[route] = cmd def resolve(self,request,handler): reply = request.reply() qname = request.q.qname cmd = self.routes.get(qname) if cmd: output = getoutput(cmd).encode() reply.add_answer(RR(qname,QTYPE.TXT,ttl=self.ttl, rdata=TXT(output[:254]))) else: reply.header.rcode = RCODE.NXDOMAIN return reply
class ShellResolver(BaseResolver): """ Example dynamic resolver. Maps DNS labels to shell commands and returns result as TXT record (Note: No context is passed to the shell command) Shell commands are passed in a a list in <label>:<cmd> format - eg: [ 'uptime.abc.com.:uptime', 'ls:ls' ] Would respond to requests to 'uptime.abc.com.' with the output of the 'uptime' command. For non-absolute labels the 'origin' parameter is prepended """ def __init__(self, routes, origin, ttl): self.origin = DNSLabel(origin) self.ttl = parse_time(ttl) self.routes = {} for r in routes: route, _, cmd = r.partition(":") if route.endswith('.'): route = DNSLabel(route) else: route = self.origin.add(route) self.routes[route] = cmd def resolve(self, request, handler): reply = request.reply() qname = request.q.qname cmd = self.routes.get(qname) if cmd: output = getoutput(cmd).encode() reply.add_answer( RR(qname, QTYPE.TXT, ttl=self.ttl, rdata=TXT(output[:254]))) else: reply.header.rcode = RCODE.NXDOMAIN return reply
class ZoneParser: """ Zone file parser >>> z = ZoneParser("www.example.com. 60 IN A 1.2.3.4") >>> list(z.parse()) [<DNS RR: 'www.example.com.' rtype=A rclass=IN ttl=60 rdata='1.2.3.4'>] """ def __init__(self, zone, origin="", ttl=0): self.l = WordLexer(zone) self.l.commentchars = ";" self.l.nltok = ("NL", None) self.l.spacetok = ("SPACE", None) self.i = iter(self.l) if type(origin) is DNSLabel: self.origin = origin else: self.origin = DNSLabel(origin) self.ttl = ttl self.label = DNSLabel("") self.prev = None def expect(self, expect): t, val = next(self.i) if t != expect: raise ValueError("Invalid Token: %s (expecting: %s)" % (t, expect)) return val def parse_label(self, label): if label.endswith("."): self.label = DNSLabel(label) elif label == "@": self.label = self.origin elif label == "": pass else: self.label = self.origin.add(label) return self.label def parse_rr(self, rr): label = self.parse_label(rr.pop(0)) ttl = int(rr.pop(0)) if rr[0].isdigit() else self.ttl rclass = rr.pop(0) if rr[0] in ("IN", "CH", "HS") else "IN" rtype = rr.pop(0) rdata = rr rd = RDMAP.get(rtype, RD) return RR( rname=label, ttl=ttl, rclass=getattr(CLASS, rclass), rtype=getattr(QTYPE, rtype), rdata=rd.fromZone(rdata, self.origin), ) def __iter__(self): return self.parse() def parse(self): rr = [] paren = False try: while True: tok, val = next(self.i) if tok == "NL": if not paren and rr: self.prev = tok yield self.parse_rr(rr) rr = [] elif tok == "SPACE" and self.prev == "NL" and not paren: rr.append("") elif tok == "ATOM": if val == "(": paren = True elif val == ")": paren = False elif val == "$ORIGIN": self.expect("SPACE") origin = self.expect("ATOM") self.origin = self.label = DNSLabel(origin) elif val == "$TTL": self.expect("SPACE") ttl = self.expect("ATOM") self.ttl = parse_time(ttl) else: rr.append(val) self.prev = tok except StopIteration: if rr: yield self.parse_rr(rr)
class ZoneParser: """ Zone file parser >>> z = ZoneParser("www.example.com. 60 IN A 1.2.3.4") >>> list(z.parse()) [<DNS RR: 'www.example.com.' rtype=A rclass=IN ttl=60 rdata='1.2.3.4'>] """ def __init__(self,zone,origin="",ttl=0): self.l = WordLexer(zone) self.l.commentchars = ';' self.l.nltok = ('NL',None) self.l.spacetok = ('SPACE',None) self.i = iter(self.l) if type(origin) is DNSLabel: self.origin = origin else: self.origin= DNSLabel(origin) self.ttl = ttl self.label = DNSLabel("") self.prev = None def expect(self,expect): t,val = next(self.i) if t != expect: raise ValueError("Invalid Token: %s (expecting: %s)" % (t,expect)) return val def parse_label(self,label): if label.endswith("."): self.label = DNSLabel(label) elif label == "@": self.label = self.origin elif label == '': pass else: self.label = self.origin.add(label) return self.label def parse_rr(self,rr): label = self.parse_label(rr.pop(0)) ttl = int(rr.pop(0)) if rr[0].isdigit() else self.ttl rclass = rr.pop(0) if rr[0] in ('IN','CH','HS') else 'IN' rtype = rr.pop(0) rdata = rr rd = RDMAP.get(rtype,RD) return RR(rname=label, ttl=ttl, rclass=getattr(CLASS,rclass), rtype=getattr(QTYPE,rtype), rdata=rd.fromZone(rdata,self.origin)) def __iter__(self): return self.parse() def parse(self): rr = [] paren = False try: while True: tok,val = next(self.i) if tok == 'NL': if not paren and rr: self.prev = tok yield self.parse_rr(rr) rr = [] elif tok == 'SPACE' and self.prev == 'NL' and not paren: rr.append('') elif tok == 'ATOM': if val == '(': paren = True elif val == ')': paren = False elif val == '$ORIGIN': self.expect('SPACE') origin = self.expect('ATOM') self.origin = self.label = DNSLabel(origin) elif val == '$TTL': self.expect('SPACE') ttl = self.expect('ATOM') self.ttl = parse_time(ttl) else: rr.append(val) self.prev = tok except StopIteration: if rr: yield self.parse_rr(rr)