1 // Package dns deals with encoding and decoding DNS wire format.
13 // The maximum number of DNS name compression pointers we are willing to follow.
14 // Without something like this, infinite loops are possible.
15 const compressionPointerLimit
= 10
18 // ErrZeroLengthLabel is the error returned for names that contain a
19 // zero-length label, like "example..com".
20 ErrZeroLengthLabel
= errors
.New("name contains a zero-length label")
22 // ErrLabelTooLong is the error returned for labels that are longer than
24 ErrLabelTooLong
= errors
.New("name contains a label longer than 63 octets")
26 // ErrNameTooLong is the error returned for names whose encoded
27 // representation is longer than 255 octets.
28 ErrNameTooLong
= errors
.New("name is longer than 255 octets")
30 // ErrReservedLabelType is the error returned when reading a label type
31 // prefix whose two most significant bits are not 00 or 11.
32 ErrReservedLabelType
= errors
.New("reserved label type")
34 // ErrTooManyPointers is the error returned when reading a compressed
35 // name that has too many compression pointers.
36 ErrTooManyPointers
= errors
.New("too many compression pointers")
38 // ErrTrailingBytes is the error returned when bytes remain in the parse
39 // buffer after parsing a message.
40 ErrTrailingBytes
= errors
.New("trailing bytes after message")
42 // ErrIntegerOverflow is the error returned when trying to encode an
43 // integer greater than 65535 into a 16-bit field.
44 ErrIntegerOverflow
= errors
.New("integer overflow")
48 // https://tools.ietf.org/html/rfc1035#section-3.2.2
50 // https://tools.ietf.org/html/rfc6891#section-6.1.1
53 // https://tools.ietf.org/html/rfc1035#section-3.2.4
56 // https://tools.ietf.org/html/rfc1035#section-4.1.1
57 RcodeNoError
= 0 // a.k.a. NOERROR
58 RcodeFormatError
= 1 // a.k.a. FORMERR
59 RcodeNameError
= 3 // a.k.a. NXDOMAIN
60 RcodeNotImplemented
= 4 // a.k.a. NOTIMPL
61 // https://tools.ietf.org/html/rfc6891#section-9
62 ExtendedRcodeBadVers
= 16 // a.k.a. BADVERS
65 // Name represents a domain name, a sequence of labels each of which is 63
66 // octets or less in length.
68 // https://tools.ietf.org/html/rfc1035#section-3.1
71 // NewName returns a Name from a slice of labels, after checking the labels for
72 // validity. Does not include a zero-length label at the end of the slice.
73 func NewName(labels
[][]byte) (Name
, error
) {
75 // https://tools.ietf.org/html/rfc1035#section-2.3.4
76 // Various objects and parameters in the DNS have size limits.
77 // labels 63 octets or less
78 // names 255 octets or less
79 for _
, label
:= range labels
{
81 return nil, ErrZeroLengthLabel
84 return nil, ErrLabelTooLong
87 // Check the total length.
88 builder
:= newMessageBuilder()
89 builder
.WriteName(name
)
90 if len(builder
.Bytes()) > 255 {
91 return nil, ErrNameTooLong
96 // ParseName returns a new Name from a string of labels separated by dots, after
97 // checking the name for validity. A single dot at the end of the string is
99 func ParseName(s
string) (Name
, error
) {
100 b
:= bytes
.TrimSuffix([]byte(s
), []byte("."))
102 // bytes.Split(b, ".") would return [""] in this case
103 return NewName([][]byte{})
105 return NewName(bytes
.Split(b
, []byte(".")))
109 // String returns a reversible string representation of name. Labels are
110 // separated by dots, and any bytes in a label that are outside the set
111 // [0-9A-Za-z-] are replaced with a \xXX hex escape sequence.
112 func (name Name
) String() string {
117 var buf strings
.Builder
118 for i
, label
:= range name
{
122 for _
, b
:= range label
{
124 ('0' <= b
&& b
<= '9') ||
125 ('A' <= b
&& b
<= 'Z') ||
126 ('a' <= b
&& b
<= 'z') {
129 fmt
.Fprintf(&buf
, "\\x%02x", b
)
136 // TrimSuffix returns a Name with the given suffix removed, if it was present.
137 // The second return value indicates whether the suffix was present. If the
138 // suffix was not present, the first return value is nil.
139 func (name Name
) TrimSuffix(suffix Name
) (Name
, bool) {
140 if len(name
) < len(suffix
) {
143 split
:= len(name
) - len(suffix
)
144 fore
, aft
:= name
[:split
], name
[split
:]
145 for i
:= 0; i
< len(aft
); i
++ {
146 if !bytes
.Equal(bytes
.ToLower(aft
[i
]), bytes
.ToLower(suffix
[i
])) {
153 // Message represents a DNS message.
155 // https://tools.ietf.org/html/rfc1035#section-4.1
156 type Message
struct {
166 // Opcode extracts the OPCODE part of the Flags field.
168 // https://tools.ietf.org/html/rfc1035#section-4.1.1
169 func (message
*Message
) Opcode() uint16 {
170 return (message
.Flags
>> 11) & 0xf
173 // Rcode extracts the RCODE part of the Flags field.
175 // https://tools.ietf.org/html/rfc1035#section-4.1.1
176 func (message
*Message
) Rcode() uint16 {
177 return message
.Flags
& 0x000f
180 // Question represents an entry in the question section of a message.
182 // https://tools.ietf.org/html/rfc1035#section-4.1.2
183 type Question
struct {
189 // RR represents a resource record.
191 // https://tools.ietf.org/html/rfc1035#section-4.1.3
200 // readName parses a DNS name from r. It leaves r positioned just after the
202 func readName(r io
.ReadSeeker
) (Name
, error
) {
204 // We limit the number of compression pointers we are willing to follow.
206 // If we followed any compression pointers, we must finally seek to just
207 // past the first pointer.
212 err
:= binary
.Read(r
, binary
.BigEndian
, &labelType
)
217 switch labelType
& 0xc0 {
219 // This is an ordinary label.
220 // https://tools.ietf.org/html/rfc1035#section-3.1
221 length
:= int(labelType
& 0x3f)
225 label
:= make([]byte, length
)
226 _
, err
:= io
.ReadFull(r
, label
)
230 labels
= append(labels
, label
)
232 // This is a compression pointer.
233 // https://tools.ietf.org/html/rfc1035#section-4.1.4
234 upper
:= labelType
& 0x3f
236 err
:= binary
.Read(r
, binary
.BigEndian
, &lower
)
240 offset
:= (uint16(upper
) << 8) |
uint16(lower
)
242 if numPointers
== 0 {
243 // The first time we encounter a pointer,
244 // remember our position so we can seek back to
246 seekTo
, err
= r
.Seek(0, io
.SeekCurrent
)
252 if numPointers
> compressionPointerLimit
{
253 return nil, ErrTooManyPointers
256 // Follow the pointer and continue.
257 _
, err
= r
.Seek(int64(offset
), io
.SeekStart
)
262 // "The 10 and 01 combinations are reserved for future
264 return nil, ErrReservedLabelType
267 // If we followed any pointers, then seek back to just after the first
270 _
, err
:= r
.Seek(seekTo
, io
.SeekStart
)
275 return NewName(labels
)
278 // readQuestion parses one entry from the Question section. It leaves r
279 // positioned just after the parsed entry.
281 // https://tools.ietf.org/html/rfc1035#section-4.1.2
282 func readQuestion(r io
.ReadSeeker
) (Question
, error
) {
283 var question Question
285 question
.Name
, err
= readName(r
)
289 for _
, ptr
:= range []*uint16{&question
.Type
, &question
.Class
} {
290 err
:= binary
.Read(r
, binary
.BigEndian
, ptr
)
299 // readRR parses one resource record. It leaves r positioned just after the
300 // parsed resource record.
302 // https://tools.ietf.org/html/rfc1035#section-4.1.3
303 func readRR(r io
.ReadSeeker
) (RR
, error
) {
306 rr
.Name
, err
= readName(r
)
310 for _
, ptr
:= range []*uint16{&rr
.Type
, &rr
.Class
} {
311 err
:= binary
.Read(r
, binary
.BigEndian
, ptr
)
316 err
= binary
.Read(r
, binary
.BigEndian
, &rr
.TTL
)
321 err
= binary
.Read(r
, binary
.BigEndian
, &rdLength
)
325 rr
.Data
= make([]byte, rdLength
)
326 _
, err
= io
.ReadFull(r
, rr
.Data
)
334 // readMessage parses a complete DNS message. It leaves r positioned just after
335 // the parsed message.
336 func readMessage(r io
.ReadSeeker
) (Message
, error
) {
340 // https://tools.ietf.org/html/rfc1035#section-4.1.1
341 var qdCount
, anCount
, nsCount
, arCount
uint16
342 for _
, ptr
:= range []*uint16{
343 &message
.ID
, &message
.Flags
,
344 &qdCount
, &anCount
, &nsCount
, &arCount
,
346 err
:= binary
.Read(r
, binary
.BigEndian
, ptr
)
353 // https://tools.ietf.org/html/rfc1035#section-4.1.2
354 for i
:= 0; i
< int(qdCount
); i
++ {
355 question
, err
:= readQuestion(r
)
359 message
.Question
= append(message
.Question
, question
)
362 // Answer, Authority, and Additional sections
363 // https://tools.ietf.org/html/rfc1035#section-4.1.3
364 for _
, rec
:= range []struct {
368 {&message
.Answer
, anCount
},
369 {&message
.Authority
, nsCount
},
370 {&message
.Additional
, arCount
},
372 for i
:= 0; i
< int(rec
.count
); i
++ {
377 *rec
.ptr
= append(*rec
.ptr
, rr
)
384 // MessageFromWireFormat parses a message from buf and returns a Message object.
385 // It returns ErrTrailingBytes if there are bytes remaining in buf after parsing
387 func MessageFromWireFormat(buf
[]byte) (Message
, error
) {
388 r
:= bytes
.NewReader(buf
)
389 message
, err
:= readMessage(r
)
391 err
= io
.ErrUnexpectedEOF
392 } else if err
== nil {
393 // Check for trailing bytes.
394 _
, err
= r
.ReadByte()
397 } else if err
== nil {
398 err
= ErrTrailingBytes
404 // messageBuilder manages the state of serializing a DNS message. Its main
405 // function is to keep track of names already written for the purpose of name
407 type messageBuilder
struct {
409 nameCache
map[string]int
412 // newMessageBuilder creates a new messageBuilder with an empty name cache.
413 func newMessageBuilder() *messageBuilder
{
414 return &messageBuilder
{
415 nameCache
: make(map[string]int),
419 // Bytes returns the serialized DNS message as a slice of bytes.
420 func (builder
*messageBuilder
) Bytes() []byte {
421 return builder
.w
.Bytes()
424 // WriteName appends name to the in-progress messageBuilder, employing
425 // compression pointers to previously written names if possible.
426 func (builder
*messageBuilder
) WriteName(name Name
) {
427 // https://tools.ietf.org/html/rfc1035#section-3.1
428 for i
:= range name
{
429 // Has this suffix already been encoded in the message?
430 if ptr
, ok
:= builder
.nameCache
[name
[i
:].String()]; ok
&& ptr
&0x3fff == ptr
{
431 // If so, we can write a compression pointer.
432 binary
.Write(&builder
.w
, binary
.BigEndian
, uint16(0xc000|ptr
))
435 // Not cached; we must encode this label verbatim. Store a cache
436 // entry pointing to the beginning of it.
437 builder
.nameCache
[name
[i
:].String()] = builder
.w
.Len()
438 length
:= len(name
[i
])
439 if length
== 0 || length
> 63 {
442 builder
.w
.WriteByte(byte(length
))
443 builder
.w
.Write(name
[i
])
445 builder
.w
.WriteByte(0)
448 // WriteQuestion appends a Question section entry to the in-progress
450 func (builder
*messageBuilder
) WriteQuestion(question
*Question
) {
451 // https://tools.ietf.org/html/rfc1035#section-4.1.2
452 builder
.WriteName(question
.Name
)
453 binary
.Write(&builder
.w
, binary
.BigEndian
, question
.Type
)
454 binary
.Write(&builder
.w
, binary
.BigEndian
, question
.Class
)
457 // WriteRR appends a resource record to the in-progress messageBuilder. It
458 // returns ErrIntegerOverflow if the length of rr.Data does not fit in 16 bits.
459 func (builder
*messageBuilder
) WriteRR(rr
*RR
) error
{
460 // https://tools.ietf.org/html/rfc1035#section-4.1.3
461 builder
.WriteName(rr
.Name
)
462 binary
.Write(&builder
.w
, binary
.BigEndian
, rr
.Type
)
463 binary
.Write(&builder
.w
, binary
.BigEndian
, rr
.Class
)
464 binary
.Write(&builder
.w
, binary
.BigEndian
, rr
.TTL
)
465 rdLength
:= uint16(len(rr
.Data
))
466 if int(rdLength
) != len(rr
.Data
) {
467 return ErrIntegerOverflow
469 binary
.Write(&builder
.w
, binary
.BigEndian
, rdLength
)
470 builder
.w
.Write(rr
.Data
)
474 // WriteMessage appends a complete DNS message to the in-progress
475 // messageBuilder. It returns ErrIntegerOverflow if the number of entries in any
476 // section, or the length of the data in any resource record, does not fit in 16
478 func (builder
*messageBuilder
) WriteMessage(message
*Message
) error
{
480 // https://tools.ietf.org/html/rfc1035#section-4.1.1
481 binary
.Write(&builder
.w
, binary
.BigEndian
, message
.ID
)
482 binary
.Write(&builder
.w
, binary
.BigEndian
, message
.Flags
)
483 for _
, count
:= range []int{
484 len(message
.Question
),
486 len(message
.Authority
),
487 len(message
.Additional
),
489 count16
:= uint16(count
)
490 if int(count16
) != count
{
491 return ErrIntegerOverflow
493 binary
.Write(&builder
.w
, binary
.BigEndian
, count16
)
497 // https://tools.ietf.org/html/rfc1035#section-4.1.2
498 for _
, question
:= range message
.Question
{
499 builder
.WriteQuestion(&question
)
502 // Answer, Authority, and Additional sections
503 // https://tools.ietf.org/html/rfc1035#section-4.1.3
504 for _
, rrs
:= range [][]RR
{message
.Answer
, message
.Authority
, message
.Additional
} {
505 for _
, rr
:= range rrs
{
506 err
:= builder
.WriteRR(&rr
)
516 // WireFormat encodes a Message as a slice of bytes in DNS wire format. It
517 // returns ErrIntegerOverflow if the number of entries in any section, or the
518 // length of the data in any resource record, does not fit in 16 bits.
519 func (message
*Message
) WireFormat() ([]byte, error
) {
520 builder
:= newMessageBuilder()
521 err
:= builder
.WriteMessage(message
)
525 return builder
.Bytes(), nil
528 // DecodeRDataTXT decodes TXT-DATA (as found in the RDATA for a resource record
529 // with TYPE=TXT) as a raw byte slice, by concatenating all the
530 // <character-string>s it contains.
532 // https://tools.ietf.org/html/rfc1035#section-3.3.14
533 func DecodeRDataTXT(p
[]byte) ([]byte, error
) {
537 return nil, io
.ErrUnexpectedEOF
542 return nil, io
.ErrUnexpectedEOF
550 return buf
.Bytes(), nil
553 // EncodeRDataTXT encodes a slice of bytes as TXT-DATA, as appropriate for the
554 // RDATA of a resource record with TYPE=TXT. No length restriction is enforced
555 // here; that must be checked at a higher level.
557 // https://tools.ietf.org/html/rfc1035#section-3.3.14
558 func EncodeRDataTXT(p
[]byte) []byte {
559 // https://tools.ietf.org/html/rfc1035#section-3.3
560 // https://tools.ietf.org/html/rfc1035#section-3.3.14
561 // TXT data is a sequence of one or more <character-string>s, where
562 // <character-string> is a length octet followed by that number of
570 // Must write here, even if len(p) == 0, because it's "*one or more*
571 // <character-string>s".
572 buf
.WriteByte(byte(len(p
)))