summaryrefslogtreecommitdiffstats
path: root/mdns-resolver
blob: b58d55b448e9648dafc9abce75c548e927e47ee3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
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)