Core DNS message construction, parsing, and manipulation with full control over all message fields and sections.
The central DNS message structure containing all message components.
type Msg struct {
MsgHdr
Compress bool // If true, compress message when packing to wire format
Question []Question // Question section
Answer []RR // Answer section
Ns []RR // Authority/Nameserver section
Extra []RR // Additional section
}Embedded MsgHdr fields:
type MsgHdr struct {
Id uint16 // Message identifier
Response bool // Query (false) or Response (true)
Opcode int // Operation code
Authoritative bool // Authoritative answer flag
Truncated bool // Truncated flag
RecursionDesired bool // Recursion desired flag
RecursionAvailable bool // Recursion available flag
Zero bool // Reserved for future use
AuthenticatedData bool // Authenticated data (DNSSEC)
CheckingDisabled bool // Checking disabled (DNSSEC)
Rcode int // Response code
}DNS question section entry.
type Question struct {
Name string // Query domain name (must be FQDN)
Qtype uint16 // Query type
Qclass uint16 // Query class
}Wire format header structure.
type Header struct {
Id uint16
Bits uint16
Qdcount, Ancount, Nscount, Arcount uint16
}// SetReply sets Msg as reply to request
func (dns *Msg) SetReply(request *Msg) *Msg
// SetQuestion sets the question section
func (dns *Msg) SetQuestion(z string, t uint16) *Msg
// SetRcode sets the response code
func (dns *Msg) SetRcode(request *Msg, rcode int) *Msg
// SetRcodeFormatError sets format error response
func (dns *Msg) SetRcodeFormatError(request *Msg) *Msg// SetNotify creates a notify message
func (dns *Msg) SetNotify(z string) *Msg
// SetUpdate creates a dynamic update message
func (dns *Msg) SetUpdate(z string) *Msg
// SetAxfr creates an AXFR request message
func (dns *Msg) SetAxfr(z string) *Msg
// SetIxfr creates an IXFR request message
func (dns *Msg) SetIxfr(z string, serial uint32, ns, mbox string) *Msg// SetTsig adds TSIG to message
func (dns *Msg) SetTsig(z, algo string, fudge uint16, timesigned int64) *Msg
// SetEdns0 adds EDNS0 OPT RR
func (dns *Msg) SetEdns0(udpsize uint16, do bool) *Msg
// IsTsig checks if message has TSIG, returns TSIG record or nil
func (dns *Msg) IsTsig() *TSIG
// IsEdns0 checks if message has EDNS0, returns OPT record or nil
func (dns *Msg) IsEdns0() *OPT// Pack converts Msg to wire format
func (dns *Msg) Pack() ([]byte, error)
// PackBuffer packs message into provided buffer
func (dns *Msg) PackBuffer(buf []byte) ([]byte, error)
// Unpack parses message from wire format
func (dns *Msg) Unpack(msg []byte) error
// Len returns message length in wire format
func (dns *Msg) Len() int
// IsMsg performs sanity check if buffer is valid DNS packet
func IsMsg(buf []byte) error// PackDomainName packs a domain name into wire format
func PackDomainName(s string, msg []byte, off int, compression map[string]int, compress bool) (off1 int, err error)
// UnpackDomainName unpacks a domain name from wire format
func UnpackDomainName(msg []byte, off int) (string, int, error)// PackRR packs a resource record to wire format
func PackRR(rr RR, msg []byte, off int, compression map[string]int, compress bool) (off1 int, err error)
// UnpackRR unpacks a resource record from wire format
func UnpackRR(msg []byte, off int) (rr RR, off1 int, err error)// Copy creates a deep copy of Msg
func (dns *Msg) Copy() *Msg
// CopyTo copies Msg to existing message
func (dns *Msg) CopyTo(r1 *Msg) *Msg
// String returns string representation
func (dns *Msg) String() string
// Truncate truncates message to size
func (dns *Msg) Truncate(size int)// Id generates random 16-bit message ID
// This is a variable and can be reassigned for testing
var Id = func() uint16 { ... }m := new(dns.Msg)
m.SetQuestion(dns.Fqdn("example.com"), dns.TypeA)
m.RecursionDesired = trueresp := new(dns.Msg)
resp.SetReply(query)
resp.Authoritative = true
// Add answer records
rr := &dns.A{
Hdr: dns.RR_Header{
Name: query.Question[0].Name,
Rrtype: dns.TypeA,
Class: dns.ClassINET,
Ttl: 3600,
},
A: net.ParseIP("192.0.2.1"),
}
resp.Answer = append(resp.Answer, rr)// Pack to wire format
buf, err := m.Pack()
if err != nil {
log.Fatal(err)
}
// Unpack from wire format
received := new(dns.Msg)
err = received.Unpack(buf)
if err != nil {
log.Fatal(err)
}// Enable compression when packing
m.Compress = true
buf, err := m.Pack()m := new(dns.Msg)
m.SetQuestion(dns.Fqdn("example.com"), dns.TypeA)
// Add EDNS0 with 4096 byte UDP size and DNSSEC OK bit
m.SetEdns0(4096, true)const (
DefaultMsgSize = 4096 // Standard default for messages larger than 512 bytes
MinMsgSize = 512 // Minimal size of a DNS packet
MaxMsgSize = 65535 // Largest possible DNS packet
)var (
ErrBuf error // Buffer size too small
ErrFqdn error // Domain must be fully qualified
ErrId error // ID mismatch
ErrRdata error // Bad rdata
ErrShortRead error // Short read
ErrLongDomain error // Domain name too long
)