mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-09-05 17:15:31 +00:00
Extend the timeouts system test that bursts the queries for large TXT record and never read any responses back filling up the server TCP write buffer. The test should work with the default wmem_max value on Linux (208k).
223 lines
6.7 KiB
Python
223 lines
6.7 KiB
Python
#!/usr/bin/python3
|
|
|
|
# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
|
#
|
|
# SPDX-License-Identifier: MPL-2.0
|
|
#
|
|
# This Source Code Form is subject to the terms of the Mozilla Public
|
|
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
# file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
|
#
|
|
# See the COPYRIGHT file distributed with this work for additional
|
|
# information regarding copyright ownership.
|
|
|
|
# pylint: disable=unused-variable
|
|
|
|
import socket
|
|
import time
|
|
|
|
import pytest
|
|
|
|
TIMEOUT = 10
|
|
|
|
|
|
def create_msg(qname, qtype):
|
|
import dns.message
|
|
msg = dns.message.make_query(qname, qtype, want_dnssec=True,
|
|
use_edns=0, payload=4096)
|
|
return msg
|
|
|
|
|
|
def timeout():
|
|
return time.time() + TIMEOUT
|
|
|
|
|
|
@pytest.mark.dnspython
|
|
@pytest.mark.dnspython2
|
|
def test_initial_timeout(port):
|
|
#
|
|
# The initial timeout is 2.5 seconds, so this should timeout
|
|
#
|
|
import dns.query
|
|
|
|
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
|
|
sock.connect(("10.53.0.1", port))
|
|
|
|
time.sleep(3)
|
|
|
|
msg = create_msg("example.", "A")
|
|
|
|
with pytest.raises(EOFError):
|
|
try:
|
|
(sbytes, stime) = dns.query.send_tcp(sock, msg, timeout())
|
|
(response, rtime) = dns.query.receive_tcp(sock, timeout())
|
|
except ConnectionError as e:
|
|
raise EOFError from e
|
|
|
|
|
|
@pytest.mark.dnspython
|
|
@pytest.mark.dnspython2
|
|
def test_idle_timeout(port):
|
|
#
|
|
# The idle timeout is 5 seconds, so the third message should fail
|
|
#
|
|
import dns.rcode
|
|
|
|
msg = create_msg("example.", "A")
|
|
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
|
|
sock.connect(("10.53.0.1", port))
|
|
|
|
time.sleep(1)
|
|
|
|
(sbytes, stime) = dns.query.send_tcp(sock, msg, timeout())
|
|
(response, rtime) = dns.query.receive_tcp(sock, timeout())
|
|
|
|
time.sleep(2)
|
|
|
|
(sbytes, stime) = dns.query.send_tcp(sock, msg, timeout())
|
|
(response, rtime) = dns.query.receive_tcp(sock, timeout())
|
|
|
|
time.sleep(6)
|
|
|
|
with pytest.raises(EOFError):
|
|
try:
|
|
(sbytes, stime) = dns.query.send_tcp(sock, msg, timeout())
|
|
(response, rtime) = dns.query.receive_tcp(sock, timeout())
|
|
except ConnectionError as e:
|
|
raise EOFError from e
|
|
|
|
|
|
@pytest.mark.dnspython
|
|
@pytest.mark.dnspython2
|
|
def test_keepalive_timeout(port):
|
|
#
|
|
# Keepalive is 7 seconds, so the third message should succeed.
|
|
#
|
|
import dns.rcode
|
|
|
|
msg = create_msg("example.", "A")
|
|
kopt = dns.edns.GenericOption(11, b'\x00')
|
|
msg.use_edns(edns=True, payload=4096, options=[kopt])
|
|
|
|
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
|
|
sock.connect(("10.53.0.1", port))
|
|
|
|
time.sleep(1)
|
|
|
|
(sbytes, stime) = dns.query.send_tcp(sock, msg, timeout())
|
|
(response, rtime) = dns.query.receive_tcp(sock, timeout())
|
|
|
|
time.sleep(2)
|
|
|
|
(sbytes, stime) = dns.query.send_tcp(sock, msg, timeout())
|
|
(response, rtime) = dns.query.receive_tcp(sock, timeout())
|
|
|
|
time.sleep(6)
|
|
|
|
(sbytes, stime) = dns.query.send_tcp(sock, msg, timeout())
|
|
(response, rtime) = dns.query.receive_tcp(sock, timeout())
|
|
|
|
|
|
@pytest.mark.dnspython
|
|
@pytest.mark.dnspython2
|
|
def test_pipelining_timeout(port):
|
|
#
|
|
# The pipelining should only timeout after the last message is received
|
|
#
|
|
import dns.query
|
|
|
|
msg = create_msg("example.", "A")
|
|
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
|
|
sock.connect(("10.53.0.1", port))
|
|
|
|
time.sleep(1)
|
|
|
|
# Send and receive 25 DNS queries
|
|
for n in range(25):
|
|
(sbytes, stime) = dns.query.send_tcp(sock, msg, timeout())
|
|
for n in range(25):
|
|
(response, rtime) = dns.query.receive_tcp(sock, timeout())
|
|
|
|
time.sleep(3)
|
|
|
|
# Send and receive 25 DNS queries
|
|
for n in range(25):
|
|
(sbytes, stime) = dns.query.send_tcp(sock, msg, timeout())
|
|
for n in range(25):
|
|
(response, rtime) = dns.query.receive_tcp(sock, timeout())
|
|
|
|
time.sleep(6)
|
|
|
|
with pytest.raises(EOFError):
|
|
try:
|
|
(sbytes, stime) = dns.query.send_tcp(sock, msg, timeout())
|
|
(response, rtime) = dns.query.receive_tcp(sock, timeout())
|
|
except ConnectionError as e:
|
|
raise EOFError from e
|
|
|
|
|
|
@pytest.mark.dnspython
|
|
@pytest.mark.dnspython2
|
|
def test_long_axfr(port):
|
|
#
|
|
# The timers should not fire during AXFR, thus the connection should not
|
|
# close abruptly
|
|
#
|
|
import dns.query
|
|
import dns.rdataclass
|
|
import dns.rdatatype
|
|
|
|
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
|
|
sock.connect(("10.53.0.1", port))
|
|
|
|
name = dns.name.from_text("example.")
|
|
msg = create_msg("example.", "AXFR")
|
|
(sbytes, stime) = dns.query.send_tcp(sock, msg, timeout())
|
|
|
|
# Receive the initial DNS message with SOA
|
|
(response, rtime) = dns.query.receive_tcp(sock, timeout(),
|
|
one_rr_per_rrset=True)
|
|
soa = response.get_rrset(dns.message.ANSWER, name,
|
|
dns.rdataclass.IN, dns.rdatatype.SOA)
|
|
assert soa is not None
|
|
|
|
# Pull DNS message from wire until the second SOA is received
|
|
while True:
|
|
(response, rtime) = dns.query.receive_tcp(sock, timeout(),
|
|
one_rr_per_rrset=True)
|
|
soa = response.get_rrset(dns.message.ANSWER, name,
|
|
dns.rdataclass.IN, dns.rdatatype.SOA)
|
|
if soa is not None:
|
|
break
|
|
assert soa is not None
|
|
|
|
|
|
@pytest.mark.dnspython
|
|
@pytest.mark.dnspython2
|
|
def test_send_timeout(port):
|
|
import dns.query
|
|
|
|
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
|
|
sock.connect(("10.53.0.1", port))
|
|
|
|
# Send and receive single large RDATA over TCP
|
|
msg = create_msg("large.example.", "TXT")
|
|
(sbytes, stime) = dns.query.send_tcp(sock, msg, timeout())
|
|
(response, rtime) = dns.query.receive_tcp(sock, timeout())
|
|
|
|
# Send and receive 28 large (~32k) DNS queries that should
|
|
# fill the default maximum 208k TCP send buffer
|
|
for n in range(28):
|
|
(sbytes, stime) = dns.query.send_tcp(sock, msg, timeout())
|
|
|
|
# configure idle interval is 5 seconds, sleep 6 to make sure we are
|
|
# above the interval
|
|
time.sleep(6)
|
|
|
|
with pytest.raises(EOFError):
|
|
try:
|
|
(sbytes, stime) = dns.query.send_tcp(sock, msg, timeout())
|
|
(response, rtime) = dns.query.receive_tcp(sock, timeout())
|
|
except ConnectionError as e:
|
|
raise EOFError from e
|