a go dns packet parser

feat: add rfc-1183 rr types

+275 -17
+225
resource_record.go
··· 536 536 return strings.Join(quoted, " ") 537 537 } 538 538 539 + func (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 + 554 + func (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 + 569 + func (rp RP) String() string { 570 + return fmt.Sprintf("%s %s", rp.MBoxDName, rp.TXTDName) 571 + } 572 + 573 + func (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 + 588 + func (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 + 599 + func (a AFSDB) String() string { 600 + return fmt.Sprintf("%d %s", a.Subtype, a.Hostname) 601 + } 602 + 603 + func (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, return_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 return_offset, nil 633 + } 634 + 635 + func (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 + 648 + func (x X25) String() string { 649 + return x.PSDNAddress 650 + } 651 + 652 + func (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 + 706 + func (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 + 717 + func (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 + 724 + func (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 + 739 + func (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 + 750 + func (rt RT) String() string { 751 + return fmt.Sprintf("%d %s", rt.Preference, rt.IntermediateHost) 752 + } 753 + 539 754 func (r *Reserved) Decode(buf []byte, offset int, rdlength int) (int, error) { 540 755 var err error 541 756 r.Bytes, offset, err = getSlice(buf, offset, int(rdlength)) ··· 619 834 r.RData = &MX{} 620 835 case 16: 621 836 r.RData = &TXT{} 837 + case 17: 838 + r.RData = &RP{} 839 + case 18: 840 + r.RData = &AFSDB{} 841 + case 19: 842 + r.RData = &X25{} 843 + case 20: 844 + r.RData = &ISDN{} 845 + case 21: 846 + r.RData = &RT{} 622 847 default: 623 848 r.RData = &Reserved{} 624 849 }
+50 -17
types.go
··· 67 67 } 68 68 69 69 const ( 70 - AType DNSType = iota + 1 71 - NSType 72 - MDType 73 - MFType 74 - CNAMEType 75 - SOAType 76 - MBType 77 - MGType 78 - MRType 79 - NULLType 80 - WKSType 81 - PTRType 82 - HINFOType 83 - MINFOType 84 - MXType 85 - TXTType 86 - AFSDBType 70 + AType DNSType = 1 71 + NSType = 2 72 + MDType = 3 73 + MFType = 4 74 + CNAMEType = 5 75 + SOAType = 6 76 + MBType = 7 77 + MGType = 8 78 + MRType = 9 79 + NULLType = 10 80 + WKSType = 11 81 + PTRType = 12 82 + HINFOType = 13 83 + MINFOType = 14 84 + MXType = 15 85 + TXTType = 16 86 + RPType = 17 87 + AFSDBType = 18 88 + X25Type = 19 89 + ISDNType = 20 90 + RTType = 21 87 91 88 92 AXFRType = 252 89 93 MAILBType = 253 ··· 127 131 return "TXT" 128 132 case AFSDBType: 129 133 return "AFSDB" 134 + case RPType: 135 + return "RP" 136 + case X25Type: 137 + return "X25" 138 + case ISDNType: 139 + return "ISDN" 140 + case RTType: 141 + return "RT" 130 142 case AXFRType: 131 143 return "AXFR" 132 144 case MAILBType: ··· 324 336 } 325 337 326 338 type AFSDB struct { 339 + Subtype uint16 340 + Hostname string 341 + } 342 + 343 + type RP struct { 344 + MBoxDName string 345 + TXTDName string 346 + } 347 + 348 + type X25 struct { 349 + PSDNAddress string 350 + } 351 + 352 + type ISDN struct { 353 + ISDNAddress string 354 + Subaddress string 355 + } 356 + 357 + type RT struct { 358 + Preference uint16 359 + IntermediateHost string 327 360 } 328 361 329 362 // Reserved represents a record that is not yet implemented.