Skip to content

getresources returns nothing for types created with Generic.create since 0.7.2 #151

Description

@stephanmoneybird

Since 0.7.2, getresources and each_resource never return records for a type created with Resolv::DNS::Resource::Generic.create, for example NAPTR (type 35), which has no named class in Resolv.

Cause

fa5e689 ("Do not register on-demand classes for unknown DNS types and SvcParamKeys") stopped registering the classes from Generic.create. So decoding a reply gives each unknown record a new anonymous class, not the class the caller passed. 05185b4 and fcff0a1 updated Message#== and Generic#== for this with Generic.type_class_equal?. DNS#extract_resources still selects answers with when typeclass, so it drops every decoded record of such a type.

Reproduction

This needs no network: it encodes and decodes a reply and gives it to getresources.

require "resolv"

naptr = Resolv::DNS::Resource::Generic.create(35, Resolv::DNS::Resource::IN::ClassValue)
name = "example.com."
rdata = "\x00\x64\x00\x0A\x01U\x07E2U+sip\x1C!^.*$!sip:info@example.com!\x00".b

reply = Resolv::DNS::Message.new
reply.add_answer(name, 60, naptr.new(rdata))
decoded = Resolv::DNS::Message.decode(reply.encode)

dns = Resolv::DNS.new
dns.define_singleton_method(:fetch_resource) {|_name, _typeclass, &block| block.call(decoded, Resolv::DNS::Name.create(name)) }

puts "resolv #{Resolv::VERSION}: #{dns.getresources(name, naptr).size} record(s)"
resolv 0.7.0: 1 record(s)
resolv 0.7.2: 0 record(s)
resolv 0.8.0: 0 record(s)

A real query shows the same result: getresources returns [], but fetch_resource gets the NAPTR answer. Ruby 4.0.7 includes 0.7.2, so a patch update of Ruby is enough to get this behaviour.

Possible fix

Compare by type and class value in extract_resources, in both when typeclass branches:

-          when typeclass
+          when ->(data) { Resource::Generic.type_class_equal?(data.class, typeclass) }

With this change, the reproduction returns 1 record on 0.8.0. Named types (IN::A, IN::AAAA) behave as before, because type_class_equal? compares identity first and returns false for classes that are not Generic.

Workaround

Register the type in the same way as Resolv's built-in types:

class NAPTR < Resolv::DNS::Resource::Generic
  const_set(:TypeValue, 35)
  const_set(:ClassValue, Resolv::DNS::Resource::IN::ClassValue)
  Resolv::DNS::Resource::ClassHash[[self::TypeValue, self::ClassValue]] = self
end

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions