Skip to content

Commit

Permalink
Add dns.edns.Option.to_generic() (#1145)
Browse files Browse the repository at this point in the history
* Add dns.edns.Option.to_generic()

Converts an EDNS option represented by a custom class into an equivalent
option represented by the generic option class.  This is similar to the
existing dns.rdata.Rdata.to_generic() method.

Also, adds a specialization to the existing dns.rdata.Rdata.to_generic()
method for GenericRdata, to avoid extra work for applications that want
to convert all rdata to generic form.

* Fix typing issue.

* Fix typing again.
  • Loading branch information
bwelling authored Oct 11, 2024
1 parent c0572cd commit 91d329a
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 0 deletions.
12 changes: 12 additions & 0 deletions dns/edns.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,15 @@ def to_wire(self, file: Optional[Any] = None) -> Optional[bytes]:
def to_text(self) -> str:
raise NotImplementedError # pragma: no cover

def to_generic(self) -> "dns.edns.GenericOption":
"""Creates a dns.edns.GenericOption equivalent of this rdata.
Returns a ``dns.edns.GenericOption``.
"""
wire = self.to_wire()
assert wire is not None # for mypy
return dns.edns.GenericOption(self.otype, wire)

@classmethod
def from_wire_parser(cls, otype: OptionType, parser: "dns.wire.Parser") -> "Option":
"""Build an EDNS option object from wire format.
Expand Down Expand Up @@ -166,6 +175,9 @@ def to_wire(self, file: Optional[Any] = None) -> Optional[bytes]:
def to_text(self) -> str:
return "Generic %d" % self.otype

def to_generic(self) -> "dns.edns.GenericOption":
return self

@classmethod
def from_wire_parser(
cls, otype: Union[OptionType, str], parser: "dns.wire.Parser"
Expand Down
5 changes: 5 additions & 0 deletions dns/rdata.py
Original file line number Diff line number Diff line change
Expand Up @@ -639,6 +639,11 @@ def from_text(
def _to_wire(self, file, compress=None, origin=None, canonicalize=False):
file.write(self.data)

def to_generic(
self, origin: Optional[dns.name.Name] = None
) -> "dns.rdata.GenericRdata":
return self

@classmethod
def from_wire_parser(cls, rdclass, rdtype, parser, origin=None):
return cls(rdclass, rdtype, parser.get_remaining())
Expand Down
10 changes: 10 additions & 0 deletions tests/test_edns.py
Original file line number Diff line number Diff line change
Expand Up @@ -302,3 +302,13 @@ def from_wire_parser(cls, otype, parser):

opt = dns.edns.option_from_wire_parser(9999, dns.wire.Parser(wire1))
self.assertEqual(opt, generic)

def test_to_generic(self):
nsid = dns.edns.NSIDOption(b"testing")
assert nsid.to_generic().data == b"testing"

ecs = dns.edns.ECSOption("1.2.3.0", 24)
assert ecs.to_generic().data == b"\x00\x01\x18\x00\x01\x02\x03"

generic = dns.edns.GenericOption(12345, "foo")
assert generic.to_generic() is generic
3 changes: 3 additions & 0 deletions tests/test_rdata.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,9 @@ def test_to_generic(self):
str(ns.to_generic(origin=origin)), r"\# 13 03666f6f076578616d706c6500"
)

generic = dns.rdata.from_text("in", "type45678", "\\# 4 00010203")
assert generic.to_generic() is generic

def test_txt_unicode(self):
# TXT records are not defined for Unicode, but if we get
# Unicode we should convert it to UTF-8 to preserve meaning as
Expand Down

0 comments on commit 91d329a

Please sign in to comment.