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