139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
|
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
|
+
-
+
+
-
-
+
+
-
+
-
+
|
end
handle_packet(buf[0, len], addr)
end
end
end
def handle_packet(packet : Bytes, sender : Socket::IPAddress) : Nil
io = IO::Memory.new(packet, writeable: false)
begin
id = packet[0].to_u16 << 8 | packet[1]
id = io.read_bytes(UInt16, IO::ByteFormat::BigEndian)
begin
context = @queries[id]
rescue KeyError
return
end
return if sender != context.used_ns
@queries.delete(id)
byte = io.read_bytes(UInt8)
if packet[2] & 0x80 == 0 || # QR
packet[2] & 0x78 != context.raw_data[2] & 0x78 # Opcode
if byte & 0x80 == 0 || # QR
byte & 0x78 != context.raw_data[2] & 0x78 # Opcode
context.block.call(Error::INVALID_REPLY)
return
end
if packet[2] & 0x02 != 0 # TC
if byte & 0x02 != 0 # TC
# TODO: Switch to TCP
context.block.call(Error::TRUNCATED)
return
end
case packet[3] & 0x0F # RCODE
case io.read_bytes(UInt8) & 0x0F # RCODE
when 0
error = nil
try_next_ns = false
when 1
error = Error::SERVER_INVALID_FORMAT
try_next_ns = false
when 2
|
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
|
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
|
-
-
|
end
if error
context.block.call(error)
return
end
io = IO::Memory.new(packet[4, packet.size - 4], writeable: false)
qdcount = io.read_bytes(UInt16, IO::ByteFormat::BigEndian)
adcount = io.read_bytes(UInt16, IO::ByteFormat::BigEndian)
nscount = io.read_bytes(UInt16, IO::ByteFormat::BigEndian)
arcount = io.read_bytes(UInt16, IO::ByteFormat::BigEndian)
rescue IndexError
rescue IO::EOFError
end
end
def stop : Nil
@v6_sock.try { |s| s.close }
@v4_sock.try { |s| s.close }
end
end
end
|