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