]> git.ipfire.org Git - thirdparty/pdns.git/blame - regression-tests.dnsdist/dnsdisttests.py
dnsdist: Add regression tests for OCSP stapling over DoH and DoT
[thirdparty/pdns.git] / regression-tests.dnsdist / dnsdisttests.py
CommitLineData
ca404e94
RG
1#!/usr/bin/env python2
2
95f0b802 3import copy
ca404e94
RG
4import os
5import socket
a227f47d 6import ssl
ca404e94
RG
7import struct
8import subprocess
9import sys
10import threading
11import time
12import unittest
5df86a8a 13import clientsubnetoption
b1bec9f0
RG
14import dns
15import dns.message
1ea747c0
RG
16import libnacl
17import libnacl.utils
ca404e94 18
b4f23783 19# Python2/3 compatibility hacks
7a0ea291 20try:
21 from queue import Queue
22except ImportError:
b4f23783 23 from Queue import Queue
7a0ea291 24
25try:
b4f23783 26 range = xrange
7a0ea291 27except NameError:
28 pass
b4f23783
CH
29
30
ca404e94
RG
31class DNSDistTest(unittest.TestCase):
32 """
33 Set up a dnsdist instance and responder threads.
34 Queries sent to dnsdist are relayed to the responder threads,
35 who reply with the response provided by the tests themselves
36 on a queue. Responder threads also queue the queries received
37 from dnsdist on a separate queue, allowing the tests to check
38 that the queries sent from dnsdist were as expected.
39 """
40 _dnsDistPort = 5340
b052847c 41 _dnsDistListeningAddr = "127.0.0.1"
ca404e94 42 _testServerPort = 5350
b4f23783
CH
43 _toResponderQueue = Queue()
44 _fromResponderQueue = Queue()
617dfe22 45 _queueTimeout = 1
b1bec9f0 46 _dnsdistStartupDelay = 2.0
ca404e94 47 _dnsdist = None
ec5f5c6b 48 _responsesCounter = {}
18a0e7c6 49 _config_template = """
18a0e7c6
CH
50 """
51 _config_params = ['_testServerPort']
52 _acl = ['127.0.0.1/32']
1ea747c0
RG
53 _consolePort = 5199
54 _consoleKey = None
98650fde
RG
55 _healthCheckName = 'a.root-servers.net.'
56 _healthCheckCounter = 0
e44df0f1 57 _answerUnexpected = True
ca404e94
RG
58
59 @classmethod
60 def startResponders(cls):
61 print("Launching responders..")
ec5f5c6b 62
5df86a8a 63 cls._UDPResponder = threading.Thread(name='UDP Responder', target=cls.UDPResponder, args=[cls._testServerPort, cls._toResponderQueue, cls._fromResponderQueue])
ca404e94
RG
64 cls._UDPResponder.setDaemon(True)
65 cls._UDPResponder.start()
5df86a8a 66 cls._TCPResponder = threading.Thread(name='TCP Responder', target=cls.TCPResponder, args=[cls._testServerPort, cls._toResponderQueue, cls._fromResponderQueue])
ca404e94
RG
67 cls._TCPResponder.setDaemon(True)
68 cls._TCPResponder.start()
69
70 @classmethod
aac2124b 71 def startDNSDist(cls):
ca404e94 72 print("Launching dnsdist..")
aac2124b 73 confFile = os.path.join('configs', 'dnsdist_%s.conf' % (cls.__name__))
18a0e7c6
CH
74 params = tuple([getattr(cls, param) for param in cls._config_params])
75 print(params)
aac2124b 76 with open(confFile, 'w') as conf:
18a0e7c6
CH
77 conf.write("-- Autogenerated by dnsdisttests.py\n")
78 conf.write(cls._config_template % params)
79
a91c99c1 80 dnsdistcmd = [os.environ['DNSDISTBIN'], '--supervised', '-C', confFile,
b052847c 81 '-l', '%s:%d' % (cls._dnsDistListeningAddr, cls._dnsDistPort) ]
18a0e7c6
CH
82 for acl in cls._acl:
83 dnsdistcmd.extend(['--acl', acl])
84 print(' '.join(dnsdistcmd))
85
6b44773a
CH
86 # validate config with --check-config, which sets client=true, possibly exposing bugs.
87 testcmd = dnsdistcmd + ['--check-config']
ff0bc6a6
JS
88 try:
89 output = subprocess.check_output(testcmd, stderr=subprocess.STDOUT, close_fds=True)
90 except subprocess.CalledProcessError as exc:
91 raise AssertionError('dnsdist --check-config failed (%d): %s' % (exc.returncode, exc.output))
aac2124b
RG
92 expectedOutput = ('Configuration \'%s\' OK!\n' % (confFile)).encode()
93 if output != expectedOutput:
6b44773a
CH
94 raise AssertionError('dnsdist --check-config failed: %s' % output)
95
aac2124b
RG
96 logFile = os.path.join('configs', 'dnsdist_%s.log' % (cls.__name__))
97 with open(logFile, 'w') as fdLog:
98 cls._dnsdist = subprocess.Popen(dnsdistcmd, close_fds=True, stdout=fdLog, stderr=fdLog)
ca404e94 99
0a2087eb
RG
100 if 'DNSDIST_FAST_TESTS' in os.environ:
101 delay = 0.5
102 else:
617dfe22
RG
103 delay = cls._dnsdistStartupDelay
104
0a2087eb 105 time.sleep(delay)
ca404e94
RG
106
107 if cls._dnsdist.poll() is not None:
0a2087eb 108 cls._dnsdist.kill()
ca404e94
RG
109 sys.exit(cls._dnsdist.returncode)
110
111 @classmethod
112 def setUpSockets(cls):
113 print("Setting up UDP socket..")
114 cls._sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
1ade83b2 115 cls._sock.settimeout(2.0)
ca404e94
RG
116 cls._sock.connect(("127.0.0.1", cls._dnsDistPort))
117
118 @classmethod
119 def setUpClass(cls):
120
121 cls.startResponders()
aac2124b 122 cls.startDNSDist()
ca404e94
RG
123 cls.setUpSockets()
124
125 print("Launching tests..")
126
127 @classmethod
128 def tearDownClass(cls):
0a2087eb
RG
129 if 'DNSDIST_FAST_TESTS' in os.environ:
130 delay = 0.1
131 else:
b1bec9f0 132 delay = 1.0
ca404e94
RG
133 if cls._dnsdist:
134 cls._dnsdist.terminate()
0a2087eb
RG
135 if cls._dnsdist.poll() is None:
136 time.sleep(delay)
137 if cls._dnsdist.poll() is None:
138 cls._dnsdist.kill()
1ade83b2 139 cls._dnsdist.wait()
ca404e94
RG
140
141 @classmethod
fe1c60f2 142 def _ResponderIncrementCounter(cls):
ec5f5c6b
RG
143 if threading.currentThread().name in cls._responsesCounter:
144 cls._responsesCounter[threading.currentThread().name] += 1
145 else:
146 cls._responsesCounter[threading.currentThread().name] = 1
147
fe1c60f2 148 @classmethod
4aa08b62 149 def _getResponse(cls, request, fromQueue, toQueue, synthesize=None):
fe1c60f2
RG
150 response = None
151 if len(request.question) != 1:
152 print("Skipping query with question count %d" % (len(request.question)))
153 return None
98650fde
RG
154 healthCheck = str(request.question[0].name).endswith(cls._healthCheckName)
155 if healthCheck:
156 cls._healthCheckCounter += 1
4aa08b62 157 response = dns.message.make_response(request)
98650fde 158 else:
fe1c60f2 159 cls._ResponderIncrementCounter()
5df86a8a 160 if not fromQueue.empty():
4aa08b62
RG
161 toQueue.put(request, True, cls._queueTimeout)
162 if synthesize is None:
163 response = fromQueue.get(True, cls._queueTimeout)
164 if response:
165 response = copy.copy(response)
166 response.id = request.id
fe1c60f2 167
e44df0f1 168 if not response:
4aa08b62 169 if synthesize is not None:
e44df0f1 170 response = dns.message.make_response(request)
4aa08b62 171 response.set_rcode(synthesize)
e44df0f1
RG
172 elif cls._answerUnexpected:
173 response = dns.message.make_response(request)
174 response.set_rcode(dns.rcode.SERVFAIL)
fe1c60f2
RG
175
176 return response
177
ec5f5c6b 178 @classmethod
a620f197 179 def UDPResponder(cls, port, fromQueue, toQueue, trailingDataResponse=False, callback=None):
3ef7ab0d
RG
180 # trailingDataResponse=True means "ignore trailing data".
181 # Other values are either False (meaning "raise an exception")
182 # or are interpreted as a response RCODE for queries with trailing data.
a620f197 183 # callback is invoked for every -even healthcheck ones- query and should return a raw response
4aa08b62 184 ignoreTrailing = trailingDataResponse is True
3ef7ab0d 185
ca404e94
RG
186 sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
187 sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)
ec5f5c6b 188 sock.bind(("127.0.0.1", port))
ca404e94
RG
189 while True:
190 data, addr = sock.recvfrom(4096)
4aa08b62
RG
191 forceRcode = None
192 try:
193 request = dns.message.from_wire(data, ignore_trailing=ignoreTrailing)
194 except dns.message.TrailingJunk as e:
3ef7ab0d 195 if trailingDataResponse is False or forceRcode is True:
4aa08b62
RG
196 raise
197 print("UDP query with trailing data, synthesizing response")
198 request = dns.message.from_wire(data, ignore_trailing=True)
199 forceRcode = trailingDataResponse
200
f3913dd2 201 wire = None
a620f197
RG
202 if callback:
203 wire = callback(request)
204 else:
205 response = cls._getResponse(request, fromQueue, toQueue, synthesize=forceRcode)
206 if response:
207 wire = response.to_wire()
87c605c4 208
f3913dd2
RG
209 if not wire:
210 continue
211
1ade83b2 212 sock.settimeout(2.0)
a620f197 213 sock.sendto(wire, addr)
1ade83b2 214 sock.settimeout(None)
ca404e94
RG
215 sock.close()
216
217 @classmethod
a620f197 218 def TCPResponder(cls, port, fromQueue, toQueue, trailingDataResponse=False, multipleResponses=False, callback=None):
3ef7ab0d
RG
219 # trailingDataResponse=True means "ignore trailing data".
220 # Other values are either False (meaning "raise an exception")
221 # or are interpreted as a response RCODE for queries with trailing data.
a620f197 222 # callback is invoked for every -even healthcheck ones- query and should return a raw response
4aa08b62 223 ignoreTrailing = trailingDataResponse is True
3ef7ab0d 224
ca404e94 225 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
501af9ae 226 sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
ca404e94
RG
227 sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)
228 try:
ec5f5c6b 229 sock.bind(("127.0.0.1", port))
ca404e94
RG
230 except socket.error as e:
231 print("Error binding in the TCP responder: %s" % str(e))
232 sys.exit(1)
233
234 sock.listen(100)
235 while True:
b1bec9f0 236 (conn, _) = sock.accept()
6ac8517d 237 conn.settimeout(5.0)
ca404e94 238 data = conn.recv(2)
98650fde
RG
239 if not data:
240 conn.close()
241 continue
242
ca404e94
RG
243 (datalen,) = struct.unpack("!H", data)
244 data = conn.recv(datalen)
4aa08b62
RG
245 forceRcode = None
246 try:
247 request = dns.message.from_wire(data, ignore_trailing=ignoreTrailing)
248 except dns.message.TrailingJunk as e:
3ef7ab0d 249 if trailingDataResponse is False or forceRcode is True:
4aa08b62
RG
250 raise
251 print("TCP query with trailing data, synthesizing response")
252 request = dns.message.from_wire(data, ignore_trailing=True)
253 forceRcode = trailingDataResponse
254
a620f197
RG
255 if callback:
256 wire = callback(request)
257 else:
258 response = cls._getResponse(request, fromQueue, toQueue, synthesize=forceRcode)
259 if response:
260 wire = response.to_wire(max_size=65535)
261
262 if not wire:
548c8b66 263 conn.close()
ca404e94 264 continue
ca404e94 265
ca404e94
RG
266 conn.send(struct.pack("!H", len(wire)))
267 conn.send(wire)
548c8b66
RG
268
269 while multipleResponses:
5df86a8a 270 if fromQueue.empty():
548c8b66
RG
271 break
272
5df86a8a 273 response = fromQueue.get(True, cls._queueTimeout)
548c8b66
RG
274 if not response:
275 break
276
277 response = copy.copy(response)
278 response.id = request.id
6ac8517d 279 wire = response.to_wire(max_size=65535)
284d460c
RG
280 try:
281 conn.send(struct.pack("!H", len(wire)))
282 conn.send(wire)
283 except socket.error as e:
284 # some of the tests are going to close
285 # the connection on us, just deal with it
286 break
548c8b66 287
ca404e94 288 conn.close()
548c8b66 289
ca404e94
RG
290 sock.close()
291
292 @classmethod
55baa1f2 293 def sendUDPQuery(cls, query, response, useQueue=True, timeout=2.0, rawQuery=False):
ca404e94 294 if useQueue:
617dfe22 295 cls._toResponderQueue.put(response, True, timeout)
ca404e94
RG
296
297 if timeout:
298 cls._sock.settimeout(timeout)
299
300 try:
55baa1f2
RG
301 if not rawQuery:
302 query = query.to_wire()
303 cls._sock.send(query)
ca404e94 304 data = cls._sock.recv(4096)
b1bec9f0 305 except socket.timeout:
ca404e94
RG
306 data = None
307 finally:
308 if timeout:
309 cls._sock.settimeout(None)
310
311 receivedQuery = None
312 message = None
313 if useQueue and not cls._fromResponderQueue.empty():
617dfe22 314 receivedQuery = cls._fromResponderQueue.get(True, timeout)
ca404e94
RG
315 if data:
316 message = dns.message.from_wire(data)
317 return (receivedQuery, message)
318
319 @classmethod
9396d955 320 def openTCPConnection(cls, timeout=None):
ca404e94 321 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
501af9ae 322 sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
ca404e94
RG
323 if timeout:
324 sock.settimeout(timeout)
325
0a2087eb 326 sock.connect(("127.0.0.1", cls._dnsDistPort))
9396d955 327 return sock
0a2087eb 328
9396d955 329 @classmethod
a227f47d
RG
330 def openTLSConnection(cls, port, serverName, caCert=None, timeout=None):
331 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
501af9ae 332 sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
a227f47d
RG
333 if timeout:
334 sock.settimeout(timeout)
335
336 # 2.7.9+
337 if hasattr(ssl, 'create_default_context'):
338 sslctx = ssl.create_default_context(cafile=caCert)
339 sslsock = sslctx.wrap_socket(sock, server_hostname=serverName)
340 else:
341 sslsock = ssl.wrap_socket(sock, ca_certs=caCert, cert_reqs=ssl.CERT_REQUIRED)
342
343 sslsock.connect(("127.0.0.1", port))
344 return sslsock
345
346 @classmethod
347 def sendTCPQueryOverConnection(cls, sock, query, rawQuery=False, response=None, timeout=2.0):
9396d955
RG
348 if not rawQuery:
349 wire = query.to_wire()
350 else:
351 wire = query
55baa1f2 352
a227f47d
RG
353 if response:
354 cls._toResponderQueue.put(response, True, timeout)
355
9396d955
RG
356 sock.send(struct.pack("!H", len(wire)))
357 sock.send(wire)
358
359 @classmethod
a227f47d 360 def recvTCPResponseOverConnection(cls, sock, useQueue=False, timeout=2.0):
9396d955
RG
361 message = None
362 data = sock.recv(2)
363 if data:
364 (datalen,) = struct.unpack("!H", data)
365 data = sock.recv(datalen)
ca404e94 366 if data:
9396d955 367 message = dns.message.from_wire(data)
a227f47d
RG
368
369 if useQueue and not cls._fromResponderQueue.empty():
370 receivedQuery = cls._fromResponderQueue.get(True, timeout)
371 return (receivedQuery, message)
372 else:
373 return message
9396d955
RG
374
375 @classmethod
376 def sendTCPQuery(cls, query, response, useQueue=True, timeout=2.0, rawQuery=False):
377 message = None
378 if useQueue:
379 cls._toResponderQueue.put(response, True, timeout)
380
381 sock = cls.openTCPConnection(timeout)
382
383 try:
384 cls.sendTCPQueryOverConnection(sock, query, rawQuery)
385 message = cls.recvTCPResponseOverConnection(sock)
ca404e94
RG
386 except socket.timeout as e:
387 print("Timeout: %s" % (str(e)))
ca404e94
RG
388 except socket.error as e:
389 print("Network error: %s" % (str(e)))
ca404e94
RG
390 finally:
391 sock.close()
392
393 receivedQuery = None
ca404e94 394 if useQueue and not cls._fromResponderQueue.empty():
617dfe22 395 receivedQuery = cls._fromResponderQueue.get(True, timeout)
9396d955 396
ca404e94 397 return (receivedQuery, message)
617dfe22 398
548c8b66
RG
399 @classmethod
400 def sendTCPQueryWithMultipleResponses(cls, query, responses, useQueue=True, timeout=2.0, rawQuery=False):
401 if useQueue:
402 for response in responses:
403 cls._toResponderQueue.put(response, True, timeout)
404 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
501af9ae 405 sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
548c8b66
RG
406 if timeout:
407 sock.settimeout(timeout)
408
409 sock.connect(("127.0.0.1", cls._dnsDistPort))
410 messages = []
411
412 try:
413 if not rawQuery:
414 wire = query.to_wire()
415 else:
416 wire = query
417
418 sock.send(struct.pack("!H", len(wire)))
419 sock.send(wire)
420 while True:
421 data = sock.recv(2)
422 if not data:
423 break
424 (datalen,) = struct.unpack("!H", data)
425 data = sock.recv(datalen)
426 messages.append(dns.message.from_wire(data))
427
428 except socket.timeout as e:
429 print("Timeout: %s" % (str(e)))
430 except socket.error as e:
431 print("Network error: %s" % (str(e)))
432 finally:
433 sock.close()
434
435 receivedQuery = None
436 if useQueue and not cls._fromResponderQueue.empty():
437 receivedQuery = cls._fromResponderQueue.get(True, timeout)
438 return (receivedQuery, messages)
439
617dfe22
RG
440 def setUp(self):
441 # This function is called before every tests
442
443 # Clear the responses counters
444 for key in self._responsesCounter:
445 self._responsesCounter[key] = 0
446
98650fde
RG
447 self._healthCheckCounter = 0
448
617dfe22
RG
449 # Make sure the queues are empty, in case
450 # a previous test failed
451 while not self._toResponderQueue.empty():
452 self._toResponderQueue.get(False)
453
454 while not self._fromResponderQueue.empty():
fe1c60f2 455 self._fromResponderQueue.get(False)
1ea747c0 456
3bef39c3
RG
457 @classmethod
458 def clearToResponderQueue(cls):
459 while not cls._toResponderQueue.empty():
460 cls._toResponderQueue.get(False)
461
462 @classmethod
463 def clearFromResponderQueue(cls):
464 while not cls._fromResponderQueue.empty():
465 cls._fromResponderQueue.get(False)
466
467 @classmethod
468 def clearResponderQueues(cls):
469 cls.clearToResponderQueue()
470 cls.clearFromResponderQueue()
471
1ea747c0
RG
472 @staticmethod
473 def generateConsoleKey():
474 return libnacl.utils.salsa_key()
475
476 @classmethod
477 def _encryptConsole(cls, command, nonce):
b4f23783 478 command = command.encode('UTF-8')
1ea747c0
RG
479 if cls._consoleKey is None:
480 return command
481 return libnacl.crypto_secretbox(command, nonce, cls._consoleKey)
482
483 @classmethod
484 def _decryptConsole(cls, command, nonce):
485 if cls._consoleKey is None:
b4f23783
CH
486 result = command
487 else:
488 result = libnacl.crypto_secretbox_open(command, nonce, cls._consoleKey)
489 return result.decode('UTF-8')
1ea747c0
RG
490
491 @classmethod
492 def sendConsoleCommand(cls, command, timeout=1.0):
493 ourNonce = libnacl.utils.rand_nonce()
494 theirNonce = None
495 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
501af9ae 496 sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
1ea747c0
RG
497 if timeout:
498 sock.settimeout(timeout)
499
500 sock.connect(("127.0.0.1", cls._consolePort))
501 sock.send(ourNonce)
502 theirNonce = sock.recv(len(ourNonce))
7b925432 503 if len(theirNonce) != len(ourNonce):
05a5b575 504 print("Received a nonce of size %d, expecting %d, console command will not be sent!" % (len(theirNonce), len(ourNonce)))
bdfa6902
RG
505 if len(theirNonce) == 0:
506 raise socket.error("Got EOF while reading a nonce of size %d, console command will not be sent!" % (len(ourNonce)))
7b925432 507 return None
1ea747c0 508
b4f23783 509 halfNonceSize = int(len(ourNonce) / 2)
333ea16e
RG
510 readingNonce = ourNonce[0:halfNonceSize] + theirNonce[halfNonceSize:]
511 writingNonce = theirNonce[0:halfNonceSize] + ourNonce[halfNonceSize:]
333ea16e 512 msg = cls._encryptConsole(command, writingNonce)
1ea747c0
RG
513 sock.send(struct.pack("!I", len(msg)))
514 sock.send(msg)
515 data = sock.recv(4)
9c9b4998
RG
516 if not data:
517 raise socket.error("Got EOF while reading the response size")
518
1ea747c0
RG
519 (responseLen,) = struct.unpack("!I", data)
520 data = sock.recv(responseLen)
333ea16e 521 response = cls._decryptConsole(data, readingNonce)
1ea747c0 522 return response
5df86a8a
RG
523
524 def compareOptions(self, a, b):
525 self.assertEquals(len(a), len(b))
b4f23783 526 for idx in range(len(a)):
5df86a8a
RG
527 self.assertEquals(a[idx], b[idx])
528
529 def checkMessageNoEDNS(self, expected, received):
530 self.assertEquals(expected, received)
531 self.assertEquals(received.edns, -1)
532 self.assertEquals(len(received.options), 0)
533
e7c732b8
RG
534 def checkMessageEDNSWithoutOptions(self, expected, received):
535 self.assertEquals(expected, received)
536 self.assertEquals(received.edns, 0)
d70d5ad3 537 self.assertEquals(expected.payload, received.payload)
e7c732b8 538
5df86a8a
RG
539 def checkMessageEDNSWithoutECS(self, expected, received, withCookies=0):
540 self.assertEquals(expected, received)
541 self.assertEquals(received.edns, 0)
d70d5ad3 542 self.assertEquals(expected.payload, received.payload)
5df86a8a
RG
543 self.assertEquals(len(received.options), withCookies)
544 if withCookies:
545 for option in received.options:
546 self.assertEquals(option.otype, 10)
547
cbf4e13a 548 def checkMessageEDNSWithECS(self, expected, received, additionalOptions=0):
5df86a8a
RG
549 self.assertEquals(expected, received)
550 self.assertEquals(received.edns, 0)
d70d5ad3 551 self.assertEquals(expected.payload, received.payload)
cbf4e13a
RG
552 self.assertEquals(len(received.options), 1 + additionalOptions)
553 hasECS = False
554 for option in received.options:
555 if option.otype == clientsubnetoption.ASSIGNED_OPTION_CODE:
556 hasECS = True
557 else:
558 self.assertNotEquals(additionalOptions, 0)
559
5df86a8a 560 self.compareOptions(expected.options, received.options)
cbf4e13a 561 self.assertTrue(hasECS)
5df86a8a 562
cbf4e13a
RG
563 def checkQueryEDNSWithECS(self, expected, received, additionalOptions=0):
564 self.checkMessageEDNSWithECS(expected, received, additionalOptions)
5df86a8a 565
cbf4e13a
RG
566 def checkResponseEDNSWithECS(self, expected, received, additionalOptions=0):
567 self.checkMessageEDNSWithECS(expected, received, additionalOptions)
5df86a8a
RG
568
569 def checkQueryEDNSWithoutECS(self, expected, received):
570 self.checkMessageEDNSWithoutECS(expected, received)
571
572 def checkResponseEDNSWithoutECS(self, expected, received, withCookies=0):
573 self.checkMessageEDNSWithoutECS(expected, received, withCookies)
574
575 def checkQueryNoEDNS(self, expected, received):
576 self.checkMessageNoEDNS(expected, received)
577
578 def checkResponseNoEDNS(self, expected, received):
579 self.checkMessageNoEDNS(expected, received)