a go dns packet parser

add support for ipv6 resource records #8

merged opened by seiso.moe targeting main from feature/ipv6

closes #4

Labels

None yet.

Participants 1
AT URI
at://did:plc:adtzorbhmmjbzxsl2y4vqlqs/sh.tangled.repo.pull/3m3tdvkquwp22
+67 -1
Diff #0
+30 -1
resource_record.go
··· 26 26 return nil, fmt.Errorf("A record: cannot encode non-IPv4 address %s", a.Address.String()) 27 27 } 28 28 29 - return append(bytes, a.Address.To4()...), nil 29 + return append(bytes, ipv4...), nil 30 30 } 31 31 32 32 func (a A) String() string { ··· 751 751 return fmt.Sprintf("%d %s", rt.Preference, rt.IntermediateHost) 752 752 } 753 753 754 + func (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 + 767 + func (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 + 777 + func (a AAAA) String() string { 778 + return a.Address.String() 779 + } 780 + 754 781 func (opt *OPT) Decode(buf []byte, offset int, rdlength int) (int, error) { 755 782 // s := offset 756 783 opt.Options = make([]EDNSOption, 0) ··· 915 942 r.RData = &ISDN{} 916 943 case 21: 917 944 r.RData = &RT{} 945 + case 28: 946 + r.RData = &AAAA{} 918 947 case 41: 919 948 r.RData = &OPT{} 920 949 default:
+30
resource_record_test.go
··· 516 516 }) 517 517 } 518 518 } 519 + 520 + func TestAAAARecord(t *testing.T) { 521 + addr := net.ParseIP("2001:db8::1") 522 + rdataBytes := []byte(addr) 523 + aaaa := &AAAA{} 524 + 525 + offset, err := aaaa.Decode([]byte{}, 0, 16) 526 + assert.Error(t, err, "Decode should fail with empty buffer") 527 + assert.True(t, errors.Is(err, &BufferOverflowError{})) 528 + 529 + offset, err = aaaa.Decode(rdataBytes, 0, 16) 530 + assert.NoError(t, err) 531 + assert.Equal(t, 16, offset) 532 + assert.Equal(t, addr, aaaa.Address) 533 + 534 + _, err = aaaa.Decode([]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, 0, 15) 535 + assert.Error(t, err) 536 + assert.Contains(t, err.Error(), "AAAA record:") 537 + 538 + aaaaEncode := &AAAA{Address: addr} 539 + encoded := encodeRData(t, aaaaEncode) 540 + assert.Equal(t, rdataBytes, encoded) 541 + 542 + ipv4 := net.ParseIP("192.168.1.1") 543 + aaaaEncodeInvalid := &AAAA{Address: ipv4} 544 + _, err = aaaaEncodeInvalid.Encode([]byte{}, &map[string]uint16{}) 545 + 546 + assert.Error(t, err) 547 + assert.Contains(t, err.Error(), "cannot encode non-IPv6 address") 548 + }
+7
types.go
··· 92 92 X25Type = 19 93 93 ISDNType = 20 94 94 RTType = 21 95 + AAAAType = 28 95 96 96 97 OPTType = 41 97 98 ··· 145 146 return "ISDN" 146 147 case RTType: 147 148 return "RT" 149 + case AAAAType: 150 + return "AAAA" 148 151 case OPTType: 149 152 return "OPT" 150 153 case AXFRType: ··· 375 378 IntermediateHost string 376 379 } 377 380 381 + type AAAA struct { 382 + Address net.IP 383 + } 384 + 378 385 type EDNSOption struct { 379 386 Code uint16 380 387 Data []byte

History

1 round 0 comments
sign up or login to add to the discussion
seiso.moe submitted #0
1 commit
expand
add ipv6 resource records
expand 0 comments
pull request successfully merged