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 net.Dial.
8
// It doesn't have to be blazing fast.
10
// Rather than write the usual handful of routines to pack and
11
// unpack every message that can appear on the wire, we use
12
// reflection to write a generic pack/unpack for structs and then
13
// use it. Thus, if in the future we need to define new message
14
// structs, no new pack/unpack/printing code needs to be written.
16
// The first half of this file defines the DNS message formats.
17
// The second half implements the conversion to and from wire format.
18
// A few of the structure elements have string tags to aid the
19
// generic pack/unpack routines.
21
// TODO(rsc): There are enough names defined in this file that they're all
22
// prefixed with dns. Perhaps put this in its own package later.
36
// valid dnsRR_Header.Rrtype and dnsQuestion.qtype
56
// valid dnsQuestion.qtype only
62
// valid dnsQuestion.qclass
71
dnsRcodeFormatError = 1
72
dnsRcodeServerFailure = 2
74
dnsRcodeNotImplemented = 4
78
// The wire format for the DNS packet header.
79
type dnsHeader struct {
82
Qdcount, Ancount, Nscount, Arcount uint16
87
_QR = 1 << 15 // query/response (response=1)
88
_AA = 1 << 10 // authoritative
89
_TC = 1 << 9 // truncated
90
_RD = 1 << 8 // recursion desired
91
_RA = 1 << 7 // recursion available
95
type dnsQuestion struct {
96
Name string "domain-name" // "domain-name" specifies encoding; see packers below
101
// DNS responses (resource records).
102
// There are many types of messages,
103
// but they all share the same header.
104
type dnsRR_Header struct {
105
Name string "domain-name"
109
Rdlength uint16 // length of data after header
112
func (h *dnsRR_Header) Header() *dnsRR_Header {
116
type dnsRR interface {
117
Header() *dnsRR_Header
120
// Specific DNS RR formats for each query type.
122
type dnsRR_CNAME struct {
124
Cname string "domain-name"
127
func (rr *dnsRR_CNAME) Header() *dnsRR_Header {
131
type dnsRR_HINFO struct {
137
func (rr *dnsRR_HINFO) Header() *dnsRR_Header {
141
type dnsRR_MB struct {
143
Mb string "domain-name"
146
func (rr *dnsRR_MB) Header() *dnsRR_Header {
150
type dnsRR_MG struct {
152
Mg string "domain-name"
155
func (rr *dnsRR_MG) Header() *dnsRR_Header {
159
type dnsRR_MINFO struct {
161
Rmail string "domain-name"
162
Email string "domain-name"
165
func (rr *dnsRR_MINFO) Header() *dnsRR_Header {
169
type dnsRR_MR struct {
171
Mr string "domain-name"
174
func (rr *dnsRR_MR) Header() *dnsRR_Header {
178
type dnsRR_MX struct {
181
Mx string "domain-name"
184
func (rr *dnsRR_MX) Header() *dnsRR_Header {
188
type dnsRR_NS struct {
190
Ns string "domain-name"
193
func (rr *dnsRR_NS) Header() *dnsRR_Header {
197
type dnsRR_PTR struct {
199
Ptr string "domain-name"
202
func (rr *dnsRR_PTR) Header() *dnsRR_Header {
206
type dnsRR_SOA struct {
208
Ns string "domain-name"
209
Mbox string "domain-name"
217
func (rr *dnsRR_SOA) Header() *dnsRR_Header {
221
type dnsRR_TXT struct {
223
Txt string // not domain name
226
func (rr *dnsRR_TXT) Header() *dnsRR_Header {
230
type dnsRR_SRV struct {
235
Target string "domain-name"
238
func (rr *dnsRR_SRV) Header() *dnsRR_Header {
242
type dnsRR_A struct {
247
func (rr *dnsRR_A) Header() *dnsRR_Header {
251
type dnsRR_AAAA struct {
256
func (rr *dnsRR_AAAA) Header() *dnsRR_Header {
260
// Packing and unpacking.
262
// All the packers and unpackers take a (msg []byte, off int)
263
// and return (off1 int, ok bool). If they return ok==false, they
264
// also return off1==len(msg), so that the next unpacker will
265
// also fail. This lets us avoid checks of ok until the end of a
268
// Map of constructors for each RR wire type.
269
var rr_mk = map[int]func() dnsRR{
270
dnsTypeCNAME: func() dnsRR { return new(dnsRR_CNAME) },
271
dnsTypeHINFO: func() dnsRR { return new(dnsRR_HINFO) },
272
dnsTypeMB: func() dnsRR { return new(dnsRR_MB) },
273
dnsTypeMG: func() dnsRR { return new(dnsRR_MG) },
274
dnsTypeMINFO: func() dnsRR { return new(dnsRR_MINFO) },
275
dnsTypeMR: func() dnsRR { return new(dnsRR_MR) },
276
dnsTypeMX: func() dnsRR { return new(dnsRR_MX) },
277
dnsTypeNS: func() dnsRR { return new(dnsRR_NS) },
278
dnsTypePTR: func() dnsRR { return new(dnsRR_PTR) },
279
dnsTypeSOA: func() dnsRR { return new(dnsRR_SOA) },
280
dnsTypeTXT: func() dnsRR { return new(dnsRR_TXT) },
281
dnsTypeSRV: func() dnsRR { return new(dnsRR_SRV) },
282
dnsTypeA: func() dnsRR { return new(dnsRR_A) },
283
dnsTypeAAAA: func() dnsRR { return new(dnsRR_AAAA) },
286
// Pack a domain name s into msg[off:].
287
// Domain names are a sequence of counted strings
288
// split at the dots. They end with a zero-length string.
289
func packDomainName(s string, msg []byte, off int) (off1 int, ok bool) {
290
// Add trailing dot to canonicalize name.
291
if n := len(s); n == 0 || s[n-1] != '.' {
295
// Each dot ends a segment of the name.
296
// We trade each dot byte for a length byte.
297
// There is also a trailing zero.
298
// Check that we have all the space we need.
300
if off+tot > len(msg) {
301
return len(msg), false
304
// Emit sequence of counted strings, chopping at dots.
306
for i := 0; i < len(s); i++ {
308
if i-begin >= 1<<6 { // top two bits of length must be clear
309
return len(msg), false
311
msg[off] = byte(i - begin)
313
for j := begin; j < i; j++ {
325
// Unpack a domain name.
326
// In addition to the simple sequences of counted strings above,
327
// domain names are allowed to refer to strings elsewhere in the
328
// packet, to avoid repeating common suffixes when returning
329
// many entries in a single domain. The pointers are marked
330
// by a length byte with the top two bits set. Ignoring those
331
// two bits, that byte and the next give a 14 bit offset from msg[0]
332
// where we should pick up the trail.
333
// Note that if we jump elsewhere in the packet,
334
// we return off1 == the offset after the first pointer we found,
335
// which is where the next record will start.
336
// In theory, the pointers are only allowed to jump backward.
337
// We let them jump anywhere and stop jumping after a while.
338
func unpackDomainName(msg []byte, off int) (s string, off1 int, ok bool) {
340
ptr := 0 // number of pointers followed
344
return "", len(msg), false
355
if off+c > len(msg) {
356
return "", len(msg), false
358
s += string(msg[off:off+c]) + "."
361
// pointer to somewhere else in msg.
362
// remember location after first ptr,
363
// since that's how many bytes we consumed.
364
// also, don't follow too many pointers --
365
// maybe there's a loop.
367
return "", len(msg), false
375
return "", len(msg), false
377
off = (c^0xC0)<<8 | int(c1)
379
// 0x80 and 0x40 are reserved
380
return "", len(msg), false
389
// TODO(rsc): Move into generic library?
390
// Pack a reflect.StructValue into msg. Struct members can only be uint16, uint32, string,
391
// [n]byte, and other (often anonymous) structs.
392
func packStructValue(val *reflect.StructValue, msg []byte, off int) (off1 int, ok bool) {
393
for i := 0; i < val.NumField(); i++ {
394
f := val.Type().(*reflect.StructType).Field(i)
395
switch fv := val.Field(i).(type) {
398
fmt.Fprintf(os.Stderr, "net: dns: unknown packing type %v", f.Type)
399
return len(msg), false
400
case *reflect.StructValue:
401
off, ok = packStructValue(fv, msg, off)
402
case *reflect.UintValue:
404
switch fv.Type().Kind() {
408
if off+2 > len(msg) {
409
return len(msg), false
411
msg[off] = byte(i >> 8)
415
if off+4 > len(msg) {
416
return len(msg), false
418
msg[off] = byte(i >> 24)
419
msg[off+1] = byte(i >> 16)
420
msg[off+2] = byte(i >> 8)
424
case *reflect.ArrayValue:
425
if fv.Type().(*reflect.ArrayType).Elem().Kind() != reflect.Uint8 {
429
if off+n > len(msg) {
430
return len(msg), false
432
reflect.Copy(reflect.NewValue(msg[off:off+n]).(*reflect.SliceValue), fv)
434
case *reflect.StringValue:
435
// There are multiple string encodings.
436
// The tag distinguishes ordinary strings from domain names.
440
fmt.Fprintf(os.Stderr, "net: dns: unknown string tag %v", f.Tag)
441
return len(msg), false
443
off, ok = packDomainName(s, msg, off)
445
return len(msg), false
448
// Counted string: 1 byte length.
449
if len(s) > 255 || off+1+len(s) > len(msg) {
450
return len(msg), false
452
msg[off] = byte(len(s))
454
off += copy(msg[off:], s)
461
func structValue(any interface{}) *reflect.StructValue {
462
return reflect.NewValue(any).(*reflect.PtrValue).Elem().(*reflect.StructValue)
465
func packStruct(any interface{}, msg []byte, off int) (off1 int, ok bool) {
466
off, ok = packStructValue(structValue(any), msg, off)
470
// TODO(rsc): Move into generic library?
471
// Unpack a reflect.StructValue from msg.
472
// Same restrictions as packStructValue.
473
func unpackStructValue(val *reflect.StructValue, msg []byte, off int) (off1 int, ok bool) {
474
for i := 0; i < val.NumField(); i++ {
475
f := val.Type().(*reflect.StructType).Field(i)
476
switch fv := val.Field(i).(type) {
479
fmt.Fprintf(os.Stderr, "net: dns: unknown packing type %v", f.Type)
480
return len(msg), false
481
case *reflect.StructValue:
482
off, ok = unpackStructValue(fv, msg, off)
483
case *reflect.UintValue:
484
switch fv.Type().Kind() {
488
if off+2 > len(msg) {
489
return len(msg), false
491
i := uint16(msg[off])<<8 | uint16(msg[off+1])
495
if off+4 > len(msg) {
496
return len(msg), false
498
i := uint32(msg[off])<<24 | uint32(msg[off+1])<<16 | uint32(msg[off+2])<<8 | uint32(msg[off+3])
502
case *reflect.ArrayValue:
503
if fv.Type().(*reflect.ArrayType).Elem().Kind() != reflect.Uint8 {
507
if off+n > len(msg) {
508
return len(msg), false
510
reflect.Copy(fv, reflect.NewValue(msg[off:off+n]).(*reflect.SliceValue))
512
case *reflect.StringValue:
516
fmt.Fprintf(os.Stderr, "net: dns: unknown string tag %v", f.Tag)
517
return len(msg), false
519
s, off, ok = unpackDomainName(msg, off)
521
return len(msg), false
524
if off >= len(msg) || off+1+int(msg[off]) > len(msg) {
525
return len(msg), false
530
for i := 0; i < n; i++ {
542
func unpackStruct(any interface{}, msg []byte, off int) (off1 int, ok bool) {
543
off, ok = unpackStructValue(structValue(any), msg, off)
547
// Generic struct printer.
548
// Doesn't care about the string tag "domain-name",
549
// but does look for an "ipv4" tag on uint32 variables
550
// and the "ipv6" tag on array variables,
551
// printing them as IP addresses.
552
func printStructValue(val *reflect.StructValue) string {
554
for i := 0; i < val.NumField(); i++ {
558
f := val.Type().(*reflect.StructType).Field(i)
563
if fv, ok := fval.(*reflect.StructValue); ok {
564
s += printStructValue(fv)
565
} else if fv, ok := fval.(*reflect.UintValue); ok && f.Tag == "ipv4" {
567
s += IPv4(byte(i>>24), byte(i>>16), byte(i>>8), byte(i)).String()
568
} else if fv, ok := fval.(*reflect.ArrayValue); ok && f.Tag == "ipv6" {
569
i := fv.Interface().([]byte)
572
s += fmt.Sprint(fval.Interface())
579
func printStruct(any interface{}) string { return printStructValue(structValue(any)) }
581
// Resource record packer.
582
func packRR(rr dnsRR, msg []byte, off int) (off2 int, ok bool) {
584
// pack twice, once to find end of header
585
// and again to find end of packet.
586
// a bit inefficient but this doesn't need to be fast.
587
// off1 is end of header
589
off1, ok = packStruct(rr.Header(), msg, off)
590
off2, ok = packStruct(rr, msg, off)
592
return len(msg), false
594
// pack a third time; redo header with correct data length
595
rr.Header().Rdlength = uint16(off2 - off1)
596
packStruct(rr.Header(), msg, off)
600
// Resource record unpacker.
601
func unpackRR(msg []byte, off int) (rr dnsRR, off1 int, ok bool) {
602
// unpack just the header, to find the rr type and length
605
if off, ok = unpackStruct(&h, msg, off); !ok {
606
return nil, len(msg), false
608
end := off + int(h.Rdlength)
610
// make an rr of that type and re-unpack.
611
// again inefficient but doesn't need to be fast.
612
mk, known := rr_mk[int(h.Rrtype)]
617
off, ok = unpackStruct(rr, msg, off0)
624
// Usable representation of a DNS packet.
626
// A manually-unpacked version of (id, bits).
627
// This is in its own struct for easy printing.
628
type dnsMsgHdr struct {
634
recursion_desired bool
635
recursion_available bool
641
question []dnsQuestion
647
func (dns *dnsMsg) Pack() (msg []byte, ok bool) {
650
// Convert convenient dnsMsg into wire-like dnsHeader.
652
dh.Bits = uint16(dns.opcode)<<11 | uint16(dns.rcode)
653
if dns.recursion_available {
656
if dns.recursion_desired {
662
if dns.authoritative {
669
// Prepare variable sized arrays.
670
question := dns.question
675
dh.Qdcount = uint16(len(question))
676
dh.Ancount = uint16(len(answer))
677
dh.Nscount = uint16(len(ns))
678
dh.Arcount = uint16(len(extra))
680
// Could work harder to calculate message size,
681
// but this is far more than we need and not
682
// big enough to hurt the allocator.
683
msg = make([]byte, 2000)
685
// Pack it in: header and then the pieces.
687
off, ok = packStruct(&dh, msg, off)
688
for i := 0; i < len(question); i++ {
689
off, ok = packStruct(&question[i], msg, off)
691
for i := 0; i < len(answer); i++ {
692
off, ok = packRR(answer[i], msg, off)
694
for i := 0; i < len(ns); i++ {
695
off, ok = packRR(ns[i], msg, off)
697
for i := 0; i < len(extra); i++ {
698
off, ok = packRR(extra[i], msg, off)
703
return msg[0:off], true
706
func (dns *dnsMsg) Unpack(msg []byte) bool {
711
if off, ok = unpackStruct(&dh, msg, off); !ok {
715
dns.response = (dh.Bits & _QR) != 0
716
dns.opcode = int(dh.Bits>>11) & 0xF
717
dns.authoritative = (dh.Bits & _AA) != 0
718
dns.truncated = (dh.Bits & _TC) != 0
719
dns.recursion_desired = (dh.Bits & _RD) != 0
720
dns.recursion_available = (dh.Bits & _RA) != 0
721
dns.rcode = int(dh.Bits & 0xF)
724
dns.question = make([]dnsQuestion, dh.Qdcount)
725
dns.answer = make([]dnsRR, dh.Ancount)
726
dns.ns = make([]dnsRR, dh.Nscount)
727
dns.extra = make([]dnsRR, dh.Arcount)
729
for i := 0; i < len(dns.question); i++ {
730
off, ok = unpackStruct(&dns.question[i], msg, off)
732
for i := 0; i < len(dns.answer); i++ {
733
dns.answer[i], off, ok = unpackRR(msg, off)
735
for i := 0; i < len(dns.ns); i++ {
736
dns.ns[i], off, ok = unpackRR(msg, off)
738
for i := 0; i < len(dns.extra); i++ {
739
dns.extra[i], off, ok = unpackRR(msg, off)
744
// if off != len(msg) {
745
// println("extra bytes in dns packet", off, "<", len(msg));
750
func (dns *dnsMsg) String() string {
751
s := "DNS: " + printStruct(&dns.dnsMsgHdr) + "\n"
752
if len(dns.question) > 0 {
753
s += "-- Questions\n"
754
for i := 0; i < len(dns.question); i++ {
755
s += printStruct(&dns.question[i]) + "\n"
758
if len(dns.answer) > 0 {
760
for i := 0; i < len(dns.answer); i++ {
761
s += printStruct(dns.answer[i]) + "\n"
765
s += "-- Name servers\n"
766
for i := 0; i < len(dns.ns); i++ {
767
s += printStruct(dns.ns[i]) + "\n"
770
if len(dns.extra) > 0 {
772
for i := 0; i < len(dns.extra); i++ {
773
s += printStruct(dns.extra[i]) + "\n"