Skip to content

Commit

Permalink
Remove trick_bag dependency. More work on RDATA. Add sample zone file…
Browse files Browse the repository at this point in the history
… text.
  • Loading branch information
Keith Bennett committed Jan 20, 2015
1 parent 0e76a6a commit 04b9879
Show file tree
Hide file tree
Showing 3 changed files with 198 additions and 126 deletions.
2 changes: 0 additions & 2 deletions dnsruby.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,6 @@ DNSSEC NSEC3 support.'
s.has_rdoc = true
s.extra_rdoc_files = ["DNSSEC", "EXAMPLES", "README.md", "EVENTMACHINE"]

s.add_dependency 'trick_bag', '~> 0.56'

unless /java/ === RUBY_PLATFORM
s.add_development_dependency 'pry', '~> 0.10'
s.add_development_dependency 'pry-byebug', '~> 2.0' if RUBY_VERSION >= '2'
Expand Down
271 changes: 148 additions & 123 deletions lib/dnsruby/resource/NXT.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,145 @@ class RR
# RFC 2535 (https://www.ietf.org/rfc/rfc2535.txt)
class NXT < RR

TypeValue = Types::NXT
ClassValue = Classes::IN
ClassHash[[TypeValue, ClassValue]] = self

attr_accessor :next_domain, :types

REQUIRED_KEYS = [:next_domain, :types]


def from_hash(params_hash)
unless REQUIRED_KEYS.all? { |key| params_hash[key] }
raise ArgumentError.new("NXT hash must contain all of: #{REQUIRED_KEYS.join(', ')}.")
end
@next_domain = params_hash[:next_domain]
@types = params_hash[:types]
end

def from_data(data)
from_hash(next_domain: data[0], types: data[1])
end

def from_string(string)
tokens = string.split
next_domain = tokens[0]
types = NxtTypes::names_to_codes(tokens[1..-1])
from_hash(next_domain: next_domain, types: types)
end

# As with all resource record subclasses of RR, this class cannot be
# directly instantiated, but instead must be instantiated via use of
# one of the RR class methods. These NXT class methods are wrappers
# around those RR methods, so that there is an interface on the NXT
# class for creating NXT instances.

# Create an instance from a hash of parameters, e.g.:
# {
# next_domain: 'techhumans.com',
# type: Types::NXT,
# types: [Types::A, Types::NS, Types::NXT]
# }
def self.from_hash(params_hash)
RR.new_from_hash(params_hash)
end


# Create an instance from a string containing parameters, e.g.:
# # TODO
def self.from_string(params_string)
RR.new_from_string(params_string)
end


# Create an instance from an ordered parameter list, e.g.:
# EXAMPLE_NXT_DATA = begin
# rdata = RR::NXT.build_rdata(TODO: what are params here?)
# end
# self.from_data(*EXAMPLE_NXT_DATA)
def self.from_data(*params_data)
RR.new_from_data(*params_data)
end


# def from_data(array) # TODO: Adjust as necessary for NXT's.
# unless [1, 2].include?(array.size)
# raise "Array size for creating NXT record must be 1 or 2 " +
# "(mandatory next_domain, optional type_bitmap). Array was:\n#{array.inspect}"
# end
#
# # TODO: what goes here?
# # from_hash(next_domain: array[0], type_bitmap: array[1])
# end

# def from_hash(init_data)
# self.class.validate_floats(init_data)
# @next_domain = init_data[:next_domain]
# @type_bitmap = init_data[:type_bitmap] || DEFAULT_TYPE_BITMAP
# self.rdata = build_rdata
# self
# end

# From the RFC:
# NXT has the following format:
# foo.nil. NXT big.foo.nil NS KEY SOA NXT
# <owner> NXT <next_domain> <record types>
#
# We handle the rdata, the RR superclass does the rest.
def rdata_to_string
"#{next_domain} #{rr_types_to_strings(type_bitmap).join(' ')}"
end

def encode_rdata(msg, _canonical)
msg.put_bytes(to_rdata)
end

def build_rdata
binary_string = ''.force_encoding('ASCII-8BIT')

binary_string << next_domain.size
binary_string << next_domain

types_binary_string = types.to_binary_string
binary_string << types_binary_string.size
binary_string << types_binary_string



binary_string
end

def self.decode_rdata(message)
rdata_s = message.get_bytes

index = 0
# require 'pry'; binding.pry

len = rdata_s[index].ord; index += 1
next_domain = rdata_s[index, len]; index += len

len = rdata_s[index].ord; index += 1
type_bitmap = rdata_s[index, len]; index += len


from_hash(next_domain: next_domain, type_bitmap: type_bitmap)
end

# 'name' is used in the RR superclass, but 'owner' is the term referred to
# in the RFC, so we'll make owner an alias for name.
def owner
name
end

# 'name' is used in the RR superclass, but 'owner' is the term referred to
# in the RFC, so we'll make owner an alias for name.
def owner=(owner_string)
self.name = owner_string
end



# Methods used to manipulate the storage and representation of
# record types as stored in NXT record bitmaps.
module NxtTypes
Expand Down Expand Up @@ -92,10 +231,10 @@ def codes_to_binary_string(codes)
def assert_legal_bitmap_value(number)
max_value = NxtTypes::MAX_BITMAP_NUMBER_VALUE
if number > max_value
raise "Bitmap maximum value is #{max_value} (0x#{max_value.to_s(16)})."
raise ArgumentError.new("Bitmap maximum value is #{max_value} (0x#{max_value.to_s(16)}).")
end
if number & 1 == 1
raise "Bitmap number must not have low bit set."
raise ArgumentError.new("Bitmap number must not have low bit set.")
end
end

Expand Down Expand Up @@ -131,6 +270,10 @@ def initialize(bitmap_number)
@bitmap = Bitmap.from_number(bitmap_number)
end

def to_binary_string
bitmap.to_binary_string
end

# Output types in dig format, e.g. "A AAAA NXT"
def to_s
type_codes = bitmap.to_set_bit_position_array
Expand All @@ -141,132 +284,14 @@ def to_s

class RData

attr_accessor :domain_name, :type_bitmap_string
end




TypeValue = Types::NXT
ClassValue = Classes::IN
ClassHash[[TypeValue, ClassValue]] = self

attr_accessor :next_domain, :type_bitmap

REQUIRED_KEYS = [:next_domain]


# As with all resource record subclasses of RR, this class cannot be
# directly instantiated, but instead must be instantiated via use of
# one of the RR class methods. These NXT class methods are wrappers
# around those RR methods, so that there is an interface on the NXT
# class for creating NXT instances.

# Create an instance from a hash of parameters, e.g.:
# {
# name: 'techhumans.com',
# type: Types::NXT,
# TODO: Add other parameters here.
# }
def self.from_hash(params_hash)
RR.new_from_hash(params_hash)
end


# Create an instance from a string containing parameters, e.g.:
# # TODO
def self.from_string(params_string)
RR.new_from_string(params_string)
end


# Create an instance from an ordered parameter list, e.g.:
# EXAMPLE_NXT_DATA = begin
# rdata = RR::NXT.build_rdata(TODO: what are params here?)
# end
# self.from_data(*EXAMPLE_NXT_DATA)
def self.from_data(*params_data)
RR.new_from_data(*params_data)
end


# def from_data(array) # TODO: Adjust as necessary for NXT's.
# unless [1, 2].include?(array.size)
# raise "Array size for creating NXT record must be 1 or 2 " +
# "(mandatory next_domain, optional type_bitmap). Array was:\n#{array.inspect}"
# end
#
# # TODO: what goes here?
# # from_hash(next_domain: array[0], type_bitmap: array[1])
# end

# def from_hash(init_data)
# self.class.validate_floats(init_data)
# @next_domain = init_data[:next_domain]
# @type_bitmap = init_data[:type_bitmap] || DEFAULT_TYPE_BITMAP
# self.rdata = build_rdata
# self
# end
attr_accessor :next_domain, :type_bitmap_string

def from_string(string)
from_data(string.gsub(',', ' ').split(' '))
end

# From the RFC:
# NXT has the following format:
# foo.nil. NXT big.foo.nil NS KEY SOA NXT
# <owner> NXT <next_domain> <record types>
#
# We handle the rdata, the RR superclass does the rest.
def rdata_to_string
"#{next_domain} #{rr_types_to_strings(type_bitmap).join(' ')}"
end

def encode_rdata(msg, _canonical)
msg.put_bytes(to_rdata)
end

def build_rdata
self.class.build_rdata(longitude, latitude, altitude)
end

def self.build_rdata # params?
binary_string = ''.force_encoding('ASCII-8BIT')

# binary_string << ?

binary_string
end

def self.decode_rdata(message)
rdata_s = message.get_bytes

index = 0

len = rdata_s[index].ord; index += 1
next_domain = rdata_s[index, len]; index += len

len = rdata_s[index].ord; index += 1
type_bitmap = rdata_s[index, len]; index += len

# TODO: This doesn't look right...what about owner?:
new([next_domain, type_bitmap].join(' ')) # e.g. "10.0 20.0 30.0"
end

# 'name' is used in the RR superclass, but 'owner' is the term referred to
# in the RFC, so we'll make owner an alias for name.
def owner
name
end

# 'name' is used in the RR superclass, but 'owner' is the term referred to
# in the RFC, so we'll make owner an alias for name.
def owner=(owner_string)
self.name = owner_string
def initialize
end
end
end
end
end



51 changes: 50 additions & 1 deletion test/tc_nxt.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@
# Tests NXT resource record. See bottom of file for sample zone file.
class TestNXT_TypeConverter < Minitest::Test

EXAMPLE_NXT_RESPONSE_AS_BINARY = "\xC2\xE0\x84\x80\x00\x01\x00\x01\x00\x01" +
"\x00\x01\x01a\adnsruby\x03com\x00" +
"\x00\x1E\x00\x01\xC0\f\x00\x1E\x00\x01\x00\x00*0\x00\x13\x01b\adnsruby\x03com\x00" +
"@\x00\x00\n\xC0\x0E\x00\x02\x00\x01\x00\x00*0\x00\x06\x03ns1\xC0\x0E\xC0J\x00\x01\x00" +
"\x01\x00\x00*0\x00\x04\x7F\x00\x00\x01"

# This is to replace the method that was strangely deleted from Minitest a while back:
def assert_nothing_raised
Expand Down Expand Up @@ -83,5 +88,49 @@ def test_type_bitmap_ctor_is_private
def test_type_bitmap_to_s
type_bitmap = RR::NXT::TypeBitmap.from_type_codes([1, 16, 30])
assert_equal('A TXT NXT', type_bitmap.to_s)
end
end


def test_parse_response_correctly
bit_flags = [1, 28, 30]
number = BitMapping.set_bit_position_array_to_number(bit_flags)
number_as_hex = number.to_s(16)
# require 'pry'; binding.pry
response = Message.decode(EXAMPLE_NXT_RESPONSE_AS_BINARY)
answer = response.answer
nxt_record = answer[0]
as_string = nxt_record.to_s
actual_tokens = as_string.split
expected_tokens = 'a.dnsruby.com. 10800 IN NXT b.dnsruby.com.dnsruby.com. A AAAA NXT'
# assert_equal...
end


end



# Sample zone file for setting up BIND to serve a NXT record:
=begin
$TTL 3h
@ IN SOA dnsruby.com. foo.dnsruby.com. (
1 ; serial
3H ; refresh after 3 hours
1H ; retry after 1 hour
1W ; expire after 1 week
1H) ; negative caching TTL of 1 hour
dnsruby.com. IN NS ns1
; Addresses for canonical names
ns1.dnsruby.com. IN A 127.0.0.1
a.dnsruby.com. IN A 2.4.6.8
IN NXT b A AAAA NXT
b.dnsruby.com. IN A 2.4.6.9
IN GPOS 40 50 60
=end

0 comments on commit 04b9879

Please sign in to comment.