github.com/Asutorufa/yuhaiin@v0.3.6-0.20240502055049-7984da7023a0/pkg/net/dns/resolver/resolve.go (about) 1 package dns 2 3 import ( 4 "bytes" 5 "errors" 6 "fmt" 7 "math/rand/v2" 8 "net" 9 "strings" 10 11 "github.com/Asutorufa/yuhaiin/pkg/log" 12 ) 13 14 type reqType [2]byte 15 16 var ( 17 A = reqType{0b00000000, 0b00000001} // 1 18 NS = reqType{0b00000000, 0b00000010} // 2 19 MD = reqType{0b00000000, 0b00000011} // 3 20 MF = reqType{0b00000000, 0b00000100} // 3 21 CNAME = reqType{0b00000000, 0b00000101} // 5 22 SOA = reqType{0b00000000, 0b00000110} // 6 23 MB = reqType{0b00000000, 0b00000111} // 7 24 MG = reqType{0b00000000, 0b00001000} // 8 25 MR = reqType{0b00000000, 0b00001001} // 9 26 NULL = reqType{0b00000000, 0b00001010} // 10 27 WKS = reqType{0b00000000, 0b00001011} // 11 28 PTR = reqType{0b00000000, 0b00001100} // 12 29 HINFO = reqType{0b00000000, 0b00001101} // 13 30 MINFO = reqType{0b00000000, 0b00001110} // 14 31 MX = reqType{0b00000000, 0b00001111} // 15 32 TXT = reqType{0b00000000, 0b00010000} // 16 33 AAAA = reqType{0b00000000, 0b00011100} // 28 https://www.ietf.org/rfc/rfc3596.txt 34 RRSIG = reqType{0b00000000, 0b00101110} // 46 dnssec 35 36 // only for req 37 AXFR = reqType{0b00000000, 0b11111100} // 252 38 ANY = reqType{0b00000000, 0b11111111} // 255 39 ) 40 41 func creatRequest(domain string, reqType reqType, arCount bool) []byte { 42 data := bytes.NewBuffer(nil) 43 data.Write([]byte{byte(rand.UintN(255)), byte(rand.UintN(255))}) // id 44 // qr 0, opcode 0000, aa 0, tc 0, rd 1 => 1 byte, ra 0, z 000, rCode 0000 => 1 byte 45 data.Write([]byte{0b0<<7 + 0b0000<<3 + 0b0<<2 + 0b0<<1 + 0b1, 0b0<<7 + 0b000<<4 + 0b0000}) 46 data.Write([]byte{0b00000000, 0b00000001}) // qdCount: request number => bit: 00000000 00000001 -> 01 47 data.Write([]byte{0b00000000, 0b00000000}) // anCount: answer number(no use for req) => bit: 00000000 00000000 48 data.Write([]byte{0b00000000, 0b00000000}) // nsCount: authority section 2 bytes 49 if arCount { // arCount: additional section 2 bytes 50 data.Write([]byte{0b00000000, 0b00000001}) 51 } else { 52 data.Write([]byte{0b00000000, 0b00000000}) 53 } 54 55 domain = domain + "." // domain: www.example.com => 3www7example3com <- last with 0 56 for i := strings.IndexByte(domain, '.'); i != -1; i = strings.IndexByte(domain, '.') { 57 data.WriteByte(byte(i)) 58 data.WriteString(domain[:i]) 59 domain = domain[i+1:] 60 } 61 data.WriteByte(0b00000000) // add the 0 for last of domain 62 63 data.Write([]byte{reqType[0], reqType[1]}) // qType 1 -> A:ipv4 01 | 28 -> AAAA:ipv6 000000 00011100 => 0 0x1c 64 data.Write([]byte{0b00000000, 0b00000001}) // qClass: 1 = from internet 65 return data.Bytes() 66 } 67 68 type respHeader struct { 69 qdCount int 70 anCount int 71 nsCount int 72 arCount int 73 dnsType reqType 74 isAnswer bool 75 name string 76 } 77 78 type resolver struct { 79 i int 80 request []byte 81 aswer []byte 82 h respHeader 83 } 84 85 func Resolve(req, answer []byte) (resp []net.IP, err error) { 86 defer func() { 87 r := recover() 88 if r != nil { 89 err = fmt.Errorf("recovering from panic resolve: %v", r) 90 } 91 }() 92 r := &resolver{request: req, aswer: answer} 93 err = r.header() 94 if err != nil { 95 return nil, err 96 } 97 if !r.h.isAnswer { 98 return nil, fmt.Errorf("the qr (%d&%d=%d) is not 1(Answer)", r.aswer[2], 128, r.aswer[2]&128) 99 } 100 resp, err = r.answer() 101 if err != nil { 102 return nil, err 103 } 104 r.authoritative() 105 r.additional() 106 return resp, nil 107 } 108 109 func (r *resolver) header() (err error) { 110 if r.aswer[0] != r.request[0] || r.aswer[1] != r.request[1] { 111 return errors.New("id not same") 112 } 113 114 if r.aswer[2]&128 != 0 { // check the QR is 1(Answer) 115 r.h.isAnswer = true 116 } 117 118 switch r.aswer[3] & 0b00001111 { // check Response code(rCode) eg:11110010 & 00001111 = 0010, 11111101 & 00001111 = 1101 119 case 0b0000: // 0 no error 120 break 121 case 0b0001: // 1 Format error 122 err = errors.New("request format error") 123 case 0b0010: // 2 Server failure 124 err = errors.New("dns Server failure") 125 case 0b0011: // 3 Name Error 126 err = errors.New("no such name") 127 case 0b0100: // 4 Not Implemented 128 err = errors.New("dns server not support this request") 129 case 0b0101: // 5 Refused 130 err = errors.New("dns server Refuse") 131 default: // 6-15 Reserved for future use. 132 err = fmt.Errorf("reserved for future use, code: %b", r.aswer[3]&0b00001111) 133 } 134 if err != nil { 135 return err 136 } 137 138 r.h.qdCount = int(r.aswer[4])<<8 + int(r.aswer[5]) // request 139 r.h.anCount = int(r.aswer[6])<<8 + int(r.aswer[7]) // answer Count 140 r.h.nsCount = int(r.aswer[8])<<8 + int(r.aswer[9]) // authority Count 141 r.h.arCount = int(r.aswer[10])<<8 + int(r.aswer[11]) // additional Count 142 143 r.i = 12 144 145 var size int 146 r.h.name, size = r.getName(r.i) 147 r.i += size 148 149 // fmt.Println(r.h) 150 151 r.h.dnsType = reqType{r.aswer[r.i], r.aswer[r.i+1]} 152 r.i += 2 // qType 153 r.i += 2 // qClass 154 155 return nil 156 } 157 158 func (r *resolver) answer() (DNS []net.IP, err error) { 159 i := r.h.anCount 160 _start: 161 i-- 162 if i < 0 { 163 return 164 } 165 166 _, size := r.getName(r.i) 167 r.i += size 168 169 tYPE := reqType{r.aswer[r.i], r.aswer[r.i+1]} 170 r.i += 2 //type 171 r.i += 2 //class 172 r.i += 4 // ttl 173 sum := int(r.aswer[r.i])<<8 + int(r.aswer[r.i+1]) 174 r.i += 2 // RDLENGTH jump sum 2+int(c[0])<<8+int(c[1]) 175 176 switch tYPE { 177 case A: 178 DNS = append(DNS, r.aswer[r.i:r.i+4]) 179 r.i += 4 // 4 byte ip addr 180 case AAAA: 181 DNS = append(DNS, r.aswer[r.i:r.i+16]) 182 r.i += 16 // 16 byte ip addr 183 case RRSIG: 184 typeCover := r.aswer[r.i : r.i+2] 185 r.i += 2 186 algorithm := r.aswer[r.i : r.i+1] 187 r.i++ 188 label := r.aswer[r.i : r.i+1] 189 r.i++ 190 originalTTL := r.aswer[r.i : r.i+4] 191 r.i += 4 192 signExpiration := r.aswer[r.i : r.i+4] 193 r.i += 4 194 signInception := r.aswer[r.i : r.i+4] 195 r.i += 4 196 keyTag := r.aswer[r.i : r.i+2] 197 r.i += 2 198 signName, size := r.getName(r.i) 199 r.i += size 200 signature := r.aswer[r.i : r.i+sum-size-18] 201 r.i += sum - size - 18 202 log.Debug(fmt.Sprintln(typeCover, algorithm, label, originalTTL, signExpiration, signInception, keyTag, signName, signature)) 203 case NS, MD, MF, CNAME, SOA, MG, MB, MR, NULL, WKS, PTR, HINFO, MINFO, MX, TXT: 204 fallthrough 205 default: 206 r.i += sum // RDATA 207 } 208 goto _start 209 } 210 211 func (r *resolver) authoritative() { 212 i := r.h.nsCount 213 _start: 214 i-- 215 if i < 0 { 216 return 217 } 218 _, size := r.getName(r.i) 219 r.i += size 220 r.i += 2 // type 221 r.i += 2 // class 222 r.i += 2 // ttl 223 dataLength := int(r.aswer[r.i])<<8 + int(r.aswer[r.i+1]) 224 r.i += 2 // data length 225 r.i += dataLength 226 goto _start 227 } 228 229 func (r *resolver) additional() { 230 i := r.h.arCount 231 _start: 232 i-- 233 if i < 0 { 234 return 235 } 236 r.i++ // name 237 typeE := r.aswer[r.i : r.i+2] 238 r.i += 2 // type 239 r.i += 2 // payLoadSize 240 r.i++ // rCode 241 r.i++ // version 242 r.i += 2 // Z 243 dataLength := int(r.aswer[r.i])<<8 + int(r.aswer[r.i+1]) 244 r.i += 2 245 if typeE[0] != 0 || typeE[1] != 41 { 246 r.i += dataLength // optData 247 goto _start 248 } 249 250 if dataLength == 0 { 251 goto _start 252 } 253 254 optCode := EDNSOPT{r.aswer[r.i], r.aswer[r.i+1]} 255 r.i += 2 256 optionLength := int(r.aswer[r.i])<<8 + int(r.aswer[r.i+1]) 257 r.i += 2 258 switch optCode { 259 case EdnsClientSubnet: 260 r.i += 2 // family 261 r.i++ // source Netmask 262 r.i++ // scope Netmask 263 r.i += optionLength - 4 // Subnet IP 264 default: 265 r.i += optionLength // opt data 266 } 267 goto _start 268 } 269 270 func (r *resolver) getName(i int) (name string, size int) { 271 s := strings.Builder{} 272 for { 273 if r.aswer[i] == 0 { 274 i++ // lastOfDomain: one byte 0 275 size++ 276 break 277 } 278 279 if r.aswer[i]&128 == 128 && r.aswer[i]&64 == 64 { 280 l := r.aswer[i+1] 281 // fmt.Println(l) 282 i += 2 283 size += 2 284 tmp, _ := r.getName(int(l)) 285 s.WriteString(tmp) 286 break 287 } 288 289 sectionLength := int(r.aswer[i]) + 1 290 s.Write(r.aswer[i+1 : i+sectionLength]) 291 s.WriteString(".") 292 size += sectionLength 293 i += sectionLength 294 } 295 return s.String(), size 296 } 297 298 /* 299 * OLD 300 */ 301 func resolveHeader(req []byte, answer []byte) (header respHeader, answerSection []byte, err error) { 302 // resolve answer 303 if answer[0] != req[0] || answer[1] != req[1] { // compare id 304 // not the answer 305 return header, nil, errors.New("id not same") 306 } 307 308 if answer[2]&128 != 0 { // check the QR is 1(Answer) 309 return header, nil, errors.New("the qr is not 1(Answer)") 310 } 311 312 switch answer[3] & 0b00001111 { // check Response code(rCode) eg:11110010 & 00001111 = 0010, 11111101 & 00001111 = 1101 313 case 0b0000: // 0 no error 314 break 315 case 0b0001: // 1 Format error 316 return header, nil, errors.New("request format error") 317 case 0b0010: // 2 Server failure 318 return header, nil, errors.New("dns Server failure") 319 case 0b0011: // 3 Name Error 320 return header, nil, errors.New("no such name") 321 case 0b0100: // 4 Not Implemented 322 return header, nil, errors.New("dns server not support this request") 323 case 0b0101: // 5 Refused 324 return header, nil, errors.New("dns server Refuse") 325 default: // 6-15 Reserved for future use. 326 return header, nil, fmt.Errorf("reserved for future use, code: %b", answer[3]&0b00001111) 327 } 328 329 header.qdCount = 0 // request 330 header.anCount = int(answer[6])<<8 + int(answer[7]) // answer Count 331 header.nsCount = int(answer[8])<<8 + int(answer[9]) // authority Count 332 header.arCount = int(answer[10])<<8 + int(answer[11]) // additional Count 333 334 c := answer[12:] 335 336 header.name, _, c = getName(c, answer) 337 338 c = c[2:] // qType 339 c = c[2:] // qClass 340 341 return header, c, nil 342 } 343 344 type answer interface { 345 Answer() 346 } 347 348 func resolveAnswer(c []byte, anCount int, b []byte) (DNS []net.IP, left []byte, err error) { 349 for i := anCount; i > 0; i-- { 350 _, _, c = getName(c, b) 351 352 tYPE := reqType{c[0], c[1]} 353 c = c[2:] // type 354 c = c[2:] // class 355 c = c[4:] // ttl 4byte 356 sum := int(c[0])<<8 + int(c[1]) 357 c = c[2:] // RDLENGTH jump sum 2+int(c[0])<<8+int(c[1]) 358 359 switch tYPE { 360 case A: 361 DNS = append(DNS, c[0:4]) 362 c = c[4:] // 4 byte ip addr 363 case AAAA: 364 DNS = append(DNS, c[0:16]) 365 c = c[16:] // 16 byte ip addr 366 case RRSIG: 367 typeCover := c[:2] 368 c = c[2:] 369 algorithm := c[:1] 370 c = c[1:] 371 label := c[:1] 372 c = c[1:] 373 originalTTL := c[:4] 374 c = c[4:] 375 signExpiration := c[:4] 376 c = c[4:] 377 signInception := c[:4] 378 c = c[4:] 379 keyTag := c[:2] 380 c = c[2:] 381 signName, size, others := getName(c, b) 382 c = others 383 signature := c[:sum-size-18] 384 c = c[sum-size-18:] 385 log.Debug(fmt.Sprintln(typeCover, algorithm, label, originalTTL, signExpiration, signInception, keyTag, signName, signature)) 386 case NS, MD, MF, CNAME, SOA, MG, MB, MR, NULL, WKS, PTR, HINFO, MINFO, MX, TXT: 387 fallthrough 388 default: 389 c = c[sum:] // RDATA 390 } 391 } 392 return DNS, c, nil 393 } 394 395 func resolveAuthoritative(c []byte, nsCount int, b []byte) (left []byte) { 396 for i := nsCount; i > 0; i-- { 397 _, _, c = getName(c, b) 398 c = c[2:] // type 399 c = c[2:] // class 400 c = c[4:] // ttl 401 dataLength := int(c[0])<<8 + int(c[1]) 402 c = c[2:] // data length 403 c = c[dataLength:] 404 } 405 return c 406 } 407 408 func getName(c []byte, all []byte) (name string, size int, x []byte) { 409 s := strings.Builder{} 410 for { 411 if c[0] == 0 { 412 c = c[1:] // lastOfDomain: one byte 0 413 size++ 414 break 415 } 416 if c[0]&128 == 128 && c[0]&64 == 64 { 417 l := c[1] 418 c = c[2:] 419 size += 2 420 tmp, _, _ := getName(all[l:], all) 421 s.WriteString(tmp) 422 break 423 } 424 425 s.Write(c[1 : int(c[0])+1]) 426 s.WriteString(".") 427 size += int(c[0]) + 1 428 c = c[int(c[0])+1:] 429 } 430 return s.String(), size, c 431 } 432 433 type reader struct { 434 raw []byte 435 r *bytes.Buffer 436 } 437 438 func newReader(raw []byte) *reader { 439 return &reader{raw: raw, r: bytes.NewBuffer(raw)} 440 } 441 442 func (r *reader) domain(rr *bytes.Buffer) (string, error) { 443 s := strings.Builder{} 444 445 var err error 446 for { 447 var b byte 448 if b, err = rr.ReadByte(); err != nil { 449 return "", fmt.Errorf("read byte failed: %w", err) 450 } 451 452 if b == 0 { 453 break 454 } 455 456 if b&128 == 128 && b&64 == 64 { 457 b, err = rr.ReadByte() 458 if err != nil { 459 return "", fmt.Errorf("read name offset failed: %w", err) 460 } 461 name, err := r.domain(bytes.NewBuffer(r.raw[b:])) 462 if err != nil { 463 return "", fmt.Errorf("read name failed: %w", err) 464 } 465 s.WriteString(name) 466 break 467 } 468 469 s.WriteString(string(rr.Next(int(b)))) 470 s.WriteString(".") 471 } 472 473 return s.String(), nil 474 } 475 476 // https://www.ietf.org/rfc/rfc1035.txt 477 /* 478 4.1.1. Header section format 479 480 The header contains the following fields: 481 482 1 1 1 1 1 1 483 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 484 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 485 | ID | 486 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 487 |QR| Opcode |AA|TC|RD|RA| Z | RCODE | 488 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 489 | QDCOUNT | 490 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 491 | ANCOUNT | 492 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 493 | NSCOUNT | 494 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 495 | ARCOUNT | 496 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 497 498 where: 499 500 ID A 16 bit identifier assigned by the program that 501 generates any kind of query. This identifier is copied 502 the corresponding reply and can be used by the requester 503 to match up replies to outstanding queries. 504 QR A one bit field that specifies whether this message is a 505 query (0), or a response (1). 506 OPCODE A four bit field that specifies kind of query in this 507 message. This value is set by the originator of a query 508 and copied into the response. The values are: 509 0 a standard query (QUERY) 510 1 an inverse query (IQUERY) 511 2 a server status request (STATUS) 512 3-15 reserved for future use 513 AA Authoritative Answer - this bit is valid in responses, 514 and specifies that the responding name server is an 515 authority for the domain name in question section. 516 Note that the contents of the answer section may have 517 multiple owner names because of aliases. The AA bit 518 519 520 521 Mockapetris [Page 26] 522 523 RFC 1035 Domain Implementation and Specification November 1987 524 525 526 corresponds to the name which matches the query name, or 527 the first owner name in the answer section. 528 529 TC TrunCation - specifies that this message was truncated 530 due to length greater than that permitted on the 531 transmission channel. 532 RD Recursion Desired - this bit may be set in a query and 533 is copied into the response. If RD is set, it directs 534 the name server to pursue the query recursively. 535 Recursive query support is optional. 536 RA Recursion Available - this be is set or cleared in a 537 response, and denotes whether recursive query support is 538 available in the name server. 539 Z Reserved for future use. Must be zero in all queries 540 and responses. 541 RCODE Response code - this 4 bit field is set as part of 542 responses. The values have the following 543 interpretation: 544 0 No error condition 545 1 Format error - The name server was 546 unable to interpret the query. 547 2 Server failure - The name server was 548 unable to process this query due to a 549 problem with the name server. 550 3 Name Error - Meaningful only for 551 responses from an authoritative name 552 server, this code signifies that the 553 domain name referenced in the query does 554 not exist. 555 4 Not Implemented - The name server does 556 not support the requested kind of query. 557 5 Refused - The name server refuses to 558 perform the specified operation for 559 policy reasons. For example, a name 560 server may not wish to provide the 561 information to the particular requester, 562 or a name server may not wish to perform 563 a particular operation (e.g., zone 564 565 566 Mockapetris [Page 27] 567 568 RFC 1035 Domain Implementation and Specification November 1987 569 570 571 transfer) for particular data. 572 6-15 Reserved for future use. 573 574 QDCOUNT an unsigned 16 bit integer specifying the number of 575 entries in the question section. 576 ANCOUNT an unsigned 16 bit integer specifying the number of 577 resource records in the answer section. 578 NSCOUNT an unsigned 16 bit integer specifying the number of name 579 server resource records in the authority records 580 section. 581 ARCOUNT an unsigned 16 bit integer specifying the number of 582 resource records in the additional records section. 583 584 585 4.1.2. Question section format 586 587 The question section is used to carry the "question" in most queries, 588 i.e., the parameters that define what is being asked. The section 589 contains QDCOUNT (usually 1) entries, each of the following format: 590 591 1 1 1 1 1 1 592 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 593 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 594 | | 595 / QNAME / 596 / / 597 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 598 | QTYPE | 599 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 600 | QCLASS | 601 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 602 603 where: 604 605 QNAME a domain name represented as a sequence of labels, where 606 each label consists of a length octet followed by that 607 number of octets. The domain name terminates with the 608 zero length octet for the null label of the root. Note 609 that this field may be an odd number of octets; no 610 padding is used. 611 QTYPE a two octet code which specifies the type of the query. 612 The values for this field include all codes valid for a 613 TYPE field, together with some more general codes which 614 can match more than one type of RR. 615 616 617 618 Mockapetris [Page 28] 619 620 RFC 1035 Domain Implementation and Specification November 1987 621 622 623 QCLASS a two octet code that specifies the class of the query. 624 For example, the QCLASS field is IN for the Internet. 625 */ 626 627 /* 628 4.1.3. Resource record format 629 630 The answer, authority, and additional sections all share the same 631 format: a variable number of resource records, where the number of 632 records is specified in the corresponding count field in the header. 633 Each resource record has the following format: 634 635 1 1 1 1 1 1 636 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 637 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 638 | | 639 / / 640 / NAME / 641 | | 642 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 643 | TYPE | 644 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 645 | CLASS | 646 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 647 | TTL | 648 | | 649 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 650 | RDLENGTH | 651 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--| 652 / RDATA / 653 / / 654 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 655 656 657 where: 658 NAME an owner name, i.e., the name of the node to which this 659 resource record pertains. 660 TYPE two octets containing one of the RR TYPE codes. 661 CLASS two octets containing one of the RR CLASS codes. 662 TTL a 32 bit signed integer that specifies the time interval 663 that the resource record may be cached before the source 664 of the information should again be consulted. Zero 665 values are interpreted to mean that the RR can only be 666 used for the transaction in progress, and should not be 667 cached. For example, SOA records are always distributed 668 with a zero TTL to prohibit caching. Zero values can 669 also be used for extremely volatile data. 670 RDLENGTH an unsigned 16 bit integer that specifies the length in 671 octets of the RDATA field. 672 673 Mockapetris [Page 11] 674 675 RFC 1035 Domain Implementation and Specification November 1987 676 677 RDATA a variable length string of octets that describes the 678 resource. The format of this information varies 679 according to the TYPE and CLASS of the resource record. 680 681 3.2.2. TYPE values 682 683 TYPE fields are used in resource records. Note that these types are a 684 subset of QTYPEs. 685 686 TYPE value and meaning 687 A 1 a host address 688 NS 2 an authoritative name server 689 MD 3 a mail destination (Obsolete - use MX) 690 MF 4 a mail forwarder (Obsolete - use MX) 691 CNAME 5 the canonical name for an alias 692 SOA 6 marks the start of a zone of authority 693 MB 7 a mailbox domain name (EXPERIMENTAL) 694 MG 8 a mail group member (EXPERIMENTAL) 695 MR 9 a mail rename domain name (EXPERIMENTAL) 696 NULL 10 a null RR (EXPERIMENTAL) 697 WKS 11 a well known service description 698 PTR 12 a domain name pointer 699 HINFO 13 host information 700 MINFO 14 mailbox or mail list information 701 MX 15 mail exchange 702 TXT 16 text strings 703 */