+++ /dev/null
-# bad NSEC3 owner (:) not in base32hex valid characters
-# header: id=0008 opcode=query questions=1 authority=1
-00 08 00 00 00 01 00 00 00 01 00 00
-# question: ./A/IN
-00 00 01 00 01
-# :./NSEC3/IN/1 length=7 hashtype=240 flags=0 interations=0 salt=- hashlen=1 hash=ff
-01 58 00 00 32 00 01 00 00 00 01 00 07 f0 00 00 00 00 01 ff
+++ /dev/null
-# oversized owner name
-# header: additional=1
-00 00 00 00 00 00 00 00 00 00 00 01
-# owner name too big (256 octets) A/IN/1 0.0.0.0
-0f 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41
-0f 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41
-0f 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41
-0f 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41
-0f 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41
-0f 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41
-0f 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41
-0f 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41
-0f 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41
-0f 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41
-0f 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41
-0f 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41
-0f 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41
-0f 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41
-0f 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41
-0e 41 41 41 41 41 41 41 41 41 41 41 41 41 41 00
-00 01 00 01 00 00 00 01 00 04 00 00 00 00
+++ /dev/null
-# multiple singletons (SOA)
-# header questions=1 answers=2
-00 00 00 00 00 01 00 02 00 00 00 00
-# question SOA/IN
-00 00 06 00 01
-# 2 SOA records that differ in expire
-00 00 06 00 01 00 00 00 01 00 16 00 00 00 00 00 01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 05
-00 00 06 00 01 00 00 00 01 00 16 00 00 00 00 00 01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 06
+++ /dev/null
-# header: 2 questions
-00 00 00 00 00 02 00 00 00 00 00 00
-# question: AAAAAAAAAAAAAA./A/IN
-0e 41 41 41 41 41 41 41 41 41 41 41 41 41 41 00
-00 01
-00 01
-# question: AAAAAAAAAAAAAA./A/IN
-0e 41 41 41 41 41 41 41 41 41 41 41 41 41 41 00
-00 01
-00 01
+++ /dev/null
-# mismatched key class
-# header: questions=1 additional=1
-00 00 00 00 00 01 00 00 00 00 00 01
-# question: ./A/IN
-00 00 01 00 01
-# additional: ./KEY/CLASS2 flags=0 protocol=0 algorithm=248 keydata=00
-00 00 19 00 02 00 00 00 01 00 05 00 00 00 f8 00
+++ /dev/null
-# UPDATE malformed 'delete type' update change (non empty data)
-# header: UPDATE authority=1
-00 00 28 00 00 00 00 00 00 01 00 00
-# ./A/ANY TTL=0 length=1 data=00
-00 00 01 00 ff 00 00 00 00 00 01 00
+++ /dev/null
-# malformed RRRSIG
-# header: QUERY, additional=1
-00 00 00 00 00 00 00 00 00 00 00 01
-# ./RRSIG/IN TTL=1 covers=0 algorithm=240 labels=0 ttl=1 expire=2 signed=3 id=0
-00 00 2e 00 01 00 00 00 01 00 14 00 00 f0 00 00 00 00 01 00 00 00 02 00 00 00 03 00 00 00 00
+++ /dev/null
-00 00 00 00 00 01 00 00 00 00 00 00
-0f 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41
-0f 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41
-0f 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41
-0f 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41
-0f 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41
-0f 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41
-0f 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41
-0f 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41
-0f 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41
-0f 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41
-0f 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41
-0f 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41
-0f 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41
-0f 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41
-0f 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41
-0e 41 41 41 41 41 41 41 41 41 41 41 41 41 41 00
-00 01
-00 01
+++ /dev/null
-00 00 00 00 00 00 00 00 00 00 00 00
+++ /dev/null
-# OPT record with wrong name (not .)
-# header: QUERY, additional=1
-00 00 00 00 00 00 00 00 00 00 00 01
-# OPT record (owner A.)
-01 41 00 00 29 00 01 00 00 00 00 00 00
+++ /dev/null
-# QTYPE-only type as answer
-# header, answers=1
-00 00 00 00 00 00 00 01 00 00 00 00
-# ./MAILB/IN
-00 00 fd 00 01 00 00 00 01 00 00
+++ /dev/null
-# two questions of different classes
-# header: QUERY, questions=2
-00 00 00 00 00 02 00 00 00 00 00 00
-# ./A/IN
-00 00 01 00 01
-# ./A/CLASS2
-00 00 01 00 02
+++ /dev/null
-# truncated question section
-# header: QUERY, questions=1
-00 00 00 00 00 01 00 00 00 00 00 00
-# truncated question (no class)
-00 00 01
+++ /dev/null
-# truncated record
-# header: QUERY, additional=1
-00 09 00 00 00 00 00 00 00 00 00 01
-# truncated A record (no ttl, length or data)
-00 00 01 00 01
# See the COPYRIGHT file distributed with this work for additional
# information regarding copyright ownership.
-from pathlib import Path
from typing import SupportsInt
import socket
return response
-PACKET_DIR = Path(__file__).parent
-
-
-def parse_packet_file(packet_name: str) -> bytes:
- text = (PACKET_DIR / packet_name).read_text(encoding="utf-8")
- hex_bytes = []
- for line in text.splitlines():
- line = line.split("#", 1)[0].strip()
- if line:
- hex_bytes.append(line)
- return bytes.fromhex(" ".join(hex_bytes))
-
-
-def validate_packet(packet_name: str, generated_wire: bytes) -> None:
- assert generated_wire == parse_packet_file(packet_name)
-
-
@pytest.mark.parametrize(
- "packet_name,query_wire,expected_wire",
+ "query_wire,expected_wire",
[
pytest.param(
- "nametoolong",
wire(
dns_header(qdcount=1),
question_wire(oversized_name_wire()),
id="nametoolong",
),
pytest.param(
- "twoquestionnames",
wire(
dns_header(qdcount=2),
question_wire(name_wire("AAAAAAAAAAAAAA."), dns.rdatatype.RdataType.A),
id="twoquestionnames",
),
pytest.param(
- "twoquestiontypes",
wire(
dns_header(qdcount=2),
question_wire(name_wire("AAAAAAAAAAAAAA."), dns.rdatatype.RdataType.A),
id="twoquestiontypes",
),
pytest.param(
- "dupquestion",
wire(
dns_header(qdcount=2),
question_wire(name_wire("AAAAAAAAAAAAAA."), dns.rdatatype.RdataType.A),
id="dupquestion",
),
pytest.param(
- "dupans",
wire(
dns_header(qdcount=1, ancount=2),
question_wire(root_wire(), dns.rdatatype.RdataType.SOA),
id="dupans",
),
pytest.param(
- "qtypeasanswer",
wire(
dns_header(ancount=1),
rr_wire(
id="qtypeasanswer",
),
pytest.param(
- "noquestions",
dns_header(),
# This would be NOERROR if it included a COOKIE option,
# but is a FORMERR without one.
id="noquestions",
),
pytest.param(
- "badnsec3owner",
wire(
dns_header(message_id=8, qdcount=1, nscount=1),
question_wire(root_wire(), dns.rdatatype.RdataType.A),
id="badnsec3owner",
),
pytest.param(
- "shortrecord",
wire(
dns_header(message_id=9, arcount=1),
# Truncated A record (no ttl, length or data)
id="shortrecord",
),
pytest.param(
- "shortquestion",
wire(
dns_header(qdcount=1),
# Truncated question (no class)
id="shortquestion",
),
pytest.param(
- "questionclass",
wire(
dns_header(qdcount=2),
question_wire(
id="questionclass",
),
pytest.param(
- "badrecordname",
wire(
dns_header(arcount=1),
a_rr(owner=oversized_name_wire()),
id="badrecordname",
),
pytest.param(
- "wrongclass",
wire(
dns_header(arcount=2),
a_rr(),
id="wrongclass",
),
pytest.param(
- "keyclass",
wire(
dns_header(qdcount=1, arcount=1),
question_wire(root_wire(), dns.rdatatype.RdataType.A),
id="keyclass",
),
pytest.param(
- "optwrongname",
wire(
dns_header(arcount=1),
# OPT owner should be root
id="optwrongname",
),
pytest.param(
- "malformedrrsig",
wire(
dns_header(arcount=1),
malformed_rrsig_rr(),
id="malformedrrsig",
),
pytest.param(
- "malformeddeltype",
wire(
dns_header(opcode=dns.opcode.UPDATE, nscount=1),
rr_wire(
id="malformeddeltype",
),
pytest.param(
- "tsigwrongclass",
wire(
dns_header(arcount=1),
# Class should be ANY not IN
id="tsigwrongclass",
),
pytest.param(
- "tsignotlast",
wire(
dns_header(arcount=2),
tsig_rr(),
],
)
def test_formerr(
- packet_name: str,
query_wire: bytes,
expected_wire: bytes,
named_port: int,
ns1,
) -> None:
- validate_packet(packet_name, query_wire)
response = query_raw_tcp(ns1.ip, named_port, query_wire)
assert response.to_wire() == expected_wire
+++ /dev/null
-# SIG not last in additional
-# header: QUERY additional=2
-00 00 00 00 00 00 00 00 00 00 00 02
-# Additional records:
-# SIG record (class ANY)
-00 00 fa 00 ff 00 00 00 01 00 12 00 01 02 03 04 05 06 01 02 00 01 00 00 00 00 00 00 00
-# A record
-00 00 01 00 01 00 00 00 01 00 04 00 00 00 00
+++ /dev/null
-# TSIG wrong class
-# header: QUERY, additional=1
-00 00 00 00 00 00 00 00 00 00 00 01
-# class should be ANY (00 ff) not IN (00 01)
-00 00 fa 00 01 00 00 00 01 00 12 00 01 02 03 04 05 06 01 02 00 01 00 00 00 00 00 00 00
+++ /dev/null
-# two questions with different names
-00 00 00 00 00 02 00 00 00 00 00 00
-# AAAAAAAAAAAAAA./A/IN
-0e 41 41 41 41 41 41 41 41 41 41 41 41 41 41 00
-00 01
-00 01
-# AAAAAAAAAAAAAB./A/IN
-0e 41 41 41 41 41 41 41 41 41 41 41 41 41 41 00
-0e 41 41 41 41 41 41 41 41 41 41 41 41 41 42 00
-00 01
-00 01
+++ /dev/null
-# two questions that differ by type
-00 00 00 00 00 02 00 00 00 00 00 00
-# AAAAAAAAAAAAAAA./A/IN
-0e 41 41 41 41 41 41 41 41 41 41 41 41 41 41 00
-00 01
-00 01
-# AAAAAAAAAAAAAAA./NS/IN
-0e 41 41 41 41 41 41 41 41 41 41 41 41 41 41 00
-00 02
-00 01
+++ /dev/null
-# class mismatch
-# header: QUERY, additional=2
-00 00 00 00 00 00 00 00 00 00 00 02
-# ./A/IN
-00 00 01 00 01 00 00 00 01 00 04 00 00 00 00
-# ./TYPE65280/CLASS256
-00 ff 00 01 00 02 00 00 01 00 04 00 00 00 00