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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
|
#!/usr/bin/env ruby
require 'set'
require 'socket'
require 'net/dns'
require 'net/dns/packet'
### Config ###
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 ###
# 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
|