diff options
-rw-r--r-- | .gitignore | 1 | ||||
-rwxr-xr-x | mdns-resolver | 99 |
2 files changed, 100 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b25c15b --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +*~ diff --git a/mdns-resolver b/mdns-resolver new file mode 100755 index 0000000..b58d55b --- /dev/null +++ b/mdns-resolver @@ -0,0 +1,99 @@ +#!/usr/bin/env python3 + +import errno +import signal +import socket +import subprocess +import sys +import threading +import traceback + +import dns.flags +import dns.message +import dns.name +import dns.opcode +import dns.query +import dns.rcode +import dns.rdataclass +import dns.rdatatype +import dns.rdtypes.IN.A +import dns.rdtypes.IN.AAAA +import dns.rrset + + +### Config ### +domain = 'mesh.ffhl' +port = 3535 +ttl = 600 +### Config end ### + + +class ResolverThread(threading.Thread): + def __init__(self, data, addr): + threading.Thread.__init__(self) + + self.daemon = True + + self._data = data + self._addr = addr + + def run(self): + request = dns.message.from_wire(self._data, question_only=True) + if request.opcode() != dns.opcode.QUERY: + return + + reply = dns.message.Message(request.id) + reply.flags = dns.flags.QR + reply.set_opcode(dns.opcode.QUERY) + reply.set_rcode(dns.rcode.NOERROR) + + for question in request.question: + if question.rdclass != dns.rdataclass.IN: + continue + + domainname = dns.name.from_text(domain) + if len(question.name) != len(domainname)+1: + continue + if not question.name.is_subdomain(domainname): + continue + + + answer = dns.rrset.RRset(question.name, question.rdclass, question.rdtype) + answer.ttl = ttl + + if question.rdtype == dns.rdatatype.A: + output = subprocess.check_output(['avahi-resolve', '-n', '-4', question.name[0]+b'.local']).split(b'\t') + if output[0] == question.name[0]+b'.local': + answer.add(dns.rdtypes.IN.A.A(question.rdclass, question.rdtype, str(output[1], encoding='ASCII').strip())) + elif question.rdtype == dns.rdatatype.AAAA: + output = subprocess.check_output(['avahi-resolve', '-n', '-6', question.name[0]+b'.local']).split(b'\t') + if output[0] == question.name[0]+b'.local': + answer.add(dns.rdtypes.IN.AAAA.AAAA(question.rdclass, question.rdtype, str(output[1], encoding='ASCII').strip())) + else: + continue + + reply.answer.append(answer) + + sock.sendto(reply.to_wire(), self._addr) + +run = True + +def exitHandler(signum, frame): + global run + run = False + +signal.signal(signal.SIGINT, exitHandler) +signal.signal(signal.SIGTERM, exitHandler) +signal.signal(signal.SIGQUIT, exitHandler) + + +sock = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM) +sock.bind(('::1', port)) + +while run: + try: + data, addr = sock.recvfrom(1024) + ResolverThread(data, addr).start() + except socket.error: + if sys.exc_info()[1].errno != errno.EINTR: + traceback.print_exc(file=sys.stderr) |