a go dns packet parser
1package magna 2 3import ( 4 "encoding/binary" 5 "fmt" 6 "net" 7 "strings" 8) 9 10func (a *A) Decode(buf []byte, offset int, rdlength int) (int, error) { 11 bytes, offset, err := getSlice(buf, offset, rdlength) 12 if err != nil { 13 return offset, fmt.Errorf("A record: failed to read address data: %w", err) 14 } 15 16 a.Address = net.IP(bytes) 17 if a.Address.To4() == nil { 18 return offset, fmt.Errorf("A record: decoded data is not a valid IPv4 address: %v", bytes) 19 } 20 return offset, nil 21} 22 23func (a *A) Encode(bytes []byte, offsets *map[string]uint16) ([]byte, error) { 24 ipv4 := a.Address.To4() 25 if ipv4 == nil { 26 return nil, fmt.Errorf("A record: cannot encode non-IPv4 address %s", a.Address.String()) 27 } 28 29 return append(bytes, ipv4...), nil 30} 31 32func (a A) String() string { 33 return a.Address.String() 34} 35 36func (ns *NS) Decode(buf []byte, offset int, rdlength int) (int, error) { 37 var err error 38 ns.NSDName, offset, err = decodeDomain(buf, offset) 39 if err != nil { 40 return offset, fmt.Errorf("NS record: failed to decode NSDName: %w", err) 41 } 42 43 return offset, nil 44} 45 46func (ns *NS) Encode(bytes []byte, offsets *map[string]uint16) ([]byte, error) { 47 var err error 48 bytes, err = encodeDomain(bytes, ns.NSDName, offsets) 49 if err != nil { 50 return nil, fmt.Errorf("NS record: failed to encode NSDName %s: %w", ns.NSDName, err) 51 } 52 53 return bytes, nil 54} 55 56func (ns NS) String() string { 57 return ns.NSDName 58} 59 60func (md *MD) Decode(buf []byte, offset int, rdlength int) (int, error) { 61 var err error 62 md.MADName, offset, err = decodeDomain(buf, offset) 63 if err != nil { 64 return offset, fmt.Errorf("MD record: failed to decode MADName %s: %w", md.MADName, err) 65 } 66 67 return offset, nil 68} 69 70func (md *MD) Encode(bytes []byte, offsets *map[string]uint16) ([]byte, error) { 71 var err error 72 bytes, err = encodeDomain(bytes, md.MADName, offsets) 73 if err != nil { 74 return nil, fmt.Errorf("MD record: failed to encode MADName %s: %w", md.MADName, err) 75 } 76 77 return bytes, nil 78} 79 80func (md MD) String() string { 81 return md.MADName 82} 83 84func (mf *MF) Decode(buf []byte, offset int, rdlength int) (int, error) { 85 var err error 86 mf.MADName, offset, err = decodeDomain(buf, offset) 87 if err != nil { 88 return offset, fmt.Errorf("MF record: failed to decode MADName: %w", err) 89 } 90 91 return offset, nil 92} 93 94func (mf *MF) Encode(bytes []byte, offsets *map[string]uint16) ([]byte, error) { 95 var err error 96 bytes, err = encodeDomain(bytes, mf.MADName, offsets) 97 if err != nil { 98 return nil, fmt.Errorf("MF record: failed to encode MADName %s: %w", mf.MADName, err) 99 } 100 101 return bytes, nil 102} 103 104func (mf MF) String() string { 105 return mf.MADName 106} 107 108func (c *CNAME) Decode(buf []byte, offset int, rdlength int) (int, error) { 109 var err error 110 c.CName, offset, err = decodeDomain(buf, offset) 111 if err != nil { 112 return offset, fmt.Errorf("CNAME record: failed to decode CNAME: %w", err) 113 } 114 115 return offset, nil 116} 117 118func (c *CNAME) Encode(bytes []byte, offsets *map[string]uint16) ([]byte, error) { 119 var err error 120 bytes, err = encodeDomain(bytes, c.CName, offsets) 121 if err != nil { 122 return nil, fmt.Errorf("CNAME record: failed to encode CNAME %s: %w", c.CName, err) 123 } 124 125 return bytes, nil 126} 127 128func (c CNAME) String() string { 129 return c.CName 130} 131 132func (soa *SOA) Decode(buf []byte, offset int, rdlength int) (int, error) { 133 var err error 134 soa.MName, offset, err = decodeDomain(buf, offset) 135 if err != nil { 136 return offset, fmt.Errorf("SOA record: failed to decode MName: %w", err) 137 } 138 139 soa.RName, offset, err = decodeDomain(buf, offset) 140 if err != nil { 141 return offset, fmt.Errorf("SOA record: failed to decode RName: %w", err) 142 } 143 144 soa.Serial, offset, err = getU32(buf, offset) 145 if err != nil { 146 return offset, fmt.Errorf("SOA record: failed to decode Serial: %w", err) 147 } 148 149 soa.Refresh, offset, err = getU32(buf, offset) 150 if err != nil { 151 return offset, fmt.Errorf("SOA record: failed to decode Refresh: %w", err) 152 } 153 154 soa.Retry, offset, err = getU32(buf, offset) 155 if err != nil { 156 return offset, fmt.Errorf("SOA record: failed to decode Retry: %w", err) 157 } 158 159 soa.Expire, offset, err = getU32(buf, offset) 160 if err != nil { 161 return offset, fmt.Errorf("SOA record: failed to decode Expire: %w", err) 162 } 163 164 soa.Minimum, offset, err = getU32(buf, offset) 165 if err != nil { 166 return offset, fmt.Errorf("SOA record: failed to decode Minimum: %w", err) 167 } 168 169 return offset, nil 170} 171 172func (soa *SOA) Encode(bytes []byte, offsets *map[string]uint16) ([]byte, error) { 173 var err error 174 bytes, err = encodeDomain(bytes, soa.MName, offsets) 175 if err != nil { 176 return nil, fmt.Errorf("SOA record: failed to encode MName %s: %w", soa.MName, err) 177 } 178 179 bytes, err = encodeDomain(bytes, soa.RName, offsets) 180 if err != nil { 181 return nil, fmt.Errorf("SOA record: failed to encode RName %s: %w", soa.RName, err) 182 } 183 184 bytes = binary.BigEndian.AppendUint32(bytes, soa.Serial) 185 bytes = binary.BigEndian.AppendUint32(bytes, soa.Refresh) 186 bytes = binary.BigEndian.AppendUint32(bytes, soa.Retry) 187 bytes = binary.BigEndian.AppendUint32(bytes, soa.Expire) 188 bytes = binary.BigEndian.AppendUint32(bytes, soa.Minimum) 189 190 return bytes, nil 191} 192 193func (soa SOA) String() string { 194 return fmt.Sprintf("%s %s %d %d %d %d %d", soa.MName, soa.RName, soa.Serial, soa.Refresh, soa.Retry, soa.Expire, soa.Minimum) 195} 196 197func (mb *MB) Decode(buf []byte, offset int, rdlength int) (int, error) { 198 madname, offset, err := decodeDomain(buf, offset) 199 if err != nil { 200 return offset, fmt.Errorf("MB record: failed to decode MADName: %w", err) 201 } 202 203 mb.MADName = string(madname) 204 return offset, nil 205} 206 207func (mb *MB) Encode(bytes []byte, offsets *map[string]uint16) ([]byte, error) { 208 var err error 209 bytes, err = encodeDomain(bytes, mb.MADName, offsets) 210 if err != nil { 211 return nil, fmt.Errorf("MB record: failed to encode MADName %s: %w", mb.MADName, err) 212 } 213 214 return bytes, nil 215} 216 217func (mb MB) String() string { 218 return mb.MADName 219} 220 221func (mg *MG) Decode(buf []byte, offset int, rdlength int) (int, error) { 222 var err error 223 mg.MGMName, offset, err = decodeDomain(buf, offset) 224 if err != nil { 225 return offset, fmt.Errorf("MG record: failed to decode MGMName: %w", err) 226 } 227 228 return offset, nil 229} 230 231func (mg *MG) Encode(bytes []byte, offsets *map[string]uint16) ([]byte, error) { 232 var err error 233 bytes, err = encodeDomain(bytes, mg.MGMName, offsets) 234 if err != nil { 235 return nil, fmt.Errorf("MG record: failed to encode MGMName %s: %w", mg.MGMName, err) 236 } 237 return bytes, nil 238} 239 240func (mg MG) String() string { 241 return mg.MGMName 242} 243 244func (mr *MR) Decode(buf []byte, offset int, rdlength int) (int, error) { 245 var err error 246 mr.NEWName, offset, err = decodeDomain(buf, offset) 247 if err != nil { 248 return offset, fmt.Errorf("MR record: failed to decode NEWName: %w", err) 249 } 250 251 return offset, nil 252} 253 254func (mr *MR) Encode(bytes []byte, offsets *map[string]uint16) ([]byte, error) { 255 var err error 256 bytes, err = encodeDomain(bytes, mr.NEWName, offsets) 257 if err != nil { 258 return nil, fmt.Errorf("MR record: failed to encode NEWName: %w", err) 259 } 260 261 return bytes, nil 262} 263 264func (mr MR) String() string { 265 return mr.NEWName 266} 267 268func (null *NULL) Decode(buf []byte, offset int, rdlength int) (int, error) { 269 var err error 270 null.Anything, offset, err = getSlice(buf, offset, int(rdlength)) 271 if err != nil { 272 return offset, fmt.Errorf("NULL record: failed to read data: %w", err) 273 } 274 275 return offset, nil 276} 277 278func (null *NULL) Encode(bytes []byte, offsets *map[string]uint16) ([]byte, error) { 279 return append(bytes, null.Anything...), nil 280} 281 282func (null NULL) String() string { 283 return string(null.Anything) 284} 285 286func (wks *WKS) Decode(buf []byte, offset int, rdlength int) (int, error) { 287 if rdlength < 5 { 288 return len(buf), fmt.Errorf("WKS record: RDLENGTH %d is too short, minimum 5 required", rdlength) 289 } 290 291 addressBytes, nextOffset, err := getSlice(buf, offset, 4) 292 if err != nil { 293 return len(buf), fmt.Errorf("WKS record: failed to read address: %w", err) 294 } 295 offset = nextOffset 296 wks.Address = net.IP(addressBytes) 297 298 protocol, nextOffset, err := getU8(buf, offset) 299 if err != nil { 300 return len(buf), fmt.Errorf("WKS record: failed to read protocol: %w", err) 301 } 302 offset = nextOffset 303 wks.Protocol = protocol 304 305 bitmapLength := rdlength - 5 306 wks.BitMap, nextOffset, err = getSlice(buf, offset, bitmapLength) 307 if err != nil { 308 return len(buf), fmt.Errorf("WKS record: failed to read bitmap: %w", err) 309 } 310 offset = nextOffset 311 312 return offset, nil 313} 314 315func (wks *WKS) Encode(bytes []byte, offsets *map[string]uint16) ([]byte, error) { 316 bytes = append(bytes, wks.Address.To4()...) 317 bytes = append(bytes, wks.Protocol) 318 bytes = append(bytes, wks.BitMap...) 319 320 return bytes, nil 321} 322 323func (wks WKS) String() string { 324 return fmt.Sprintf("%s %d %x", wks.Address.String(), wks.Protocol, wks.BitMap) 325} 326 327func (ptr *PTR) Decode(buf []byte, offset int, rdlength int) (int, error) { 328 var err error 329 ptr.PTRDName, offset, err = decodeDomain(buf, offset) 330 if err != nil { 331 return offset, fmt.Errorf("PTR record: failed to decode PTRDName: %w", err) 332 } 333 334 return offset, nil 335} 336 337func (ptr *PTR) Encode(bytes []byte, offsets *map[string]uint16) ([]byte, error) { 338 var err error 339 bytes, err = encodeDomain(bytes, ptr.PTRDName, offsets) 340 if err != nil { 341 return nil, fmt.Errorf("PTR record: failed to encode PTRD %s: %w", ptr.PTRDName, err) 342 } 343 344 return bytes, nil 345} 346 347func (ptr PTR) String() string { 348 return ptr.PTRDName 349} 350 351func (hinfo *HINFO) Decode(buf []byte, offset int, rdlength int) (int, error) { 352 startOffset := offset 353 endOffset := offset + rdlength 354 if endOffset > len(buf) { 355 return len(buf), &BufferOverflowError{Length: len(buf), Offset: endOffset} 356 } 357 358 currentOffset := offset 359 var err error 360 361 cpuLen, nextOffset, err := getU8(buf, currentOffset) 362 if err != nil { 363 return len(buf), fmt.Errorf("HINFO record: failed to read CPU length: %w", err) 364 } 365 currentOffset = nextOffset 366 if currentOffset+int(cpuLen) > endOffset { 367 return len(buf), &BufferOverflowError{Length: len(buf), Offset: currentOffset + int(cpuLen)} 368 } 369 cpuBytes, nextOffset, err := getSlice(buf, currentOffset, int(cpuLen)) 370 if err != nil { 371 return len(buf), fmt.Errorf("HINFO record: failed to read CPU data: %w", err) 372 } 373 currentOffset = nextOffset 374 hinfo.CPU = string(cpuBytes) 375 376 osLen, nextOffset, err := getU8(buf, currentOffset) 377 if err != nil { 378 if currentOffset == endOffset { 379 return len(buf), fmt.Errorf("HINFO record: missing OS length byte at offset %d (expected end: %d)", currentOffset, endOffset) 380 } 381 return len(buf), fmt.Errorf("HINFO record: failed to read OS length: %w", err) 382 } 383 currentOffset = nextOffset 384 if currentOffset+int(osLen) > endOffset { 385 return len(buf), &BufferOverflowError{Length: len(buf), Offset: currentOffset + int(osLen)} 386 } 387 osBytes, nextOffset, err := getSlice(buf, currentOffset, int(osLen)) 388 if err != nil { 389 return len(buf), fmt.Errorf("HINFO record: failed to read OS data: %w", err) 390 } 391 currentOffset = nextOffset 392 hinfo.OS = string(osBytes) 393 394 if currentOffset != endOffset { 395 return len(buf), fmt.Errorf("HINFO record: RDATA length mismatch, consumed %d bytes, expected %d", currentOffset-startOffset, rdlength) 396 } 397 398 return currentOffset, nil 399} 400 401func (hinfo *HINFO) Encode(bytes []byte, offsets *map[string]uint16) ([]byte, error) { 402 if len(hinfo.CPU) > 255 { 403 return nil, fmt.Errorf("HINFO record: CPU string length %d exceeds maximum 255", len(hinfo.CPU)) 404 } 405 if len(hinfo.OS) > 255 { 406 return nil, fmt.Errorf("HINFO record: OS string length %d exceeds maximum 255", len(hinfo.OS)) 407 } 408 409 bytes = append(bytes, byte(len(hinfo.CPU))) 410 bytes = append(bytes, []byte(hinfo.CPU)...) 411 bytes = append(bytes, byte(len(hinfo.OS))) 412 bytes = append(bytes, []byte(hinfo.OS)...) 413 return bytes, nil 414} 415 416func (hinfo HINFO) String() string { 417 return fmt.Sprintf("%q %q", hinfo.CPU, hinfo.OS) 418} 419 420func (minfo *MINFO) Decode(buf []byte, offset int, rdlength int) (int, error) { 421 var err error 422 423 minfo.RMailBx, offset, err = decodeDomain(buf, offset) 424 if err != nil { 425 return offset, fmt.Errorf("MINFO record: failed to decode RMailBx: %w", err) 426 } 427 428 minfo.EMailBx, offset, err = decodeDomain(buf, offset) 429 if err != nil { 430 return offset, fmt.Errorf("MINFO record: failed to decode EMailBx: %w", err) 431 } 432 433 return offset, nil 434} 435 436func (minfo *MINFO) Encode(bytes []byte, offsets *map[string]uint16) ([]byte, error) { 437 var err error 438 bytes, err = encodeDomain(bytes, minfo.RMailBx, offsets) 439 if err != nil { 440 return nil, fmt.Errorf("MINFO record: failed to encode RMailBx %s: %w", minfo.RMailBx, err) 441 } 442 443 bytes, err = encodeDomain(bytes, minfo.EMailBx, offsets) 444 if err != nil { 445 return nil, fmt.Errorf("MINFO record: failed to encode EMailBx %s: %w", minfo.EMailBx, err) 446 } 447 448 return bytes, nil 449} 450 451func (minfo MINFO) String() string { 452 return minfo.RMailBx + " " + minfo.EMailBx 453} 454 455func (mx *MX) Decode(buf []byte, offset int, rdlength int) (int, error) { 456 var err error 457 mx.Preference, offset, err = getU16(buf, offset) 458 if err != nil { 459 return offset, fmt.Errorf("MX record: failed to decode Preference: %w", err) 460 } 461 462 mx.Exchange, offset, err = decodeDomain(buf, offset) 463 if err != nil { 464 return offset, fmt.Errorf("MX record: failed to decode Exchange: %w", err) 465 } 466 467 return offset, nil 468} 469 470func (mx *MX) Encode(bytes []byte, offsets *map[string]uint16) ([]byte, error) { 471 var err error 472 bytes = binary.BigEndian.AppendUint16(bytes, mx.Preference) 473 bytes, err = encodeDomain(bytes, mx.Exchange, offsets) 474 if err != nil { 475 return nil, fmt.Errorf("MX record: failed to encode Exchange %s: %w", mx.Exchange, err) 476 } 477 478 return bytes, nil 479} 480 481func (mx MX) String() string { 482 return fmt.Sprintf("%d %s", mx.Preference, mx.Exchange) 483} 484 485func (txt *TXT) Decode(buf []byte, offset int, rdlength int) (int, error) { 486 txt.TxtData = make([]string, 0, 1) 487 endOffset := offset + rdlength 488 if endOffset > len(buf) { 489 return len(buf), &BufferOverflowError{Length: len(buf), Offset: endOffset} 490 } 491 492 currentOffset := offset 493 for currentOffset < endOffset { 494 strLen, nextOffsetAfterLen, err := getU8(buf, currentOffset) 495 if err != nil { 496 return len(buf), fmt.Errorf("TXT record: failed to read string length byte: %w", err) 497 } 498 499 nextOffsetAfterData := nextOffsetAfterLen + int(strLen) 500 if nextOffsetAfterData > endOffset { 501 return len(buf), fmt.Errorf("TXT record: string segment length %d exceeds RDLENGTH boundary %d", strLen, endOffset) 502 } 503 504 strBytes, actualNextOffsetAfterData, err := getSlice(buf, nextOffsetAfterLen, int(strLen)) 505 if err != nil { 506 return len(buf), fmt.Errorf("TXT record: failed to read string data (length %d): %w", strLen, err) 507 } 508 509 txt.TxtData = append(txt.TxtData, string(strBytes)) 510 currentOffset = actualNextOffsetAfterData 511 } 512 513 if currentOffset != endOffset { 514 return len(buf), fmt.Errorf("TXT record: RDATA parsing finished at offset %d, but expected end at %d", currentOffset, endOffset) 515 } 516 517 return currentOffset, nil 518} 519 520func (txt *TXT) Encode(bytes []byte, offsets *map[string]uint16) ([]byte, error) { 521 for _, s := range txt.TxtData { 522 if len(s) > 255 { 523 return nil, fmt.Errorf("TXT record: string segment length %d exceeds maximum 255", len(s)) 524 } 525 bytes = append(bytes, byte(len(s))) 526 bytes = append(bytes, []byte(s)...) 527 } 528 return bytes, nil 529} 530 531func (txt TXT) String() string { 532 quoted := make([]string, len(txt.TxtData)) 533 for i, s := range txt.TxtData { 534 quoted[i] = fmt.Sprintf("%q", s) 535 } 536 return strings.Join(quoted, " ") 537} 538 539func (rp *RP) Decode(buf []byte, offset int, rdlength int) (int, error) { 540 var err error 541 rp.MBoxDName, offset, err = decodeDomain(buf, offset) 542 if err != nil { 543 return offset, fmt.Errorf("RP record: failed to decode mbox-dname: %w", err) 544 } 545 546 rp.TXTDName, offset, err = decodeDomain(buf, offset) 547 if err != nil { 548 return offset, fmt.Errorf("RP record: failed to decode txt-dname: %w", err) 549 } 550 551 return offset, nil 552} 553 554func (rp *RP) Encode(bytes []byte, offsets *map[string]uint16) ([]byte, error) { 555 var err error 556 bytes, err = encodeDomain(bytes, rp.MBoxDName, offsets) 557 if err != nil { 558 return nil, fmt.Errorf("RP record: failed to encode mbox-dname %s: %w", rp.MBoxDName, err) 559 } 560 561 bytes, err = encodeDomain(bytes, rp.TXTDName, offsets) 562 if err != nil { 563 return nil, fmt.Errorf("RP record: failed to encode txt-dname %s: %w", rp.TXTDName, err) 564 } 565 566 return bytes, nil 567} 568 569func (rp RP) String() string { 570 return fmt.Sprintf("%s %s", rp.MBoxDName, rp.TXTDName) 571} 572 573func (a *AFSDB) Decode(buf []byte, offset int, rdlength int) (int, error) { 574 var err error 575 a.Subtype, offset, err = getU16(buf, offset) 576 if err != nil || !(a.Subtype == 1 || a.Subtype == 2) { 577 return offset, fmt.Errorf("AFSDB record: failed to decode Subtype: %w", err) 578 } 579 580 a.Hostname, offset, err = decodeDomain(buf, offset) 581 if err != nil { 582 return offset, fmt.Errorf("AFSDB record: failed to decode Hostname: %w", err) 583 } 584 585 return offset, nil 586} 587 588func (a *AFSDB) Encode(bytes []byte, offsets *map[string]uint16) ([]byte, error) { 589 var err error 590 bytes = binary.BigEndian.AppendUint16(bytes, a.Subtype) 591 bytes, err = encodeDomain(bytes, a.Hostname, offsets) 592 if err != nil { 593 return nil, fmt.Errorf("AFSDB record: failed to encode Domain %s: %w", a.Hostname, err) 594 } 595 596 return bytes, nil 597} 598 599func (a AFSDB) String() string { 600 return fmt.Sprintf("%d %s", a.Subtype, a.Hostname) 601} 602 603func (x *X25) Decode(buf []byte, offset int, rdlength int) (int, error) { 604 var err error 605 endOffset := offset + rdlength 606 if endOffset > len(buf) { 607 return len(buf), &BufferOverflowError{Length: len(buf), Offset: endOffset} 608 } 609 610 strLen, nextOffsetAfterLen, err := getU8(buf, offset) 611 if err != nil { 612 return len(buf), fmt.Errorf("x25 record: failed to read string length byte: %w", err) 613 } 614 615 nextOffsetAfterData := nextOffsetAfterLen + int(strLen) 616 if nextOffsetAfterData > endOffset { 617 return len(buf), fmt.Errorf("x25 record: string segment length %d exceeds RDLENGTH boundary %d", strLen, endOffset) 618 } 619 620 strBytes, offset, err := getSlice(buf, nextOffsetAfterLen, int(strLen)) 621 if err != nil { 622 return len(buf), fmt.Errorf("x25 record: failed to read string data (length %d): %w", strLen, err) 623 } 624 625 x.PSDNAddress = string(strBytes) 626 for _, c := range x.PSDNAddress { 627 if c < '0' || c > '9' { 628 return offset, fmt.Errorf("X25 record: PSDN address contains non-digit character: %c", c) 629 } 630 } 631 632 return offset, nil 633} 634 635func (x *X25) Encode(bytes []byte, offsets *map[string]uint16) ([]byte, error) { 636 for _, r := range x.PSDNAddress { 637 if r < '0' || r > '9' { 638 return nil, fmt.Errorf("X25 record: PSDN address contains non-digit character: %c", r) 639 } 640 } 641 642 bytes = append(bytes, byte(len(x.PSDNAddress))) 643 bytes = append(bytes, []byte(x.PSDNAddress)...) 644 645 return bytes, nil 646} 647 648func (x X25) String() string { 649 return x.PSDNAddress 650} 651 652func (isdn *ISDN) Decode(buf []byte, offset int, rdlength int) (int, error) { 653 var err error 654 endOffset := offset + rdlength 655 if endOffset > len(buf) { 656 return len(buf), &BufferOverflowError{Length: len(buf), Offset: endOffset} 657 } 658 659 strLen, nextOffsetAfterLen, err := getU8(buf, offset) 660 if err != nil { 661 return len(buf), fmt.Errorf("ISDN record: failed to read string length byte: %w", err) 662 } 663 664 nextOffsetAfterData := nextOffsetAfterLen + int(strLen) 665 if nextOffsetAfterData > endOffset { 666 return len(buf), fmt.Errorf("ISDN record: string segment length %d exceeds RDLENGTH boundary %d", strLen, endOffset) 667 } 668 669 strBytes, offset, err := getSlice(buf, nextOffsetAfterLen, int(strLen)) 670 if err != nil { 671 return len(buf), fmt.Errorf("ISDN record: failed to read string data (length %d): %w", strLen, err) 672 } 673 674 isdn.ISDNAddress = string(strBytes) 675 for _, c := range isdn.ISDNAddress { 676 if c < '0' || c > '9' { 677 return offset, fmt.Errorf("ISDN record: ISDN address contains non-digit character: %c", c) 678 } 679 } 680 681 // the subaddress is an optional field 682 if offset < endOffset { 683 subAddrLen, nextOffsetAfterSubAddrLen, err := getU8(buf, offset) 684 if err != nil { 685 return offset, fmt.Errorf("ISDN record: failed to read subaddress length: %w", err) 686 } 687 offset = nextOffsetAfterSubAddrLen 688 689 if offset+int(subAddrLen) > endOffset { 690 return offset, fmt.Errorf("ISDN record: subaddress data length %d exceeds RDLENGTH boundary (available: %d bytes from offset %d up to %d)", subAddrLen, endOffset-offset, offset, endOffset) 691 } 692 693 subAddrBytes, nextOffsetAfterSubAddrData, err := getSlice(buf, offset, int(subAddrLen)) 694 if err != nil { 695 return offset, fmt.Errorf("ISDN record: failed to read subaddress data (length %d): %w", subAddrLen, err) 696 } 697 offset = nextOffsetAfterSubAddrData 698 isdn.Subaddress = string(subAddrBytes) 699 } else { 700 isdn.Subaddress = "" 701 } 702 703 return offset, nil 704} 705 706func (isdn *ISDN) Encode(bytes []byte, offsets *map[string]uint16) ([]byte, error) { 707 bytes = append(bytes, byte(len(isdn.ISDNAddress))) 708 bytes = append(bytes, []byte(isdn.ISDNAddress)...) 709 710 if isdn.Subaddress != "" { 711 bytes = append(bytes, byte(len(isdn.Subaddress))) 712 bytes = append(bytes, []byte(isdn.Subaddress)...) 713 } 714 return bytes, nil 715} 716 717func (isdn ISDN) String() string { 718 if isdn.Subaddress != "" { 719 return fmt.Sprintf("%q %q", isdn.ISDNAddress, isdn.Subaddress) 720 } 721 return fmt.Sprintf("%q", isdn.ISDNAddress) 722} 723 724func (rt *RT) Decode(buf []byte, offset int, rdlength int) (int, error) { 725 var err error 726 rt.Preference, offset, err = getU16(buf, offset) 727 if err != nil { 728 return offset, fmt.Errorf("RT record: failed to decode Preference: %w", err) 729 } 730 731 rt.IntermediateHost, offset, err = decodeDomain(buf, offset) 732 if err != nil { 733 return offset, fmt.Errorf("RT record: failed to decode Exchange: %w", err) 734 } 735 736 return offset, nil 737} 738 739func (rt *RT) Encode(bytes []byte, offsets *map[string]uint16) ([]byte, error) { 740 var err error 741 bytes = binary.BigEndian.AppendUint16(bytes, rt.Preference) 742 bytes, err = encodeDomain(bytes, rt.IntermediateHost, offsets) 743 if err != nil { 744 return nil, fmt.Errorf("RT record: failed to encode Intermediate Host %s: %w", rt.IntermediateHost, err) 745 } 746 747 return bytes, nil 748} 749 750func (rt RT) String() string { 751 return fmt.Sprintf("%d %s", rt.Preference, rt.IntermediateHost) 752} 753 754func (a *AAAA) Decode(buf []byte, offset int, rdlength int) (int, error) { 755 bytes, offset, err := getSlice(buf, offset, rdlength) 756 if err != nil { 757 return offset, fmt.Errorf("AAAA record: failed to read address data: %w", err) 758 } 759 760 a.Address = net.IP(bytes) 761 if a.Address.To16() == nil { 762 return offset, fmt.Errorf("AAAA record: decoded data is not a valid IPv6 address: %v", bytes) 763 } 764 return offset, nil 765} 766 767func (a *AAAA) Encode(bytes []byte, offsets *map[string]uint16) ([]byte, error) { 768 ipv6 := a.Address.To16() 769 // XXX: ipv6 encodes ipv4 so need to check its not ipv4 770 if a.Address.To4() != nil || ipv6 == nil { 771 return nil, fmt.Errorf("AAAA record: cannot encode non-IPv6 address %s", a.Address.String()) 772 } 773 774 return append(bytes, ipv6...), nil 775} 776 777func (a AAAA) String() string { 778 return a.Address.String() 779} 780 781func (opt *OPT) Decode(buf []byte, offset int, rdlength int) (int, error) { 782 // s := offset 783 opt.Options = make([]EDNSOption, 0) 784 785 if rdlength == 0 { 786 return offset, nil 787 } 788 789 endOffset := offset + rdlength 790 curOffset := offset 791 for curOffset < endOffset { 792 // need 4 bytes for both code and length 793 if offset+4 > endOffset { 794 return offset, fmt.Errorf("OPT record: truncated option header at offset: %d", offset) 795 } 796 797 optCode, offset, err := getU16(buf, offset) 798 if err != nil { 799 return offset, fmt.Errorf("OPT Record: failed to read option code: %w", err) 800 } 801 802 optLength, offset, err := getU16(buf, offset) 803 if err != nil { 804 return offset, fmt.Errorf("OPT Record: failed to read option length: %w", err) 805 } 806 807 if offset+int(optLength) > endOffset { 808 return offset, fmt.Errorf("OPT Record: failed to read option data of length: %d", offset) 809 } 810 811 optData, offset, err := getSlice(buf, offset, int(optLength)) 812 if err != nil { 813 return offset, fmt.Errorf("OPT Record: failed to read option data: %w", err) 814 } 815 816 opt.Options = append(opt.Options, EDNSOption{ 817 Code: optCode, 818 Data: optData, 819 }) 820 821 curOffset = offset 822 } 823 824 return offset, nil 825} 826 827func (opt *OPT) Encode(bytes []byte, offsets *map[string]uint16) ([]byte, error) { 828 for _, opt := range opt.Options { 829 bytes = binary.BigEndian.AppendUint16(bytes, opt.Code) 830 bytes = binary.BigEndian.AppendUint16(bytes, uint16(len(opt.Data))) 831 bytes = append(bytes, opt.Data...) 832 } 833 834 return bytes, nil 835} 836 837func (opt OPT) String() string { 838 var result strings.Builder 839 result.WriteString("OPT [") 840 for i, o := range opt.Options { 841 if i < len(opt.Options)-1 { 842 result.WriteString(fmt.Sprintf("%d <%x>,", o.Code, o.Data)) 843 } else { 844 result.WriteString(fmt.Sprintf("%d <%x>,", o.Code, o.Data)) 845 } 846 } 847 result.WriteString("]") 848 849 return result.String() 850} 851 852func (r *Reserved) Decode(buf []byte, offset int, rdlength int) (int, error) { 853 var err error 854 r.Bytes, offset, err = getSlice(buf, offset, int(rdlength)) 855 if err != nil { 856 return offset, fmt.Errorf("reserved record: failed to read data: %w", err) 857 } 858 859 return offset, err 860} 861 862func (r *Reserved) Encode(bytes []byte, offsets *map[string]uint16) ([]byte, error) { 863 return append(bytes, r.Bytes...), nil 864} 865 866func (r Reserved) String() string { 867 return fmt.Sprintf("[Reserved Data: %x]", r.Bytes) 868} 869 870// Decode decodes a resource record from buf at the offset. 871func (r *ResourceRecord) Decode(buf []byte, offset int) (int, error) { 872 var err error 873 r.Name, offset, err = decodeDomain(buf, offset) 874 if err != nil { 875 return offset, fmt.Errorf("rr decode: failed to decode record name: %w", err) 876 } 877 878 var rtype uint16 879 rtype, offset, err = getU16(buf, offset) 880 if err != nil { 881 return offset, fmt.Errorf("rr decode: failed to decode RType for %s: %w", r.Name, err) 882 } 883 r.RType = DNSType(rtype) 884 885 var rclass uint16 886 rclass, offset, err = getU16(buf, offset) 887 if err != nil { 888 return offset, fmt.Errorf("rr decode: failed to decode RClass for %s: %w", r.Name, err) 889 } 890 r.RClass = DNSClass(rclass) 891 892 r.TTL, offset, err = getU32(buf, offset) 893 if err != nil { 894 return offset, fmt.Errorf("rr decode: failed to decode TTL for %s: %w", r.Name, err) 895 } 896 897 r.RDLength, offset, err = getU16(buf, offset) 898 if err != nil { 899 return offset, fmt.Errorf("rr decode: failed to decode RDLength for %s: %w", r.Name, err) 900 } 901 902 switch r.RType { 903 case 1: 904 r.RData = &A{} 905 case 2: 906 r.RData = &NS{} 907 case 3: 908 r.RData = &MD{} 909 case 4: 910 r.RData = &MF{} 911 case 5: 912 r.RData = &CNAME{} 913 case 6: 914 r.RData = &SOA{} 915 case 7: 916 r.RData = &MB{} 917 case 8: 918 r.RData = &MG{} 919 case 9: 920 r.RData = &MR{} 921 case 10: 922 r.RData = &NULL{} 923 case 11: 924 r.RData = &WKS{} 925 case 12: 926 r.RData = &PTR{} 927 case 13: 928 r.RData = &HINFO{} 929 case 14: 930 r.RData = &MINFO{} 931 case 15: 932 r.RData = &MX{} 933 case 16: 934 r.RData = &TXT{} 935 case 17: 936 r.RData = &RP{} 937 case 18: 938 r.RData = &AFSDB{} 939 case 19: 940 r.RData = &X25{} 941 case 20: 942 r.RData = &ISDN{} 943 case 21: 944 r.RData = &RT{} 945 case 28: 946 r.RData = &AAAA{} 947 case 41: 948 r.RData = &OPT{} 949 default: 950 r.RData = &Reserved{} 951 } 952 953 if r.RData != nil { 954 offset, err = r.RData.Decode(buf, offset, int(r.RDLength)) 955 if err != nil { 956 return offset, fmt.Errorf("rr decode: failed to decode RData for %s (%s): %w", r.Name, r.RType.String(), err) 957 } 958 } 959 960 return offset, nil 961} 962 963// Encode encdoes a resource record and returns the input bytes appened. 964func (r *ResourceRecord) Encode(bytes []byte, offsets *map[string]uint16) ([]byte, error) { 965 var err error 966 bytes, err = encodeDomain(bytes, r.Name, offsets) 967 if err != nil { 968 return nil, fmt.Errorf("rr encode: failed to encode record name %s: %w", r.Name, err) 969 } 970 971 bytes = binary.BigEndian.AppendUint16(bytes, uint16(r.RType)) 972 bytes = binary.BigEndian.AppendUint16(bytes, uint16(r.RClass)) 973 bytes = binary.BigEndian.AppendUint32(bytes, r.TTL) 974 975 rdataStart := len(bytes) 976 bytes = binary.BigEndian.AppendUint16(bytes, 0) 977 bytes, err = r.RData.Encode(bytes, offsets) 978 if err != nil { 979 return nil, fmt.Errorf("rr encode: failed to encode RData for %s (%s): %w", r.Name, r.RType.String(), err) 980 } 981 982 rdataLength := uint16(len(bytes) - rdataStart - 2) 983 binary.BigEndian.PutUint16(bytes[rdataStart:rdataStart+2], rdataLength) 984 985 return bytes, nil 986}