]> git.ipfire.org Git - thirdparty/pdns.git/blame - regression-tests.dnsdist/test_Protobuf.py
Merge pull request #12544 from romeroalx/workaround-ci-unixodbc-dev
[thirdparty/pdns.git] / regression-tests.dnsdist / test_Protobuf.py
CommitLineData
1d0bd88a 1#!/usr/bin/env python
1d0bd88a
RG
2import threading
3import socket
4import struct
5import sys
6import time
b4f23783 7from dnsdisttests import DNSDistTest, Queue
1d0bd88a
RG
8
9import dns
10import dnsmessage_pb2
11
f29fabd9 12class DNSDistProtobufTest(DNSDistTest):
1d0bd88a 13 _protobufServerPort = 4242
b4f23783 14 _protobufQueue = Queue()
312a09a6 15 _protobufServerID = 'dnsdist-server-1'
1d0bd88a 16 _protobufCounter = 0
1d0bd88a
RG
17
18 @classmethod
19 def ProtobufListener(cls, port):
7373e3a6 20 cls._backgroundThreads[threading.get_native_id()] = True
1d0bd88a
RG
21 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
22 sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)
23 try:
24 sock.bind(("127.0.0.1", port))
25 except socket.error as e:
26 print("Error binding in the protbuf listener: %s" % str(e))
27 sys.exit(1)
28
29 sock.listen(100)
7373e3a6 30 sock.settimeout(1.0)
1d0bd88a 31 while True:
7373e3a6
RG
32 try:
33 (conn, _) = sock.accept()
34 except socket.timeout:
35 if cls._backgroundThreads.get(threading.get_native_id(), False) == False:
36 del cls._backgroundThreads[threading.get_native_id()]
37 break
38 else:
39 continue
40
1d0bd88a
RG
41 data = None
42 while True:
43 data = conn.recv(2)
44 if not data:
45 break
46 (datalen,) = struct.unpack("!H", data)
47 data = conn.recv(datalen)
48 if not data:
49 break
50
51 cls._protobufQueue.put(data, True, timeout=2.0)
52
53 conn.close()
54 sock.close()
55
56 @classmethod
57 def startResponders(cls):
5df86a8a 58 cls._UDPResponder = threading.Thread(name='UDP Responder', target=cls.UDPResponder, args=[cls._testServerPort, cls._toResponderQueue, cls._fromResponderQueue])
1d0bd88a
RG
59 cls._UDPResponder.setDaemon(True)
60 cls._UDPResponder.start()
741ebe08 61
5df86a8a 62 cls._TCPResponder = threading.Thread(name='TCP Responder', target=cls.TCPResponder, args=[cls._testServerPort, cls._toResponderQueue, cls._fromResponderQueue])
1d0bd88a
RG
63 cls._TCPResponder.setDaemon(True)
64 cls._TCPResponder.start()
65
66 cls._protobufListener = threading.Thread(name='Protobuf Listener', target=cls.ProtobufListener, args=[cls._protobufServerPort])
67 cls._protobufListener.setDaemon(True)
68 cls._protobufListener.start()
69
70 def getFirstProtobufMessage(self):
71 self.assertFalse(self._protobufQueue.empty())
72 data = self._protobufQueue.get(False)
73 self.assertTrue(data)
74 msg = dnsmessage_pb2.PBDNSMessage()
75 msg.ParseFromString(data)
76 return msg
77
29cd61cc 78 def checkProtobufBase(self, msg, protocol, query, initiator, normalQueryResponse=True):
1d0bd88a
RG
79 self.assertTrue(msg)
80 self.assertTrue(msg.HasField('timeSec'))
81 self.assertTrue(msg.HasField('socketFamily'))
4bfebc93 82 self.assertEqual(msg.socketFamily, dnsmessage_pb2.PBDNSMessage.INET)
1d0bd88a
RG
83 self.assertTrue(msg.HasField('from'))
84 fromvalue = getattr(msg, 'from')
4bfebc93 85 self.assertEqual(socket.inet_ntop(socket.AF_INET, fromvalue), initiator)
1d0bd88a 86 self.assertTrue(msg.HasField('socketProtocol'))
4bfebc93 87 self.assertEqual(msg.socketProtocol, protocol)
1d0bd88a
RG
88 self.assertTrue(msg.HasField('messageId'))
89 self.assertTrue(msg.HasField('id'))
4bfebc93 90 self.assertEqual(msg.id, query.id)
1d0bd88a 91 self.assertTrue(msg.HasField('inBytes'))
312a09a6 92 self.assertTrue(msg.HasField('serverIdentity'))
4bfebc93 93 self.assertEqual(msg.serverIdentity, self._protobufServerID.encode('utf-8'))
312a09a6 94
0096ada6
RG
95 if normalQueryResponse:
96 # compare inBytes with length of query/response
4bfebc93 97 self.assertEqual(msg.inBytes, len(query.to_wire()))
1d0bd88a
RG
98 # dnsdist doesn't set the existing EDNS Subnet for now,
99 # although it might be set from Lua
100 # self.assertTrue(msg.HasField('originalRequestorSubnet'))
4bfebc93
CH
101 # self.assertEqual(len(msg.originalRequestorSubnet), 4)
102 # self.assertEqual(socket.inet_ntop(socket.AF_INET, msg.originalRequestorSubnet), '127.0.0.1')
1d0bd88a 103
8667904b 104 def checkProtobufQuery(self, msg, protocol, query, qclass, qtype, qname, initiator='127.0.0.1'):
4bfebc93 105 self.assertEqual(msg.type, dnsmessage_pb2.PBDNSMessage.DNSQueryType)
8667904b 106 self.checkProtobufBase(msg, protocol, query, initiator)
1d0bd88a
RG
107 # dnsdist doesn't fill the responder field for responses
108 # because it doesn't keep the information around.
109 self.assertTrue(msg.HasField('to'))
4bfebc93 110 self.assertEqual(socket.inet_ntop(socket.AF_INET, msg.to), '127.0.0.1')
1d0bd88a
RG
111 self.assertTrue(msg.HasField('question'))
112 self.assertTrue(msg.question.HasField('qClass'))
4bfebc93 113 self.assertEqual(msg.question.qClass, qclass)
1d0bd88a 114 self.assertTrue(msg.question.HasField('qType'))
4bfebc93 115 self.assertEqual(msg.question.qClass, qtype)
1d0bd88a 116 self.assertTrue(msg.question.HasField('qName'))
4bfebc93 117 self.assertEqual(msg.question.qName, qname)
1d0bd88a 118
0096ada6
RG
119 def checkProtobufTags(self, tags, expectedTags):
120 # only differences will be in new list
121 listx = set(tags) ^ set(expectedTags)
122 # exclusive or of lists should be empty
123 self.assertEqual(len(listx), 0, "Protobuf tags don't match")
741ebe08 124
29cd61cc 125 def checkProtobufQueryConvertedToResponse(self, msg, protocol, response, initiator='127.0.0.0'):
4bfebc93 126 self.assertEqual(msg.type, dnsmessage_pb2.PBDNSMessage.DNSResponseType)
0096ada6
RG
127 # skip comparing inBytes (size of the query) with the length of the generated response
128 self.checkProtobufBase(msg, protocol, response, initiator, False)
29cd61cc
SO
129 self.assertTrue(msg.HasField('response'))
130 self.assertTrue(msg.response.HasField('queryTimeSec'))
131
8667904b 132 def checkProtobufResponse(self, msg, protocol, response, initiator='127.0.0.1'):
4bfebc93 133 self.assertEqual(msg.type, dnsmessage_pb2.PBDNSMessage.DNSResponseType)
8667904b 134 self.checkProtobufBase(msg, protocol, response, initiator)
29cd61cc
SO
135 self.assertTrue(msg.HasField('response'))
136 self.assertTrue(msg.response.HasField('queryTimeSec'))
741ebe08 137
8667904b
RG
138 def checkProtobufResponseRecord(self, record, rclass, rtype, rname, rttl):
139 self.assertTrue(record.HasField('class'))
4bfebc93 140 self.assertEqual(getattr(record, 'class'), rclass)
8667904b 141 self.assertTrue(record.HasField('type'))
4bfebc93 142 self.assertEqual(record.type, rtype)
8667904b 143 self.assertTrue(record.HasField('name'))
4bfebc93 144 self.assertEqual(record.name, rname)
8667904b 145 self.assertTrue(record.HasField('ttl'))
4bfebc93 146 self.assertEqual(record.ttl, rttl)
8667904b
RG
147 self.assertTrue(record.HasField('rdata'))
148
f29fabd9
RG
149class TestProtobuf(DNSDistProtobufTest):
150 _config_params = ['_testServerPort', '_protobufServerPort', '_protobufServerID', '_protobufServerID']
151 _config_template = """
152 luasmn = newSuffixMatchNode()
153 luasmn:add(newDNSName('lua.protobuf.tests.powerdns.com.'))
154
155 function alterProtobufResponse(dq, protobuf)
156 if luasmn:check(dq.qname) then
207e77dd 157 requestor = newCA(tostring(dq.remoteaddr)) -- called by testLuaProtobuf()
f29fabd9
RG
158 if requestor:isIPv4() then
159 requestor:truncate(24)
160 else
161 requestor:truncate(56)
162 end
163 protobuf:setRequestor(requestor)
164
165 local tableTags = {}
166 table.insert(tableTags, "TestLabel1,TestData1")
167 table.insert(tableTags, "TestLabel2,TestData2")
168
169 protobuf:setTagArray(tableTags)
170
171 protobuf:setTag('TestLabel3,TestData3')
172
173 protobuf:setTag("Response,456")
174
175 else
176
177 local tableTags = {} -- called by testProtobuf()
178 table.insert(tableTags, "TestLabel1,TestData1")
179 table.insert(tableTags, "TestLabel2,TestData2")
180 protobuf:setTagArray(tableTags)
181
182 protobuf:setTag('TestLabel3,TestData3')
183
184 protobuf:setTag("Response,456")
185
186 end
187 end
188
189 function alterProtobufQuery(dq, protobuf)
190
191 if luasmn:check(dq.qname) then
207e77dd 192 requestor = newCA(tostring(dq.remoteaddr)) -- called by testLuaProtobuf()
f29fabd9
RG
193 if requestor:isIPv4() then
194 requestor:truncate(24)
195 else
196 requestor:truncate(56)
197 end
198 protobuf:setRequestor(requestor)
199
200 local tableTags = {}
201 tableTags = dq:getTagArray() -- get table from DNSQuery
202
203 local tablePB = {}
204 for k, v in pairs( tableTags) do
205 table.insert(tablePB, k .. "," .. v)
206 end
207
208 protobuf:setTagArray(tablePB) -- store table in protobuf
209 protobuf:setTag("Query,123") -- add another tag entry in protobuf
210
d3ec24f9 211 protobuf:setResponseCode(DNSRCode.NXDOMAIN) -- set protobuf response code to be NXDOMAIN
f29fabd9 212
207e77dd 213 local strReqName = tostring(dq.qname) -- get request dns name
f29fabd9
RG
214
215 protobuf:setProtobufResponseType() -- set protobuf to look like a response and not a query, with 0 default time
216
87f46425 217 blobData = '\127' .. '\000' .. '\000' .. '\002' -- 127.0.0.2, note: lua 5.1 can only embed decimal not hex
f29fabd9
RG
218
219 protobuf:addResponseRR(strReqName, 1, 1, 123, blobData) -- add a RR to the protobuf
220
221 protobuf:setBytes(65) -- set the size of the query to confirm in checkProtobufBase
222
223 else
224
225 local tableTags = {} -- called by testProtobuf()
226 table.insert(tableTags, "TestLabel1,TestData1")
227 table.insert(tableTags, "TestLabel2,TestData2")
228
229 protobuf:setTagArray(tableTags)
230 protobuf:setTag('TestLabel3,TestData3')
231 protobuf:setTag("Query,123")
232
233 end
234 end
235
236 function alterLuaFirst(dq) -- called when dnsdist receives new request
237 local tt = {}
238 tt["TestLabel1"] = "TestData1"
239 tt["TestLabel2"] = "TestData2"
240
241 dq:setTagArray(tt)
242
243 dq:setTag("TestLabel3","TestData3")
244 return DNSAction.None, "" -- continue to the next rule
245 end
246
247 newServer{address="127.0.0.1:%s", useClientSubnet=true}
248 rl = newRemoteLogger('127.0.0.1:%s')
249
250 addAction(AllRule(), LuaAction(alterLuaFirst)) -- Add tags to DNSQuery first
251
252 addAction(AllRule(), RemoteLogAction(rl, alterProtobufQuery, {serverID='%s'})) -- Send protobuf message before lookup
253
254 addResponseAction(AllRule(), RemoteLogResponseAction(rl, alterProtobufResponse, true, {serverID='%s'})) -- Send protobuf message after lookup
255
256 """
257
1d0bd88a
RG
258 def testProtobuf(self):
259 """
260 Protobuf: Send data to a protobuf server
261 """
29cd61cc 262 name = 'query.protobuf.tests.powerdns.com.'
741ebe08 263
165c9030 264 target = 'target.protobuf.tests.powerdns.com.'
1d0bd88a
RG
265 query = dns.message.make_query(name, 'A', 'IN')
266 response = dns.message.make_response(query)
741ebe08 267
1d0bd88a 268 rrset = dns.rrset.from_text(name,
165c9030
RG
269 3600,
270 dns.rdataclass.IN,
271 dns.rdatatype.CNAME,
272 target)
273 response.answer.append(rrset)
741ebe08 274
165c9030 275 rrset = dns.rrset.from_text(target,
1d0bd88a
RG
276 3600,
277 dns.rdataclass.IN,
278 dns.rdatatype.A,
279 '127.0.0.1')
280 response.answer.append(rrset)
281
282 (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
283 self.assertTrue(receivedQuery)
284 self.assertTrue(receivedResponse)
285 receivedQuery.id = query.id
4bfebc93
CH
286 self.assertEqual(query, receivedQuery)
287 self.assertEqual(response, receivedResponse)
1d0bd88a
RG
288
289 # let the protobuf messages the time to get there
290 time.sleep(1)
291
292 # check the protobuf message corresponding to the UDP query
293 msg = self.getFirstProtobufMessage()
741ebe08 294
29cd61cc 295 self.checkProtobufQuery(msg, dnsmessage_pb2.PBDNSMessage.UDP, query, dns.rdataclass.IN, dns.rdatatype.A, name)
0096ada6 296 self.checkProtobufTags(msg.response.tags, [u"TestLabel1,TestData1", u"TestLabel2,TestData2", u"TestLabel3,TestData3", u"Query,123"])
1d0bd88a
RG
297
298 # check the protobuf message corresponding to the UDP response
299 msg = self.getFirstProtobufMessage()
0096ada6
RG
300 self.checkProtobufResponse(msg, dnsmessage_pb2.PBDNSMessage.UDP, response)
301 self.checkProtobufTags(msg.response.tags, [ u"TestLabel1,TestData1", u"TestLabel2,TestData2", u"TestLabel3,TestData3", u"Response,456"])
4bfebc93 302 self.assertEqual(len(msg.response.rrs), 2)
165c9030
RG
303 rr = msg.response.rrs[0]
304 self.checkProtobufResponseRecord(rr, dns.rdataclass.IN, dns.rdatatype.CNAME, name, 3600)
4bfebc93 305 self.assertEqual(rr.rdata.decode('utf-8'), target)
165c9030
RG
306 rr = msg.response.rrs[1]
307 self.checkProtobufResponseRecord(rr, dns.rdataclass.IN, dns.rdatatype.A, target, 3600)
4bfebc93 308 self.assertEqual(socket.inet_ntop(socket.AF_INET, rr.rdata), '127.0.0.1')
1d0bd88a
RG
309
310 (receivedQuery, receivedResponse) = self.sendTCPQuery(query, response)
311 self.assertTrue(receivedQuery)
312 self.assertTrue(receivedResponse)
313 receivedQuery.id = query.id
4bfebc93
CH
314 self.assertEqual(query, receivedQuery)
315 self.assertEqual(response, receivedResponse)
1d0bd88a
RG
316
317 # let the protobuf messages the time to get there
318 time.sleep(1)
319
320 # check the protobuf message corresponding to the TCP query
321 msg = self.getFirstProtobufMessage()
29cd61cc 322
1d0bd88a 323 self.checkProtobufQuery(msg, dnsmessage_pb2.PBDNSMessage.TCP, query, dns.rdataclass.IN, dns.rdatatype.A, name)
0096ada6 324 self.checkProtobufTags(msg.response.tags, [u"TestLabel1,TestData1", u"TestLabel2,TestData2", u"TestLabel3,TestData3", u"Query,123"])
1d0bd88a
RG
325
326 # check the protobuf message corresponding to the TCP response
327 msg = self.getFirstProtobufMessage()
0096ada6
RG
328 self.checkProtobufResponse(msg, dnsmessage_pb2.PBDNSMessage.TCP, response)
329 self.checkProtobufTags(msg.response.tags, [ u"TestLabel1,TestData1", u"TestLabel2,TestData2", u"TestLabel3,TestData3", u"Response,456"])
4bfebc93 330 self.assertEqual(len(msg.response.rrs), 2)
165c9030
RG
331 rr = msg.response.rrs[0]
332 self.checkProtobufResponseRecord(rr, dns.rdataclass.IN, dns.rdatatype.CNAME, name, 3600)
4bfebc93 333 self.assertEqual(rr.rdata.decode('utf-8'), target)
165c9030
RG
334 rr = msg.response.rrs[1]
335 self.checkProtobufResponseRecord(rr, dns.rdataclass.IN, dns.rdatatype.A, target, 3600)
4bfebc93 336 self.assertEqual(socket.inet_ntop(socket.AF_INET, rr.rdata), '127.0.0.1')
8667904b
RG
337
338 def testLuaProtobuf(self):
741ebe08 339
8667904b
RG
340 """
341 Protobuf: Check that the Lua callback rewrote the initiator
342 """
343 name = 'lua.protobuf.tests.powerdns.com.'
344 query = dns.message.make_query(name, 'A', 'IN')
345 response = dns.message.make_response(query)
346 rrset = dns.rrset.from_text(name,
347 3600,
348 dns.rdataclass.IN,
349 dns.rdatatype.A,
350 '127.0.0.1')
351 response.answer.append(rrset)
352
741ebe08 353
8667904b 354 (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
741ebe08 355
29cd61cc
SO
356 self.assertTrue(receivedQuery)
357 self.assertTrue(receivedResponse)
8667904b 358 receivedQuery.id = query.id
4bfebc93
CH
359 self.assertEqual(query, receivedQuery)
360 self.assertEqual(response, receivedResponse)
8667904b 361
741ebe08 362
8667904b
RG
363 # let the protobuf messages the time to get there
364 time.sleep(1)
365
366 # check the protobuf message corresponding to the UDP query
367 msg = self.getFirstProtobufMessage()
29cd61cc 368
0096ada6
RG
369 self.checkProtobufQueryConvertedToResponse(msg, dnsmessage_pb2.PBDNSMessage.UDP, response, '127.0.0.0')
370 self.checkProtobufTags(msg.response.tags, [ u"TestLabel1,TestData1", u"TestLabel2,TestData2", u"TestLabel3,TestData3", u"Query,123"])
8667904b
RG
371
372 # check the protobuf message corresponding to the UDP response
373 msg = self.getFirstProtobufMessage()
0096ada6
RG
374 self.checkProtobufResponse(msg, dnsmessage_pb2.PBDNSMessage.UDP, response, '127.0.0.0')
375 self.checkProtobufTags(msg.response.tags, [ u"TestLabel1,TestData1", u"TestLabel2,TestData2", u"TestLabel3,TestData3", u"Response,456"])
4bfebc93 376 self.assertEqual(len(msg.response.rrs), 1)
8667904b
RG
377 for rr in msg.response.rrs:
378 self.checkProtobufResponseRecord(rr, dns.rdataclass.IN, dns.rdatatype.A, name, 3600)
4bfebc93 379 self.assertEqual(socket.inet_ntop(socket.AF_INET, rr.rdata), '127.0.0.1')
8667904b
RG
380
381 (receivedQuery, receivedResponse) = self.sendTCPQuery(query, response)
382 self.assertTrue(receivedQuery)
383 self.assertTrue(receivedResponse)
384 receivedQuery.id = query.id
4bfebc93
CH
385 self.assertEqual(query, receivedQuery)
386 self.assertEqual(response, receivedResponse)
8667904b
RG
387
388 # let the protobuf messages the time to get there
389 time.sleep(1)
390
391 # check the protobuf message corresponding to the TCP query
392 msg = self.getFirstProtobufMessage()
0096ada6
RG
393 self.checkProtobufQueryConvertedToResponse(msg, dnsmessage_pb2.PBDNSMessage.TCP, response, '127.0.0.0')
394 self.checkProtobufTags(msg.response.tags, [ u"TestLabel1,TestData1", u"TestLabel2,TestData2", u"TestLabel3,TestData3", u"Query,123"])
8667904b
RG
395
396 # check the protobuf message corresponding to the TCP response
397 msg = self.getFirstProtobufMessage()
0096ada6
RG
398 self.checkProtobufResponse(msg, dnsmessage_pb2.PBDNSMessage.TCP, response, '127.0.0.0')
399 self.checkProtobufTags(msg.response.tags, [ u"TestLabel1,TestData1", u"TestLabel2,TestData2", u"TestLabel3,TestData3", u"Response,456"])
4bfebc93 400 self.assertEqual(len(msg.response.rrs), 1)
8667904b
RG
401 for rr in msg.response.rrs:
402 self.checkProtobufResponseRecord(rr, dns.rdataclass.IN, dns.rdatatype.A, name, 3600)
4bfebc93 403 self.assertEqual(socket.inet_ntop(socket.AF_INET, rr.rdata), '127.0.0.1')
f29fabd9
RG
404
405class TestProtobufIPCipher(DNSDistProtobufTest):
406 _config_params = ['_testServerPort', '_protobufServerPort', '_protobufServerID', '_protobufServerID']
407 _config_template = """
408 newServer{address="127.0.0.1:%s", useClientSubnet=true}
409 key = makeIPCipherKey("some 16-byte key")
410 rl = newRemoteLogger('127.0.0.1:%s')
411 addAction(AllRule(), RemoteLogAction(rl, nil, {serverID='%s', ipEncryptKey=key})) -- Send protobuf message before lookup
412 addResponseAction(AllRule(), RemoteLogResponseAction(rl, nil, true, {serverID='%s', ipEncryptKey=key})) -- Send protobuf message after lookup
413
414 """
415
416 def testProtobuf(self):
417 """
87f46425 418 Protobuf: Send data to a protobuf server, with pseudonymization
f29fabd9
RG
419 """
420 name = 'query.protobuf-ipcipher.tests.powerdns.com.'
421
78603024 422 target = 'target.protobuf-ipcipher.tests.powerdns.com.'
f29fabd9
RG
423 query = dns.message.make_query(name, 'A', 'IN')
424 response = dns.message.make_response(query)
425
426 rrset = dns.rrset.from_text(name,
427 3600,
428 dns.rdataclass.IN,
429 dns.rdatatype.CNAME,
430 target)
431 response.answer.append(rrset)
432
433 rrset = dns.rrset.from_text(target,
434 3600,
435 dns.rdataclass.IN,
436 dns.rdatatype.A,
437 '127.0.0.1')
438 response.answer.append(rrset)
439
440 (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
441 self.assertTrue(receivedQuery)
442 self.assertTrue(receivedResponse)
443 receivedQuery.id = query.id
4bfebc93
CH
444 self.assertEqual(query, receivedQuery)
445 self.assertEqual(response, receivedResponse)
f29fabd9
RG
446
447 # let the protobuf messages the time to get there
448 time.sleep(1)
449
450 # check the protobuf message corresponding to the UDP query
451 msg = self.getFirstProtobufMessage()
452
453 # 108.41.239.98 is 127.0.0.1 pseudonymized with ipcipher and the current key
454 self.checkProtobufQuery(msg, dnsmessage_pb2.PBDNSMessage.UDP, query, dns.rdataclass.IN, dns.rdatatype.A, name, '108.41.239.98')
455
456 # check the protobuf message corresponding to the UDP response
457 msg = self.getFirstProtobufMessage()
458 self.checkProtobufResponse(msg, dnsmessage_pb2.PBDNSMessage.UDP, response, '108.41.239.98')
459
4bfebc93 460 self.assertEqual(len(msg.response.rrs), 2)
f29fabd9
RG
461 rr = msg.response.rrs[0]
462 self.checkProtobufResponseRecord(rr, dns.rdataclass.IN, dns.rdatatype.CNAME, name, 3600)
4bfebc93 463 self.assertEqual(rr.rdata.decode('ascii'), target)
f29fabd9
RG
464 rr = msg.response.rrs[1]
465 self.checkProtobufResponseRecord(rr, dns.rdataclass.IN, dns.rdatatype.A, target, 3600)
4bfebc93 466 self.assertEqual(socket.inet_ntop(socket.AF_INET, rr.rdata), '127.0.0.1')
f29fabd9
RG
467
468 (receivedQuery, receivedResponse) = self.sendTCPQuery(query, response)
469 self.assertTrue(receivedQuery)
470 self.assertTrue(receivedResponse)
471 receivedQuery.id = query.id
4bfebc93
CH
472 self.assertEqual(query, receivedQuery)
473 self.assertEqual(response, receivedResponse)
f29fabd9
RG
474
475 # let the protobuf messages the time to get there
476 time.sleep(1)
477
478 # check the protobuf message corresponding to the TCP query
479 msg = self.getFirstProtobufMessage()
480 # 108.41.239.98 is 127.0.0.1 pseudonymized with ipcipher and the current key
481 self.checkProtobufQuery(msg, dnsmessage_pb2.PBDNSMessage.TCP, query, dns.rdataclass.IN, dns.rdatatype.A, name, '108.41.239.98')
482
483 # check the protobuf message corresponding to the TCP response
484 msg = self.getFirstProtobufMessage()
485 self.checkProtobufResponse(msg, dnsmessage_pb2.PBDNSMessage.TCP, response, '108.41.239.98')
4bfebc93 486 self.assertEqual(len(msg.response.rrs), 2)
f29fabd9
RG
487 rr = msg.response.rrs[0]
488 self.checkProtobufResponseRecord(rr, dns.rdataclass.IN, dns.rdatatype.CNAME, name, 3600)
4bfebc93 489 self.assertEqual(rr.rdata.decode('ascii'), target)
f29fabd9
RG
490 rr = msg.response.rrs[1]
491 self.checkProtobufResponseRecord(rr, dns.rdataclass.IN, dns.rdatatype.A, target, 3600)
4bfebc93 492 self.assertEqual(socket.inet_ntop(socket.AF_INET, rr.rdata), '127.0.0.1')