Class DnsMessage

java.lang.Object
org.microproxy.dns.DnsMessage

public final class DnsMessage extends Object
A DNS message (RFC 1035 section 4.1): its header, questions and resource records, decoded from the wire format and encoded back. Records keep their RDATA as bytes, with embedded names expanded, and DnsMessage.ResourceRecord.data() reads the RDATA of the common types (A, AAAA, NS, CNAME, PTR, DNAME, MX, SRV, TXT, SOA) as a typed DnsMessage.Rdata.

Messages are immutable: the with methods return changed copies. encode() compresses the questions' and records' owner names; names inside RDATA are written as they are.


 DnsMessage answer = DnsMessage.decode(bytes);
 List<DnsMessage.ResourceRecord> blocked = answer.answers().stream()
         .map(r -> r.type() == DnsMessage.A && r.name().equals("ads.example")
                 ? r.withData(DnsMessage.Address.of("0.0.0.0")) : r)
         .toList();
 byte[] rewritten = answer.withAnswers(blocked).encode();
 

Names are given and shown in presentation format without the final dot ( www.example.com, . for the root), with \., \\ and \DDD escapes for bytes that need them.

  • Field Details

  • Method Details

    • decode

      public static DnsMessage decode(byte[] data)
      Decodes a message from its wire format, following compression pointers.
      Parameters:
      data - the message
      Returns:
      the message
      Throws:
      IllegalArgumentException - if the bytes are not a well-formed DNS message
    • query

      public static DnsMessage query(int id, String name, int type)
      A query with recursion desired, for one name and type of class IN, without EDNS.
      Parameters:
      id - the message ID
      name - the name
      type - the type (A, ...)
      Returns:
      the query
      Throws:
      IllegalArgumentException - if the name is not a valid domain name
    • of

      public static DnsMessage of(int id, int flags, List<DnsMessage.Question> questions, List<DnsMessage.ResourceRecord> answers, List<DnsMessage.ResourceRecord> authorities, List<DnsMessage.ResourceRecord> additionals)
      A message made of its parts.
      Parameters:
      id - the message ID, 16 bits
      flags - the header's flags, 16 bits (see flags())
      questions - the question section
      answers - the answer section
      authorities - the authority section
      additionals - the additional section
      Returns:
      the message
    • reply

      public DnsMessage reply(List<DnsMessage.ResourceRecord> answers)
      An answer to this query: a response with the same ID, opcode, questions and recursion desired bit, recursion available, the RCODE NOERROR, and answers.
      Parameters:
      answers - the answer section
      Returns:
      the response
    • encode

      public byte[] encode()
      Encodes the message, compressing the questions' and records' owner names.
      Returns:
      the wire format
      Throws:
      IllegalArgumentException - if a section has more than 65535 entries
    • id

      public int id()
      Returns the message ID.
      Returns:
      the message ID
    • flags

      public int flags()
      Returns the header's flags: QR, opcode, AA, TC, RD, RA, Z, AD, CD and RCODE, as 16 bits.
      Returns:
      the header's flags: QR, opcode, AA, TC, RD, RA, Z, AD, CD and RCODE, as 16 bits
    • rcode

      public int rcode()
      Returns the RCODE: 0 NOERROR, 2 SERVFAIL, 3 NXDOMAIN, ....
      Returns:
      the RCODE: 0 NOERROR, 2 SERVFAIL, 3 NXDOMAIN, ...
    • opcode

      public int opcode()
      Returns the opcode: 0 for a standard query.
      Returns:
      the opcode: 0 for a standard query
    • isResponse

      public boolean isResponse()
      Returns whether the message is a response (QR).
      Returns:
      whether the message is a response (QR)
    • isAuthoritative

      public boolean isAuthoritative()
      Returns whether the answer is authoritative (AA).
      Returns:
      whether the answer is authoritative (AA)
    • isTruncated

      public boolean isTruncated()
      Returns whether the message was truncated (TC).
      Returns:
      whether the message was truncated (TC)
    • isRecursionDesired

      public boolean isRecursionDesired()
      Returns whether recursion is desired (RD).
      Returns:
      whether recursion is desired (RD)
    • isRecursionAvailable

      public boolean isRecursionAvailable()
      Returns whether recursion is available (RA).
      Returns:
      whether recursion is available (RA)
    • questions

      public List<DnsMessage.Question> questions()
      Returns the question section.
      Returns:
      the question section
    • answers

      public List<DnsMessage.ResourceRecord> answers()
      Returns the answer section.
      Returns:
      the answer section
    • authorities

      public List<DnsMessage.ResourceRecord> authorities()
      Returns the authority section.
      Returns:
      the authority section
    • additionals

      public List<DnsMessage.ResourceRecord> additionals()
      Returns the additional section, an EDNS OPT record included.
      Returns:
      the additional section, an EDNS OPT record included
    • withId

      public DnsMessage withId(int id)
      This message with another ID.
      Parameters:
      id - the ID, 16 bits
      Returns:
      the copy
    • withFlags

      public DnsMessage withFlags(int flags)
      This message with other header flags (QR, opcode, AA, TC, RD, RA, Z, AD, CD and RCODE).
      Parameters:
      flags - the flags, 16 bits
      Returns:
      the copy
    • withRcode

      public DnsMessage withRcode(int rcode)
      This message with another RCODE (3 for NXDOMAIN, ...).
      Parameters:
      rcode - the RCODE, 4 bits
      Returns:
      the copy
    • withQuestions

      public DnsMessage withQuestions(List<DnsMessage.Question> questions)
      This message with other questions.
      Parameters:
      questions - the question section
      Returns:
      the copy
    • withAnswers

      public DnsMessage withAnswers(List<DnsMessage.ResourceRecord> answers)
      This message with other answers.
      Parameters:
      answers - the answer section
      Returns:
      the copy
    • withAuthorities

      public DnsMessage withAuthorities(List<DnsMessage.ResourceRecord> authorities)
      This message with another authority section.
      Parameters:
      authorities - the authority section
      Returns:
      the copy
    • withAdditionals

      public DnsMessage withAdditionals(List<DnsMessage.ResourceRecord> additionals)
      This message with another additional section.
      Parameters:
      additionals - the additional section
      Returns:
      the copy
    • typeName

      public static String typeName(int type)
      The mnemonic of a type.
      Parameters:
      type - the type
      Returns:
      A, AAAA, ..., or TYPE<n> for a type without one (RFC 3597)
    • type

      public static int type(String name)
      The type a mnemonic names.
      Parameters:
      name - A, aaaa, ..., or TYPE<n>
      Returns:
      the type
      Throws:
      IllegalArgumentException - for a name this class does not know
    • rcodeName

      public static String rcodeName(int rcode)
      The name of an RCODE.
      Parameters:
      rcode - the RCODE
      Returns:
      NOERROR, NXDOMAIN, ..., or RCODE<n>
    • render

      public String render()
      The message as dig shows it: the header, then each section.
      Returns:
      the text, ending with a newline
    • toString

      public String toString()
      Overrides:
      toString in class Object