]>
Commit | Line | Data |
---|---|---|
8c87daac RG |
1 | #!/usr/bin/env python |
2 | import time | |
3 | import requests | |
4 | import dns | |
5 | from dnsdisttests import DNSDistTest, pickAvailablePort | |
6 | ||
7 | _maintenanceWaitTime = 2 | |
8 | ||
9 | def waitForMaintenanceToRun(): | |
10 | time.sleep(_maintenanceWaitTime) | |
11 | ||
12 | class DynBlocksTest(DNSDistTest): | |
13 | ||
14 | _webTimeout = 2.0 | |
15 | _webServerPort = pickAvailablePort() | |
16 | _webServerBasicAuthPassword = 'secret' | |
17 | _webServerBasicAuthPasswordHashed = '$scrypt$ln=10,p=1,r=8$6DKLnvUYEeXWh3JNOd3iwg==$kSrhdHaRbZ7R74q3lGBqO1xetgxRxhmWzYJ2Qvfm7JM=' | |
18 | _webServerAPIKey = 'apisecret' | |
19 | _webServerAPIKeyHashed = '$scrypt$ln=10,p=1,r=8$9v8JxDfzQVyTpBkTbkUqYg==$bDQzAOHeK1G9UvTPypNhrX48w974ZXbFPtRKS34+aso=' | |
20 | _dynBlockQPS = 10 | |
21 | _dynBlockPeriod = 2 | |
22 | # this needs to be greater than maintenanceWaitTime | |
23 | _dynBlockDuration = _maintenanceWaitTime + 2 | |
24 | _config_params = ['_dynBlockQPS', '_dynBlockPeriod', '_dynBlockDuration', '_testServerPort'] | |
25 | ||
9bf515e1 | 26 | def doTestDynBlockViaAPI(self, ipRange, reason, minSeconds, maxSeconds, minBlocks, maxBlocks, ebpf=False): |
8c87daac RG |
27 | headers = {'x-api-key': self._webServerAPIKey} |
28 | url = 'http://127.0.0.1:' + str(self._webServerPort) + '/jsonstat?command=dynblocklist' | |
29 | r = requests.get(url, headers=headers, timeout=self._webTimeout) | |
30 | self.assertTrue(r) | |
31 | self.assertEqual(r.status_code, 200) | |
32 | ||
33 | content = r.json() | |
34 | self.assertIsNotNone(content) | |
35 | self.assertIn(ipRange, content) | |
36 | ||
37 | values = content[ipRange] | |
9bf515e1 | 38 | for key in ['reason', 'seconds', 'blocks', 'action', 'ebpf']: |
8c87daac RG |
39 | self.assertIn(key, values) |
40 | ||
41 | self.assertEqual(values['reason'], reason) | |
42 | self.assertGreaterEqual(values['seconds'], minSeconds) | |
43 | self.assertLessEqual(values['seconds'], maxSeconds) | |
44 | self.assertGreaterEqual(values['blocks'], minBlocks) | |
45 | self.assertLessEqual(values['blocks'], maxBlocks) | |
9bf515e1 | 46 | self.assertEqual(values['ebpf'], True if ebpf else False) |
8c87daac | 47 | |
9bf515e1 | 48 | def doTestQRate(self, name, testViaAPI=True, ebpf=False): |
8c87daac RG |
49 | query = dns.message.make_query(name, 'A', 'IN') |
50 | response = dns.message.make_response(query) | |
51 | rrset = dns.rrset.from_text(name, | |
52 | 60, | |
53 | dns.rdataclass.IN, | |
54 | dns.rdatatype.A, | |
55 | '192.0.2.1') | |
56 | response.answer.append(rrset) | |
57 | ||
58 | allowed = 0 | |
59 | sent = 0 | |
60 | for _ in range((self._dynBlockQPS * self._dynBlockPeriod) + 1): | |
61 | (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response) | |
62 | sent = sent + 1 | |
63 | if receivedQuery: | |
64 | receivedQuery.id = query.id | |
65 | self.assertEqual(query, receivedQuery) | |
66 | self.assertEqual(response, receivedResponse) | |
67 | allowed = allowed + 1 | |
68 | else: | |
69 | # the query has not reached the responder, | |
70 | # let's clear the response queue | |
71 | self.clearToResponderQueue() | |
72 | ||
73 | # we might be already blocked, but we should have been able to send | |
74 | # at least self._dynBlockQPS queries | |
75 | self.assertGreaterEqual(allowed, self._dynBlockQPS) | |
76 | ||
77 | if allowed == sent: | |
78 | waitForMaintenanceToRun() | |
79 | ||
80 | # we should now be dropped for up to self._dynBlockDuration + self._dynBlockPeriod | |
110624de | 81 | (_, receivedResponse) = self.sendUDPQuery(query, response=None, useQueue=False, timeout=0.5) |
8c87daac RG |
82 | self.assertEqual(receivedResponse, None) |
83 | ||
84 | if testViaAPI: | |
9bf515e1 | 85 | self.doTestDynBlockViaAPI('127.0.0.1/32', 'Exceeded query rate', 1, self._dynBlockDuration, (sent-allowed)+1, (sent-allowed)+1, ebpf) |
8c87daac RG |
86 | |
87 | # wait until we are not blocked anymore | |
88 | time.sleep(self._dynBlockDuration + self._dynBlockPeriod) | |
89 | ||
90 | # this one should succeed | |
91 | (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response) | |
92 | receivedQuery.id = query.id | |
93 | self.assertEqual(query, receivedQuery) | |
94 | self.assertEqual(response, receivedResponse) | |
95 | ||
96 | # again, over TCP this time | |
97 | allowed = 0 | |
98 | sent = 0 | |
99 | for _ in range((self._dynBlockQPS * self._dynBlockPeriod) + 1): | |
100 | (receivedQuery, receivedResponse) = self.sendTCPQuery(query, response) | |
101 | sent = sent + 1 | |
102 | if receivedQuery: | |
103 | receivedQuery.id = query.id | |
104 | self.assertEqual(query, receivedQuery) | |
105 | self.assertEqual(response, receivedResponse) | |
106 | allowed = allowed + 1 | |
107 | else: | |
108 | # the query has not reached the responder, | |
109 | # let's clear the response queue | |
110 | self.clearToResponderQueue() | |
111 | ||
112 | # we might be already blocked, but we should have been able to send | |
113 | # at least self._dynBlockQPS queries | |
114 | self.assertGreaterEqual(allowed, self._dynBlockQPS) | |
115 | ||
116 | if allowed == sent: | |
117 | waitForMaintenanceToRun() | |
118 | ||
119 | # we should now be dropped for up to self._dynBlockDuration + self._dynBlockPeriod | |
110624de | 120 | (_, receivedResponse) = self.sendTCPQuery(query, response=None, useQueue=False, timeout=0.5) |
8c87daac RG |
121 | self.assertEqual(receivedResponse, None) |
122 | ||
123 | # wait until we are not blocked anymore | |
124 | time.sleep(self._dynBlockDuration + self._dynBlockPeriod) | |
125 | ||
126 | # this one should succeed | |
127 | (receivedQuery, receivedResponse) = self.sendTCPQuery(query, response) | |
128 | receivedQuery.id = query.id | |
129 | self.assertEqual(query, receivedQuery) | |
130 | self.assertEqual(response, receivedResponse) | |
131 | ||
132 | def doTestQRateRCode(self, name, rcode): | |
133 | query = dns.message.make_query(name, 'A', 'IN') | |
134 | response = dns.message.make_response(query) | |
135 | rrset = dns.rrset.from_text(name, | |
136 | 60, | |
137 | dns.rdataclass.IN, | |
138 | dns.rdatatype.A, | |
139 | '192.0.2.1') | |
140 | response.answer.append(rrset) | |
141 | expectedResponse = dns.message.make_response(query) | |
142 | expectedResponse.set_rcode(rcode) | |
143 | ||
144 | allowed = 0 | |
145 | sent = 0 | |
146 | for _ in range((self._dynBlockQPS * self._dynBlockPeriod) + 1): | |
147 | (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response) | |
148 | sent = sent + 1 | |
149 | if receivedQuery: | |
150 | receivedQuery.id = query.id | |
151 | self.assertEqual(query, receivedQuery) | |
152 | self.assertEqual(receivedResponse, response) | |
153 | allowed = allowed + 1 | |
154 | else: | |
155 | self.assertEqual(receivedResponse, expectedResponse) | |
156 | # the query has not reached the responder, | |
157 | # let's clear the response queue | |
158 | self.clearToResponderQueue() | |
159 | ||
160 | # we might be already blocked, but we should have been able to send | |
161 | # at least self._dynBlockQPS queries | |
162 | self.assertGreaterEqual(allowed, self._dynBlockQPS) | |
163 | ||
164 | if allowed == sent: | |
165 | waitForMaintenanceToRun() | |
166 | ||
167 | # we should now be 'rcode' for up to self._dynBlockDuration + self._dynBlockPeriod | |
168 | (_, receivedResponse) = self.sendUDPQuery(query, response=None, useQueue=False) | |
169 | self.assertEqual(receivedResponse, expectedResponse) | |
170 | ||
171 | # wait until we are not blocked anymore | |
172 | time.sleep(self._dynBlockDuration + self._dynBlockPeriod) | |
173 | ||
174 | # this one should succeed | |
175 | (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response) | |
176 | receivedQuery.id = query.id | |
177 | self.assertEqual(query, receivedQuery) | |
178 | self.assertEqual(response, receivedResponse) | |
179 | ||
180 | allowed = 0 | |
181 | sent = 0 | |
182 | # again, over TCP this time | |
183 | for _ in range((self._dynBlockQPS * self._dynBlockPeriod) + 1): | |
184 | (receivedQuery, receivedResponse) = self.sendTCPQuery(query, response) | |
185 | sent = sent + 1 | |
186 | if receivedQuery: | |
187 | receivedQuery.id = query.id | |
188 | self.assertEqual(query, receivedQuery) | |
189 | self.assertEqual(receivedResponse, response) | |
190 | allowed = allowed + 1 | |
191 | else: | |
192 | self.assertEqual(receivedResponse, expectedResponse) | |
193 | # the query has not reached the responder, | |
194 | # let's clear the response queue | |
195 | self.clearToResponderQueue() | |
196 | ||
197 | # we might be already blocked, but we should have been able to send | |
198 | # at least self._dynBlockQPS queries | |
199 | self.assertGreaterEqual(allowed, self._dynBlockQPS) | |
200 | ||
201 | if allowed == sent: | |
202 | waitForMaintenanceToRun() | |
203 | ||
204 | # we should now be 'rcode' for up to self._dynBlockDuration + self._dynBlockPeriod | |
205 | (_, receivedResponse) = self.sendTCPQuery(query, response=None, useQueue=False) | |
206 | self.assertEqual(receivedResponse, expectedResponse) | |
207 | ||
208 | # wait until we are not blocked anymore | |
209 | time.sleep(self._dynBlockDuration + self._dynBlockPeriod) | |
210 | ||
211 | # this one should succeed | |
212 | (receivedQuery, receivedResponse) = self.sendTCPQuery(query, response) | |
213 | receivedQuery.id = query.id | |
214 | self.assertEqual(query, receivedQuery) | |
215 | self.assertEqual(response, receivedResponse) | |
216 | ||
217 | def doTestResponseByteRate(self, name, dynBlockBytesPerSecond): | |
218 | query = dns.message.make_query(name, 'A', 'IN') | |
219 | response = dns.message.make_response(query) | |
220 | response.answer.append(dns.rrset.from_text_list(name, | |
221 | 60, | |
222 | dns.rdataclass.IN, | |
223 | dns.rdatatype.A, | |
224 | ['192.0.2.1', '192.0.2.2', '192.0.2.3', '192.0.2.4'])) | |
225 | response.answer.append(dns.rrset.from_text(name, | |
226 | 60, | |
227 | dns.rdataclass.IN, | |
228 | dns.rdatatype.AAAA, | |
229 | '2001:DB8::1')) | |
230 | ||
231 | allowed = 0 | |
232 | sent = 0 | |
233 | ||
234 | print(time.time()) | |
235 | ||
236 | for _ in range(int(dynBlockBytesPerSecond * 5 / len(response.to_wire()))): | |
237 | (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response) | |
238 | sent = sent + len(response.to_wire()) | |
239 | if receivedQuery: | |
240 | receivedQuery.id = query.id | |
241 | self.assertEqual(query, receivedQuery) | |
242 | self.assertEqual(response, receivedResponse) | |
243 | allowed = allowed + len(response.to_wire()) | |
244 | else: | |
245 | # the query has not reached the responder, | |
246 | # let's clear the response queue | |
247 | self.clearToResponderQueue() | |
248 | # and stop right there, otherwise we might | |
249 | # wait for so long that the dynblock is gone | |
250 | # by the time we finished | |
251 | break | |
252 | ||
253 | # we might be already blocked, but we should have been able to send | |
254 | # at least dynBlockBytesPerSecond bytes | |
255 | print(allowed) | |
256 | print(sent) | |
257 | print(time.time()) | |
258 | self.assertGreaterEqual(allowed, dynBlockBytesPerSecond) | |
259 | ||
260 | print(self.sendConsoleCommand("showDynBlocks()")) | |
261 | print(self.sendConsoleCommand("grepq(\"\")")) | |
262 | print(time.time()) | |
263 | ||
264 | if allowed == sent: | |
265 | print("Waiting for the maintenance function to run") | |
266 | waitForMaintenanceToRun() | |
267 | ||
268 | print(self.sendConsoleCommand("showDynBlocks()")) | |
269 | print(self.sendConsoleCommand("grepq(\"\")")) | |
270 | print(time.time()) | |
271 | ||
272 | # we should now be dropped for up to self._dynBlockDuration + self._dynBlockPeriod | |
63291e0c | 273 | (_, receivedResponse) = self.sendUDPQuery(query, response=None, useQueue=False, timeout=1) |
8c87daac RG |
274 | self.assertEqual(receivedResponse, None) |
275 | ||
276 | print(self.sendConsoleCommand("showDynBlocks()")) | |
277 | print(self.sendConsoleCommand("grepq(\"\")")) | |
278 | print(time.time()) | |
279 | ||
280 | # wait until we are not blocked anymore | |
281 | time.sleep(self._dynBlockDuration + self._dynBlockPeriod) | |
282 | ||
283 | print(self.sendConsoleCommand("showDynBlocks()")) | |
284 | print(self.sendConsoleCommand("grepq(\"\")")) | |
285 | print(time.time()) | |
286 | ||
287 | # this one should succeed | |
288 | (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response) | |
289 | receivedQuery.id = query.id | |
290 | self.assertEqual(query, receivedQuery) | |
291 | self.assertEqual(response, receivedResponse) | |
292 | ||
293 | # again, over TCP this time | |
294 | allowed = 0 | |
295 | sent = 0 | |
296 | for _ in range(int(dynBlockBytesPerSecond * 5 / len(response.to_wire()))): | |
110624de | 297 | (receivedQuery, receivedResponse) = self.sendTCPQuery(query, response, timeout=0.5) |
8c87daac RG |
298 | sent = sent + len(response.to_wire()) |
299 | if receivedQuery: | |
300 | receivedQuery.id = query.id | |
301 | self.assertEqual(query, receivedQuery) | |
302 | self.assertEqual(response, receivedResponse) | |
303 | allowed = allowed + len(response.to_wire()) | |
304 | else: | |
305 | # the query has not reached the responder, | |
306 | # let's clear the response queue | |
307 | self.clearToResponderQueue() | |
308 | # and stop right there, otherwise we might | |
309 | # wait for so long that the dynblock is gone | |
310 | # by the time we finished | |
311 | break | |
312 | ||
313 | # we might be already blocked, but we should have been able to send | |
314 | # at least dynBlockBytesPerSecond bytes | |
315 | self.assertGreaterEqual(allowed, dynBlockBytesPerSecond) | |
316 | ||
317 | if allowed == sent: | |
318 | waitForMaintenanceToRun() | |
319 | ||
320 | # we should now be dropped for up to self._dynBlockDuration + self._dynBlockPeriod | |
321 | (_, receivedResponse) = self.sendTCPQuery(query, response=None, useQueue=False) | |
322 | self.assertEqual(receivedResponse, None) | |
323 | ||
324 | # wait until we are not blocked anymore | |
325 | time.sleep(self._dynBlockDuration + self._dynBlockPeriod) | |
326 | ||
327 | # this one should succeed | |
328 | (receivedQuery, receivedResponse) = self.sendTCPQuery(query, response) | |
329 | receivedQuery.id = query.id | |
330 | self.assertEqual(query, receivedQuery) | |
331 | self.assertEqual(response, receivedResponse) | |
332 | ||
333 | def doTestRCodeRate(self, name, rcode): | |
334 | query = dns.message.make_query(name, 'A', 'IN') | |
335 | response = dns.message.make_response(query) | |
336 | rrset = dns.rrset.from_text(name, | |
337 | 60, | |
338 | dns.rdataclass.IN, | |
339 | dns.rdatatype.A, | |
340 | '192.0.2.1') | |
341 | response.answer.append(rrset) | |
342 | expectedResponse = dns.message.make_response(query) | |
343 | expectedResponse.set_rcode(rcode) | |
344 | ||
345 | # start with normal responses | |
346 | for _ in range((self._dynBlockQPS * self._dynBlockPeriod) + 1): | |
347 | (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response) | |
348 | receivedQuery.id = query.id | |
349 | self.assertEqual(query, receivedQuery) | |
350 | self.assertEqual(response, receivedResponse) | |
351 | ||
352 | waitForMaintenanceToRun() | |
353 | ||
354 | # we should NOT be dropped! | |
355 | (_, receivedResponse) = self.sendUDPQuery(query, response) | |
356 | self.assertEqual(receivedResponse, response) | |
357 | ||
358 | # now with rcode! | |
359 | sent = 0 | |
360 | allowed = 0 | |
361 | for _ in range((self._dynBlockQPS * self._dynBlockPeriod) + 1): | |
362 | (receivedQuery, receivedResponse) = self.sendUDPQuery(query, expectedResponse) | |
363 | sent = sent + 1 | |
364 | if receivedQuery: | |
365 | receivedQuery.id = query.id | |
366 | self.assertEqual(query, receivedQuery) | |
367 | self.assertEqual(expectedResponse, receivedResponse) | |
368 | allowed = allowed + 1 | |
369 | else: | |
370 | # the query has not reached the responder, | |
371 | # let's clear the response queue | |
372 | self.clearToResponderQueue() | |
373 | ||
374 | # we might be already blocked, but we should have been able to send | |
375 | # at least self._dynBlockQPS queries | |
376 | self.assertGreaterEqual(allowed, self._dynBlockQPS) | |
377 | ||
378 | if allowed == sent: | |
379 | waitForMaintenanceToRun() | |
380 | ||
381 | # we should now be dropped for up to self._dynBlockDuration + self._dynBlockPeriod | |
63291e0c | 382 | (_, receivedResponse) = self.sendUDPQuery(query, response=None, useQueue=False, timeout=1) |
8c87daac RG |
383 | self.assertEqual(receivedResponse, None) |
384 | ||
385 | # wait until we are not blocked anymore | |
386 | time.sleep(self._dynBlockDuration + self._dynBlockPeriod) | |
387 | ||
388 | # this one should succeed | |
389 | (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response) | |
390 | receivedQuery.id = query.id | |
391 | self.assertEqual(query, receivedQuery) | |
392 | self.assertEqual(response, receivedResponse) | |
393 | ||
394 | # again, over TCP this time | |
395 | # start with normal responses | |
396 | for _ in range((self._dynBlockQPS * self._dynBlockPeriod) + 1): | |
397 | (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response) | |
398 | receivedQuery.id = query.id | |
399 | self.assertEqual(query, receivedQuery) | |
400 | self.assertEqual(response, receivedResponse) | |
401 | ||
402 | waitForMaintenanceToRun() | |
403 | ||
404 | # we should NOT be dropped! | |
405 | (_, receivedResponse) = self.sendUDPQuery(query, response) | |
406 | self.assertEqual(receivedResponse, response) | |
407 | ||
408 | # now with rcode! | |
409 | sent = 0 | |
410 | allowed = 0 | |
411 | for _ in range((self._dynBlockQPS * self._dynBlockPeriod) + 1): | |
412 | (receivedQuery, receivedResponse) = self.sendTCPQuery(query, expectedResponse) | |
413 | sent = sent + 1 | |
414 | if receivedQuery: | |
415 | receivedQuery.id = query.id | |
416 | self.assertEqual(query, receivedQuery) | |
417 | self.assertEqual(expectedResponse, receivedResponse) | |
418 | allowed = allowed + 1 | |
419 | else: | |
420 | # the query has not reached the responder, | |
421 | # let's clear the response queue | |
422 | self.clearToResponderQueue() | |
423 | ||
424 | # we might be already blocked, but we should have been able to send | |
425 | # at least self._dynBlockQPS queries | |
426 | self.assertGreaterEqual(allowed, self._dynBlockQPS) | |
427 | ||
428 | if allowed == sent: | |
429 | waitForMaintenanceToRun() | |
430 | ||
431 | # we should now be dropped for up to self._dynBlockDuration + self._dynBlockPeriod | |
110624de | 432 | (_, receivedResponse) = self.sendTCPQuery(query, response=None, useQueue=False, timeout=0.5) |
8c87daac RG |
433 | self.assertEqual(receivedResponse, None) |
434 | ||
435 | # wait until we are not blocked anymore | |
436 | time.sleep(self._dynBlockDuration + self._dynBlockPeriod) | |
437 | ||
438 | # this one should succeed | |
439 | (receivedQuery, receivedResponse) = self.sendTCPQuery(query, response) | |
440 | receivedQuery.id = query.id | |
441 | self.assertEqual(query, receivedQuery) | |
442 | self.assertEqual(response, receivedResponse) | |
443 | ||
444 | def doTestRCodeRatio(self, name, rcode, noerrorcount, rcodecount): | |
445 | query = dns.message.make_query(name, 'A', 'IN') | |
446 | response = dns.message.make_response(query) | |
447 | rrset = dns.rrset.from_text(name, | |
448 | 60, | |
449 | dns.rdataclass.IN, | |
450 | dns.rdatatype.A, | |
451 | '192.0.2.1') | |
452 | response.answer.append(rrset) | |
453 | expectedResponse = dns.message.make_response(query) | |
454 | expectedResponse.set_rcode(rcode) | |
455 | ||
456 | # start with normal responses | |
457 | for _ in range(noerrorcount-1): | |
458 | (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response) | |
459 | receivedQuery.id = query.id | |
460 | self.assertEqual(query, receivedQuery) | |
461 | self.assertEqual(response, receivedResponse) | |
462 | ||
463 | waitForMaintenanceToRun() | |
464 | ||
465 | # we should NOT be dropped! | |
466 | (_, receivedResponse) = self.sendUDPQuery(query, response) | |
467 | self.assertEqual(receivedResponse, response) | |
468 | ||
469 | # now with rcode! | |
470 | sent = 0 | |
471 | allowed = 0 | |
472 | for _ in range(rcodecount): | |
473 | (receivedQuery, receivedResponse) = self.sendUDPQuery(query, expectedResponse) | |
474 | sent = sent + 1 | |
475 | if receivedQuery: | |
476 | receivedQuery.id = query.id | |
477 | self.assertEqual(query, receivedQuery) | |
478 | self.assertEqual(expectedResponse, receivedResponse) | |
479 | allowed = allowed + 1 | |
480 | else: | |
481 | # the query has not reached the responder, | |
482 | # let's clear the response queue | |
483 | self.clearToResponderQueue() | |
484 | ||
485 | # we should have been able to send all our queries since the minimum number of queries is set to noerrorcount + rcodecount | |
486 | self.assertGreaterEqual(allowed, rcodecount) | |
487 | ||
488 | waitForMaintenanceToRun() | |
489 | ||
490 | # we should now be dropped for up to self._dynBlockDuration + self._dynBlockPeriod | |
63291e0c | 491 | (_, receivedResponse) = self.sendUDPQuery(query, response=None, useQueue=False, timeout=1) |
8c87daac RG |
492 | self.assertEqual(receivedResponse, None) |
493 | ||
494 | # wait until we are not blocked anymore | |
495 | time.sleep(self._dynBlockDuration + self._dynBlockPeriod) | |
496 | ||
497 | # this one should succeed | |
498 | (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response) | |
499 | receivedQuery.id = query.id | |
500 | self.assertEqual(query, receivedQuery) | |
501 | self.assertEqual(response, receivedResponse) | |
502 | ||
503 | # again, over TCP this time | |
504 | # start with normal responses | |
505 | for _ in range(noerrorcount-1): | |
506 | (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response) | |
507 | receivedQuery.id = query.id | |
508 | self.assertEqual(query, receivedQuery) | |
509 | self.assertEqual(response, receivedResponse) | |
510 | ||
511 | waitForMaintenanceToRun() | |
512 | ||
513 | # we should NOT be dropped! | |
514 | (_, receivedResponse) = self.sendUDPQuery(query, response) | |
515 | self.assertEqual(receivedResponse, response) | |
516 | ||
517 | # now with rcode! | |
518 | sent = 0 | |
519 | allowed = 0 | |
520 | for _ in range(rcodecount): | |
521 | (receivedQuery, receivedResponse) = self.sendTCPQuery(query, expectedResponse) | |
522 | sent = sent + 1 | |
523 | if receivedQuery: | |
524 | receivedQuery.id = query.id | |
525 | self.assertEqual(query, receivedQuery) | |
526 | self.assertEqual(expectedResponse, receivedResponse) | |
527 | allowed = allowed + 1 | |
528 | else: | |
529 | # the query has not reached the responder, | |
530 | # let's clear the response queue | |
531 | self.clearToResponderQueue() | |
532 | ||
533 | # we should have been able to send all our queries since the minimum number of queries is set to noerrorcount + rcodecount | |
534 | self.assertGreaterEqual(allowed, rcodecount) | |
535 | ||
536 | waitForMaintenanceToRun() | |
537 | ||
538 | # we should now be dropped for up to self._dynBlockDuration + self._dynBlockPeriod | |
110624de | 539 | (_, receivedResponse) = self.sendTCPQuery(query, response=None, useQueue=False, timeout=0.5) |
8c87daac RG |
540 | self.assertEqual(receivedResponse, None) |
541 | ||
542 | # wait until we are not blocked anymore | |
543 | time.sleep(self._dynBlockDuration + self._dynBlockPeriod) | |
544 | ||
545 | # this one should succeed | |
546 | (receivedQuery, receivedResponse) = self.sendTCPQuery(query, response) | |
547 | receivedQuery.id = query.id | |
548 | self.assertEqual(query, receivedQuery) | |
549 | self.assertEqual(response, receivedResponse) |