1 // Copyright 2009 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
5 // DNS packet assembly. See RFC 1035.
7 // This is intended to support name resolution during Dial.
8 // It doesn't have to be blazing fast.
10 // Each message structure has a Walk method that is used by
11 // a generic pack/unpack routine. Thus, if in the future we need
12 // to define new message structs, no new pack/unpack/printing code
13 // needs to be written.
15 // The first half of this file defines the DNS message formats.
16 // The second half implements the conversion to and from wire format.
17 // A few of the structure elements have string tags to aid the
18 // generic pack/unpack routines.
20 // TODO(rsc): There are enough names defined in this file that they're all
21 // prefixed with dns. Perhaps put this in its own package later.
29 // valid dnsRR_Header.Rrtype and dnsQuestion.qtype
49 // valid dnsQuestion.qtype only
55 // valid dnsQuestion.qclass
64 dnsRcodeFormatError
= 1
65 dnsRcodeServerFailure
= 2
67 dnsRcodeNotImplemented
= 4
71 // A dnsStruct describes how to iterate over its fields to emulate
72 // reflective marshaling.
73 type dnsStruct
interface {
74 // Walk iterates over fields of a structure and calls f
75 // with a reference to that field, the name of the field
76 // and a tag ("", "domain", "ipv4", "ipv6") specifying
77 // particular encodings. Possible concrete types
78 // for v are *uint16, *uint32, *string, or []byte, and
79 // *int, *bool in the case of dnsMsgHdr.
80 // Whenever f returns false, Walk must stop and return
81 // false, and otherwise return true.
82 Walk(f
func(v
interface{}, name
, tag
string) (ok
bool)) (ok
bool)
85 // The wire format for the DNS packet header.
86 type dnsHeader
struct {
89 Qdcount
, Ancount
, Nscount
, Arcount
uint16
92 func (h
*dnsHeader
) Walk(f
func(v
interface{}, name
, tag
string) bool) bool {
93 return f(&h
.Id
, "Id", "") &&
94 f(&h
.Bits
, "Bits", "") &&
95 f(&h
.Qdcount
, "Qdcount", "") &&
96 f(&h
.Ancount
, "Ancount", "") &&
97 f(&h
.Nscount
, "Nscount", "") &&
98 f(&h
.Arcount
, "Arcount", "")
103 _QR
= 1 << 15 // query/response (response=1)
104 _AA
= 1 << 10 // authoritative
105 _TC
= 1 << 9 // truncated
106 _RD
= 1 << 8 // recursion desired
107 _RA
= 1 << 7 // recursion available
111 type dnsQuestion
struct {
117 func (q
*dnsQuestion
) Walk(f
func(v
interface{}, name
, tag
string) bool) bool {
118 return f(&q
.Name
, "Name", "domain") &&
119 f(&q
.Qtype
, "Qtype", "") &&
120 f(&q
.Qclass
, "Qclass", "")
123 // DNS responses (resource records).
124 // There are many types of messages,
125 // but they all share the same header.
126 type dnsRR_Header
struct {
131 Rdlength
uint16 // length of data after header
134 func (h
*dnsRR_Header
) Header() *dnsRR_Header
{
138 func (h
*dnsRR_Header
) Walk(f
func(v
interface{}, name
, tag
string) bool) bool {
139 return f(&h
.Name
, "Name", "domain") &&
140 f(&h
.Rrtype
, "Rrtype", "") &&
141 f(&h
.Class
, "Class", "") &&
142 f(&h
.Ttl
, "Ttl", "") &&
143 f(&h
.Rdlength
, "Rdlength", "")
146 type dnsRR
interface {
148 Header() *dnsRR_Header
151 // Specific DNS RR formats for each query type.
153 type dnsRR_CNAME
struct {
158 func (rr
*dnsRR_CNAME
) Header() *dnsRR_Header
{
162 func (rr
*dnsRR_CNAME
) Walk(f
func(v
interface{}, name
, tag
string) bool) bool {
163 return rr
.Hdr
.Walk(f
) && f(&rr
.Cname
, "Cname", "domain")
166 type dnsRR_MX
struct {
172 func (rr
*dnsRR_MX
) Header() *dnsRR_Header
{
176 func (rr
*dnsRR_MX
) Walk(f
func(v
interface{}, name
, tag
string) bool) bool {
177 return rr
.Hdr
.Walk(f
) && f(&rr
.Pref
, "Pref", "") && f(&rr
.Mx
, "Mx", "domain")
180 type dnsRR_NS
struct {
185 func (rr
*dnsRR_NS
) Header() *dnsRR_Header
{
189 func (rr
*dnsRR_NS
) Walk(f
func(v
interface{}, name
, tag
string) bool) bool {
190 return rr
.Hdr
.Walk(f
) && f(&rr
.Ns
, "Ns", "domain")
193 type dnsRR_PTR
struct {
198 func (rr
*dnsRR_PTR
) Header() *dnsRR_Header
{
202 func (rr
*dnsRR_PTR
) Walk(f
func(v
interface{}, name
, tag
string) bool) bool {
203 return rr
.Hdr
.Walk(f
) && f(&rr
.Ptr
, "Ptr", "domain")
206 type dnsRR_SOA
struct {
217 func (rr
*dnsRR_SOA
) Header() *dnsRR_Header
{
221 func (rr
*dnsRR_SOA
) Walk(f
func(v
interface{}, name
, tag
string) bool) bool {
222 return rr
.Hdr
.Walk(f
) &&
223 f(&rr
.Ns
, "Ns", "domain") &&
224 f(&rr
.Mbox
, "Mbox", "domain") &&
225 f(&rr
.Serial
, "Serial", "") &&
226 f(&rr
.Refresh
, "Refresh", "") &&
227 f(&rr
.Retry
, "Retry", "") &&
228 f(&rr
.Expire
, "Expire", "") &&
229 f(&rr
.Minttl
, "Minttl", "")
232 type dnsRR_TXT
struct {
234 Txt
string // not domain name
237 func (rr
*dnsRR_TXT
) Header() *dnsRR_Header
{
241 func (rr
*dnsRR_TXT
) Walk(f
func(v
interface{}, name
, tag
string) bool) bool {
246 for n
< rr
.Hdr
.Rdlength
{
248 if !f(&txt
, "Txt", "") {
251 // more bytes than rr.Hdr.Rdlength said there would be
252 if rr
.Hdr
.Rdlength
-n
< uint16(len(txt
))+1 {
255 n
+= uint16(len(txt
)) + 1
261 type dnsRR_SRV
struct {
269 func (rr
*dnsRR_SRV
) Header() *dnsRR_Header
{
273 func (rr
*dnsRR_SRV
) Walk(f
func(v
interface{}, name
, tag
string) bool) bool {
274 return rr
.Hdr
.Walk(f
) &&
275 f(&rr
.Priority
, "Priority", "") &&
276 f(&rr
.Weight
, "Weight", "") &&
277 f(&rr
.Port
, "Port", "") &&
278 f(&rr
.Target
, "Target", "domain")
281 type dnsRR_A
struct {
286 func (rr
*dnsRR_A
) Header() *dnsRR_Header
{
290 func (rr
*dnsRR_A
) Walk(f
func(v
interface{}, name
, tag
string) bool) bool {
291 return rr
.Hdr
.Walk(f
) && f(&rr
.A
, "A", "ipv4")
294 type dnsRR_AAAA
struct {
299 func (rr
*dnsRR_AAAA
) Header() *dnsRR_Header
{
303 func (rr
*dnsRR_AAAA
) Walk(f
func(v
interface{}, name
, tag
string) bool) bool {
304 return rr
.Hdr
.Walk(f
) && f(rr
.AAAA
[:], "AAAA", "ipv6")
307 // Packing and unpacking.
309 // All the packers and unpackers take a (msg []byte, off int)
310 // and return (off1 int, ok bool). If they return ok==false, they
311 // also return off1==len(msg), so that the next unpacker will
312 // also fail. This lets us avoid checks of ok until the end of a
315 // Map of constructors for each RR wire type.
316 var rr_mk
= map[int]func() dnsRR
{
317 dnsTypeCNAME
: func() dnsRR
{ return new(dnsRR_CNAME
) },
318 dnsTypeMX
: func() dnsRR
{ return new(dnsRR_MX
) },
319 dnsTypeNS
: func() dnsRR
{ return new(dnsRR_NS
) },
320 dnsTypePTR
: func() dnsRR
{ return new(dnsRR_PTR
) },
321 dnsTypeSOA
: func() dnsRR
{ return new(dnsRR_SOA
) },
322 dnsTypeTXT
: func() dnsRR
{ return new(dnsRR_TXT
) },
323 dnsTypeSRV
: func() dnsRR
{ return new(dnsRR_SRV
) },
324 dnsTypeA
: func() dnsRR
{ return new(dnsRR_A
) },
325 dnsTypeAAAA
: func() dnsRR
{ return new(dnsRR_AAAA
) },
328 // Pack a domain name s into msg[off:].
329 // Domain names are a sequence of counted strings
330 // split at the dots. They end with a zero-length string.
331 func packDomainName(s
string, msg
[]byte, off
int) (off1
int, ok
bool) {
332 // Add trailing dot to canonicalize name.
333 if n
:= len(s
); n
== 0 || s
[n
-1] != '.' {
337 // Allow root domain.
344 // Each dot ends a segment of the name.
345 // We trade each dot byte for a length byte.
346 // There is also a trailing zero.
347 // Check that we have all the space we need.
349 if off
+tot
> len(msg
) {
350 return len(msg
), false
353 // Emit sequence of counted strings, chopping at dots.
355 for i
:= 0; i
< len(s
); i
++ {
357 if i
-begin
>= 1<<6 { // top two bits of length must be clear
358 return len(msg
), false
361 return len(msg
), false
364 msg
[off
] = byte(i
- begin
)
367 for j
:= begin
; j
< i
; j
++ {
379 // Unpack a domain name.
380 // In addition to the simple sequences of counted strings above,
381 // domain names are allowed to refer to strings elsewhere in the
382 // packet, to avoid repeating common suffixes when returning
383 // many entries in a single domain. The pointers are marked
384 // by a length byte with the top two bits set. Ignoring those
385 // two bits, that byte and the next give a 14 bit offset from msg[0]
386 // where we should pick up the trail.
387 // Note that if we jump elsewhere in the packet,
388 // we return off1 == the offset after the first pointer we found,
389 // which is where the next record will start.
390 // In theory, the pointers are only allowed to jump backward.
391 // We let them jump anywhere and stop jumping after a while.
392 func unpackDomainName(msg
[]byte, off
int) (s
string, off1
int, ok
bool) {
394 ptr
:= 0 // number of pointers followed
398 return "", len(msg
), false
409 if off
+c
> len(msg
) {
410 return "", len(msg
), false
412 s
+= string(msg
[off
:off
+c
]) + "."
415 // pointer to somewhere else in msg.
416 // remember location after first ptr,
417 // since that's how many bytes we consumed.
418 // also, don't follow too many pointers --
419 // maybe there's a loop.
421 return "", len(msg
), false
429 return "", len(msg
), false
431 off
= (c
^0xC0)<<8 |
int(c1
)
433 // 0x80 and 0x40 are reserved
434 return "", len(msg
), false
446 // packStruct packs a structure into msg at specified offset off, and
447 // returns off1 such that msg[off:off1] is the encoded data.
448 func packStruct(any dnsStruct
, msg
[]byte, off
int) (off1
int, ok
bool) {
449 ok
= any
.Walk(func(field
interface{}, name
, tag
string) bool {
450 switch fv
:= field
.(type) {
452 println("net: dns: unknown packing type")
456 if off
+2 > len(msg
) {
459 msg
[off
] = byte(i
>> 8)
464 msg
[off
] = byte(i
>> 24)
465 msg
[off
+1] = byte(i
>> 16)
466 msg
[off
+2] = byte(i
>> 8)
471 if off
+n
> len(msg
) {
474 copy(msg
[off
:off
+n
], fv
)
480 println("net: dns: unknown string tag", tag
)
483 off
, ok
= packDomainName(s
, msg
, off
)
488 // Counted string: 1 byte length.
489 if len(s
) > 255 || off
+1+len(s
) > len(msg
) {
492 msg
[off
] = byte(len(s
))
494 off
+= copy(msg
[off
:], s
)
500 return len(msg
), false
505 // unpackStruct decodes msg[off:] into the given structure, and
506 // returns off1 such that msg[off:off1] is the encoded data.
507 func unpackStruct(any dnsStruct
, msg
[]byte, off
int) (off1
int, ok
bool) {
508 ok
= any
.Walk(func(field
interface{}, name
, tag
string) bool {
509 switch fv
:= field
.(type) {
511 println("net: dns: unknown packing type")
514 if off
+2 > len(msg
) {
517 *fv
= uint16(msg
[off
])<<8 |
uint16(msg
[off
+1])
520 if off
+4 > len(msg
) {
523 *fv
= uint32(msg
[off
])<<24 |
uint32(msg
[off
+1])<<16 |
524 uint32(msg
[off
+2])<<8 |
uint32(msg
[off
+3])
528 if off
+n
> len(msg
) {
531 copy(fv
, msg
[off
:off
+n
])
537 println("net: dns: unknown string tag", tag
)
540 s
, off
, ok
= unpackDomainName(msg
, off
)
545 if off
>= len(msg
) || off
+1+int(msg
[off
]) > len(msg
) {
551 for i
:= 0; i
< n
; i
++ {
562 return len(msg
), false
567 // Generic struct printer. Prints fields with tag "ipv4" or "ipv6"
569 func printStruct(any dnsStruct
) string {
572 any
.Walk(func(val
interface{}, name
, tag
string) bool {
581 s
+= IPv4(byte(i
>>24), byte(i
>>16), byte(i
>>8), byte(i
)).String()
587 switch v
:= val
.(type) {
589 // can't really happen.
590 s
+= "<unknown type>"
628 // Resource record packer.
629 func packRR(rr dnsRR
, msg
[]byte, off
int) (off2
int, ok
bool) {
631 // pack twice, once to find end of header
632 // and again to find end of packet.
633 // a bit inefficient but this doesn't need to be fast.
634 // off1 is end of header
636 off1
, ok
= packStruct(rr
.Header(), msg
, off
)
638 return len(msg
), false
640 off2
, ok
= packStruct(rr
, msg
, off
)
642 return len(msg
), false
644 // pack a third time; redo header with correct data length
645 rr
.Header().Rdlength
= uint16(off2
- off1
)
646 packStruct(rr
.Header(), msg
, off
)
650 // Resource record unpacker.
651 func unpackRR(msg
[]byte, off
int) (rr dnsRR
, off1
int, ok
bool) {
652 // unpack just the header, to find the rr type and length
655 if off
, ok
= unpackStruct(&h
, msg
, off
); !ok
{
656 return nil, len(msg
), false
658 end
:= off
+ int(h
.Rdlength
)
660 // make an rr of that type and re-unpack.
661 // again inefficient but doesn't need to be fast.
662 mk
, known
:= rr_mk
[int(h
.Rrtype
)]
667 off
, ok
= unpackStruct(rr
, msg
, off0
)
674 // Usable representation of a DNS packet.
676 // A manually-unpacked version of (id, bits).
677 // This is in its own struct for easy printing.
678 type dnsMsgHdr
struct {
684 recursion_desired
bool
685 recursion_available
bool
689 func (h
*dnsMsgHdr
) Walk(f
func(v
interface{}, name
, tag
string) bool) bool {
690 return f(&h
.id
, "id", "") &&
691 f(&h
.response
, "response", "") &&
692 f(&h
.opcode
, "opcode", "") &&
693 f(&h
.authoritative
, "authoritative", "") &&
694 f(&h
.truncated
, "truncated", "") &&
695 f(&h
.recursion_desired
, "recursion_desired", "") &&
696 f(&h
.recursion_available
, "recursion_available", "") &&
697 f(&h
.rcode
, "rcode", "")
702 question
[]dnsQuestion
708 func (dns
*dnsMsg
) Pack() (msg
[]byte, ok
bool) {
711 // Convert convenient dnsMsg into wire-like dnsHeader.
713 dh
.Bits
= uint16(dns
.opcode
)<<11 |
uint16(dns
.rcode
)
714 if dns
.recursion_available
{
717 if dns
.recursion_desired
{
723 if dns
.authoritative
{
730 // Prepare variable sized arrays.
731 question
:= dns
.question
736 dh
.Qdcount
= uint16(len(question
))
737 dh
.Ancount
= uint16(len(answer
))
738 dh
.Nscount
= uint16(len(ns
))
739 dh
.Arcount
= uint16(len(extra
))
741 // Could work harder to calculate message size,
742 // but this is far more than we need and not
743 // big enough to hurt the allocator.
744 msg
= make([]byte, 2000)
746 // Pack it in: header and then the pieces.
748 off
, ok
= packStruct(&dh
, msg
, off
)
752 for i
:= 0; i
< len(question
); i
++ {
753 off
, ok
= packStruct(&question
[i
], msg
, off
)
758 for i
:= 0; i
< len(answer
); i
++ {
759 off
, ok
= packRR(answer
[i
], msg
, off
)
764 for i
:= 0; i
< len(ns
); i
++ {
765 off
, ok
= packRR(ns
[i
], msg
, off
)
770 for i
:= 0; i
< len(extra
); i
++ {
771 off
, ok
= packRR(extra
[i
], msg
, off
)
776 return msg
[0:off
], true
779 func (dns
*dnsMsg
) Unpack(msg
[]byte) bool {
784 if off
, ok
= unpackStruct(&dh
, msg
, off
); !ok
{
788 dns
.response
= (dh
.Bits
& _QR
) != 0
789 dns
.opcode
= int(dh
.Bits
>>11) & 0xF
790 dns
.authoritative
= (dh
.Bits
& _AA
) != 0
791 dns
.truncated
= (dh
.Bits
& _TC
) != 0
792 dns
.recursion_desired
= (dh
.Bits
& _RD
) != 0
793 dns
.recursion_available
= (dh
.Bits
& _RA
) != 0
794 dns
.rcode
= int(dh
.Bits
& 0xF)
797 dns
.question
= make([]dnsQuestion
, dh
.Qdcount
)
798 dns
.answer
= make([]dnsRR
, 0, dh
.Ancount
)
799 dns
.ns
= make([]dnsRR
, 0, dh
.Nscount
)
800 dns
.extra
= make([]dnsRR
, 0, dh
.Arcount
)
804 for i
:= 0; i
< len(dns
.question
); i
++ {
805 off
, ok
= unpackStruct(&dns
.question
[i
], msg
, off
)
810 for i
:= 0; i
< int(dh
.Ancount
); i
++ {
811 rec
, off
, ok
= unpackRR(msg
, off
)
815 dns
.answer
= append(dns
.answer
, rec
)
817 for i
:= 0; i
< int(dh
.Nscount
); i
++ {
818 rec
, off
, ok
= unpackRR(msg
, off
)
822 dns
.ns
= append(dns
.ns
, rec
)
824 for i
:= 0; i
< int(dh
.Arcount
); i
++ {
825 rec
, off
, ok
= unpackRR(msg
, off
)
829 dns
.extra
= append(dns
.extra
, rec
)
831 // if off != len(msg) {
832 // println("extra bytes in dns packet", off, "<", len(msg));
837 func (dns
*dnsMsg
) String() string {
838 s
:= "DNS: " + printStruct(&dns
.dnsMsgHdr
) + "\n"
839 if len(dns
.question
) > 0 {
840 s
+= "-- Questions\n"
841 for i
:= 0; i
< len(dns
.question
); i
++ {
842 s
+= printStruct(&dns
.question
[i
]) + "\n"
845 if len(dns
.answer
) > 0 {
847 for i
:= 0; i
< len(dns
.answer
); i
++ {
848 s
+= printStruct(dns
.answer
[i
]) + "\n"
852 s
+= "-- Name servers\n"
853 for i
:= 0; i
< len(dns
.ns
); i
++ {
854 s
+= printStruct(dns
.ns
[i
]) + "\n"
857 if len(dns
.extra
) > 0 {
859 for i
:= 0; i
< len(dns
.extra
); i
++ {
860 s
+= printStruct(dns
.extra
[i
]) + "\n"
866 // IsResponseTo reports whether m is an acceptable response to query.
867 func (m
*dnsMsg
) IsResponseTo(query
*dnsMsg
) bool {
871 if m
.id
!= query
.id
{
874 if len(m
.question
) != len(query
.question
) {
877 for i
, q
:= range m
.question
{
878 q2
:= query
.question
[i
]
879 if !equalASCIILabel(q
.Name
, q2
.Name
) || q
.Qtype
!= q2
.Qtype || q
.Qclass
!= q2
.Qclass
{