summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthias Schiffer <mschiffer@universe-factory.net>2012-05-13 01:14:25 +0200
committerMatthias Schiffer <mschiffer@universe-factory.net>2012-05-13 01:14:25 +0200
commit0f5879b87f4c3e28adfbc486de5fe573618e0833 (patch)
tree26e8d480baa7405e91eee21cbed2f3670064e269
parent480f29f31db110bdcabe3de357e0091deb5220bc (diff)
downloadmdns-resolver-0f5879b87f4c3e28adfbc486de5fe573618e0833.tar
mdns-resolver-0f5879b87f4c3e28adfbc486de5fe573618e0833.zip
Reimplement in Ruby
-rwxr-xr-xmdns-resolver213
1 files changed, 120 insertions, 93 deletions
diff --git a/mdns-resolver b/mdns-resolver
index b58d55b..cbaf35b 100755
--- a/mdns-resolver
+++ b/mdns-resolver
@@ -1,99 +1,126 @@
-#!/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
+#!/usr/bin/env ruby
+require 'set'
+require 'socket'
+require 'net/dns'
+require 'net/dns/packet'
### Config ###
-domain = 'mesh.ffhl'
-port = 3535
-ttl = 600
+domain = 'mesh.ffhl'
+port = 53
+ttl = 600
+ns = ['mesh.ffhl. 3600 IN NS paul.ffhl.']
+soa = 'mesh.ffhl. 0 IN SOA paul.ffhl. freifunk\.luebeck.asta.uni-luebeck.de. 1 3600 180 600 60'
### 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)
+# Fix bugs and hack FQDN validation :>
+module Net
+ module DNS
+ class RR
+ class SOA
+ def build_pack
+ @soa_pack = pack_name(@mname)
+ @soa_pack += pack_name(@rname)
+ @soa_pack += [@serial,@refresh,@retry,@expire,@minimum].pack("N5")
+ @rdlength = @soa_pack.size
+ end
+ end
+ end
+
+ module Names
+ def valid?(name)
+ return true
+ end
+ end
+ end
+end
+
+
+run = true
+
+sock = UDPSocket.new Socket::AF_INET6
+
+sock.setsockopt Socket::Option.bool(:INET6, :IPV6, :V6ONLY, false)
+
+sock.setsockopt Socket::Option.bool(:INET, :IP, :PKTINFO, true)
+sock.setsockopt Socket::Option.bool(:INET6, :IPV6, :RECVPKTINFO, true)
+
+sock.bind('::', port)
+
+while run do
+ data, sendaddr, rflags, *controls = sock.recvmsg
+
+ #Thread.new(data, sendaddr, controls) do |data, sendaddr, controls|
+ pktinfo = nil
+ controls.each do |c|
+ pktinfo = c if c.cmsg_is?(:IP, :PKTINFO) or c.cmsg_is?(:IPV6, :PKTINFO)
+ end
+ return if pktinfo.nil?
+
+ packet = Net::DNS::Packet::parse(data)
+
+ return unless packet.header.opCode == Net::DNS::Header::QUERY
+ return unless packet.header.query?
+
+ packet.header.qr = 1
+ packet.header.aa = 1
+ packet.header.tc = 0
+ packet.header.ra = 0
+ packet.header.cd = 0
+ packet.header.ad = 0
+ packet.header.rCode = Net::DNS::Header::RCode::NOERROR
+
+ packet.question.each do |q|
+ next unless q.qClass.to_i == Net::DNS::IN
+
+ host, qdomain = q.qName.split('.', 2)
+ next unless qdomain == domain+'.'
+
+ begin
+ if q.qType.to_i == Net::DNS::A
+ addresses = Set.new
+ Socket.getaddrinfo(host+'.local', nil, :INET).each { |addr| addresses << addr[3] }
+
+ addresses.each do |addr|
+ packet.answer << Net::DNS::RR::A.new(:name => q.qName,
+ :ttl => ttl,
+ :cls => Net::DNS::IN,
+ :type => Net::DNS::A,
+ :address => addr)
+ end
+ elsif q.qType.to_i == Net::DNS::AAAA
+ addresses = Set.new
+ Socket.getaddrinfo(host+'.local', nil, :INET6).each { |addr| addresses << addr[3] }
+
+ addresses.each do |addr|
+ packet.answer << Net::DNS::RR::AAAA.new(:name => q.qName,
+ :ttl => ttl,
+ :cls => Net::DNS::IN,
+ :type => Net::DNS::AAAA,
+ :address => addr)
+ end
+ end
+ rescue
+ packet.header.rCode = Net::DNS::Header::RCode::NAME
+ end
+ end
+
+ if packet.answer.empty?
+ record = Net::DNS::RR::SOA.new(soa)
+ packet.authority = [Net::DNS::RR::SOA.new(:name => record.name,
+ :ttl => record.ttl,
+ :mname => record.mname,
+ :rname => record.rname,
+ :refresh => record.refresh,
+ :retry => record.retry,
+ :expire => record.expire,
+ :minimum => record.minimum,
+ :serial => Time.now.to_i)]
+ else
+ ns.each { |line| packet.authority << Net::DNS::RR::NS.new(line) }
+ end
+
+ sock.sendmsg(packet.data, 0, sendaddr, pktinfo)
+ #end
+end