|
@@ -21,16 +21,6 @@ import (
|
|
|
// A Type is a type of DNS request and response.
|
|
// A Type is a type of DNS request and response.
|
|
|
type Type uint16
|
|
type Type uint16
|
|
|
|
|
|
|
|
-// A Class is a type of network.
|
|
|
|
|
-type Class uint16
|
|
|
|
|
-
|
|
|
|
|
-// An OpCode is a DNS operation code.
|
|
|
|
|
-type OpCode uint16
|
|
|
|
|
-
|
|
|
|
|
-// An RCode is a DNS response status code.
|
|
|
|
|
-type RCode uint16
|
|
|
|
|
-
|
|
|
|
|
-// Wire constants.
|
|
|
|
|
const (
|
|
const (
|
|
|
// ResourceHeader.Type and Question.Type
|
|
// ResourceHeader.Type and Question.Type
|
|
|
TypeA Type = 1
|
|
TypeA Type = 1
|
|
@@ -50,7 +40,46 @@ const (
|
|
|
TypeMINFO Type = 14
|
|
TypeMINFO Type = 14
|
|
|
TypeAXFR Type = 252
|
|
TypeAXFR Type = 252
|
|
|
TypeALL Type = 255
|
|
TypeALL Type = 255
|
|
|
|
|
+)
|
|
|
|
|
+
|
|
|
|
|
+var typeNames = map[Type]string{
|
|
|
|
|
+ TypeA: "TypeA",
|
|
|
|
|
+ TypeNS: "TypeNS",
|
|
|
|
|
+ TypeCNAME: "TypeCNAME",
|
|
|
|
|
+ TypeSOA: "TypeSOA",
|
|
|
|
|
+ TypePTR: "TypePTR",
|
|
|
|
|
+ TypeMX: "TypeMX",
|
|
|
|
|
+ TypeTXT: "TypeTXT",
|
|
|
|
|
+ TypeAAAA: "TypeAAAA",
|
|
|
|
|
+ TypeSRV: "TypeSRV",
|
|
|
|
|
+ TypeOPT: "TypeOPT",
|
|
|
|
|
+ TypeWKS: "TypeWKS",
|
|
|
|
|
+ TypeHINFO: "TypeHINFO",
|
|
|
|
|
+ TypeMINFO: "TypeMINFO",
|
|
|
|
|
+ TypeAXFR: "TypeAXFR",
|
|
|
|
|
+ TypeALL: "TypeALL",
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// String implements fmt.Stringer.String.
|
|
|
|
|
+func (t Type) String() string {
|
|
|
|
|
+ if n, ok := typeNames[t]; ok {
|
|
|
|
|
+ return n
|
|
|
|
|
+ }
|
|
|
|
|
+ return printUint16(uint16(t))
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// GoString implements fmt.GoStringer.GoString.
|
|
|
|
|
+func (t Type) GoString() string {
|
|
|
|
|
+ if n, ok := typeNames[t]; ok {
|
|
|
|
|
+ return "dnsmessage." + n
|
|
|
|
|
+ }
|
|
|
|
|
+ return printUint16(uint16(t))
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// A Class is a type of network.
|
|
|
|
|
+type Class uint16
|
|
|
|
|
|
|
|
|
|
+const (
|
|
|
// ResourceHeader.Class and Question.Class
|
|
// ResourceHeader.Class and Question.Class
|
|
|
ClassINET Class = 1
|
|
ClassINET Class = 1
|
|
|
ClassCSNET Class = 2
|
|
ClassCSNET Class = 2
|
|
@@ -59,7 +88,44 @@ const (
|
|
|
|
|
|
|
|
// Question.Class
|
|
// Question.Class
|
|
|
ClassANY Class = 255
|
|
ClassANY Class = 255
|
|
|
|
|
+)
|
|
|
|
|
+
|
|
|
|
|
+var classNames = map[Class]string{
|
|
|
|
|
+ ClassINET: "ClassINET",
|
|
|
|
|
+ ClassCSNET: "ClassCSNET",
|
|
|
|
|
+ ClassCHAOS: "ClassCHAOS",
|
|
|
|
|
+ ClassHESIOD: "ClassHESIOD",
|
|
|
|
|
+ ClassANY: "ClassANY",
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// String implements fmt.Stringer.String.
|
|
|
|
|
+func (c Class) String() string {
|
|
|
|
|
+ if n, ok := classNames[c]; ok {
|
|
|
|
|
+ return n
|
|
|
|
|
+ }
|
|
|
|
|
+ return printUint16(uint16(c))
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
|
|
+// GoString implements fmt.GoStringer.GoString.
|
|
|
|
|
+func (c Class) GoString() string {
|
|
|
|
|
+ if n, ok := classNames[c]; ok {
|
|
|
|
|
+ return "dnsmessage." + n
|
|
|
|
|
+ }
|
|
|
|
|
+ return printUint16(uint16(c))
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// An OpCode is a DNS operation code.
|
|
|
|
|
+type OpCode uint16
|
|
|
|
|
+
|
|
|
|
|
+// GoString implements fmt.GoStringer.GoString.
|
|
|
|
|
+func (o OpCode) GoString() string {
|
|
|
|
|
+ return printUint16(uint16(o))
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// An RCode is a DNS response status code.
|
|
|
|
|
+type RCode uint16
|
|
|
|
|
+
|
|
|
|
|
+const (
|
|
|
// Message.Rcode
|
|
// Message.Rcode
|
|
|
RCodeSuccess RCode = 0
|
|
RCodeSuccess RCode = 0
|
|
|
RCodeFormatError RCode = 1
|
|
RCodeFormatError RCode = 1
|
|
@@ -69,6 +135,116 @@ const (
|
|
|
RCodeRefused RCode = 5
|
|
RCodeRefused RCode = 5
|
|
|
)
|
|
)
|
|
|
|
|
|
|
|
|
|
+var rCodeNames = map[RCode]string{
|
|
|
|
|
+ RCodeSuccess: "RCodeSuccess",
|
|
|
|
|
+ RCodeFormatError: "RCodeFormatError",
|
|
|
|
|
+ RCodeServerFailure: "RCodeServerFailure",
|
|
|
|
|
+ RCodeNameError: "RCodeNameError",
|
|
|
|
|
+ RCodeNotImplemented: "RCodeNotImplemented",
|
|
|
|
|
+ RCodeRefused: "RCodeRefused",
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// String implements fmt.Stringer.String.
|
|
|
|
|
+func (r RCode) String() string {
|
|
|
|
|
+ if n, ok := rCodeNames[r]; ok {
|
|
|
|
|
+ return n
|
|
|
|
|
+ }
|
|
|
|
|
+ return printUint16(uint16(r))
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// GoString implements fmt.GoStringer.GoString.
|
|
|
|
|
+func (r RCode) GoString() string {
|
|
|
|
|
+ if n, ok := rCodeNames[r]; ok {
|
|
|
|
|
+ return "dnsmessage." + n
|
|
|
|
|
+ }
|
|
|
|
|
+ return printUint16(uint16(r))
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+func printPaddedUint8(i uint8) string {
|
|
|
|
|
+ b := byte(i)
|
|
|
|
|
+ return string([]byte{
|
|
|
|
|
+ b/100 + '0',
|
|
|
|
|
+ b/10%10 + '0',
|
|
|
|
|
+ b%10 + '0',
|
|
|
|
|
+ })
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+func printUint8Bytes(buf []byte, i uint8) []byte {
|
|
|
|
|
+ b := byte(i)
|
|
|
|
|
+ if i >= 100 {
|
|
|
|
|
+ buf = append(buf, b/100+'0')
|
|
|
|
|
+ }
|
|
|
|
|
+ if i >= 10 {
|
|
|
|
|
+ buf = append(buf, b/10%10+'0')
|
|
|
|
|
+ }
|
|
|
|
|
+ return append(buf, b%10+'0')
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+func printByteSlice(b []byte) string {
|
|
|
|
|
+ if len(b) == 0 {
|
|
|
|
|
+ return ""
|
|
|
|
|
+ }
|
|
|
|
|
+ buf := make([]byte, 0, 5*len(b))
|
|
|
|
|
+ buf = printUint8Bytes(buf, uint8(b[0]))
|
|
|
|
|
+ for _, n := range b[1:] {
|
|
|
|
|
+ buf = append(buf, ',', ' ')
|
|
|
|
|
+ buf = printUint8Bytes(buf, uint8(n))
|
|
|
|
|
+ }
|
|
|
|
|
+ return string(buf)
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+const hexDigits = "0123456789abcdef"
|
|
|
|
|
+
|
|
|
|
|
+func printString(str []byte) string {
|
|
|
|
|
+ buf := make([]byte, 0, len(str))
|
|
|
|
|
+ for i := 0; i < len(str); i++ {
|
|
|
|
|
+ c := str[i]
|
|
|
|
|
+ if c == '.' || c == '-' || c == ' ' ||
|
|
|
|
|
+ 'A' <= c && c <= 'Z' ||
|
|
|
|
|
+ 'a' <= c && c <= 'z' ||
|
|
|
|
|
+ '0' <= c && c <= '9' {
|
|
|
|
|
+ buf = append(buf, c)
|
|
|
|
|
+ continue
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ upper := c >> 4
|
|
|
|
|
+ lower := (c << 4) >> 4
|
|
|
|
|
+ buf = append(
|
|
|
|
|
+ buf,
|
|
|
|
|
+ '\\',
|
|
|
|
|
+ 'x',
|
|
|
|
|
+ hexDigits[upper],
|
|
|
|
|
+ hexDigits[lower],
|
|
|
|
|
+ )
|
|
|
|
|
+ }
|
|
|
|
|
+ return string(buf)
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+func printUint16(i uint16) string {
|
|
|
|
|
+ return printUint32(uint32(i))
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+func printUint32(i uint32) string {
|
|
|
|
|
+ // Max value is 4294967295.
|
|
|
|
|
+ buf := make([]byte, 10)
|
|
|
|
|
+ for b, d := buf, uint32(1000000000); d > 0; d /= 10 {
|
|
|
|
|
+ b[0] = byte(i/d%10 + '0')
|
|
|
|
|
+ if b[0] == '0' && len(b) == len(buf) && len(buf) > 1 {
|
|
|
|
|
+ buf = buf[1:]
|
|
|
|
|
+ }
|
|
|
|
|
+ b = b[1:]
|
|
|
|
|
+ i %= d
|
|
|
|
|
+ }
|
|
|
|
|
+ return string(buf)
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+func printBool(b bool) string {
|
|
|
|
|
+ if b {
|
|
|
|
|
+ return "true"
|
|
|
|
|
+ }
|
|
|
|
|
+ return "false"
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
var (
|
|
var (
|
|
|
// ErrNotStarted indicates that the prerequisite information isn't
|
|
// ErrNotStarted indicates that the prerequisite information isn't
|
|
|
// available yet because the previous records haven't been appropriately
|
|
// available yet because the previous records haven't been appropriately
|
|
@@ -165,6 +341,19 @@ func (m *Header) pack() (id uint16, bits uint16) {
|
|
|
return
|
|
return
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+// GoString implements fmt.GoStringer.GoString.
|
|
|
|
|
+func (m *Header) GoString() string {
|
|
|
|
|
+ return "dnsmessage.Header{" +
|
|
|
|
|
+ "ID: " + printUint16(m.ID) + ", " +
|
|
|
|
|
+ "Response: " + printBool(m.Response) + ", " +
|
|
|
|
|
+ "OpCode: " + m.OpCode.GoString() + ", " +
|
|
|
|
|
+ "Authoritative: " + printBool(m.Authoritative) + ", " +
|
|
|
|
|
+ "Truncated: " + printBool(m.Truncated) + ", " +
|
|
|
|
|
+ "RecursionDesired: " + printBool(m.RecursionDesired) + ", " +
|
|
|
|
|
+ "RecursionAvailable: " + printBool(m.RecursionAvailable) + ", " +
|
|
|
|
|
+ "RCode: " + m.RCode.GoString() + "}"
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
// Message is a representation of a DNS message.
|
|
// Message is a representation of a DNS message.
|
|
|
type Message struct {
|
|
type Message struct {
|
|
|
Header
|
|
Header
|
|
@@ -277,6 +466,13 @@ type Resource struct {
|
|
|
Body ResourceBody
|
|
Body ResourceBody
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+func (r *Resource) GoString() string {
|
|
|
|
|
+ return "dnsmessage.Resource{" +
|
|
|
|
|
+ "Header: " + r.Header.GoString() +
|
|
|
|
|
+ ", Body: &" + r.Body.GoString() +
|
|
|
|
|
+ "}"
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
// A ResourceBody is a DNS resource record minus the header.
|
|
// A ResourceBody is a DNS resource record minus the header.
|
|
|
type ResourceBody interface {
|
|
type ResourceBody interface {
|
|
|
// pack packs a Resource except for its header.
|
|
// pack packs a Resource except for its header.
|
|
@@ -285,6 +481,9 @@ type ResourceBody interface {
|
|
|
// realType returns the actual type of the Resource. This is used to
|
|
// realType returns the actual type of the Resource. This is used to
|
|
|
// fill in the header Type field.
|
|
// fill in the header Type field.
|
|
|
realType() Type
|
|
realType() Type
|
|
|
|
|
+
|
|
|
|
|
+ // GoString implements fmt.GoStringer.GoString.
|
|
|
|
|
+ GoString() string
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// pack appends the wire format of the Resource to msg.
|
|
// pack appends the wire format of the Resource to msg.
|
|
@@ -919,6 +1118,40 @@ func (m *Message) AppendPack(b []byte) ([]byte, error) {
|
|
|
return msg, nil
|
|
return msg, nil
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+// GoString implements fmt.GoStringer.GoString.
|
|
|
|
|
+func (m *Message) GoString() string {
|
|
|
|
|
+ s := "dnsmessage.Message{Header: " + m.Header.GoString() + ", " +
|
|
|
|
|
+ "Questions: []dnsmessage.Question{"
|
|
|
|
|
+ if len(m.Questions) > 0 {
|
|
|
|
|
+ s += m.Questions[0].GoString()
|
|
|
|
|
+ for _, q := range m.Questions[1:] {
|
|
|
|
|
+ s += ", " + q.GoString()
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ s += "}, Answers: []dnsmessage.Resource{"
|
|
|
|
|
+ if len(m.Answers) > 0 {
|
|
|
|
|
+ s += m.Answers[0].GoString()
|
|
|
|
|
+ for _, a := range m.Answers[1:] {
|
|
|
|
|
+ s += ", " + a.GoString()
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ s += "}, Authorities: []dnsmessage.Resource{"
|
|
|
|
|
+ if len(m.Authorities) > 0 {
|
|
|
|
|
+ s += m.Authorities[0].GoString()
|
|
|
|
|
+ for _, a := range m.Authorities[1:] {
|
|
|
|
|
+ s += ", " + a.GoString()
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ s += "}, Additionals: []dnsmessage.Resource{"
|
|
|
|
|
+ if len(m.Additionals) > 0 {
|
|
|
|
|
+ s += m.Additionals[0].GoString()
|
|
|
|
|
+ for _, a := range m.Additionals[1:] {
|
|
|
|
|
+ s += ", " + a.GoString()
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ return s + "}}"
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
// A Builder allows incrementally packing a DNS message.
|
|
// A Builder allows incrementally packing a DNS message.
|
|
|
//
|
|
//
|
|
|
// Example usage:
|
|
// Example usage:
|
|
@@ -1361,6 +1594,16 @@ type ResourceHeader struct {
|
|
|
Length uint16
|
|
Length uint16
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+// GoString implements fmt.GoStringer.GoString.
|
|
|
|
|
+func (h *ResourceHeader) GoString() string {
|
|
|
|
|
+ return "dnsmessage.ResourceHeader{" +
|
|
|
|
|
+ "Name: " + h.Name.GoString() + ", " +
|
|
|
|
|
+ "Type: " + h.Type.GoString() + ", " +
|
|
|
|
|
+ "Class: " + h.Class.GoString() + ", " +
|
|
|
|
|
+ "TTL: " + printUint32(h.TTL) + ", " +
|
|
|
|
|
+ "Length: " + printUint16(h.Length) + "}"
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
// pack appends the wire format of the ResourceHeader to oldMsg.
|
|
// pack appends the wire format of the ResourceHeader to oldMsg.
|
|
|
//
|
|
//
|
|
|
// The bytes where length was packed are returned as a slice so they can be
|
|
// The bytes where length was packed are returned as a slice so they can be
|
|
@@ -1623,10 +1866,25 @@ func NewName(name string) (Name, error) {
|
|
|
return n, nil
|
|
return n, nil
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+// MustNewName creates a new Name from a string and panics on error.
|
|
|
|
|
+func MustNewName(name string) Name {
|
|
|
|
|
+ n, err := NewName(name)
|
|
|
|
|
+ if err != nil {
|
|
|
|
|
+ panic("creating name: " + err.Error())
|
|
|
|
|
+ }
|
|
|
|
|
+ return n
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// String implements fmt.Stringer.String.
|
|
|
func (n Name) String() string {
|
|
func (n Name) String() string {
|
|
|
return string(n.Data[:n.Length])
|
|
return string(n.Data[:n.Length])
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+// GoString implements fmt.GoStringer.GoString.
|
|
|
|
|
+func (n *Name) GoString() string {
|
|
|
|
|
+ return `dnsmessage.MustNewName("` + printString(n.Data[:n.Length]) + `")`
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
// pack appends the wire format of the Name to msg.
|
|
// pack appends the wire format of the Name to msg.
|
|
|
//
|
|
//
|
|
|
// Domain names are a sequence of counted strings split at the dots. They end
|
|
// Domain names are a sequence of counted strings split at the dots. They end
|
|
@@ -1826,6 +2084,14 @@ func (q *Question) pack(msg []byte, compression map[string]int, compressionOff i
|
|
|
return packClass(msg, q.Class), nil
|
|
return packClass(msg, q.Class), nil
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+// GoString implements fmt.GoStringer.GoString.
|
|
|
|
|
+func (q *Question) GoString() string {
|
|
|
|
|
+ return "dnsmessage.Question{" +
|
|
|
|
|
+ "Name: " + q.Name.GoString() + ", " +
|
|
|
|
|
+ "Type: " + q.Type.GoString() + ", " +
|
|
|
|
|
+ "Class: " + q.Class.GoString() + "}"
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
func unpackResourceBody(msg []byte, off int, hdr ResourceHeader) (ResourceBody, int, error) {
|
|
func unpackResourceBody(msg []byte, off int, hdr ResourceHeader) (ResourceBody, int, error) {
|
|
|
var (
|
|
var (
|
|
|
r ResourceBody
|
|
r ResourceBody
|
|
@@ -1907,6 +2173,11 @@ func (r *CNAMEResource) pack(msg []byte, compression map[string]int, compression
|
|
|
return r.CNAME.pack(msg, compression, compressionOff)
|
|
return r.CNAME.pack(msg, compression, compressionOff)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+// GoString implements fmt.GoStringer.GoString.
|
|
|
|
|
+func (r *CNAMEResource) GoString() string {
|
|
|
|
|
+ return "dnsmessage.CNAMEResource{CNAME: " + r.CNAME.GoString() + "}"
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
func unpackCNAMEResource(msg []byte, off int) (CNAMEResource, error) {
|
|
func unpackCNAMEResource(msg []byte, off int) (CNAMEResource, error) {
|
|
|
var cname Name
|
|
var cname Name
|
|
|
if _, err := cname.unpack(msg, off); err != nil {
|
|
if _, err := cname.unpack(msg, off); err != nil {
|
|
@@ -1936,6 +2207,13 @@ func (r *MXResource) pack(msg []byte, compression map[string]int, compressionOff
|
|
|
return msg, nil
|
|
return msg, nil
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+// GoString implements fmt.GoStringer.GoString.
|
|
|
|
|
+func (r *MXResource) GoString() string {
|
|
|
|
|
+ return "dnsmessage.MXResource{" +
|
|
|
|
|
+ "Pref: " + printUint16(r.Pref) + ", " +
|
|
|
|
|
+ "MX: " + r.MX.GoString() + "}"
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
func unpackMXResource(msg []byte, off int) (MXResource, error) {
|
|
func unpackMXResource(msg []byte, off int) (MXResource, error) {
|
|
|
pref, off, err := unpackUint16(msg, off)
|
|
pref, off, err := unpackUint16(msg, off)
|
|
|
if err != nil {
|
|
if err != nil {
|
|
@@ -1962,6 +2240,11 @@ func (r *NSResource) pack(msg []byte, compression map[string]int, compressionOff
|
|
|
return r.NS.pack(msg, compression, compressionOff)
|
|
return r.NS.pack(msg, compression, compressionOff)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+// GoString implements fmt.GoStringer.GoString.
|
|
|
|
|
+func (r *NSResource) GoString() string {
|
|
|
|
|
+ return "dnsmessage.NSResource{NS: " + r.NS.GoString() + "}"
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
func unpackNSResource(msg []byte, off int) (NSResource, error) {
|
|
func unpackNSResource(msg []byte, off int) (NSResource, error) {
|
|
|
var ns Name
|
|
var ns Name
|
|
|
if _, err := ns.unpack(msg, off); err != nil {
|
|
if _, err := ns.unpack(msg, off); err != nil {
|
|
@@ -1984,6 +2267,11 @@ func (r *PTRResource) pack(msg []byte, compression map[string]int, compressionOf
|
|
|
return r.PTR.pack(msg, compression, compressionOff)
|
|
return r.PTR.pack(msg, compression, compressionOff)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+// GoString implements fmt.GoStringer.GoString.
|
|
|
|
|
+func (r *PTRResource) GoString() string {
|
|
|
|
|
+ return "dnsmessage.PTRResource{PTR: " + r.PTR.GoString() + "}"
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
func unpackPTRResource(msg []byte, off int) (PTRResource, error) {
|
|
func unpackPTRResource(msg []byte, off int) (PTRResource, error) {
|
|
|
var ptr Name
|
|
var ptr Name
|
|
|
if _, err := ptr.unpack(msg, off); err != nil {
|
|
if _, err := ptr.unpack(msg, off); err != nil {
|
|
@@ -2029,6 +2317,18 @@ func (r *SOAResource) pack(msg []byte, compression map[string]int, compressionOf
|
|
|
return packUint32(msg, r.MinTTL), nil
|
|
return packUint32(msg, r.MinTTL), nil
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+// GoString implements fmt.GoStringer.GoString.
|
|
|
|
|
+func (r *SOAResource) GoString() string {
|
|
|
|
|
+ return "dnsmessage.SOAResource{" +
|
|
|
|
|
+ "NS: " + r.NS.GoString() + ", " +
|
|
|
|
|
+ "MBox: " + r.MBox.GoString() + ", " +
|
|
|
|
|
+ "Serial: " + printUint32(r.Serial) + ", " +
|
|
|
|
|
+ "Refresh: " + printUint32(r.Refresh) + ", " +
|
|
|
|
|
+ "Retry: " + printUint32(r.Retry) + ", " +
|
|
|
|
|
+ "Expire: " + printUint32(r.Expire) + ", " +
|
|
|
|
|
+ "MinTTL: " + printUint32(r.MinTTL) + "}"
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
func unpackSOAResource(msg []byte, off int) (SOAResource, error) {
|
|
func unpackSOAResource(msg []byte, off int) (SOAResource, error) {
|
|
|
var ns Name
|
|
var ns Name
|
|
|
off, err := ns.unpack(msg, off)
|
|
off, err := ns.unpack(msg, off)
|
|
@@ -2084,6 +2384,19 @@ func (r *TXTResource) pack(msg []byte, compression map[string]int, compressionOf
|
|
|
return msg, nil
|
|
return msg, nil
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+// GoString implements fmt.GoStringer.GoString.
|
|
|
|
|
+func (r *TXTResource) GoString() string {
|
|
|
|
|
+ s := "dnsmessage.TXTResource{TXT: []string{"
|
|
|
|
|
+ if len(r.TXT) == 0 {
|
|
|
|
|
+ return s + "}}"
|
|
|
|
|
+ }
|
|
|
|
|
+ s += `"` + printString([]byte(r.TXT[0]))
|
|
|
|
|
+ for _, t := range r.TXT[1:] {
|
|
|
|
|
+ s += `", "` + printString([]byte(t))
|
|
|
|
|
+ }
|
|
|
|
|
+ return s + `"}}`
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
func unpackTXTResource(msg []byte, off int, length uint16) (TXTResource, error) {
|
|
func unpackTXTResource(msg []byte, off int, length uint16) (TXTResource, error) {
|
|
|
txts := make([]string, 0, 1)
|
|
txts := make([]string, 0, 1)
|
|
|
for n := uint16(0); n < length; {
|
|
for n := uint16(0); n < length; {
|
|
@@ -2127,6 +2440,15 @@ func (r *SRVResource) pack(msg []byte, compression map[string]int, compressionOf
|
|
|
return msg, nil
|
|
return msg, nil
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+// GoString implements fmt.GoStringer.GoString.
|
|
|
|
|
+func (r *SRVResource) GoString() string {
|
|
|
|
|
+ return "dnsmessage.SRVResource{" +
|
|
|
|
|
+ "Priority: " + printUint16(r.Priority) + ", " +
|
|
|
|
|
+ "Weight: " + printUint16(r.Weight) + ", " +
|
|
|
|
|
+ "Port: " + printUint16(r.Port) + ", " +
|
|
|
|
|
+ "Target: " + r.Target.GoString() + "}"
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
func unpackSRVResource(msg []byte, off int) (SRVResource, error) {
|
|
func unpackSRVResource(msg []byte, off int) (SRVResource, error) {
|
|
|
priority, off, err := unpackUint16(msg, off)
|
|
priority, off, err := unpackUint16(msg, off)
|
|
|
if err != nil {
|
|
if err != nil {
|
|
@@ -2161,6 +2483,12 @@ func (r *AResource) pack(msg []byte, compression map[string]int, compressionOff
|
|
|
return packBytes(msg, r.A[:]), nil
|
|
return packBytes(msg, r.A[:]), nil
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+// GoString implements fmt.GoStringer.GoString.
|
|
|
|
|
+func (r *AResource) GoString() string {
|
|
|
|
|
+ return "dnsmessage.AResource{" +
|
|
|
|
|
+ "A: [4]byte{" + printByteSlice(r.A[:]) + "}}"
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
func unpackAResource(msg []byte, off int) (AResource, error) {
|
|
func unpackAResource(msg []byte, off int) (AResource, error) {
|
|
|
var a [4]byte
|
|
var a [4]byte
|
|
|
if _, err := unpackBytes(msg, off, a[:]); err != nil {
|
|
if _, err := unpackBytes(msg, off, a[:]); err != nil {
|
|
@@ -2178,6 +2506,12 @@ func (r *AAAAResource) realType() Type {
|
|
|
return TypeAAAA
|
|
return TypeAAAA
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+// GoString implements fmt.GoStringer.GoString.
|
|
|
|
|
+func (r *AAAAResource) GoString() string {
|
|
|
|
|
+ return "dnsmessage.AAAAResource{" +
|
|
|
|
|
+ "AAAA: [16]byte{" + printByteSlice(r.AAAA[:]) + "}}"
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
// pack appends the wire format of the AAAAResource to msg.
|
|
// pack appends the wire format of the AAAAResource to msg.
|
|
|
func (r *AAAAResource) pack(msg []byte, compression map[string]int, compressionOff int) ([]byte, error) {
|
|
func (r *AAAAResource) pack(msg []byte, compression map[string]int, compressionOff int) ([]byte, error) {
|
|
|
return packBytes(msg, r.AAAA[:]), nil
|
|
return packBytes(msg, r.AAAA[:]), nil
|
|
@@ -2208,6 +2542,13 @@ type Option struct {
|
|
|
Data []byte
|
|
Data []byte
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+// GoString implements fmt.GoStringer.GoString.
|
|
|
|
|
+func (o *Option) GoString() string {
|
|
|
|
|
+ return "dnsmessage.Option{" +
|
|
|
|
|
+ "Code: " + printUint16(o.Code) + ", " +
|
|
|
|
|
+ "Data: []byte{" + printByteSlice(o.Data) + "}}"
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
func (r *OPTResource) realType() Type {
|
|
func (r *OPTResource) realType() Type {
|
|
|
return TypeOPT
|
|
return TypeOPT
|
|
|
}
|
|
}
|
|
@@ -2222,6 +2563,19 @@ func (r *OPTResource) pack(msg []byte, compression map[string]int, compressionOf
|
|
|
return msg, nil
|
|
return msg, nil
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+// GoString implements fmt.GoStringer.GoString.
|
|
|
|
|
+func (r *OPTResource) GoString() string {
|
|
|
|
|
+ s := "dnsmessage.OPTResource{Options: []dnsmessage.Option{"
|
|
|
|
|
+ if len(r.Options) == 0 {
|
|
|
|
|
+ return s + "}}"
|
|
|
|
|
+ }
|
|
|
|
|
+ s += r.Options[0].GoString()
|
|
|
|
|
+ for _, o := range r.Options[1:] {
|
|
|
|
|
+ s += ", " + o.GoString()
|
|
|
|
|
+ }
|
|
|
|
|
+ return s + "}}"
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
func unpackOPTResource(msg []byte, off int, length uint16) (OPTResource, error) {
|
|
func unpackOPTResource(msg []byte, off int, length uint16) (OPTResource, error) {
|
|
|
var opts []Option
|
|
var opts []Option
|
|
|
for oldOff := off; off < oldOff+int(length); {
|
|
for oldOff := off; off < oldOff+int(length); {
|