1// Copyright 2014 Google, Inc. All rights reserved. 2// 3// Use of this source code is governed by a BSD-style license 4// that can be found in the LICENSE file in the root of the source 5// tree. 6 7package layers 8 9import ( 10 "encoding/binary" 11 "errors" 12 "fmt" 13 "net" 14 15 "github.com/google/gopacket" 16) 17 18// DNSClass defines the class associated with a request/response. Different DNS 19// classes can be thought of as an array of parallel namespace trees. 20type DNSClass uint16 21 22// DNSClass known values. 23const ( 24 DNSClassIN DNSClass = 1 // Internet 25 DNSClassCS DNSClass = 2 // the CSNET class (Obsolete) 26 DNSClassCH DNSClass = 3 // the CHAOS class 27 DNSClassHS DNSClass = 4 // Hesiod [Dyer 87] 28 DNSClassAny DNSClass = 255 // AnyClass 29) 30 31func (dc DNSClass) String() string { 32 switch dc { 33 default: 34 return "Unknown" 35 case DNSClassIN: 36 return "IN" 37 case DNSClassCS: 38 return "CS" 39 case DNSClassCH: 40 return "CH" 41 case DNSClassHS: 42 return "HS" 43 case DNSClassAny: 44 return "Any" 45 } 46} 47 48// DNSType defines the type of data being requested/returned in a 49// question/answer. 50type DNSType uint16 51 52// DNSType known values. 53const ( 54 DNSTypeA DNSType = 1 // a host address 55 DNSTypeNS DNSType = 2 // an authoritative name server 56 DNSTypeMD DNSType = 3 // a mail destination (Obsolete - use MX) 57 DNSTypeMF DNSType = 4 // a mail forwarder (Obsolete - use MX) 58 DNSTypeCNAME DNSType = 5 // the canonical name for an alias 59 DNSTypeSOA DNSType = 6 // marks the start of a zone of authority 60 DNSTypeMB DNSType = 7 // a mailbox domain name (EXPERIMENTAL) 61 DNSTypeMG DNSType = 8 // a mail group member (EXPERIMENTAL) 62 DNSTypeMR DNSType = 9 // a mail rename domain name (EXPERIMENTAL) 63 DNSTypeNULL DNSType = 10 // a null RR (EXPERIMENTAL) 64 DNSTypeWKS DNSType = 11 // a well known service description 65 DNSTypePTR DNSType = 12 // a domain name pointer 66 DNSTypeHINFO DNSType = 13 // host information 67 DNSTypeMINFO DNSType = 14 // mailbox or mail list information 68 DNSTypeMX DNSType = 15 // mail exchange 69 DNSTypeTXT DNSType = 16 // text strings 70 DNSTypeAAAA DNSType = 28 // a IPv6 host address [RFC3596] 71 DNSTypeSRV DNSType = 33 // server discovery [RFC2782] [RFC6195] 72) 73 74func (dt DNSType) String() string { 75 switch dt { 76 default: 77 return "Unknown" 78 case DNSTypeA: 79 return "A" 80 case DNSTypeNS: 81 return "NS" 82 case DNSTypeMD: 83 return "MD" 84 case DNSTypeMF: 85 return "MF" 86 case DNSTypeCNAME: 87 return "CNAME" 88 case DNSTypeSOA: 89 return "SOA" 90 case DNSTypeMB: 91 return "MB" 92 case DNSTypeMG: 93 return "MG" 94 case DNSTypeMR: 95 return "MR" 96 case DNSTypeNULL: 97 return "NULL" 98 case DNSTypeWKS: 99 return "WKS" 100 case DNSTypePTR: 101 return "PTR" 102 case DNSTypeHINFO: 103 return "HINFO" 104 case DNSTypeMINFO: 105 return "MINFO" 106 case DNSTypeMX: 107 return "MX" 108 case DNSTypeTXT: 109 return "TXT" 110 case DNSTypeAAAA: 111 return "AAAA" 112 case DNSTypeSRV: 113 return "SRV" 114 } 115} 116 117// DNSResponseCode provides response codes for question answers. 118type DNSResponseCode uint8 119 120// DNSResponseCode known values. 121const ( 122 DNSResponseCodeNoErr DNSResponseCode = 0 // No error 123 DNSResponseCodeFormErr DNSResponseCode = 1 // Format Error [RFC1035] 124 DNSResponseCodeServFail DNSResponseCode = 2 // Server Failure [RFC1035] 125 DNSResponseCodeNXDomain DNSResponseCode = 3 // Non-Existent Domain [RFC1035] 126 DNSResponseCodeNotImp DNSResponseCode = 4 // Not Implemented [RFC1035] 127 DNSResponseCodeRefused DNSResponseCode = 5 // Query Refused [RFC1035] 128 DNSResponseCodeYXDomain DNSResponseCode = 6 // Name Exists when it should not [RFC2136] 129 DNSResponseCodeYXRRSet DNSResponseCode = 7 // RR Set Exists when it should not [RFC2136] 130 DNSResponseCodeNXRRSet DNSResponseCode = 8 // RR Set that should exist does not [RFC2136] 131 DNSResponseCodeNotAuth DNSResponseCode = 9 // Server Not Authoritative for zone [RFC2136] 132 DNSResponseCodeNotZone DNSResponseCode = 10 // Name not contained in zone [RFC2136] 133 DNSResponseCodeBadVers DNSResponseCode = 16 // Bad OPT Version [RFC2671] 134 DNSResponseCodeBadSig DNSResponseCode = 16 // TSIG Signature Failure [RFC2845] 135 DNSResponseCodeBadKey DNSResponseCode = 17 // Key not recognized [RFC2845] 136 DNSResponseCodeBadTime DNSResponseCode = 18 // Signature out of time window [RFC2845] 137 DNSResponseCodeBadMode DNSResponseCode = 19 // Bad TKEY Mode [RFC2930] 138 DNSResponseCodeBadName DNSResponseCode = 20 // Duplicate key name [RFC2930] 139 DNSResponseCodeBadAlg DNSResponseCode = 21 // Algorithm not supported [RFC2930] 140 DNSResponseCodeBadTruc DNSResponseCode = 22 // Bad Truncation [RFC4635] 141) 142 143func (drc DNSResponseCode) String() string { 144 switch drc { 145 default: 146 return "Unknown" 147 case DNSResponseCodeNoErr: 148 return "No Error" 149 case DNSResponseCodeFormErr: 150 return "Format Error" 151 case DNSResponseCodeServFail: 152 return "Server Failure " 153 case DNSResponseCodeNXDomain: 154 return "Non-Existent Domain" 155 case DNSResponseCodeNotImp: 156 return "Not Implemented" 157 case DNSResponseCodeRefused: 158 return "Query Refused" 159 case DNSResponseCodeYXDomain: 160 return "Name Exists when it should not" 161 case DNSResponseCodeYXRRSet: 162 return "RR Set Exists when it should not" 163 case DNSResponseCodeNXRRSet: 164 return "RR Set that should exist does not" 165 case DNSResponseCodeNotAuth: 166 return "Server Not Authoritative for zone" 167 case DNSResponseCodeNotZone: 168 return "Name not contained in zone" 169 case DNSResponseCodeBadVers: 170 return "Bad OPT Version" 171 case DNSResponseCodeBadKey: 172 return "Key not recognized" 173 case DNSResponseCodeBadTime: 174 return "Signature out of time window" 175 case DNSResponseCodeBadMode: 176 return "Bad TKEY Mode" 177 case DNSResponseCodeBadName: 178 return "Duplicate key name" 179 case DNSResponseCodeBadAlg: 180 return "Algorithm not supported" 181 case DNSResponseCodeBadTruc: 182 return "Bad Truncation" 183 } 184} 185 186// DNSOpCode defines a set of different operation types. 187type DNSOpCode uint8 188 189// DNSOpCode known values. 190const ( 191 DNSOpCodeQuery DNSOpCode = 0 // Query [RFC1035] 192 DNSOpCodeIQuery DNSOpCode = 1 // Inverse Query Obsolete [RFC3425] 193 DNSOpCodeStatus DNSOpCode = 2 // Status [RFC1035] 194 DNSOpCodeNotify DNSOpCode = 4 // Notify [RFC1996] 195 DNSOpCodeUpdate DNSOpCode = 5 // Update [RFC2136] 196) 197 198func (doc DNSOpCode) String() string { 199 switch doc { 200 default: 201 return "Unknown" 202 case DNSOpCodeQuery: 203 return "Query" 204 case DNSOpCodeIQuery: 205 return "Inverse Query" 206 case DNSOpCodeStatus: 207 return "Status" 208 case DNSOpCodeNotify: 209 return "Notify" 210 case DNSOpCodeUpdate: 211 return "Update" 212 } 213} 214 215// DNS is specified in RFC 1034 / RFC 1035 216// +---------------------+ 217// | Header | 218// +---------------------+ 219// | Question | the question for the name server 220// +---------------------+ 221// | Answer | RRs answering the question 222// +---------------------+ 223// | Authority | RRs pointing toward an authority 224// +---------------------+ 225// | Additional | RRs holding additional information 226// +---------------------+ 227// 228// DNS Header 229// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 230// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 231// | ID | 232// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 233// |QR| Opcode |AA|TC|RD|RA| Z | RCODE | 234// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 235// | QDCOUNT | 236// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 237// | ANCOUNT | 238// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 239// | NSCOUNT | 240// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 241// | ARCOUNT | 242// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 243 244// DNS contains data from a single Domain Name Service packet. 245type DNS struct { 246 BaseLayer 247 248 // Header fields 249 ID uint16 250 QR bool 251 OpCode DNSOpCode 252 253 AA bool // Authoritative answer 254 TC bool // Truncated 255 RD bool // Recursion desired 256 RA bool // Recursion available 257 Z uint8 // Reserved for future use 258 259 ResponseCode DNSResponseCode 260 QDCount uint16 // Number of questions to expect 261 ANCount uint16 // Number of answers to expect 262 NSCount uint16 // Number of authorities to expect 263 ARCount uint16 // Number of additional records to expect 264 265 // Entries 266 Questions []DNSQuestion 267 Answers []DNSResourceRecord 268 Authorities []DNSResourceRecord 269 Additionals []DNSResourceRecord 270 271 // buffer for doing name decoding. We use a single reusable buffer to avoid 272 // name decoding on a single object via multiple DecodeFromBytes calls 273 // requiring constant allocation of small byte slices. 274 buffer []byte 275} 276 277// LayerType returns gopacket.LayerTypeDNS. 278func (d *DNS) LayerType() gopacket.LayerType { return LayerTypeDNS } 279 280// decodeDNS decodes the byte slice into a DNS type. It also 281// setups the application Layer in PacketBuilder. 282func decodeDNS(data []byte, p gopacket.PacketBuilder) error { 283 d := &DNS{} 284 err := d.DecodeFromBytes(data, p) 285 if err != nil { 286 return err 287 } 288 p.AddLayer(d) 289 p.SetApplicationLayer(d) 290 return nil 291} 292 293// DecodeFromBytes decodes the slice into the DNS struct. 294func (d *DNS) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error { 295 d.buffer = d.buffer[:0] 296 297 if len(data) < 12 { 298 df.SetTruncated() 299 return errDNSPacketTooShort 300 } 301 302 // since there are no further layers, the baselayer's content is 303 // pointing to this layer 304 d.BaseLayer = BaseLayer{Contents: data[:len(data)]} 305 d.ID = binary.BigEndian.Uint16(data[:2]) 306 d.QR = data[2]&0x80 != 0 307 d.OpCode = DNSOpCode(data[2]>>3) & 0x0F 308 d.AA = data[2]&0x04 != 0 309 d.TC = data[2]&0x02 != 0 310 d.RD = data[2]&0x01 != 0 311 d.RA = data[3]&0x80 != 0 312 d.Z = uint8(data[3]>>4) & 0x7 313 d.ResponseCode = DNSResponseCode(data[3] & 0xF) 314 d.QDCount = binary.BigEndian.Uint16(data[4:6]) 315 d.ANCount = binary.BigEndian.Uint16(data[6:8]) 316 d.NSCount = binary.BigEndian.Uint16(data[8:10]) 317 d.ARCount = binary.BigEndian.Uint16(data[10:12]) 318 319 d.Questions = d.Questions[:0] 320 d.Answers = d.Answers[:0] 321 d.Authorities = d.Authorities[:0] 322 d.Additionals = d.Additionals[:0] 323 324 offset := 12 325 var err error 326 for i := 0; i < int(d.QDCount); i++ { 327 var q DNSQuestion 328 if offset, err = q.decode(data, offset, df, &d.buffer); err != nil { 329 return err 330 } 331 d.Questions = append(d.Questions, q) 332 } 333 334 // For some horrible reason, if we do the obvious thing in this loop: 335 // var r DNSResourceRecord 336 // if blah := r.decode(blah); err != nil { 337 // return err 338 // } 339 // d.Foo = append(d.Foo, r) 340 // the Go compiler thinks that 'r' escapes to the heap, causing a malloc for 341 // every Answer, Authority, and Additional. To get around this, we do 342 // something really silly: we append an empty resource record to our slice, 343 // then use the last value in the slice to call decode. Since the value is 344 // already in the slice, there's no WAY it can escape... on the other hand our 345 // code is MUCH uglier :( 346 for i := 0; i < int(d.ANCount); i++ { 347 d.Answers = append(d.Answers, DNSResourceRecord{}) 348 if offset, err = d.Answers[i].decode(data, offset, df, &d.buffer); err != nil { 349 d.Answers = d.Answers[:i] // strip off erroneous value 350 return err 351 } 352 } 353 for i := 0; i < int(d.NSCount); i++ { 354 d.Authorities = append(d.Authorities, DNSResourceRecord{}) 355 if offset, err = d.Authorities[i].decode(data, offset, df, &d.buffer); err != nil { 356 d.Authorities = d.Authorities[:i] // strip off erroneous value 357 return err 358 } 359 } 360 for i := 0; i < int(d.ARCount); i++ { 361 d.Additionals = append(d.Additionals, DNSResourceRecord{}) 362 if offset, err = d.Additionals[i].decode(data, offset, df, &d.buffer); err != nil { 363 d.Additionals = d.Additionals[:i] // strip off erroneous value 364 return err 365 } 366 } 367 368 if uint16(len(d.Questions)) != d.QDCount { 369 return errDecodeQueryBadQDCount 370 } else if uint16(len(d.Answers)) != d.ANCount { 371 return errDecodeQueryBadANCount 372 } else if uint16(len(d.Authorities)) != d.NSCount { 373 return errDecodeQueryBadNSCount 374 } else if uint16(len(d.Additionals)) != d.ARCount { 375 return errDecodeQueryBadARCount 376 } 377 return nil 378} 379 380// CanDecode implements gopacket.DecodingLayer. 381func (d *DNS) CanDecode() gopacket.LayerClass { 382 return LayerTypeDNS 383} 384 385// NextLayerType implements gopacket.DecodingLayer. 386func (d *DNS) NextLayerType() gopacket.LayerType { 387 return gopacket.LayerTypePayload 388} 389 390// Payload returns nil. 391func (d *DNS) Payload() []byte { 392 return nil 393} 394 395func b2i(b bool) int { 396 if b { 397 return 1 398 } 399 return 0 400} 401 402func recSize(rr *DNSResourceRecord) int { 403 switch rr.Type { 404 case DNSTypeA: 405 return 4 406 case DNSTypeAAAA: 407 return 16 408 case DNSTypeNS: 409 return len(rr.NS) + 2 410 case DNSTypeCNAME: 411 return len(rr.CNAME) + 2 412 case DNSTypePTR: 413 return len(rr.PTR) + 2 414 case DNSTypeSOA: 415 return len(rr.SOA.MName) + 2 + len(rr.SOA.RName) + 2 + 20 416 case DNSTypeMX: 417 return 2 + len(rr.MX.Name) + 2 418 case DNSTypeTXT: 419 l := len(rr.TXTs) 420 for _, txt := range rr.TXTs { 421 l += len(txt) 422 } 423 return l 424 case DNSTypeSRV: 425 return 6 + len(rr.SRV.Name) + 2 426 } 427 428 return 0 429} 430 431func computeSize(recs []DNSResourceRecord) int { 432 sz := 0 433 for _, rr := range recs { 434 sz += len(rr.Name) + 12 435 sz += recSize(&rr) 436 } 437 return sz 438} 439 440// SerializeTo writes the serialized form of this layer into the 441// SerializationBuffer, implementing gopacket.SerializableLayer. 442func (d *DNS) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error { 443 dsz := 0 444 for _, q := range d.Questions { 445 dsz += len(q.Name) + 6 446 } 447 dsz += computeSize(d.Answers) 448 dsz += computeSize(d.Authorities) 449 dsz += computeSize(d.Additionals) 450 451 bytes, err := b.PrependBytes(12 + dsz) 452 if err != nil { 453 return err 454 } 455 binary.BigEndian.PutUint16(bytes, d.ID) 456 bytes[2] = byte((b2i(d.QR) << 7) | (int(d.OpCode) << 3) | (b2i(d.AA) << 2) | (b2i(d.TC) << 1) | b2i(d.RD)) 457 bytes[3] = byte((b2i(d.RA) << 7) | (int(d.Z) << 4) | int(d.ResponseCode)) 458 459 if opts.FixLengths { 460 d.QDCount = uint16(len(d.Questions)) 461 d.ANCount = uint16(len(d.Answers)) 462 d.NSCount = uint16(len(d.Authorities)) 463 d.ARCount = uint16(len(d.Additionals)) 464 } 465 binary.BigEndian.PutUint16(bytes[4:], d.QDCount) 466 binary.BigEndian.PutUint16(bytes[6:], d.ANCount) 467 binary.BigEndian.PutUint16(bytes[8:], d.NSCount) 468 binary.BigEndian.PutUint16(bytes[10:], d.ARCount) 469 470 off := 12 471 for _, qd := range d.Questions { 472 n := qd.encode(bytes, off) 473 off += n 474 } 475 476 for i := range d.Answers { 477 // done this way so we can modify DNSResourceRecord to fix 478 // lengths if requested 479 qa := &d.Answers[i] 480 n, err := qa.encode(bytes, off, opts) 481 if err != nil { 482 return err 483 } 484 off += n 485 } 486 487 for i := range d.Authorities { 488 qa := &d.Authorities[i] 489 n, err := qa.encode(bytes, off, opts) 490 if err != nil { 491 return err 492 } 493 off += n 494 } 495 for i := range d.Additionals { 496 qa := &d.Additionals[i] 497 n, err := qa.encode(bytes, off, opts) 498 if err != nil { 499 return err 500 } 501 off += n 502 } 503 504 return nil 505} 506 507const maxRecursionLevel = 255 508 509func decodeName(data []byte, offset int, buffer *[]byte, level int) ([]byte, int, error) { 510 if level > maxRecursionLevel { 511 return nil, 0, errMaxRecursion 512 } else if offset >= len(data) { 513 return nil, 0, errDNSNameOffsetTooHigh 514 } else if offset < 0 { 515 return nil, 0, errDNSNameOffsetNegative 516 } 517 start := len(*buffer) 518 index := offset 519 if data[index] == 0x00 { 520 return nil, index + 1, nil 521 } 522loop: 523 for data[index] != 0x00 { 524 switch data[index] & 0xc0 { 525 default: 526 /* RFC 1035 527 A domain name represented as a sequence of labels, where 528 each label consists of a length octet followed by that 529 number of octets. The domain name terminates with the 530 zero length octet for the null label of the root. Note 531 that this field may be an odd number of octets; no 532 padding is used. 533 */ 534 index2 := index + int(data[index]) + 1 535 if index2-offset > 255 { 536 return nil, 0, errDNSNameTooLong 537 } else if index2 < index+1 || index2 > len(data) { 538 return nil, 0, errDNSNameInvalidIndex 539 } 540 *buffer = append(*buffer, '.') 541 *buffer = append(*buffer, data[index+1:index2]...) 542 index = index2 543 544 case 0xc0: 545 /* RFC 1035 546 The pointer takes the form of a two octet sequence. 547 548 The first two bits are ones. This allows a pointer to 549 be distinguished from a label, since the label must 550 begin with two zero bits because labels are restricted 551 to 63 octets or less. (The 10 and 01 combinations are 552 reserved for future use.) The OFFSET field specifies 553 an offset from the start of the message (i.e., the 554 first octet of the ID field in the domain header). A 555 zero offset specifies the first byte of the ID field, 556 etc. 557 558 The compression scheme allows a domain name in a message to be 559 represented as either: 560 - a sequence of labels ending in a zero octet 561 - a pointer 562 - a sequence of labels ending with a pointer 563 */ 564 if index+2 > len(data) { 565 return nil, 0, errDNSPointerOffsetTooHigh 566 } 567 offsetp := int(binary.BigEndian.Uint16(data[index:index+2]) & 0x3fff) 568 if offsetp > len(data) { 569 return nil, 0, errDNSPointerOffsetTooHigh 570 } 571 // This looks a little tricky, but actually isn't. Because of how 572 // decodeName is written, calling it appends the decoded name to the 573 // current buffer. We already have the start of the buffer, then, so 574 // once this call is done buffer[start:] will contain our full name. 575 _, _, err := decodeName(data, offsetp, buffer, level+1) 576 if err != nil { 577 return nil, 0, err 578 } 579 index++ // pointer is two bytes, so add an extra byte here. 580 break loop 581 /* EDNS, or other DNS option ? */ 582 case 0x40: // RFC 2673 583 return nil, 0, fmt.Errorf("qname '0x40' - RFC 2673 unsupported yet (data=%x index=%d)", 584 data[index], index) 585 586 case 0x80: 587 return nil, 0, fmt.Errorf("qname '0x80' unsupported yet (data=%x index=%d)", 588 data[index], index) 589 } 590 if index >= len(data) { 591 return nil, 0, errDNSIndexOutOfRange 592 } 593 } 594 if len(*buffer) <= start { 595 return nil, 0, errDNSNameHasNoData 596 } 597 return (*buffer)[start+1:], index + 1, nil 598} 599 600// DNSQuestion wraps a single request (question) within a DNS query. 601type DNSQuestion struct { 602 Name []byte 603 Type DNSType 604 Class DNSClass 605} 606 607func (q *DNSQuestion) decode(data []byte, offset int, df gopacket.DecodeFeedback, buffer *[]byte) (int, error) { 608 name, endq, err := decodeName(data, offset, buffer, 1) 609 if err != nil { 610 return 0, err 611 } 612 613 q.Name = name 614 q.Type = DNSType(binary.BigEndian.Uint16(data[endq : endq+2])) 615 q.Class = DNSClass(binary.BigEndian.Uint16(data[endq+2 : endq+4])) 616 617 return endq + 4, nil 618} 619 620func (q *DNSQuestion) encode(data []byte, offset int) int { 621 noff := encodeName(q.Name, data, offset) 622 binary.BigEndian.PutUint16(data[noff:], uint16(q.Type)) 623 binary.BigEndian.PutUint16(data[noff+2:], uint16(q.Class)) 624 return len(q.Name) + 6 625} 626 627// DNSResourceRecord 628// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 629// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 630// | | 631// / / 632// / NAME / 633// | | 634// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 635// | TYPE | 636// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 637// | CLASS | 638// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 639// | TTL | 640// | | 641// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 642// | RDLENGTH | 643// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--| 644// / RDATA / 645// / / 646// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 647 648// DNSResourceRecord wraps the data from a single DNS resource within a 649// response. 650type DNSResourceRecord struct { 651 // Header 652 Name []byte 653 Type DNSType 654 Class DNSClass 655 TTL uint32 656 657 // RDATA Raw Values 658 DataLength uint16 659 Data []byte 660 661 // RDATA Decoded Values 662 IP net.IP 663 NS, CNAME, PTR []byte 664 TXTs [][]byte 665 SOA DNSSOA 666 SRV DNSSRV 667 MX DNSMX 668 669 // Undecoded TXT for backward compatibility 670 TXT []byte 671} 672 673// decode decodes the resource record, returning the total length of the record. 674func (rr *DNSResourceRecord) decode(data []byte, offset int, df gopacket.DecodeFeedback, buffer *[]byte) (int, error) { 675 name, endq, err := decodeName(data, offset, buffer, 1) 676 if err != nil { 677 return 0, err 678 } 679 680 rr.Name = name 681 rr.Type = DNSType(binary.BigEndian.Uint16(data[endq : endq+2])) 682 rr.Class = DNSClass(binary.BigEndian.Uint16(data[endq+2 : endq+4])) 683 rr.TTL = binary.BigEndian.Uint32(data[endq+4 : endq+8]) 684 rr.DataLength = binary.BigEndian.Uint16(data[endq+8 : endq+10]) 685 end := endq + 10 + int(rr.DataLength) 686 if end > len(data) { 687 return 0, errDecodeRecordLength 688 } 689 rr.Data = data[endq+10 : end] 690 691 if err = rr.decodeRData(data, endq+10, buffer); err != nil { 692 return 0, err 693 } 694 695 return endq + 10 + int(rr.DataLength), nil 696} 697 698func encodeName(name []byte, data []byte, offset int) int { 699 l := 0 700 for i := range name { 701 if name[i] == '.' { 702 data[offset+i-l] = byte(l) 703 l = 0 704 } else { 705 // skip one to write the length 706 data[offset+i+1] = name[i] 707 l++ 708 } 709 } 710 // length for final portion 711 data[offset+len(name)-l] = byte(l) 712 data[offset+len(name)+1] = 0x00 // terminal 713 return offset + len(name) + 2 714} 715 716func (rr *DNSResourceRecord) encode(data []byte, offset int, opts gopacket.SerializeOptions) (int, error) { 717 718 noff := encodeName(rr.Name, data, offset) 719 720 binary.BigEndian.PutUint16(data[noff:], uint16(rr.Type)) 721 binary.BigEndian.PutUint16(data[noff+2:], uint16(rr.Class)) 722 binary.BigEndian.PutUint32(data[noff+4:], uint32(rr.TTL)) 723 724 switch rr.Type { 725 case DNSTypeA: 726 copy(data[noff+10:], rr.IP.To4()) 727 case DNSTypeAAAA: 728 copy(data[noff+10:], rr.IP) 729 case DNSTypeNS: 730 encodeName(rr.NS, data, noff+10) 731 case DNSTypeCNAME: 732 encodeName(rr.CNAME, data, noff+10) 733 case DNSTypePTR: 734 encodeName(rr.PTR, data, noff+10) 735 case DNSTypeSOA: 736 noff2 := encodeName(rr.SOA.MName, data, noff+10) 737 noff2 = encodeName(rr.SOA.RName, data, noff2) 738 binary.BigEndian.PutUint32(data[noff2:], rr.SOA.Serial) 739 binary.BigEndian.PutUint32(data[noff2+4:], rr.SOA.Refresh) 740 binary.BigEndian.PutUint32(data[noff2+8:], rr.SOA.Retry) 741 binary.BigEndian.PutUint32(data[noff2+12:], rr.SOA.Expire) 742 binary.BigEndian.PutUint32(data[noff2+16:], rr.SOA.Minimum) 743 case DNSTypeMX: 744 binary.BigEndian.PutUint16(data[noff+10:], rr.MX.Preference) 745 encodeName(rr.MX.Name, data, noff+12) 746 case DNSTypeTXT: 747 noff2 := noff + 10 748 for _, txt := range rr.TXTs { 749 data[noff2] = byte(len(txt)) 750 copy(data[noff2+1:], txt) 751 noff2 += 1 + len(txt) 752 } 753 case DNSTypeSRV: 754 binary.BigEndian.PutUint16(data[noff+10:], rr.SRV.Priority) 755 binary.BigEndian.PutUint16(data[noff+12:], rr.SRV.Weight) 756 binary.BigEndian.PutUint16(data[noff+14:], rr.SRV.Port) 757 encodeName(rr.SRV.Name, data, noff+16) 758 default: 759 return 0, fmt.Errorf("serializing resource record of type %v not supported", rr.Type) 760 } 761 762 // DataLength 763 dSz := recSize(rr) 764 binary.BigEndian.PutUint16(data[noff+8:], uint16(dSz)) 765 766 if opts.FixLengths { 767 rr.DataLength = uint16(dSz) 768 } 769 770 return len(rr.Name) + 1 + 11 + dSz, nil 771} 772 773func (rr *DNSResourceRecord) String() string { 774 775 if rr.Class == DNSClassIN { 776 switch rr.Type { 777 case DNSTypeA, DNSTypeAAAA: 778 return rr.IP.String() 779 case DNSTypeNS: 780 return "NS " + string(rr.NS) 781 case DNSTypeCNAME: 782 return "CNAME " + string(rr.CNAME) 783 case DNSTypePTR: 784 return "PTR " + string(rr.PTR) 785 case DNSTypeTXT: 786 return "TXT " + string(rr.TXT) 787 } 788 } 789 790 return fmt.Sprintf("<%v, %v>", rr.Class, rr.Type) 791} 792 793func decodeCharacterStrings(data []byte) ([][]byte, error) { 794 strings := make([][]byte, 0, 1) 795 end := len(data) 796 for index, index2 := 0, 0; index != end; index = index2 { 797 index2 = index + 1 + int(data[index]) // index increases by 1..256 and does not overflow 798 if index2 > end { 799 return nil, errCharStringMissData 800 } 801 strings = append(strings, data[index+1:index2]) 802 } 803 return strings, nil 804} 805 806func (rr *DNSResourceRecord) decodeRData(data []byte, offset int, buffer *[]byte) error { 807 switch rr.Type { 808 case DNSTypeA: 809 rr.IP = rr.Data 810 case DNSTypeAAAA: 811 rr.IP = rr.Data 812 case DNSTypeTXT, DNSTypeHINFO: 813 rr.TXT = rr.Data 814 txts, err := decodeCharacterStrings(rr.Data) 815 if err != nil { 816 return err 817 } 818 rr.TXTs = txts 819 case DNSTypeNS: 820 name, _, err := decodeName(data, offset, buffer, 1) 821 if err != nil { 822 return err 823 } 824 rr.NS = name 825 case DNSTypeCNAME: 826 name, _, err := decodeName(data, offset, buffer, 1) 827 if err != nil { 828 return err 829 } 830 rr.CNAME = name 831 case DNSTypePTR: 832 name, _, err := decodeName(data, offset, buffer, 1) 833 if err != nil { 834 return err 835 } 836 rr.PTR = name 837 case DNSTypeSOA: 838 name, endq, err := decodeName(data, offset, buffer, 1) 839 if err != nil { 840 return err 841 } 842 rr.SOA.MName = name 843 name, endq, err = decodeName(data, endq, buffer, 1) 844 if err != nil { 845 return err 846 } 847 rr.SOA.RName = name 848 rr.SOA.Serial = binary.BigEndian.Uint32(data[endq : endq+4]) 849 rr.SOA.Refresh = binary.BigEndian.Uint32(data[endq+4 : endq+8]) 850 rr.SOA.Retry = binary.BigEndian.Uint32(data[endq+8 : endq+12]) 851 rr.SOA.Expire = binary.BigEndian.Uint32(data[endq+12 : endq+16]) 852 rr.SOA.Minimum = binary.BigEndian.Uint32(data[endq+16 : endq+20]) 853 case DNSTypeMX: 854 rr.MX.Preference = binary.BigEndian.Uint16(data[offset : offset+2]) 855 name, _, err := decodeName(data, offset+2, buffer, 1) 856 if err != nil { 857 return err 858 } 859 rr.MX.Name = name 860 case DNSTypeSRV: 861 rr.SRV.Priority = binary.BigEndian.Uint16(data[offset : offset+2]) 862 rr.SRV.Weight = binary.BigEndian.Uint16(data[offset+2 : offset+4]) 863 rr.SRV.Port = binary.BigEndian.Uint16(data[offset+4 : offset+6]) 864 name, _, err := decodeName(data, offset+6, buffer, 1) 865 if err != nil { 866 return err 867 } 868 rr.SRV.Name = name 869 } 870 return nil 871} 872 873// DNSSOA is a Start of Authority record. Each domain requires a SOA record at 874// the cutover where a domain is delegated from its parent. 875type DNSSOA struct { 876 MName, RName []byte 877 Serial, Refresh, Retry, Expire, Minimum uint32 878} 879 880// DNSSRV is a Service record, defining a location (hostname/port) of a 881// server/service. 882type DNSSRV struct { 883 Priority, Weight, Port uint16 884 Name []byte 885} 886 887// DNSMX is a mail exchange record, defining a mail server for a recipient's 888// domain. 889type DNSMX struct { 890 Preference uint16 891 Name []byte 892} 893 894var ( 895 errMaxRecursion = errors.New("max DNS recursion level hit") 896 897 errDNSNameOffsetTooHigh = errors.New("dns name offset too high") 898 errDNSNameOffsetNegative = errors.New("dns name offset is negative") 899 errDNSPacketTooShort = errors.New("DNS packet too short") 900 errDNSNameTooLong = errors.New("dns name is too long") 901 errDNSNameInvalidIndex = errors.New("dns name uncomputable: invalid index") 902 errDNSPointerOffsetTooHigh = errors.New("dns offset pointer too high") 903 errDNSIndexOutOfRange = errors.New("dns index walked out of range") 904 errDNSNameHasNoData = errors.New("no dns data found for name") 905 906 errCharStringMissData = errors.New("Insufficient data for a <character-string>") 907 908 errDecodeRecordLength = errors.New("resource record length exceeds data") 909 910 errDecodeQueryBadQDCount = errors.New("Invalid query decoding, not the right number of questions") 911 errDecodeQueryBadANCount = errors.New("Invalid query decoding, not the right number of answers") 912 errDecodeQueryBadNSCount = errors.New("Invalid query decoding, not the right number of authorities") 913 errDecodeQueryBadARCount = errors.New("Invalid query decoding, not the right number of additionals info") 914) 915