github.com/gopacket/gopacket@v1.1.0/layers/dns.go (about) 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 7 package layers 8 9 import ( 10 "encoding/binary" 11 "errors" 12 "fmt" 13 "net" 14 "strings" 15 16 "github.com/gopacket/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. 21 type DNSClass uint16 22 23 // DNSClass known values. 24 const ( 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 32 func (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. 51 type DNSType uint16 52 53 // DNSType known values. 54 const ( 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 77 func (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. 125 type DNSResponseCode uint8 126 127 // DNSResponseCode known values. 128 const ( 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 151 func (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. 197 type DNSOpCode uint8 198 199 // DNSOpCode known values. 200 const ( 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 208 func (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. 255 type 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. 288 func (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. 292 func 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. 304 func (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. 395 func (d *DNS) CanDecode() gopacket.LayerClass { 396 return LayerTypeDNS 397 } 398 399 // NextLayerType implements gopacket.DecodingLayer. 400 func (d *DNS) NextLayerType() gopacket.LayerType { 401 return gopacket.LayerTypePayload 402 } 403 404 // Payload returns nil. 405 func (d *DNS) Payload() []byte { 406 return nil 407 } 408 409 func b2i(b bool) int { 410 if b { 411 return 1 412 } 413 return 0 414 } 415 416 func 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 453 func 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. 471 func (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 536 const maxRecursionLevel = 255 537 538 func 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 } 551 loop: 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. 630 type DNSQuestion struct { 631 Name []byte 632 Type DNSType 633 Class DNSClass 634 } 635 636 func (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 if len(data) < endq+4 { 643 return 0, errors.New("DNS question too small") 644 } 645 646 q.Name = name 647 q.Type = DNSType(binary.BigEndian.Uint16(data[endq : endq+2])) 648 q.Class = DNSClass(binary.BigEndian.Uint16(data[endq+2 : endq+4])) 649 650 return endq + 4, nil 651 } 652 653 func (q *DNSQuestion) encode(data []byte, offset int) int { 654 noff := encodeName(q.Name, data, offset) 655 nSz := noff - offset 656 binary.BigEndian.PutUint16(data[noff:], uint16(q.Type)) 657 binary.BigEndian.PutUint16(data[noff+2:], uint16(q.Class)) 658 return nSz + 4 659 } 660 661 // DNSResourceRecord 662 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 663 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 664 // | | 665 // / / 666 // / NAME / 667 // | | 668 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 669 // | TYPE | 670 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 671 // | CLASS | 672 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 673 // | TTL | 674 // | | 675 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 676 // | RDLENGTH | 677 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--| 678 // / RDATA / 679 // / / 680 // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 681 682 // DNSResourceRecord wraps the data from a single DNS resource within a 683 // response. 684 type DNSResourceRecord struct { 685 // Header 686 Name []byte 687 Type DNSType 688 Class DNSClass 689 TTL uint32 690 691 // RDATA Raw Values 692 DataLength uint16 693 Data []byte 694 695 // RDATA Decoded Values 696 IP net.IP 697 NS, CNAME, PTR []byte 698 TXTs [][]byte 699 SOA DNSSOA 700 SRV DNSSRV 701 MX DNSMX 702 OPT []DNSOPT // See RFC 6891, section 6.1.2 703 URI DNSURI 704 705 // Undecoded TXT for backward compatibility 706 TXT []byte 707 } 708 709 // decode decodes the resource record, returning the total length of the record. 710 func (rr *DNSResourceRecord) decode(data []byte, offset int, df gopacket.DecodeFeedback, buffer *[]byte) (int, error) { 711 name, endq, err := decodeName(data, offset, buffer, 1) 712 if err != nil { 713 return 0, err 714 } 715 716 if len(data) < endq+10 { 717 return 0, errors.New("DNS record too small") 718 } 719 720 rr.Name = name 721 rr.Type = DNSType(binary.BigEndian.Uint16(data[endq : endq+2])) 722 rr.Class = DNSClass(binary.BigEndian.Uint16(data[endq+2 : endq+4])) 723 rr.TTL = binary.BigEndian.Uint32(data[endq+4 : endq+8]) 724 rr.DataLength = binary.BigEndian.Uint16(data[endq+8 : endq+10]) 725 end := endq + 10 + int(rr.DataLength) 726 if end > len(data) { 727 return 0, errDecodeRecordLength 728 } 729 rr.Data = data[endq+10 : end] 730 731 if rr.DataLength > 0 { 732 if err = rr.decodeRData(data[:end], endq+10, buffer); err != nil { 733 return 0, err 734 } 735 } 736 737 return endq + 10 + int(rr.DataLength), nil 738 } 739 740 func encodeName(name []byte, data []byte, offset int) int { 741 l := 0 742 for i := range name { 743 if name[i] == '.' { 744 data[offset+i-l] = byte(l) 745 l = 0 746 } else { 747 // skip one to write the length 748 data[offset+i+1] = name[i] 749 l++ 750 } 751 } 752 753 if len(name) == 0 { 754 data[offset] = 0x00 // terminal 755 return offset + 1 756 } 757 758 // length for final portion 759 data[offset+len(name)-l] = byte(l) 760 data[offset+len(name)+1] = 0x00 // terminal 761 return offset + len(name) + 2 762 } 763 764 func (rr *DNSResourceRecord) encode(data []byte, offset int, opts gopacket.SerializeOptions) (int, error) { 765 766 noff := encodeName(rr.Name, data, offset) 767 nSz := noff - offset 768 769 binary.BigEndian.PutUint16(data[noff:], uint16(rr.Type)) 770 binary.BigEndian.PutUint16(data[noff+2:], uint16(rr.Class)) 771 binary.BigEndian.PutUint32(data[noff+4:], uint32(rr.TTL)) 772 773 switch rr.Type { 774 case DNSTypeA: 775 copy(data[noff+10:], rr.IP.To4()) 776 case DNSTypeAAAA: 777 copy(data[noff+10:], rr.IP) 778 case DNSTypeNS: 779 encodeName(rr.NS, data, noff+10) 780 case DNSTypeCNAME: 781 encodeName(rr.CNAME, data, noff+10) 782 case DNSTypePTR: 783 encodeName(rr.PTR, data, noff+10) 784 case DNSTypeSOA: 785 noff2 := encodeName(rr.SOA.MName, data, noff+10) 786 noff2 = encodeName(rr.SOA.RName, data, noff2) 787 binary.BigEndian.PutUint32(data[noff2:], rr.SOA.Serial) 788 binary.BigEndian.PutUint32(data[noff2+4:], rr.SOA.Refresh) 789 binary.BigEndian.PutUint32(data[noff2+8:], rr.SOA.Retry) 790 binary.BigEndian.PutUint32(data[noff2+12:], rr.SOA.Expire) 791 binary.BigEndian.PutUint32(data[noff2+16:], rr.SOA.Minimum) 792 case DNSTypeMX: 793 binary.BigEndian.PutUint16(data[noff+10:], rr.MX.Preference) 794 encodeName(rr.MX.Name, data, noff+12) 795 case DNSTypeTXT: 796 noff2 := noff + 10 797 for _, txt := range rr.TXTs { 798 data[noff2] = byte(len(txt)) 799 copy(data[noff2+1:], txt) 800 noff2 += 1 + len(txt) 801 } 802 case DNSTypeSRV: 803 binary.BigEndian.PutUint16(data[noff+10:], rr.SRV.Priority) 804 binary.BigEndian.PutUint16(data[noff+12:], rr.SRV.Weight) 805 binary.BigEndian.PutUint16(data[noff+14:], rr.SRV.Port) 806 encodeName(rr.SRV.Name, data, noff+16) 807 case DNSTypeURI: 808 binary.BigEndian.PutUint16(data[noff+10:], rr.URI.Priority) 809 binary.BigEndian.PutUint16(data[noff+12:], rr.URI.Weight) 810 copy(data[noff+14:], rr.URI.Target) 811 case DNSTypeOPT: 812 noff2 := noff + 10 813 for _, opt := range rr.OPT { 814 binary.BigEndian.PutUint16(data[noff2:], uint16(opt.Code)) 815 binary.BigEndian.PutUint16(data[noff2+2:], uint16(len(opt.Data))) 816 copy(data[noff2+4:], opt.Data) 817 noff2 += 4 + len(opt.Data) 818 } 819 default: 820 return 0, fmt.Errorf("serializing resource record of type %v not supported", rr.Type) 821 } 822 823 // DataLength 824 dSz := recSize(rr) 825 binary.BigEndian.PutUint16(data[noff+8:], uint16(dSz)) 826 827 if opts.FixLengths { 828 rr.DataLength = uint16(dSz) 829 } 830 831 return nSz + 10 + dSz, nil 832 } 833 834 func (rr *DNSResourceRecord) String() string { 835 836 if rr.Type == DNSTypeOPT { 837 opts := make([]string, len(rr.OPT)) 838 for i, opt := range rr.OPT { 839 opts[i] = opt.String() 840 } 841 return "OPT " + strings.Join(opts, ",") 842 } 843 if rr.Type == DNSTypeURI { 844 return fmt.Sprintf("URI %d %d %s", rr.URI.Priority, rr.URI.Weight, string(rr.URI.Target)) 845 } 846 if rr.Class == DNSClassIN { 847 switch rr.Type { 848 case DNSTypeA, DNSTypeAAAA: 849 return rr.IP.String() 850 case DNSTypeNS: 851 return "NS " + string(rr.NS) 852 case DNSTypeCNAME: 853 return "CNAME " + string(rr.CNAME) 854 case DNSTypePTR: 855 return "PTR " + string(rr.PTR) 856 case DNSTypeTXT: 857 return "TXT " + string(rr.TXT) 858 } 859 } 860 861 return fmt.Sprintf("<%v, %v>", rr.Class, rr.Type) 862 } 863 864 func decodeCharacterStrings(data []byte) ([][]byte, error) { 865 strings := make([][]byte, 0, 1) 866 end := len(data) 867 for index, index2 := 0, 0; index != end; index = index2 { 868 index2 = index + 1 + int(data[index]) // index increases by 1..256 and does not overflow 869 if index2 > end { 870 return nil, errCharStringMissData 871 } 872 strings = append(strings, data[index+1:index2]) 873 } 874 return strings, nil 875 } 876 877 func decodeOPTs(data []byte, offset int) ([]DNSOPT, error) { 878 allOPT := []DNSOPT{} 879 end := len(data) 880 881 if offset == end { 882 return allOPT, nil // There is no data to read 883 } 884 885 if offset+4 > end { 886 return allOPT, fmt.Errorf("DNSOPT record is of length %d, it should be at least length 4", end-offset) 887 } 888 889 for i := offset; i < end; { 890 opt := DNSOPT{} 891 if len(data) < i+4 { 892 return allOPT, fmt.Errorf("Malformed DNSOPT record. Length %d < %d", len(data), i+4) 893 } 894 opt.Code = DNSOptionCode(binary.BigEndian.Uint16(data[i : i+2])) 895 l := binary.BigEndian.Uint16(data[i+2 : i+4]) 896 if i+4+int(l) > end { 897 return allOPT, fmt.Errorf("Malformed DNSOPT record. The length (%d) field implies a packet larger than the one received", l) 898 } 899 opt.Data = data[i+4 : i+4+int(l)] 900 allOPT = append(allOPT, opt) 901 i += int(l) + 4 902 } 903 return allOPT, nil 904 } 905 906 func (rr *DNSResourceRecord) decodeRData(data []byte, offset int, buffer *[]byte) error { 907 switch rr.Type { 908 case DNSTypeA: 909 rr.IP = rr.Data 910 case DNSTypeAAAA: 911 rr.IP = rr.Data 912 case DNSTypeTXT, DNSTypeHINFO: 913 rr.TXT = rr.Data 914 txts, err := decodeCharacterStrings(rr.Data) 915 if err != nil { 916 return err 917 } 918 rr.TXTs = txts 919 case DNSTypeNS: 920 name, _, err := decodeName(data, offset, buffer, 1) 921 if err != nil { 922 return err 923 } 924 rr.NS = name 925 case DNSTypeCNAME: 926 name, _, err := decodeName(data, offset, buffer, 1) 927 if err != nil { 928 return err 929 } 930 rr.CNAME = name 931 case DNSTypePTR: 932 name, _, err := decodeName(data, offset, buffer, 1) 933 if err != nil { 934 return err 935 } 936 rr.PTR = name 937 case DNSTypeSOA: 938 name, endq, err := decodeName(data, offset, buffer, 1) 939 if err != nil { 940 return err 941 } 942 rr.SOA.MName = name 943 name, endq, err = decodeName(data, endq, buffer, 1) 944 if err != nil { 945 return err 946 } 947 if len(data) < endq+20 { 948 return errors.New("SOA too small") 949 } 950 rr.SOA.RName = name 951 rr.SOA.Serial = binary.BigEndian.Uint32(data[endq : endq+4]) 952 rr.SOA.Refresh = binary.BigEndian.Uint32(data[endq+4 : endq+8]) 953 rr.SOA.Retry = binary.BigEndian.Uint32(data[endq+8 : endq+12]) 954 rr.SOA.Expire = binary.BigEndian.Uint32(data[endq+12 : endq+16]) 955 rr.SOA.Minimum = binary.BigEndian.Uint32(data[endq+16 : endq+20]) 956 case DNSTypeMX: 957 if len(data) < offset+2 { 958 return errors.New("MX too small") 959 } 960 rr.MX.Preference = binary.BigEndian.Uint16(data[offset : offset+2]) 961 name, _, err := decodeName(data, offset+2, buffer, 1) 962 if err != nil { 963 return err 964 } 965 rr.MX.Name = name 966 case DNSTypeURI: 967 if len(rr.Data) < 4 { 968 return errors.New("URI too small") 969 } 970 rr.URI.Priority = binary.BigEndian.Uint16(data[offset : offset+2]) 971 rr.URI.Weight = binary.BigEndian.Uint16(data[offset+2 : offset+4]) 972 rr.URI.Target = rr.Data[4:] 973 case DNSTypeSRV: 974 if len(data) < offset+6 { 975 return errors.New("SRV too small") 976 } 977 rr.SRV.Priority = binary.BigEndian.Uint16(data[offset : offset+2]) 978 rr.SRV.Weight = binary.BigEndian.Uint16(data[offset+2 : offset+4]) 979 rr.SRV.Port = binary.BigEndian.Uint16(data[offset+4 : offset+6]) 980 name, _, err := decodeName(data, offset+6, buffer, 1) 981 if err != nil { 982 return err 983 } 984 rr.SRV.Name = name 985 case DNSTypeOPT: 986 allOPT, err := decodeOPTs(data, offset) 987 if err != nil { 988 return err 989 } 990 rr.OPT = allOPT 991 } 992 return nil 993 } 994 995 // DNSSOA is a Start of Authority record. Each domain requires a SOA record at 996 // the cutover where a domain is delegated from its parent. 997 type DNSSOA struct { 998 MName, RName []byte 999 Serial, Refresh, Retry, Expire, Minimum uint32 1000 } 1001 1002 // DNSSRV is a Service record, defining a location (hostname/port) of a 1003 // server/service. 1004 type DNSSRV struct { 1005 Priority, Weight, Port uint16 1006 Name []byte 1007 } 1008 1009 // DNSMX is a mail exchange record, defining a mail server for a recipient's 1010 // domain. 1011 type DNSMX struct { 1012 Preference uint16 1013 Name []byte 1014 } 1015 1016 // DNSURI is a URI record, defining a target (URI) of a server/service 1017 type DNSURI struct { 1018 Priority, Weight uint16 1019 Target []byte 1020 } 1021 1022 // DNSOptionCode represents the code of a DNS Option, see RFC6891, section 6.1.2 1023 type DNSOptionCode uint16 1024 1025 func (doc DNSOptionCode) String() string { 1026 switch doc { 1027 default: 1028 return "Unknown" 1029 case DNSOptionCodeNSID: 1030 return "NSID" 1031 case DNSOptionCodeDAU: 1032 return "DAU" 1033 case DNSOptionCodeDHU: 1034 return "DHU" 1035 case DNSOptionCodeN3U: 1036 return "N3U" 1037 case DNSOptionCodeEDNSClientSubnet: 1038 return "EDNSClientSubnet" 1039 case DNSOptionCodeEDNSExpire: 1040 return "EDNSExpire" 1041 case DNSOptionCodeCookie: 1042 return "Cookie" 1043 case DNSOptionCodeEDNSKeepAlive: 1044 return "EDNSKeepAlive" 1045 case DNSOptionCodePadding: 1046 return "CodePadding" 1047 case DNSOptionCodeChain: 1048 return "CodeChain" 1049 case DNSOptionCodeEDNSKeyTag: 1050 return "CodeEDNSKeyTag" 1051 case DNSOptionCodeEDNSClientTag: 1052 return "EDNSClientTag" 1053 case DNSOptionCodeEDNSServerTag: 1054 return "EDNSServerTag" 1055 case DNSOptionCodeDeviceID: 1056 return "DeviceID" 1057 } 1058 } 1059 1060 // DNSOptionCode known values. See IANA 1061 const ( 1062 DNSOptionCodeNSID DNSOptionCode = 3 1063 DNSOptionCodeDAU DNSOptionCode = 5 1064 DNSOptionCodeDHU DNSOptionCode = 6 1065 DNSOptionCodeN3U DNSOptionCode = 7 1066 DNSOptionCodeEDNSClientSubnet DNSOptionCode = 8 1067 DNSOptionCodeEDNSExpire DNSOptionCode = 9 1068 DNSOptionCodeCookie DNSOptionCode = 10 1069 DNSOptionCodeEDNSKeepAlive DNSOptionCode = 11 1070 DNSOptionCodePadding DNSOptionCode = 12 1071 DNSOptionCodeChain DNSOptionCode = 13 1072 DNSOptionCodeEDNSKeyTag DNSOptionCode = 14 1073 DNSOptionCodeEDNSClientTag DNSOptionCode = 16 1074 DNSOptionCodeEDNSServerTag DNSOptionCode = 17 1075 DNSOptionCodeDeviceID DNSOptionCode = 26946 1076 ) 1077 1078 // DNSOPT is a DNS Option, see RFC6891, section 6.1.2 1079 type DNSOPT struct { 1080 Code DNSOptionCode 1081 Data []byte 1082 } 1083 1084 func (opt DNSOPT) String() string { 1085 return fmt.Sprintf("%s=%x", opt.Code, opt.Data) 1086 } 1087 1088 var ( 1089 errMaxRecursion = errors.New("max DNS recursion level hit") 1090 1091 errDNSNameOffsetTooHigh = errors.New("dns name offset too high") 1092 errDNSNameOffsetNegative = errors.New("dns name offset is negative") 1093 errDNSPacketTooShort = errors.New("DNS packet too short") 1094 errDNSNameTooLong = errors.New("dns name is too long") 1095 errDNSNameInvalidIndex = errors.New("dns name uncomputable: invalid index") 1096 errDNSPointerOffsetTooHigh = errors.New("dns offset pointer too high") 1097 errDNSIndexOutOfRange = errors.New("dns index walked out of range") 1098 errDNSNameHasNoData = errors.New("no dns data found for name") 1099 1100 errCharStringMissData = errors.New("Insufficient data for a <character-string>") 1101 1102 errDecodeRecordLength = errors.New("resource record length exceeds data") 1103 1104 errDecodeQueryBadQDCount = errors.New("Invalid query decoding, not the right number of questions") 1105 errDecodeQueryBadANCount = errors.New("Invalid query decoding, not the right number of answers") 1106 errDecodeQueryBadNSCount = errors.New("Invalid query decoding, not the right number of authorities") 1107 errDecodeQueryBadARCount = errors.New("Invalid query decoding, not the right number of additionals info") 1108 )