class PacketGen::Header::DNS
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 # opcode may be set as an Integer (all values are possible) # or as a String (only keys from PacketGen::Header::DNS::OPCODES) dns.opcode = 0xe # set as integer, value not defined in standard dns.opcode = 'query' # set as string dns.aa = dns.tc = dns.rd = dns.ra = false # rcode may be set as an Integer (all values are possible) # or as a String (only keys from PacketGen::Header::DNS::RCODES) dns.rcode = 11 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 {RRSection#<< RRSection#<<} automagically increments section counter. To not modify it, use {RRSection#push RRSection#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.options << PacketGen::Header::DNS::Option.new(code: 48, data: '12') # or dns.ar.last.options << { code: 48, data: '12' }
@author Sylvain Daubert @since 1.3.0
Constants
- OPCODES
DNS
opcodes- Option
@!parse
# DNS option is a TLV object: # * {#code} is a {Types::Int16}, # * {#length #length} is a {Types::Int16}, # * {#data} is a {Types::String}. # # @since 1.3.0 # @since 3.1.0 defined with {Types::AbstractTLV} # @!parse class Option < Types::AbstractTLV; end # @!attribute code # Alias for {#type} # @return [Integer] # @!attribute data # Alias for {#value} # @return [Types::String] class Option < Types::AbstractTLV; end
@private
- RCODES
DNS
Response codes- TCP_PORT
- UDP_PORT
Public Instance Methods
@return [String]
# File lib/packetgen/header/dns.rb, line 240 def inspect super do |attr| next unless attr == :u16 flags = %i[qr aa tc rd ra].select! { |flag| send "#{flag}?" } .map(&:to_s).join(',') str = Inspect.shift_level str << Inspect::FMT_ATTR % ['Flags', 'flags', flags] opcode = '%-16s (%u)' % [OPCODES.key(self.opcode), self.opcode] str << Inspect.shift_level str << Inspect::FMT_ATTR % ['Integer', 'opcode', opcode] rcode = '%-16s (%u)' % [RCODES.key(self.rcode), self.rcode] str << Inspect.shift_level str << Inspect::FMT_ATTR % ['Integer', 'rcode', rcode] end end
Set opcode @param [Integer,String] value @return [Integer]
# File lib/packetgen/header/dns.rb, line 198 def opcode=(value) intg = case value when Integer value else OPCODES[value.to_s] end raise ArgumentError, "unknown opcode #{value.inspect}" unless intg self.u16 &= 0x87ff self.u16 |= (intg & 0xf) << 11 end
Is message a query @return [Boolean]
# File lib/packetgen/header/dns.rb, line 235 def query? !qr? end
Set rcode @param [Integer,String] value @return [Integer]
# File lib/packetgen/header/dns.rb, line 214 def rcode=(value) intg = case value when Integer value else RCODES[value] end raise ArgumentError, "unknown rcode #{value.inspect}" unless intg self.u16 &= 0xfff0 self.u16 |= intg & 0xf end
Is message a response @return [Boolean]
# File lib/packetgen/header/dns.rb, line 229 def response? qr? end