# See the COPYRIGHT file distributed with this work for additional
# information regarding copyright ownership.
-from typing import Container, Iterable, FrozenSet
+from typing import Iterable, FrozenSet
-import pytest
-
-pytest.importorskip("dns", minversion="2.3.0") # NameRelation
-from dns.name import Name, NameRelation
+import dns.name
import dns.zone
import dns.rdatatype
+from dns.name import Name
+
def prepend_label(label: str, name: Name) -> Name:
return Name((label,) + name.labels)
return cls(zonedb)
def __init__(self, zone: dns.zone.Zone):
+ self._abort_on_old_dnspython()
self.zone = zone
assert self.zone.origin # mypy hack
# based on individual nodes but not relationship between nodes
.union(self.reachable_dnames)
)
+ def _abort_on_old_dnspython(self):
+ if not hasattr(dns.name, "NameRelation"):
+ raise RuntimeError(
+ "ZoneAnalyzer requires dnspython>=2.3.0 for dns.name.NameRelation support. "
+ "Use pytest.importorskip('dns', minversion='2.3.0') to the test module to "
+ "skip this test."
+ )
+
def get_names_with_type(self, rdtype) -> FrozenSet[Name]:
return frozenset(
name for name in self.zone if self.zone.get_rdataset(name, rdtype)
for name in reachable:
relation, _, _ = name.fullcompare(self.zone.origin)
if relation in (
- NameRelation.NONE, # out of zone?
- NameRelation.SUPERDOMAIN, # parent of apex?!
+ dns.name.NameRelation.NONE, # out of zone?
+ dns.name.NameRelation.SUPERDOMAIN, # parent of apex?!
):
raise NotImplementedError
for maybe_occluded in reachable.copy():
for cut in self.delegations:
rel, _, _ = maybe_occluded.fullcompare(cut)
- if rel == NameRelation.EQUAL:
+ if rel == dns.name.NameRelation.EQUAL:
# data _on_ a parent-side of a zone cut are in limbo:
# - are not really authoritative (except for DS)
# - but NS is not really 'occluded'
if maybe_occluded in reachable:
reachable.remove(maybe_occluded)
- if rel == NameRelation.SUBDOMAIN:
+ if rel == dns.name.NameRelation.SUBDOMAIN:
_mark_occluded(maybe_occluded)
# do not break cycle - handle also nested NS and DNAME
# DNAME itself is authoritative but nothing under it is reachable
for dname in self.dnames:
rel, _, _ = maybe_occluded.fullcompare(dname)
- if rel == NameRelation.SUBDOMAIN:
+ if rel == dns.name.NameRelation.SUBDOMAIN:
_mark_occluded(maybe_occluded)
# do not break cycle - handle also nested NS and DNAME
nce = None # Next closer name, RFC 5155
for zname in self.all_existing_names:
relation, _, common_labels = qname.fullcompare(zname)
- if relation == NameRelation.SUBDOMAIN:
+ if relation == dns.name.NameRelation.SUBDOMAIN:
if not ce or common_labels > len(ce):
# longest match so far
ce = zname
"""
ce, _ = self.closest_encloser(qname)
return Name("*") + ce
-
-
-def is_related_to_any(
- test_name: Name,
- acceptable_relations: Container[NameRelation],
- candidates: Iterable[Name],
-) -> bool:
- for maybe_parent in candidates:
- relation, _, _ = test_name.fullcompare(maybe_parent)
- if relation in acceptable_relations:
- return True
- return False
from dataclasses import dataclass
import os
from pathlib import Path
-from typing import Optional, Set, Tuple
+from typing import Container, Iterable, Optional, Set, Tuple
import pytest
)
+def is_related_to_any(
+ test_name: dns.name.Name,
+ acceptable_relations: Container[dns.name.NameRelation],
+ candidates: Iterable[dns.name.Name],
+) -> bool:
+ for maybe_parent in candidates:
+ relation, _, _ = test_name.fullcompare(maybe_parent)
+ if relation in acceptable_relations:
+ return True
+ return False
+
+
def do_test_query(
qname: dns.name.Name, qtype: dns.rdatatype.RdataType, server: str, named_port: int
) -> Tuple[dns.message.QueryMessage, "NSEC3Checker"]:
# name must not be under a delegation or DNAME:
# it would not work with resolver ns2
assume(
- not isctest.name.is_related_to_any(
+ not is_related_to_any(
qname,
(dns.name.NameRelation.EQUAL, dns.name.NameRelation.SUBDOMAIN),
ZONE.reachable_delegations.union(ZONE.reachable_dnames),