a go dns packet parser

Compare changes

Choose any two refs to compare.

+1
.tangled/lint.yml
···
when:
- event: ["push", "pull_request"]
+
branch: ["main"]
dependencies:
nix-pkgs:
+1
.tangled/test.yml
···
when:
- event: ["push", "pull_request"]
+
branch: ["main"]
dependencies:
nixpkgs:
+30 -1
resource_record.go
···
return nil, fmt.Errorf("A record: cannot encode non-IPv4 address %s", a.Address.String())
}
-
return append(bytes, a.Address.To4()...), nil
+
return append(bytes, ipv4...), nil
}
func (a A) String() string {
···
return fmt.Sprintf("%d %s", rt.Preference, rt.IntermediateHost)
}
+
func (a *AAAA) Decode(buf []byte, offset int, rdlength int) (int, error) {
+
bytes, offset, err := getSlice(buf, offset, rdlength)
+
if err != nil {
+
return offset, fmt.Errorf("AAAA record: failed to read address data: %w", err)
+
}
+
+
a.Address = net.IP(bytes)
+
if a.Address.To16() == nil {
+
return offset, fmt.Errorf("AAAA record: decoded data is not a valid IPv6 address: %v", bytes)
+
}
+
return offset, nil
+
}
+
+
func (a *AAAA) Encode(bytes []byte, offsets *map[string]uint16) ([]byte, error) {
+
ipv6 := a.Address.To16()
+
// XXX: ipv6 encodes ipv4 so need to check its not ipv4
+
if a.Address.To4() != nil || ipv6 == nil {
+
return nil, fmt.Errorf("AAAA record: cannot encode non-IPv6 address %s", a.Address.String())
+
}
+
+
return append(bytes, ipv6...), nil
+
}
+
+
func (a AAAA) String() string {
+
return a.Address.String()
+
}
+
func (opt *OPT) Decode(buf []byte, offset int, rdlength int) (int, error) {
// s := offset
opt.Options = make([]EDNSOption, 0)
···
r.RData = &ISDN{}
case 21:
r.RData = &RT{}
+
case 28:
+
r.RData = &AAAA{}
case 41:
r.RData = &OPT{}
default:
+30
resource_record_test.go
···
})
}
}
+
+
func TestAAAARecord(t *testing.T) {
+
addr := net.ParseIP("2001:db8::1")
+
rdataBytes := []byte(addr)
+
aaaa := &AAAA{}
+
+
offset, err := aaaa.Decode([]byte{}, 0, 16)
+
assert.Error(t, err, "Decode should fail with empty buffer")
+
assert.True(t, errors.Is(err, &BufferOverflowError{}))
+
+
offset, err = aaaa.Decode(rdataBytes, 0, 16)
+
assert.NoError(t, err)
+
assert.Equal(t, 16, offset)
+
assert.Equal(t, addr, aaaa.Address)
+
+
_, err = aaaa.Decode([]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, 0, 15)
+
assert.Error(t, err)
+
assert.Contains(t, err.Error(), "AAAA record:")
+
+
aaaaEncode := &AAAA{Address: addr}
+
encoded := encodeRData(t, aaaaEncode)
+
assert.Equal(t, rdataBytes, encoded)
+
+
ipv4 := net.ParseIP("192.168.1.1")
+
aaaaEncodeInvalid := &AAAA{Address: ipv4}
+
_, err = aaaaEncodeInvalid.Encode([]byte{}, &map[string]uint16{})
+
+
assert.Error(t, err)
+
assert.Contains(t, err.Error(), "cannot encode non-IPv6 address")
+
}
+7
types.go
···
X25Type = 19
ISDNType = 20
RTType = 21
+
AAAAType = 28
OPTType = 41
···
return "ISDN"
case RTType:
return "RT"
+
case AAAAType:
+
return "AAAA"
case OPTType:
return "OPT"
case AXFRType:
···
IntermediateHost string
}
+
type AAAA struct {
+
Address net.IP
+
}
+
type EDNSOption struct {
Code uint16
Data []byte