Class: PacketGen::Header::DNS
- Inherits:
-
Base
- Object
- Types::Fields
- Base
- PacketGen::Header::DNS
- Defined in:
- lib/packetgen/header/dns.rb,
lib/packetgen/header/dns.rb,
lib/packetgen/header/dns/rr.rb,
lib/packetgen/header/dns/opt.rb,
lib/packetgen/header/dns/name.rb,
lib/packetgen/header/dns/option.rb,
lib/packetgen/header/dns/question.rb,
lib/packetgen/header/dns/qdsection.rb,
lib/packetgen/header/dns/rrsection.rb
Overview
DNS: Domain Name Service
A DNS packet consists of a header:
1 1 1 1 1 1
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| ID |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|QR| Opcode |AA|TC|RD|RA| Z | RCODE |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| QDCOUNT |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| ANCOUNT |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| NSCOUNT |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| ARCOUNT |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
A DNS packet also contains up to 4 sections:
-
#qd, question section,
-
#an, answer section,
-
#ns, authoritary section,
-
#ar, additional information section.
Create a DNS header
# standalone
dns = PacketGen::Header::DNS.new
# in a IP packet
pkt = PacketGen.gen('IP').add('DNS')
# access to DNS header
pkt.dns # => PacketGen::Header::DNS
DNS attributes
dns.id = 0x1234
dns.qr = false
dns.opcode = 0xe
dns.opcode = 'query'
dns.aa = dns.tc = dns.rd = dns.ra = false
dns.rcode = 0xa
dns.rcode = 'refused'
dns.qdcount = 123
dns.ancount = 0x1234
dns.nscount = 1
dns.arcount = 0
One can also access to DNS sections:
dns.qd # => PacketGen::Header::DNS::QDSection
dns.an # => PacketGen::Header::DNS::RRSection
dns.ns # => PacketGen::Header::DNS::RRSection
dns.ar # => PacketGen::Header::DNS::RRSection
Add a question to DNS question section
Adding a Question with QDSection#<< automagically increments #qdcount. To not modify qdcount, use QDSection#push.
# add a question about example.net IP address. Increment qdcount
dns.qd << PacketGen::Header::DNS::Question.new(dns, name: 'example.net')
# or
dns.qd << { rtype: 'Question', name: 'example.net' }
# add a question about example.net IPv6 address. Dot not modify qdcount
dns.qd.push PacketGen::Header::DNS::Question.new(dns, name: 'example.net', type: 'AAAA')
# or
dns.qd.push({ rtype: 'Question', name: 'example.net', type: 'AAAA' })
Add a ressource record to a DNS section
Adding a RR with Types::Array#<< automagically increments section counter. To not modify it, use Types::Array#push
# add a RR to answer section. Increment ancount
dns.an << PacketGen::Header::DNS::RR.new(dns, name: 'example.net', rdata: IPAddr.new('1.2.3.4').hton)
# or
dns.an << { rtype: 'RR', name: 'example.net', rdata: IPAddr.new('1.2.3.4').hton }
# add a RR to NS section. Dot not modify nscount
rdata = PacketGen::Header::DNS::Name.new(dns).parse('dns.net')
dns.ns.push PacketGen::Header::DNS::RR.new(dns, name: 'example.net', type: 'NS', rdata: rdata)
# or
dns.ns.push(rtype: 'RR', name: 'example.net', type: 'NS', rdata: rdata)
Extended DNS EDNS(0)
# Add an OPT to ar section
dns.ar << PacketGen::Header::DNS::OPT.new(dns, udp_size: 4096, ext_rcode: 43)
# or
dns.ar << { rtype: 'OPT', udp_size: 4096, ext_rcode: 43 }
# add an option to OPT record
dns.ar.last. << PacketGen::Header::DNS::Option.new(code: 48, length: 2, data: "12")
Defined Under Namespace
Classes: Name, OPT, Option, QDSection, Question, RR, RRSection
Constant Summary collapse
- UDP_PORT =
Port number for DNS over UDP
53- TCP_PORT =
Port number for DNS over TCP
UDP_PORT- OPCODES =
DNS opcodes
{ 'query' => 0, 'iquery' => 1, 'status' => 2, 'notify' => 4, 'update' => 5 }
- RCODES =
DNS Response codes
{ 'ok' => 0, 'no-error' => 0, 'format-error' => 1, 'server-failure' => 2, 'name-error' => 3, 'not-implemented' => 4, 'refused' => 5 }
Instance Attribute Summary collapse
-
#aa ⇒ Boolean
Authoritative answer.
-
#ad ⇒ Boolean
Authentic Data.
- #an ⇒ RRSection
- #ancount ⇒ Integer
- #ar ⇒ RRSection
- #arcount ⇒ Integer
-
#cd ⇒ Boolean
Checking Disabled.
- #id ⇒ Integer
- #ns ⇒ RRSection
- #nscount ⇒ Integer
-
#opcode ⇒ Integer
Kind of query.
- #qd ⇒ QDSection
- #qdcount ⇒ Integer
-
#qr ⇒ Boolean
Query (
false) or response (true). -
#ra ⇒ Boolean
Recursion Available.
-
#rcode ⇒ Integer
Response code.
-
#rd ⇒ Boolean
Recursion Desired.
-
#tc ⇒ Boolean
Truncation.
- #u16 ⇒ Integer
Attributes inherited from Base
Instance Method Summary collapse
- #inspect ⇒ String
-
#query? ⇒ Boolean
Is message a query.
-
#read(str) ⇒ self
Read DNS header and sections from a string.
-
#response? ⇒ Boolean
Is message a response.
Methods inherited from Base
bind_header, #header_id, inherited, #ip_header, known_headers, #parse?, #protocol_name
Methods inherited from Types::Fields
#[], #[]=, #body=, define_bit_fields_on, define_field, define_field_after, define_field_before, #fields, #force_binary, inherited, #initialize, #sz, #to_h, #to_s
Constructor Details
This class inherits a constructor from PacketGen::Types::Fields
Instance Attribute Details
#aa ⇒ Boolean
Returns Authoritative answer.
176 177 |
# File 'lib/packetgen/header/dns.rb', line 176 define_bit_fields_on :u16, :qr, :opcode, 4, :aa, :tc, :rd, :ra, :z, :ad, :cd, :rcode, 4 |
#ad ⇒ Boolean
Returns Authentic Data.
176 177 |
# File 'lib/packetgen/header/dns.rb', line 176 define_bit_fields_on :u16, :qr, :opcode, 4, :aa, :tc, :rd, :ra, :z, :ad, :cd, :rcode, 4 |
#an ⇒ RRSection
150 |
# File 'lib/packetgen/header/dns.rb', line 150 define_field :an, RRSection, builder: ->(dns) { RRSection.new(dns, dns[:ancount]) } |
#ancount ⇒ Integer
138 |
# File 'lib/packetgen/header/dns.rb', line 138 define_field :ancount, Types::Int16 |
#ar ⇒ RRSection
156 |
# File 'lib/packetgen/header/dns.rb', line 156 define_field :ar, RRSection, builder: ->(dns) { RRSection.new(dns, dns[:arcount]) } |
#arcount ⇒ Integer
144 |
# File 'lib/packetgen/header/dns.rb', line 144 define_field :arcount, Types::Int16 |
#cd ⇒ Boolean
Returns Checking Disabled.
176 177 |
# File 'lib/packetgen/header/dns.rb', line 176 define_bit_fields_on :u16, :qr, :opcode, 4, :aa, :tc, :rd, :ra, :z, :ad, :cd, :rcode, 4 |
#id ⇒ Integer
129 |
# File 'lib/packetgen/header/dns.rb', line 129 define_field :id, Types::Int16 |
#ns ⇒ RRSection
153 |
# File 'lib/packetgen/header/dns.rb', line 153 define_field :ns, RRSection, builder: ->(dns) { RRSection.new(dns, dns[:nscount]) } |
#nscount ⇒ Integer
141 |
# File 'lib/packetgen/header/dns.rb', line 141 define_field :nscount, Types::Int16 |
#opcode ⇒ Integer
Returns Kind of query. See OPCODES.
176 177 |
# File 'lib/packetgen/header/dns.rb', line 176 define_bit_fields_on :u16, :qr, :opcode, 4, :aa, :tc, :rd, :ra, :z, :ad, :cd, :rcode, 4 |
#qd ⇒ QDSection
147 |
# File 'lib/packetgen/header/dns.rb', line 147 define_field :qd, QDSection, builder: ->(dns) { QDSection.new(dns, dns[:qdcount]) } |
#qdcount ⇒ Integer
135 |
# File 'lib/packetgen/header/dns.rb', line 135 define_field :qdcount, Types::Int16 |
#qr ⇒ Boolean
Returns query (false) or response (true).
176 177 |
# File 'lib/packetgen/header/dns.rb', line 176 define_bit_fields_on :u16, :qr, :opcode, 4, :aa, :tc, :rd, :ra, :z, :ad, :cd, :rcode, 4 |
#ra ⇒ Boolean
Returns Recursion Available.
176 177 |
# File 'lib/packetgen/header/dns.rb', line 176 define_bit_fields_on :u16, :qr, :opcode, 4, :aa, :tc, :rd, :ra, :z, :ad, :cd, :rcode, 4 |
#rcode ⇒ Integer
Returns Response code. See RCODES.
176 177 |
# File 'lib/packetgen/header/dns.rb', line 176 define_bit_fields_on :u16, :qr, :opcode, 4, :aa, :tc, :rd, :ra, :z, :ad, :cd, :rcode, 4 |
#rd ⇒ Boolean
Returns Recursion Desired.
176 177 |
# File 'lib/packetgen/header/dns.rb', line 176 define_bit_fields_on :u16, :qr, :opcode, 4, :aa, :tc, :rd, :ra, :z, :ad, :cd, :rcode, 4 |
#tc ⇒ Boolean
Returns Truncation.
176 177 |
# File 'lib/packetgen/header/dns.rb', line 176 define_bit_fields_on :u16, :qr, :opcode, 4, :aa, :tc, :rd, :ra, :z, :ad, :cd, :rcode, 4 |
#u16 ⇒ Integer
132 |
# File 'lib/packetgen/header/dns.rb', line 132 define_field :u16, Types::Int16 |
Instance Method Details
#inspect ⇒ String
244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 |
# File 'lib/packetgen/header/dns.rb', line 244 def inspect str = Inspect.dashed_line(self.class, 2) to_h.each do |attr, value| if attr == :u16 flags = [:qr, :aa, :tc, :rd, :ra].select! { |attr| send "#{attr}?" }. map(&:to_s).join(',') str << Inspect.shift_level(2) str << Inspect::INSPECT_FMT_ATTR % ['Flags', 'flags', flags] opcode = '%-10s (%u)' % [OPCODES.key(self.opcode), self.opcode] str << Inspect.shift_level(2) str << Inspect::INSPECT_FMT_ATTR % ['Integer', 'opcode', opcode] rcode = '%-10s (%u)' % [RCODES.key(self.rcode), self.rcode] str << Inspect.shift_level(2) str << Inspect::INSPECT_FMT_ATTR % ['Integer', 'rcode', rcode] else str << Inspect.inspect_attribute(attr, value, 2) end end str end |
#query? ⇒ Boolean
Is message a query
239 240 241 |
# File 'lib/packetgen/header/dns.rb', line 239 def query? !qr? end |
#read(str) ⇒ self
Read DNS header and sections from a string
182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 |
# File 'lib/packetgen/header/dns.rb', line 182 def read(str) return self if str.nil? force_binary str self[:id].read str[0, 2] self[:u16].read str[2, 2] self[:qdcount].read str[4, 2] self[:ancount].read str[6, 2] self[:nscount].read str[8, 2] self[:arcount].read str[10, 2] self[:qd].read str[12..-1] if self.qdcount > 0 start = 12 + self[:qd].sz self[:an].read str[start..-1] if self.ancount > 0 start += self[:an].sz self[:ns].read str[start..-1] if self.nscount > 0 start += self[:ns].sz self[:ar].read str[start..-1] if self.arcount > 0 self end |
#response? ⇒ Boolean
Is message a response
233 234 235 |
# File 'lib/packetgen/header/dns.rb', line 233 def response? qr? end |