class DNSMessage::Message
Message
is the central class that most users of the API will use
Constants
- HEADER_SIZE
- NAME_POINTER
- POINTER_MASK
- QUERY
- REPLY
Attributes
aa[RW]
additionals[RW]
ancount[R]
answers[RW]
arcount[R]
id[RW]
nscount[R]
opcode[RW]
qdcount[R]
qr[RW]
questions[RW]
ra[RW]
rcode[RW]
rd[RW]
tc[RW]
z[RW]
Public Class Methods
new()
click to toggle source
# File lib/dnsmessage/message.rb, line 16 def initialize @questions = [] @answers = [] @additionals = [] @authority = [] @qdcount = 0 @ancount = 0 @nscount = 0 @arcount = 0 @id = @qr = @opcode = @aa = @tc = @rd = @ra = @z = @rcode = 0 end
parse(input)
click to toggle source
# File lib/dnsmessage/message.rb, line 37 def self.parse(input) new.tap do |m| m.parse(input) end end
reply_to(query)
click to toggle source
# File lib/dnsmessage/message.rb, line 43 def self.reply_to(query) new.tap do |r| r.id = query.id r.qr = REPLY r.questions = query.questions end end
Public Instance Methods
build()
click to toggle source
# File lib/dnsmessage/message.rb, line 91 def build ptr = Pointer.new packet = build_header packet << build_questions(ptr, packet.size) packet << build_answers(ptr, packet.size) packet << build_authority(ptr, packet.size) packet << build_additionals(ptr, packet.size) end
build_aa()
click to toggle source
# File lib/dnsmessage/message.rb, line 121 def build_aa (@aa & 0x1) << 10 end
build_additionals(ptr, idx)
click to toggle source
# File lib/dnsmessage/message.rb, line 161 def build_additionals(ptr, idx) build_record(ptr, idx, @additionals) end
build_answers(ptr, idx)
click to toggle source
# File lib/dnsmessage/message.rb, line 153 def build_answers(ptr, idx) build_record(ptr, idx, @answers) end
build_header()
click to toggle source
# File lib/dnsmessage/message.rb, line 100 def build_header [@id, build_opts, @questions.length, @answers.length, @authority.length, @additionals.length].pack("n6") end
build_opcode()
click to toggle source
# File lib/dnsmessage/message.rb, line 117 def build_opcode (@opcode & 0xf) << 11 end
build_opts()
click to toggle source
# File lib/dnsmessage/message.rb, line 108 def build_opts build_qr | build_opcode | build_aa | build_tc | build_rd | build_ra | build_z | build_rcode end
build_qr()
click to toggle source
# File lib/dnsmessage/message.rb, line 113 def build_qr (@qr & 0x1) << 15 end
build_questions(ptr, idx)
click to toggle source
# File lib/dnsmessage/message.rb, line 145 def build_questions(ptr, idx) @questions.map do |q| q.build(ptr, idx).tap do |bytes| idx += bytes.length end end.join("") end
build_ra()
click to toggle source
# File lib/dnsmessage/message.rb, line 133 def build_ra (@ra & 0x1) << 7 end
build_rcode()
click to toggle source
# File lib/dnsmessage/message.rb, line 141 def build_rcode (@rcode & 0xf) end
build_rd()
click to toggle source
# File lib/dnsmessage/message.rb, line 129 def build_rd (@rd & 0x1) << 8 end
build_record(ptr, idx, records)
click to toggle source
# File lib/dnsmessage/message.rb, line 165 def build_record(ptr, idx, records) records.map do |rr| rr.build(ptr, idx).tap do |r| idx += r.length end end.join("") end
build_tc()
click to toggle source
# File lib/dnsmessage/message.rb, line 125 def build_tc (@tc & 0x1) << 9 end
build_z()
click to toggle source
# File lib/dnsmessage/message.rb, line 137 def build_z (@z & 0x1) << 7 end
check_validity()
click to toggle source
# File lib/dnsmessage/message.rb, line 173 def check_validity raise(StandardError, "Bad qr type") if @qr != 0 raise(StandardError, "No questions in query") if @qdcount < 1 raise(StandardError, "Empty domain") if @domain_name.empty? end
parse(input)
click to toggle source
# File lib/dnsmessage/message.rb, line 28 def parse(input) ptr = Pointer.new parse_header(input) idx = parse_questions(input, @qdcount, ptr) @answers, idx = parse_records(input, @ancount, idx, ptr) @authority, idx = parse_records(input, @nscount, idx, ptr) @additionals, = parse_records(input, @arcount, idx, ptr) end
parse_header(message)
click to toggle source
# File lib/dnsmessage/message.rb, line 51 def parse_header(message) return nil if message.nil? || message.empty? @id, opts, @qdcount, @ancount, @nscount, @arcount = message[0...12].unpack("n6") parse_opts(opts) end
parse_opts(opts)
click to toggle source
# File lib/dnsmessage/message.rb, line 60 def parse_opts(opts) @qr = (opts >> 15) & 0x1 @opcode = (opts >> 11) & 0xf @aa = (opts >> 10) & 0x1 @tc = (opts >> 9) & 0x1 @rd = (opts >> 8) & 0x1 @ra = (opts >> 7) & 0x1 @z = (opts >> 4) & 0x7 @rcode = opts & 0xf end
parse_questions(message, num_questions, ptr)
click to toggle source
# File lib/dnsmessage/message.rb, line 71 def parse_questions(message, num_questions, ptr) idx = HEADER_SIZE # Header takes up the first 12 bytes @questions = (0...num_questions).map do Question.parse(message, ptr, idx).tap do |q| idx += q.size end end idx end
parse_records(message, num_records, idx, ptr)
click to toggle source
# File lib/dnsmessage/message.rb, line 81 def parse_records(message, num_records, idx, ptr) [num_records.times.map do ResourceRecord.parse(message[idx..], ptr).tap do |rr| ptr.add_arr(rr.add_to_hash, idx) idx += rr.size end end, idx] end