diff --git a/conn.go b/conn.go index 54254ae..048a624 100644 --- a/conn.go +++ b/conn.go @@ -17,6 +17,7 @@ type Conn struct { Address *AddressService Route *RouteService Neigh *NeighService + Rule *RuleService } var _ conn = &netlink.Conn{} @@ -54,6 +55,7 @@ func newConn(c conn) *Conn { rtc.Address = &AddressService{c: rtc} rtc.Route = &RouteService{c: rtc} rtc.Neigh = &NeighService{c: rtc} + rtc.Rule = &RuleService{c: rtc} return rtc } @@ -179,6 +181,8 @@ func unpackMessages(msgs []netlink.Message) ([]Message, error) { m = &RouteMessage{} case unix.RTM_GETNEIGH, unix.RTM_NEWNEIGH, unix.RTM_DELNEIGH: m = &NeighMessage{} + case unix.RTM_GETRULE, unix.RTM_NEWRULE, unix.RTM_DELRULE: + m = &RuleMessage{} default: continue } diff --git a/example_rule_list_test.go b/example_rule_list_test.go new file mode 100644 index 0000000..02647ce --- /dev/null +++ b/example_rule_list_test.go @@ -0,0 +1,27 @@ +package rtnetlink_test + +import ( + "log" + + "github.com/jsimonetti/rtnetlink" +) + +// List all rules +func Example_listRule() { + // Dial a connection to the rtnetlink socket + conn, err := rtnetlink.Dial(nil) + if err != nil { + log.Fatal(err) + } + defer conn.Close() + + // Request a list of rules + rules, err := conn.Rule.List() + if err != nil { + log.Fatal(err) + } + + for _, rule := range rules { + log.Printf("%+v", rule) + } +} diff --git a/fuzz.go b/fuzz.go index 8a2267e..5e176e0 100644 --- a/fuzz.go +++ b/fuzz.go @@ -58,3 +58,17 @@ func FuzzNeighMessage(data []byte) int { return 1 } + +// FuzzRuleMessage will fuzz a RuleMessage +func FuzzRuleMessage(data []byte) int { + m := &RuleMessage{} + if err := (m).UnmarshalBinary(data); err != nil { + return 0 + } + + if _, err := m.MarshalBinary(); err != nil { + panic(err) + } + + return 1 +} diff --git a/go.mod b/go.mod index 69e0525..af27a0f 100644 --- a/go.mod +++ b/go.mod @@ -6,5 +6,5 @@ require ( github.com/cilium/ebpf v0.8.1 github.com/google/go-cmp v0.5.7 github.com/mdlayher/netlink v1.6.0 - golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27 + golang.org/x/sys v0.0.0-20220408201424-a24fb2fb8a0f ) diff --git a/go.sum b/go.sum index 4f367f4..e7d4e64 100644 --- a/go.sum +++ b/go.sum @@ -34,6 +34,8 @@ golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27 h1:XDXtA5hveEEV8JB2l7nhMTp3t3cHp9ZpwcdjqyEWLlo= golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220408201424-a24fb2fb8a0f h1:8w7RhxzTVgUzw/AH/9mUV5q0vMgy40SQRursCcfmkCw= +golang.org/x/sys v0.0.0-20220408201424-a24fb2fb8a0f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= diff --git a/internal/unix/types_linux.go b/internal/unix/types_linux.go index 58bbaed..b9655e9 100644 --- a/internal/unix/types_linux.go +++ b/internal/unix/types_linux.go @@ -108,4 +108,32 @@ const ( RT_SCOPE_UNIVERSE = linux.RT_SCOPE_UNIVERSE RT_SCOPE_HOST = linux.RT_SCOPE_HOST RT_SCOPE_LINK = linux.RT_SCOPE_LINK + RTM_NEWRULE = linux.RTM_NEWRULE + RTM_GETRULE = linux.RTM_GETRULE + RTM_DELRULE = linux.RTM_DELRULE + FRA_UNSPEC = linux.FRA_UNSPEC + FRA_DST = linux.FRA_DST + FRA_SRC = linux.FRA_SRC + FRA_IIFNAME = linux.FRA_IIFNAME + FRA_GOTO = linux.FRA_GOTO + FRA_UNUSED2 = linux.FRA_UNUSED2 + FRA_PRIORITY = linux.FRA_PRIORITY + FRA_UNUSED3 = linux.FRA_UNUSED3 + FRA_UNUSED4 = linux.FRA_UNUSED4 + FRA_UNUSED5 = linux.FRA_UNUSED5 + FRA_FWMARK = linux.FRA_FWMARK + FRA_FLOW = linux.FRA_FLOW + FRA_TUN_ID = linux.FRA_TUN_ID + FRA_SUPPRESS_IFGROUP = linux.FRA_SUPPRESS_IFGROUP + FRA_SUPPRESS_PREFIXLEN = linux.FRA_SUPPRESS_PREFIXLEN + FRA_TABLE = linux.FRA_TABLE + FRA_FWMASK = linux.FRA_FWMASK + FRA_OIFNAME = linux.FRA_OIFNAME + FRA_PAD = linux.FRA_PAD + FRA_L3MDEV = linux.FRA_L3MDEV + FRA_UID_RANGE = linux.FRA_UID_RANGE + FRA_PROTOCOL = linux.FRA_PROTOCOL + FRA_IP_PROTO = linux.FRA_IP_PROTO + FRA_SPORT_RANGE = linux.FRA_SPORT_RANGE + FRA_DPORT_RANGE = linux.FRA_DPORT_RANGE ) diff --git a/internal/unix/types_other.go b/internal/unix/types_other.go index b98d4cc..39866ed 100644 --- a/internal/unix/types_other.go +++ b/internal/unix/types_other.go @@ -104,4 +104,32 @@ const ( RT_SCOPE_UNIVERSE = 0x0 RT_SCOPE_HOST = 0xfe RT_SCOPE_LINK = 0xfd + RTM_NEWRULE = 0x20 + RTM_GETRULE = 0x22 + RTM_DELRULE = 0x21 + FRA_UNSPEC = 0x0 + FRA_DST = 0x1 + FRA_SRC = 0x2 + FRA_IIFNAME = 0x3 + FRA_GOTO = 0x4 + FRA_UNUSED2 = 0x5 + FRA_PRIORITY = 0x6 + FRA_UNUSED3 = 0x7 + FRA_UNUSED4 = 0x8 + FRA_UNUSED5 = 0x9 + FRA_FWMARK = 0xa + FRA_FLOW = 0xb + FRA_TUN_ID = 0xc + FRA_SUPPRESS_IFGROUP = 0xd + FRA_SUPPRESS_PREFIXLEN = 0xe + FRA_TABLE = 0xf + FRA_FWMASK = 0x10 + FRA_OIFNAME = 0x11 + FRA_PAD = 0x12 + FRA_L3MDEV = 0x13 + FRA_UID_RANGE = 0x14 + FRA_PROTOCOL = 0x15 + FRA_IP_PROTO = 0x16 + FRA_SPORT_RANGE = 0x17 + FRA_DPORT_RANGE = 0x18 ) diff --git a/rule.go b/rule.go new file mode 100644 index 0000000..9d62b4f --- /dev/null +++ b/rule.go @@ -0,0 +1,394 @@ +package rtnetlink + +import ( + "bytes" + "encoding/binary" + "errors" + "net" + + "github.com/jsimonetti/rtnetlink/internal/unix" + "github.com/mdlayher/netlink" +) + +var ( + // errInvalidRuleMessage is returned when a RuleMessage is malformed. + errInvalidRuleMessage = errors.New("rtnetlink RuleMessage is invalid or too short") + + // errInvalidRuleAttribute is returned when a RuleMessage contains an unknown attribute. + errInvalidRuleAttribute = errors.New("rtnetlink RuleMessage contains an unknown Attribute") +) + +var _ Message = &RuleMessage{} + +// A RuleMessage is a route netlink link message. +type RuleMessage struct { + // Address family + Family uint8 + + // Length of destination prefix + DstLength uint8 + + // Length of source prefix + SrcLength uint8 + + // Rule TOS + TOS uint8 + + // Routing table identifier + Table uint8 + + // Rule action + Action uint8 + + // Rule flags + Flags uint32 + + // Attributes List + Attributes *RuleAttributes +} + +// MarshalBinary marshals a LinkMessage into a byte slice. +func (m *RuleMessage) MarshalBinary() ([]byte, error) { + b := make([]byte, 12) + + // fib_rule_hdr + b[0] = m.Family + b[1] = m.DstLength + b[2] = m.SrcLength + b[3] = m.TOS + b[4] = m.Table + b[7] = m.Action + nativeEndian.PutUint32(b[8:12], m.Flags) + + if m.Attributes != nil { + ae := netlink.NewAttributeEncoder() + ae.ByteOrder = nativeEndian + err := m.Attributes.encode(ae) + if err != nil { + return nil, err + } + + a, err := ae.Encode() + if err != nil { + return nil, err + } + + return append(b, a...), nil + } + + return b, nil +} + +// UnmarshalBinary unmarshals the contents of a byte slice into a LinkMessage. +func (m *RuleMessage) UnmarshalBinary(b []byte) error { + l := len(b) + if l < 12 { + return errInvalidRuleMessage + } + m.Family = b[0] + m.DstLength = b[1] + m.SrcLength = b[2] + m.TOS = b[3] + m.Table = b[4] + // b[5] and b[6] are reserved fields + m.Action = b[7] + m.Flags = nativeEndian.Uint32(b[8:12]) + + if l > 12 { + m.Attributes = &RuleAttributes{} + ad, err := netlink.NewAttributeDecoder(b[12:]) + if err != nil { + return err + } + ad.ByteOrder = nativeEndian + return m.Attributes.decode(ad) + } + return nil +} + +// rtMessage is an empty method to sattisfy the Message interface. +func (*RuleMessage) rtMessage() {} + +// RuleService is used to retrieve rtnetlink family information. +type RuleService struct { + c *Conn +} + +func (r *RuleService) execute(m Message, family uint16, flags netlink.HeaderFlags) ([]RuleMessage, error) { + msgs, err := r.c.Execute(m, family, flags) + + rules := make([]RuleMessage, len(msgs)) + for i := range msgs { + rules[i] = *msgs[i].(*RuleMessage) + } + + return rules, err +} + +// Add new rule +func (r *RuleService) Add(req *RuleMessage) error { + flags := netlink.Request | netlink.Create | netlink.Acknowledge | netlink.Excl + _, err := r.c.Execute(req, unix.RTM_NEWRULE, flags) + + return err +} + +// Replace or add new rule +func (r *RuleService) Replace(req *RuleMessage) error { + flags := netlink.Request | netlink.Create | netlink.Replace | netlink.Acknowledge + _, err := r.c.Execute(req, unix.RTM_NEWRULE, flags) + + return err +} + +// Delete existing rule +func (r *RuleService) Delete(req *RuleMessage) error { + flags := netlink.Request | netlink.Acknowledge + _, err := r.c.Execute(req, unix.RTM_DELRULE, flags) + + return err +} + +// Get Rule(s) +func (r *RuleService) Get(req *RuleMessage) ([]RuleMessage, error) { + flags := netlink.Request | netlink.DumpFiltered + return r.execute(req, unix.RTM_GETRULE, flags) +} + +// List all rules +func (r *RuleService) List() ([]RuleMessage, error) { + flags := netlink.Request | netlink.Dump + return r.execute(&RuleMessage{}, unix.RTM_GETRULE, flags) +} + +// RuleAttributes contains all attributes for a rule. +type RuleAttributes struct { + Src, Dst *net.IP + IIFName, OIFName *string + Goto *uint32 + Priority *uint32 + FwMark, FwMask *uint32 + SrcRealm *uint16 + DstRealm *uint16 + TunID *uint64 + Table *uint32 + L3MDev *uint8 + Protocol *uint8 + IPProto *uint8 + SuppressPrefixLen *uint32 + SuppressIFGroup *uint32 + UIDRange *RuleUIDRange + SPortRange *RulePortRange + DPortRange *RulePortRange +} + +// unmarshalBinary unmarshals the contents of a byte slice into a RuleMessage. +func (r *RuleAttributes) decode(ad *netlink.AttributeDecoder) error { + for ad.Next() { + switch ad.Type() { + case unix.FRA_UNSPEC: + // unused + continue + case unix.FRA_DST: + r.Dst = &net.IP{} + ad.Do(decodeIP(r.Dst)) + case unix.FRA_SRC: + r.Src = &net.IP{} + ad.Do(decodeIP(r.Src)) + case unix.FRA_IIFNAME: + v := ad.String() + r.IIFName = &v + case unix.FRA_GOTO: + v := ad.Uint32() + r.Goto = &v + case unix.FRA_UNUSED2: + // unused + continue + case unix.FRA_PRIORITY: + v := ad.Uint32() + r.Priority = &v + case unix.FRA_UNUSED3: + // unused + continue + case unix.FRA_UNUSED4: + // unused + continue + case unix.FRA_UNUSED5: + // unused + continue + case unix.FRA_FWMARK: + v := ad.Uint32() + r.FwMark = &v + case unix.FRA_FLOW: + dst32 := ad.Uint32() + src32 := uint32(dst32 >> 16) + src32 &= 0xFFFF + dst32 &= 0xFFFF + src16 := uint16(src32) + dst16 := uint16(dst32) + r.SrcRealm = &src16 + r.DstRealm = &dst16 + case unix.FRA_TUN_ID: + v := ad.Uint64() + r.TunID = &v + case unix.FRA_SUPPRESS_IFGROUP: + v := ad.Uint32() + r.SuppressIFGroup = &v + case unix.FRA_SUPPRESS_PREFIXLEN: + v := ad.Uint32() + r.SuppressPrefixLen = &v + case unix.FRA_TABLE: + v := ad.Uint32() + r.Table = &v + case unix.FRA_FWMASK: + v := ad.Uint32() + r.FwMask = &v + case unix.FRA_OIFNAME: + v := ad.String() + r.OIFName = &v + case unix.FRA_PAD: + // unused + continue + case unix.FRA_L3MDEV: + v := ad.Uint8() + r.L3MDev = &v + case unix.FRA_UID_RANGE: + r.UIDRange = &RuleUIDRange{} + err := r.UIDRange.unmarshalBinary(ad.Bytes()) + if err != nil { + return err + } + case unix.FRA_PROTOCOL: + v := ad.Uint8() + r.Protocol = &v + case unix.FRA_IP_PROTO: + v := ad.Uint8() + r.IPProto = &v + case unix.FRA_SPORT_RANGE: + r.SPortRange = &RulePortRange{} + err := r.SPortRange.unmarshalBinary(ad.Bytes()) + if err != nil { + return err + } + case unix.FRA_DPORT_RANGE: + r.DPortRange = &RulePortRange{} + err := r.DPortRange.unmarshalBinary(ad.Bytes()) + if err != nil { + return err + } + default: + return errInvalidRuleAttribute + } + } + return ad.Err() +} + +// MarshalBinary marshals a RuleAttributes into a byte slice. +func (r *RuleAttributes) encode(ae *netlink.AttributeEncoder) error { + if r.Table != nil { + ae.Uint32(unix.FRA_TABLE, *r.Table) + } + if r.Protocol != nil { + ae.Uint8(unix.FRA_PROTOCOL, *r.Protocol) + } + if r.Src != nil { + ae.Do(unix.FRA_SRC, encodeIP(*r.Src)) + } + if r.Dst != nil { + ae.Do(unix.FRA_DST, encodeIP(*r.Dst)) + } + if r.IIFName != nil { + ae.String(unix.FRA_IIFNAME, *r.IIFName) + } + if r.OIFName != nil { + ae.String(unix.FRA_OIFNAME, *r.OIFName) + } + if r.Goto != nil { + ae.Uint32(unix.FRA_GOTO, *r.Goto) + } + if r.Priority != nil { + ae.Uint32(unix.FRA_PRIORITY, *r.Priority) + } + if r.FwMark != nil { + ae.Uint32(unix.FRA_FWMARK, *r.FwMark) + } + if r.FwMask != nil { + ae.Uint32(unix.FRA_FWMASK, *r.FwMask) + } + if r.DstRealm != nil { + value := uint32(*r.DstRealm) + if r.SrcRealm != nil { + value |= (uint32(*r.SrcRealm&0xFFFF) << 16) + } + ae.Uint32(unix.FRA_FLOW, value) + } + if r.TunID != nil { + ae.Uint64(unix.FRA_TUN_ID, *r.TunID) + } + if r.L3MDev != nil { + ae.Uint8(unix.FRA_L3MDEV, *r.L3MDev) + } + if r.IPProto != nil { + ae.Uint8(unix.FRA_IP_PROTO, *r.IPProto) + } + if r.SuppressIFGroup != nil { + ae.Uint32(unix.FRA_SUPPRESS_IFGROUP, *r.SuppressIFGroup) + } + if r.SuppressPrefixLen != nil { + ae.Uint32(unix.FRA_SUPPRESS_PREFIXLEN, *r.SuppressPrefixLen) + } + if r.UIDRange != nil { + data, err := marshalRuleUIDRange(*r.UIDRange) + if err != nil { + return err + } + ae.Bytes(unix.FRA_UID_RANGE, data) + } + if r.SPortRange != nil { + data, err := marshalRulePortRange(*r.SPortRange) + if err != nil { + return err + } + ae.Bytes(unix.FRA_SPORT_RANGE, data) + } + if r.DPortRange != nil { + data, err := marshalRulePortRange(*r.DPortRange) + if err != nil { + return err + } + ae.Bytes(unix.FRA_DPORT_RANGE, data) + } + return nil +} + +// RulePortRange defines start and end ports for a rule +type RulePortRange struct { + Start, End uint16 +} + +func (r *RulePortRange) unmarshalBinary(data []byte) error { + b := bytes.NewReader(data) + return binary.Read(b, nativeEndian, r) +} + +func marshalRulePortRange(s RulePortRange) ([]byte, error) { + var buf bytes.Buffer + err := binary.Write(&buf, nativeEndian, s) + return buf.Bytes(), err +} + +// RuleUIDRange defines the start and end for UID matches +type RuleUIDRange struct { + Start, End uint16 +} + +func (r *RuleUIDRange) unmarshalBinary(data []byte) error { + b := bytes.NewReader(data) + return binary.Read(b, nativeEndian, r) +} + +func marshalRuleUIDRange(s RuleUIDRange) ([]byte, error) { + var buf bytes.Buffer + err := binary.Write(&buf, nativeEndian, s) + return buf.Bytes(), err +} diff --git a/rule_test.go b/rule_test.go new file mode 100644 index 0000000..97c822f --- /dev/null +++ b/rule_test.go @@ -0,0 +1,200 @@ +package rtnetlink + +import ( + "bytes" + "errors" + "net" + "reflect" + "testing" +) + +func TestRuleMessage(t *testing.T) { + skipBigEndian(t) + + tests := map[string]struct { + m Message + b []byte + marshalErr error + unmarshalErr error + }{ + "empty": { + m: &RuleMessage{}, + b: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + }, + "no attributes": { + m: &RuleMessage{ + Family: 1, + DstLength: 2, + SrcLength: 3, + TOS: 4, + Table: 5, + Action: 6, + Flags: 7, + }, + b: []byte{0x01, 0x02, 0x03, 0x04, 0x05, 0x00, 0x00, 0x06, 0x07, 0x00, 0x00, 0x00}, + }, + "with attributes": { + m: &RuleMessage{ + Family: 7, + DstLength: 6, + SrcLength: 5, + TOS: 4, + Table: 3, + Action: 2, + Flags: 1, + Attributes: &RuleAttributes{ + Src: netIPPtr(net.ParseIP("8.8.8.8")), + Dst: netIPPtr(net.ParseIP("1.1.1.1")), + IIFName: strPtr("eth0"), + OIFName: strPtr("br0"), + Goto: uint32Ptr(1), + Priority: uint32Ptr(2), + FwMark: uint32Ptr(3), + FwMask: uint32Ptr(5), + L3MDev: uint8Ptr(7), + DstRealm: uint16Ptr(11), + SrcRealm: uint16Ptr(13), + TunID: uint64Ptr(17), + Protocol: uint8Ptr(19), + IPProto: uint8Ptr(23), + Table: uint32Ptr(29), + SuppressPrefixLen: uint32Ptr(31), + SuppressIFGroup: uint32Ptr(37), + UIDRange: &RuleUIDRange{ + Start: 22, + End: 25, + }, + SPortRange: &RulePortRange{ + Start: 23, + End: 26, + }, + DPortRange: &RulePortRange{ + Start: 24, + End: 27, + }, + }, + }, + b: []byte{ + 0x07, 0x06, 0x05, 0x04, 0x03, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, + 0x0f, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x05, 0x00, 0x15, 0x00, 0x13, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x02, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x01, 0x00, 0x01, 0x01, + 0x01, 0x01, 0x09, 0x00, 0x03, 0x00, 0x65, 0x74, 0x68, 0x30, 0x00, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x11, 0x00, 0x62, 0x72, 0x30, 0x00, 0x08, 0x00, 0x04, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x08, 0x00, 0x06, 0x00, 0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0a, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x08, 0x00, 0x10, 0x00, 0x05, 0x00, 0x00, 0x00, 0x08, 0x00, + 0x0b, 0x00, 0x0b, 0x00, 0x0d, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x11, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x13, 0x00, 0x07, 0x00, 0x00, 0x00, 0x05, 0x00, + 0x16, 0x00, 0x17, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0d, 0x00, 0x25, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x0e, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x08, 0x00, 0x14, 0x00, 0x16, 0x00, + 0x19, 0x00, 0x08, 0x00, 0x17, 0x00, 0x17, 0x00, 0x1a, 0x00, 0x08, 0x00, 0x18, 0x00, + 0x18, 0x00, 0x1b, 0x00, + }, + }, + } + + for name, tt := range tests { + t.Run(name, func(t *testing.T) { + var b []byte + t.Run("marshal", func(t *testing.T) { + var marshalErr error + b, marshalErr = tt.m.MarshalBinary() + + if !errors.Is(marshalErr, tt.marshalErr) { + t.Fatalf("Expected error '%v' but got '%v'", tt.marshalErr, marshalErr) + } + }) + + t.Run("compare bytes", func(t *testing.T) { + if want, got := tt.b, b; !bytes.Equal(want, got) { + t.Fatalf("unexpected Message bytes:\n- want: [%# x]\n- got: [%# x]", want, got) + } + }) + + m := &RuleMessage{} + t.Run("unmarshal", func(t *testing.T) { + unmarshalErr := (m).UnmarshalBinary(b) + if !errors.Is(unmarshalErr, tt.unmarshalErr) { + t.Fatalf("Expected error '%v' but got '%v'", tt.unmarshalErr, unmarshalErr) + } + }) + + t.Run("compare messages", func(t *testing.T) { + if !reflect.DeepEqual(tt.m, m) { + t.Fatalf("unexpected Message:\n- want: %#v\n- got: %#v", tt.m, m) + } + }) + }) + } + + t.Run("invalid length", func(t *testing.T) { + m := &RuleMessage{} + unmarshalErr := (m).UnmarshalBinary([]byte{0x00, 0x01, 0x2, 0x03}) + if !errors.Is(unmarshalErr, errInvalidRuleMessage) { + t.Fatalf("Expected 'errInvalidRuleMessage' but got '%v'", unmarshalErr) + } + }) + + t.Run("skipped attributes", func(t *testing.T) { + m := &RuleMessage{} + unmarshalErr := (m).UnmarshalBinary([]byte{ + 0x01, 0x00, 0x00, 0x02, 0x03, 0x00, 0x00, 0x04, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, + 0x00, 0x00, 0x04, 0x00, 0x05, 0x00, 0x04, 0x00, 0x07, 0x00, 0x04, 0x00, 0x08, 0x00, + 0x04, 0x00, 0x09, 0x00, 0x04, 0x00, 0x12, 0x00, + }) + if !errors.Is(unmarshalErr, nil) { + t.Fatalf("Expected no error but got '%v'", unmarshalErr) + } + expected := &RuleMessage{ + Family: 1, + TOS: 2, + Table: 3, + Action: 4, + Flags: 5, + Attributes: &RuleAttributes{}, + } + if !reflect.DeepEqual(expected, m) { + t.Fatalf("unexpected Message:\n- want: %#v\n- got: %#v", expected, m) + } + }) + + t.Run("invalid attribute", func(t *testing.T) { + m := &RuleMessage{} + unmarshalErr := (m).UnmarshalBinary([]byte{ + 0x01, 0x00, 0x00, 0x02, 0x03, 0x00, 0x00, 0x04, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, + 0x2a, 0x00, + }) + if !errors.Is(unmarshalErr, errInvalidRuleAttribute) { + t.Fatalf("Expected 'errInvalidRuleAttribute' error but got '%v'", unmarshalErr) + } + }) +} + +func uint64Ptr(v uint64) *uint64 { + return &v +} + +func uint32Ptr(v uint32) *uint32 { + return &v +} + +func uint16Ptr(v uint16) *uint16 { + return &v +} + +func uint8Ptr(v uint8) *uint8 { + return &v +} + +func netIPPtr(v net.IP) *net.IP { + if ip4 := v.To4(); ip4 != nil { + // By default net.IP returns the 16 byte representation. + // But netlink requires us to provide only four bytes + // for legacy IPs. + return &ip4 + } + return &v +} + +func strPtr(v string) *string { + return &v +} diff --git a/testdata/corpus/000c54925a3391eba539f847d3c4937a22a82a50-20 b/testdata/corpus/000c54925a3391eba539f847d3c4937a22a82a50-20 new file mode 100644 index 0000000..6827c5e Binary files /dev/null and b/testdata/corpus/000c54925a3391eba539f847d3c4937a22a82a50-20 differ diff --git a/testdata/corpus/009c1e6326977ed570af9d0a3d82cbe44150fb0e-23 b/testdata/corpus/009c1e6326977ed570af9d0a3d82cbe44150fb0e-23 new file mode 100644 index 0000000..f44c95c Binary files /dev/null and b/testdata/corpus/009c1e6326977ed570af9d0a3d82cbe44150fb0e-23 differ diff --git a/testdata/corpus/00b211ddd3949e326bbcb839b5676b98da7e8446-25 b/testdata/corpus/00b211ddd3949e326bbcb839b5676b98da7e8446-25 new file mode 100644 index 0000000..2e66c8d Binary files /dev/null and b/testdata/corpus/00b211ddd3949e326bbcb839b5676b98da7e8446-25 differ diff --git a/testdata/corpus/038b07fe763eeff1f396be5d2b20093f7506a1ad-20 b/testdata/corpus/038b07fe763eeff1f396be5d2b20093f7506a1ad-20 new file mode 100644 index 0000000..35f7e56 Binary files /dev/null and b/testdata/corpus/038b07fe763eeff1f396be5d2b20093f7506a1ad-20 differ diff --git a/testdata/corpus/041f0e6825e25cb64a77c98991b7377577fe7597-29 b/testdata/corpus/041f0e6825e25cb64a77c98991b7377577fe7597-29 new file mode 100644 index 0000000..c7279df Binary files /dev/null and b/testdata/corpus/041f0e6825e25cb64a77c98991b7377577fe7597-29 differ diff --git a/testdata/corpus/099c634ff82ad664151d46cb60b97069d441a407-26 b/testdata/corpus/099c634ff82ad664151d46cb60b97069d441a407-26 new file mode 100644 index 0000000..3e35ac3 Binary files /dev/null and b/testdata/corpus/099c634ff82ad664151d46cb60b97069d441a407-26 differ diff --git a/testdata/corpus/0b942a751646e82a0105ac6886368617cc46a414-23 b/testdata/corpus/0b942a751646e82a0105ac6886368617cc46a414-23 new file mode 100644 index 0000000..b3a7eb3 Binary files /dev/null and b/testdata/corpus/0b942a751646e82a0105ac6886368617cc46a414-23 differ diff --git a/testdata/corpus/0e6c24ef9886932fc194197746267d78fde85fdf-20 b/testdata/corpus/0e6c24ef9886932fc194197746267d78fde85fdf-20 new file mode 100644 index 0000000..3a00dba Binary files /dev/null and b/testdata/corpus/0e6c24ef9886932fc194197746267d78fde85fdf-20 differ diff --git a/testdata/corpus/10cdf79db931be0fe2187daab653329f9088ab93-24 b/testdata/corpus/10cdf79db931be0fe2187daab653329f9088ab93-24 new file mode 100644 index 0000000..f1b6071 Binary files /dev/null and b/testdata/corpus/10cdf79db931be0fe2187daab653329f9088ab93-24 differ diff --git a/testdata/corpus/10f2b0ec0e92605d64c22e84712f8f449c587652-28 b/testdata/corpus/10f2b0ec0e92605d64c22e84712f8f449c587652-28 new file mode 100644 index 0000000..6d215f2 Binary files /dev/null and b/testdata/corpus/10f2b0ec0e92605d64c22e84712f8f449c587652-28 differ diff --git a/testdata/corpus/132ef7a47eac7d01f07b3c7266aaa69b9208c3f1-19 b/testdata/corpus/132ef7a47eac7d01f07b3c7266aaa69b9208c3f1-19 new file mode 100644 index 0000000..1e4e4e2 Binary files /dev/null and b/testdata/corpus/132ef7a47eac7d01f07b3c7266aaa69b9208c3f1-19 differ diff --git a/testdata/corpus/133c6203a11d34d494460e0ccd5860bc8e56c8b1-24 b/testdata/corpus/133c6203a11d34d494460e0ccd5860bc8e56c8b1-24 new file mode 100644 index 0000000..c30838d Binary files /dev/null and b/testdata/corpus/133c6203a11d34d494460e0ccd5860bc8e56c8b1-24 differ diff --git a/testdata/corpus/144b30b754b40adc16300bede112114a23f7874e-21 b/testdata/corpus/144b30b754b40adc16300bede112114a23f7874e-21 new file mode 100644 index 0000000..cbb43a2 Binary files /dev/null and b/testdata/corpus/144b30b754b40adc16300bede112114a23f7874e-21 differ diff --git a/testdata/corpus/149a633ccd3b6b6209876c15406b9dbd43bc001d-26 b/testdata/corpus/149a633ccd3b6b6209876c15406b9dbd43bc001d-26 new file mode 100644 index 0000000..dcdd725 Binary files /dev/null and b/testdata/corpus/149a633ccd3b6b6209876c15406b9dbd43bc001d-26 differ diff --git a/testdata/corpus/14ff3db06a25e33c6abe888f59f0ea0d17c615f9-25 b/testdata/corpus/14ff3db06a25e33c6abe888f59f0ea0d17c615f9-25 new file mode 100644 index 0000000..a3533ec Binary files /dev/null and b/testdata/corpus/14ff3db06a25e33c6abe888f59f0ea0d17c615f9-25 differ diff --git a/testdata/corpus/15dc0cfaddd1bbd33c62ea16c339d520cb654616-22 b/testdata/corpus/15dc0cfaddd1bbd33c62ea16c339d520cb654616-22 new file mode 100644 index 0000000..a34a94e Binary files /dev/null and b/testdata/corpus/15dc0cfaddd1bbd33c62ea16c339d520cb654616-22 differ diff --git a/testdata/corpus/1898cf2be9f0d73cab589f7a4baffab3b5024fe8-25 b/testdata/corpus/1898cf2be9f0d73cab589f7a4baffab3b5024fe8-25 new file mode 100644 index 0000000..3ffe6d6 Binary files /dev/null and b/testdata/corpus/1898cf2be9f0d73cab589f7a4baffab3b5024fe8-25 differ diff --git a/testdata/corpus/1bf05fd9f40c46905b81b22da21bb5ac3c51e0a2-23 b/testdata/corpus/1bf05fd9f40c46905b81b22da21bb5ac3c51e0a2-23 new file mode 100644 index 0000000..2dce38b Binary files /dev/null and b/testdata/corpus/1bf05fd9f40c46905b81b22da21bb5ac3c51e0a2-23 differ diff --git a/testdata/corpus/1c3817eb0b0b278583ecdb4bf3f0eb20570e7bde-25 b/testdata/corpus/1c3817eb0b0b278583ecdb4bf3f0eb20570e7bde-25 new file mode 100644 index 0000000..7d1fb84 Binary files /dev/null and b/testdata/corpus/1c3817eb0b0b278583ecdb4bf3f0eb20570e7bde-25 differ diff --git a/testdata/corpus/1da46a06af7e4f65ba414cbad322e8bdb7035003-27 b/testdata/corpus/1da46a06af7e4f65ba414cbad322e8bdb7035003-27 new file mode 100644 index 0000000..536fdaf Binary files /dev/null and b/testdata/corpus/1da46a06af7e4f65ba414cbad322e8bdb7035003-27 differ diff --git a/testdata/corpus/24026c2a921f527c2c61e9947f5d0f8c44b4bccc-30 b/testdata/corpus/24026c2a921f527c2c61e9947f5d0f8c44b4bccc-30 new file mode 100644 index 0000000..7981a8d Binary files /dev/null and b/testdata/corpus/24026c2a921f527c2c61e9947f5d0f8c44b4bccc-30 differ diff --git a/testdata/corpus/257b03bc2f1d85a55384eb973ad36fbb824ca6f3-28 b/testdata/corpus/257b03bc2f1d85a55384eb973ad36fbb824ca6f3-28 new file mode 100644 index 0000000..afb5c6b Binary files /dev/null and b/testdata/corpus/257b03bc2f1d85a55384eb973ad36fbb824ca6f3-28 differ diff --git a/testdata/corpus/2592ea9e0fd7b42419b54de73c05d2d99b13df24-18 b/testdata/corpus/2592ea9e0fd7b42419b54de73c05d2d99b13df24-18 new file mode 100644 index 0000000..d510f55 Binary files /dev/null and b/testdata/corpus/2592ea9e0fd7b42419b54de73c05d2d99b13df24-18 differ diff --git a/testdata/corpus/26b2b4d750c52d006493c4e319ba349658d4a61f-26 b/testdata/corpus/26b2b4d750c52d006493c4e319ba349658d4a61f-26 new file mode 100644 index 0000000..7b0d4b8 Binary files /dev/null and b/testdata/corpus/26b2b4d750c52d006493c4e319ba349658d4a61f-26 differ diff --git a/testdata/corpus/2c35a00089c0fb60511083386c7033e1f4347143-22 b/testdata/corpus/2c35a00089c0fb60511083386c7033e1f4347143-22 new file mode 100644 index 0000000..7e9446e Binary files /dev/null and b/testdata/corpus/2c35a00089c0fb60511083386c7033e1f4347143-22 differ diff --git a/testdata/corpus/35cbabd1b4813019bc384933383dd526d18d59e2-26 b/testdata/corpus/35cbabd1b4813019bc384933383dd526d18d59e2-26 new file mode 100644 index 0000000..6b8b89c Binary files /dev/null and b/testdata/corpus/35cbabd1b4813019bc384933383dd526d18d59e2-26 differ diff --git a/testdata/corpus/36786d46f73cb119fc6638c6e29fb2e9c74396e2-26 b/testdata/corpus/36786d46f73cb119fc6638c6e29fb2e9c74396e2-26 new file mode 100644 index 0000000..2f279c7 Binary files /dev/null and b/testdata/corpus/36786d46f73cb119fc6638c6e29fb2e9c74396e2-26 differ diff --git a/testdata/corpus/3ad77e9956ebcb9e0b0072103c2f6f681be6b536-21 b/testdata/corpus/3ad77e9956ebcb9e0b0072103c2f6f681be6b536-21 new file mode 100644 index 0000000..8255da8 Binary files /dev/null and b/testdata/corpus/3ad77e9956ebcb9e0b0072103c2f6f681be6b536-21 differ diff --git a/testdata/corpus/3f98fdf1ac7b64c5e3d99c164821c1fafb740063-24 b/testdata/corpus/3f98fdf1ac7b64c5e3d99c164821c1fafb740063-24 new file mode 100644 index 0000000..9da27c3 Binary files /dev/null and b/testdata/corpus/3f98fdf1ac7b64c5e3d99c164821c1fafb740063-24 differ diff --git a/testdata/corpus/421f3fe64fd443a5e2311b6b91d4444df441f420-24 b/testdata/corpus/421f3fe64fd443a5e2311b6b91d4444df441f420-24 new file mode 100644 index 0000000..ad5fbe8 Binary files /dev/null and b/testdata/corpus/421f3fe64fd443a5e2311b6b91d4444df441f420-24 differ diff --git a/testdata/corpus/43b3231898ad43ca71f2e5676fe3d996eee720af-22 b/testdata/corpus/43b3231898ad43ca71f2e5676fe3d996eee720af-22 new file mode 100644 index 0000000..ccc9da4 Binary files /dev/null and b/testdata/corpus/43b3231898ad43ca71f2e5676fe3d996eee720af-22 differ diff --git a/testdata/corpus/43cf95eed2b63d204c5e5c488cf27382124e5ccf-28 b/testdata/corpus/43cf95eed2b63d204c5e5c488cf27382124e5ccf-28 new file mode 100644 index 0000000..7596983 Binary files /dev/null and b/testdata/corpus/43cf95eed2b63d204c5e5c488cf27382124e5ccf-28 differ diff --git a/testdata/corpus/4602005c8b057564c7915fb995d9b5493e43c8b8-23 b/testdata/corpus/4602005c8b057564c7915fb995d9b5493e43c8b8-23 new file mode 100644 index 0000000..dd7d3a6 Binary files /dev/null and b/testdata/corpus/4602005c8b057564c7915fb995d9b5493e43c8b8-23 differ diff --git a/testdata/corpus/46f7d66e2363f6cf626df43782fbb422f9a5250b-22 b/testdata/corpus/46f7d66e2363f6cf626df43782fbb422f9a5250b-22 new file mode 100644 index 0000000..c89db95 Binary files /dev/null and b/testdata/corpus/46f7d66e2363f6cf626df43782fbb422f9a5250b-22 differ diff --git a/testdata/corpus/49ed76feb9bc20c4ad39a26a31d481f6e3efb001-26 b/testdata/corpus/49ed76feb9bc20c4ad39a26a31d481f6e3efb001-26 new file mode 100644 index 0000000..0cf34b1 Binary files /dev/null and b/testdata/corpus/49ed76feb9bc20c4ad39a26a31d481f6e3efb001-26 differ diff --git a/testdata/corpus/4a2ee3a20fdea57760bc9ed8b8eff048044b22c5-19 b/testdata/corpus/4a2ee3a20fdea57760bc9ed8b8eff048044b22c5-19 new file mode 100644 index 0000000..e1b5bcc Binary files /dev/null and b/testdata/corpus/4a2ee3a20fdea57760bc9ed8b8eff048044b22c5-19 differ diff --git a/testdata/corpus/4faa81537e211ad2a5e7c2976e9068326f7b8ae5-22 b/testdata/corpus/4faa81537e211ad2a5e7c2976e9068326f7b8ae5-22 new file mode 100644 index 0000000..5c3d1ed Binary files /dev/null and b/testdata/corpus/4faa81537e211ad2a5e7c2976e9068326f7b8ae5-22 differ diff --git a/testdata/corpus/507831810eb04b0ab951b933c46e35a228b57e71-26 b/testdata/corpus/507831810eb04b0ab951b933c46e35a228b57e71-26 new file mode 100644 index 0000000..035b66b Binary files /dev/null and b/testdata/corpus/507831810eb04b0ab951b933c46e35a228b57e71-26 differ diff --git a/testdata/corpus/510580a628376865dc1af7d36bb17342f1b7afd6-15 b/testdata/corpus/510580a628376865dc1af7d36bb17342f1b7afd6-15 new file mode 100644 index 0000000..719f1ad Binary files /dev/null and b/testdata/corpus/510580a628376865dc1af7d36bb17342f1b7afd6-15 differ diff --git a/testdata/corpus/53ee26032f00098aee0f1a18f06c43bd7deff445-22 b/testdata/corpus/53ee26032f00098aee0f1a18f06c43bd7deff445-22 new file mode 100644 index 0000000..2795bc8 Binary files /dev/null and b/testdata/corpus/53ee26032f00098aee0f1a18f06c43bd7deff445-22 differ diff --git a/testdata/corpus/5b262a86f4e870e5a8bb6ba2b61b72b4b28afdab-15 b/testdata/corpus/5b262a86f4e870e5a8bb6ba2b61b72b4b28afdab-15 new file mode 100644 index 0000000..fd8bedb Binary files /dev/null and b/testdata/corpus/5b262a86f4e870e5a8bb6ba2b61b72b4b28afdab-15 differ diff --git a/testdata/corpus/5bd1e85c8266889abce74d54a8405220a5ee6779-22 b/testdata/corpus/5bd1e85c8266889abce74d54a8405220a5ee6779-22 new file mode 100644 index 0000000..b3c2d89 Binary files /dev/null and b/testdata/corpus/5bd1e85c8266889abce74d54a8405220a5ee6779-22 differ diff --git a/testdata/corpus/5c96e253b991e3683b48e88b521324924cb20489-23 b/testdata/corpus/5c96e253b991e3683b48e88b521324924cb20489-23 new file mode 100644 index 0000000..e7aa4c8 Binary files /dev/null and b/testdata/corpus/5c96e253b991e3683b48e88b521324924cb20489-23 differ diff --git a/testdata/corpus/5d45a18789afa6bfe420f3b92624733e1b6b400d-26 b/testdata/corpus/5d45a18789afa6bfe420f3b92624733e1b6b400d-26 new file mode 100644 index 0000000..93a0efd Binary files /dev/null and b/testdata/corpus/5d45a18789afa6bfe420f3b92624733e1b6b400d-26 differ diff --git a/testdata/corpus/5fee9480466c6bd457ab0973ed1773f201423dcf-22 b/testdata/corpus/5fee9480466c6bd457ab0973ed1773f201423dcf-22 new file mode 100644 index 0000000..4f63301 Binary files /dev/null and b/testdata/corpus/5fee9480466c6bd457ab0973ed1773f201423dcf-22 differ diff --git a/testdata/corpus/6137580c2219d8be74dddc0f34ecd2db3c53f4f6-22 b/testdata/corpus/6137580c2219d8be74dddc0f34ecd2db3c53f4f6-22 new file mode 100644 index 0000000..bbd1126 Binary files /dev/null and b/testdata/corpus/6137580c2219d8be74dddc0f34ecd2db3c53f4f6-22 differ diff --git a/testdata/corpus/62c46be36964f1e076447829594dfb379860946a-16 b/testdata/corpus/62c46be36964f1e076447829594dfb379860946a-16 new file mode 100644 index 0000000..755930d Binary files /dev/null and b/testdata/corpus/62c46be36964f1e076447829594dfb379860946a-16 differ diff --git a/testdata/corpus/6daf24135b70a74d6c4b227044fa6ddce6b07fe3-20 b/testdata/corpus/6daf24135b70a74d6c4b227044fa6ddce6b07fe3-20 new file mode 100644 index 0000000..47b7989 Binary files /dev/null and b/testdata/corpus/6daf24135b70a74d6c4b227044fa6ddce6b07fe3-20 differ diff --git a/testdata/corpus/710e3342b121a02db40b8bbdeb24ead8dadfd7cd-21 b/testdata/corpus/710e3342b121a02db40b8bbdeb24ead8dadfd7cd-21 new file mode 100644 index 0000000..175af76 Binary files /dev/null and b/testdata/corpus/710e3342b121a02db40b8bbdeb24ead8dadfd7cd-21 differ diff --git a/testdata/corpus/73faac654b2668bdeda7c30be1dd134c3bed0c1c-15 b/testdata/corpus/73faac654b2668bdeda7c30be1dd134c3bed0c1c-15 new file mode 100644 index 0000000..d938a56 Binary files /dev/null and b/testdata/corpus/73faac654b2668bdeda7c30be1dd134c3bed0c1c-15 differ diff --git a/testdata/corpus/754a426dbe41c2a53fd38308992ec6c98bf1ba0c-23 b/testdata/corpus/754a426dbe41c2a53fd38308992ec6c98bf1ba0c-23 new file mode 100644 index 0000000..a79efcc Binary files /dev/null and b/testdata/corpus/754a426dbe41c2a53fd38308992ec6c98bf1ba0c-23 differ diff --git a/testdata/corpus/75867803304877cf925c2fb8339867de26e0125a-22 b/testdata/corpus/75867803304877cf925c2fb8339867de26e0125a-22 new file mode 100644 index 0000000..cc210f0 Binary files /dev/null and b/testdata/corpus/75867803304877cf925c2fb8339867de26e0125a-22 differ diff --git a/testdata/corpus/7844bd2f24c49dd9e86b785f35b9f6654dcd30ea-24 b/testdata/corpus/7844bd2f24c49dd9e86b785f35b9f6654dcd30ea-24 new file mode 100644 index 0000000..11e0f1a Binary files /dev/null and b/testdata/corpus/7844bd2f24c49dd9e86b785f35b9f6654dcd30ea-24 differ diff --git a/testdata/corpus/7852ae0ac17fc6d9c941454945ce6e319aef222e-22 b/testdata/corpus/7852ae0ac17fc6d9c941454945ce6e319aef222e-22 new file mode 100644 index 0000000..5f14db1 Binary files /dev/null and b/testdata/corpus/7852ae0ac17fc6d9c941454945ce6e319aef222e-22 differ diff --git a/testdata/corpus/78f7070e047be466596fa9028fa7103ba851d238-25 b/testdata/corpus/78f7070e047be466596fa9028fa7103ba851d238-25 new file mode 100644 index 0000000..ac2b37f Binary files /dev/null and b/testdata/corpus/78f7070e047be466596fa9028fa7103ba851d238-25 differ diff --git a/testdata/corpus/79079a1b4dd13427a4dd4b3cedc1bbcb7e1d2368-19 b/testdata/corpus/79079a1b4dd13427a4dd4b3cedc1bbcb7e1d2368-19 new file mode 100644 index 0000000..85754f2 Binary files /dev/null and b/testdata/corpus/79079a1b4dd13427a4dd4b3cedc1bbcb7e1d2368-19 differ diff --git a/testdata/corpus/799960a900389c990c5303154e1a01d236bd991f-17 b/testdata/corpus/799960a900389c990c5303154e1a01d236bd991f-17 new file mode 100644 index 0000000..378de72 Binary files /dev/null and b/testdata/corpus/799960a900389c990c5303154e1a01d236bd991f-17 differ diff --git a/testdata/corpus/7ab0cd930c99f2a2044a39dd42ce15dad185aab2-27 b/testdata/corpus/7ab0cd930c99f2a2044a39dd42ce15dad185aab2-27 new file mode 100644 index 0000000..8cf8a63 Binary files /dev/null and b/testdata/corpus/7ab0cd930c99f2a2044a39dd42ce15dad185aab2-27 differ diff --git a/testdata/corpus/7c8ed8a74e3b25b9ab2af412684d3e78f2551be9-26 b/testdata/corpus/7c8ed8a74e3b25b9ab2af412684d3e78f2551be9-26 new file mode 100644 index 0000000..002c3b5 Binary files /dev/null and b/testdata/corpus/7c8ed8a74e3b25b9ab2af412684d3e78f2551be9-26 differ diff --git a/testdata/corpus/7d238709fb1566509ae01e8be2329af666d8996d-21 b/testdata/corpus/7d238709fb1566509ae01e8be2329af666d8996d-21 new file mode 100644 index 0000000..c558928 Binary files /dev/null and b/testdata/corpus/7d238709fb1566509ae01e8be2329af666d8996d-21 differ diff --git a/testdata/corpus/8049ea23c981c73734e540b3313ddad4080b8dfe-25 b/testdata/corpus/8049ea23c981c73734e540b3313ddad4080b8dfe-25 new file mode 100644 index 0000000..a60eb5b Binary files /dev/null and b/testdata/corpus/8049ea23c981c73734e540b3313ddad4080b8dfe-25 differ diff --git a/testdata/corpus/82b50a2a30f0cd12bdd9e3cc8a319f4332187b2e-27 b/testdata/corpus/82b50a2a30f0cd12bdd9e3cc8a319f4332187b2e-27 new file mode 100644 index 0000000..17da21d Binary files /dev/null and b/testdata/corpus/82b50a2a30f0cd12bdd9e3cc8a319f4332187b2e-27 differ diff --git a/testdata/corpus/8353d46921b6fde028f970a604c2849cc5aa810c-24 b/testdata/corpus/8353d46921b6fde028f970a604c2849cc5aa810c-24 new file mode 100644 index 0000000..3df8508 Binary files /dev/null and b/testdata/corpus/8353d46921b6fde028f970a604c2849cc5aa810c-24 differ diff --git a/testdata/corpus/89e9ef3ebb14109ac96d689aeb6feccb3400da24-32 b/testdata/corpus/89e9ef3ebb14109ac96d689aeb6feccb3400da24-32 new file mode 100644 index 0000000..1531f4d Binary files /dev/null and b/testdata/corpus/89e9ef3ebb14109ac96d689aeb6feccb3400da24-32 differ diff --git a/testdata/corpus/8c2c63b03bfc98755d27a16b6ed31fc1b2bf5d35-25 b/testdata/corpus/8c2c63b03bfc98755d27a16b6ed31fc1b2bf5d35-25 new file mode 100644 index 0000000..bc6124d Binary files /dev/null and b/testdata/corpus/8c2c63b03bfc98755d27a16b6ed31fc1b2bf5d35-25 differ diff --git a/testdata/corpus/8c5db57d3a45d4ebd00f1f5a64dea8c59120cb34-27 b/testdata/corpus/8c5db57d3a45d4ebd00f1f5a64dea8c59120cb34-27 new file mode 100644 index 0000000..f20663f Binary files /dev/null and b/testdata/corpus/8c5db57d3a45d4ebd00f1f5a64dea8c59120cb34-27 differ diff --git a/testdata/corpus/8d17753428489bd447512e86803ff91b5cd4a618-23 b/testdata/corpus/8d17753428489bd447512e86803ff91b5cd4a618-23 new file mode 100644 index 0000000..2ed314f Binary files /dev/null and b/testdata/corpus/8d17753428489bd447512e86803ff91b5cd4a618-23 differ diff --git a/testdata/corpus/905486ceb3c7a06f5ba779bdf8c7b9b7fe52d166-23 b/testdata/corpus/905486ceb3c7a06f5ba779bdf8c7b9b7fe52d166-23 new file mode 100644 index 0000000..488c38f Binary files /dev/null and b/testdata/corpus/905486ceb3c7a06f5ba779bdf8c7b9b7fe52d166-23 differ diff --git a/testdata/corpus/90d6e4244cf25054afb865d8f5b100afdb9311ea-22 b/testdata/corpus/90d6e4244cf25054afb865d8f5b100afdb9311ea-22 new file mode 100644 index 0000000..607447b Binary files /dev/null and b/testdata/corpus/90d6e4244cf25054afb865d8f5b100afdb9311ea-22 differ diff --git a/testdata/corpus/91bb3e18e2358e1f90017ff4524edd54e304cc62-22 b/testdata/corpus/91bb3e18e2358e1f90017ff4524edd54e304cc62-22 new file mode 100644 index 0000000..46cf5a8 Binary files /dev/null and b/testdata/corpus/91bb3e18e2358e1f90017ff4524edd54e304cc62-22 differ diff --git a/testdata/corpus/94161383e168655eec9c6560cc3fcf11559c0644-24 b/testdata/corpus/94161383e168655eec9c6560cc3fcf11559c0644-24 new file mode 100644 index 0000000..2aa7b77 Binary files /dev/null and b/testdata/corpus/94161383e168655eec9c6560cc3fcf11559c0644-24 differ diff --git a/testdata/corpus/958236df30daef0dabef7c95f7d9c4ae8674147d-20 b/testdata/corpus/958236df30daef0dabef7c95f7d9c4ae8674147d-20 new file mode 100644 index 0000000..ad0650e Binary files /dev/null and b/testdata/corpus/958236df30daef0dabef7c95f7d9c4ae8674147d-20 differ diff --git a/testdata/corpus/9e35b7dd88c61d43565909b39d7062be8ced6b59-20 b/testdata/corpus/9e35b7dd88c61d43565909b39d7062be8ced6b59-20 new file mode 100644 index 0000000..bc5f19a Binary files /dev/null and b/testdata/corpus/9e35b7dd88c61d43565909b39d7062be8ced6b59-20 differ diff --git a/testdata/corpus/a045a8219d4c35f1ee204edc87d9488524ed644a-26 b/testdata/corpus/a045a8219d4c35f1ee204edc87d9488524ed644a-26 new file mode 100644 index 0000000..52bafcd Binary files /dev/null and b/testdata/corpus/a045a8219d4c35f1ee204edc87d9488524ed644a-26 differ diff --git a/testdata/corpus/a27377086a04fda74ea2b153153fe88a2ceae6f0-22 b/testdata/corpus/a27377086a04fda74ea2b153153fe88a2ceae6f0-22 new file mode 100644 index 0000000..9e17886 Binary files /dev/null and b/testdata/corpus/a27377086a04fda74ea2b153153fe88a2ceae6f0-22 differ diff --git a/testdata/corpus/a282e300b54d73d83f2eb94160c721a3c632c849-24 b/testdata/corpus/a282e300b54d73d83f2eb94160c721a3c632c849-24 new file mode 100644 index 0000000..88036b8 Binary files /dev/null and b/testdata/corpus/a282e300b54d73d83f2eb94160c721a3c632c849-24 differ diff --git a/testdata/corpus/a6e20dcf12412996120dbd1c2e5e6f523d677887-27 b/testdata/corpus/a6e20dcf12412996120dbd1c2e5e6f523d677887-27 new file mode 100644 index 0000000..986748f Binary files /dev/null and b/testdata/corpus/a6e20dcf12412996120dbd1c2e5e6f523d677887-27 differ diff --git a/testdata/corpus/a8f496ff9fbeebd3de79cccb57180543d7c796d2-31 b/testdata/corpus/a8f496ff9fbeebd3de79cccb57180543d7c796d2-31 new file mode 100644 index 0000000..d55b1ea Binary files /dev/null and b/testdata/corpus/a8f496ff9fbeebd3de79cccb57180543d7c796d2-31 differ diff --git a/testdata/corpus/a97c70f84b45e6db9a1f5ded724b37a8352bb521-25 b/testdata/corpus/a97c70f84b45e6db9a1f5ded724b37a8352bb521-25 new file mode 100644 index 0000000..39e2fd6 Binary files /dev/null and b/testdata/corpus/a97c70f84b45e6db9a1f5ded724b37a8352bb521-25 differ diff --git a/testdata/corpus/aa54bb91bce9e07e00982df872b42edc13f84d55-19 b/testdata/corpus/aa54bb91bce9e07e00982df872b42edc13f84d55-19 new file mode 100644 index 0000000..996afd9 Binary files /dev/null and b/testdata/corpus/aa54bb91bce9e07e00982df872b42edc13f84d55-19 differ diff --git a/testdata/corpus/afc99d9a8ef8ae5e60f5a553d09f775f34ea32c2-15 b/testdata/corpus/afc99d9a8ef8ae5e60f5a553d09f775f34ea32c2-15 new file mode 100644 index 0000000..8a9655c Binary files /dev/null and b/testdata/corpus/afc99d9a8ef8ae5e60f5a553d09f775f34ea32c2-15 differ diff --git a/testdata/corpus/b04b3d040073e2f6e350a4b4ed4624fcdab39409-20 b/testdata/corpus/b04b3d040073e2f6e350a4b4ed4624fcdab39409-20 new file mode 100644 index 0000000..cf17ff8 Binary files /dev/null and b/testdata/corpus/b04b3d040073e2f6e350a4b4ed4624fcdab39409-20 differ diff --git a/testdata/corpus/b1678cda7c01da8024141f32c90dba72632ed561-27 b/testdata/corpus/b1678cda7c01da8024141f32c90dba72632ed561-27 new file mode 100644 index 0000000..ba22ee6 Binary files /dev/null and b/testdata/corpus/b1678cda7c01da8024141f32c90dba72632ed561-27 differ diff --git a/testdata/corpus/b5a5683b55006b63277d7e4e279002b6ff28bec9-24 b/testdata/corpus/b5a5683b55006b63277d7e4e279002b6ff28bec9-24 new file mode 100644 index 0000000..9daa939 Binary files /dev/null and b/testdata/corpus/b5a5683b55006b63277d7e4e279002b6ff28bec9-24 differ diff --git a/testdata/corpus/b7f4fcd62ea8fdd1ae9ce3d3fb65ac3dfbe7fb94-26 b/testdata/corpus/b7f4fcd62ea8fdd1ae9ce3d3fb65ac3dfbe7fb94-26 new file mode 100644 index 0000000..936e785 Binary files /dev/null and b/testdata/corpus/b7f4fcd62ea8fdd1ae9ce3d3fb65ac3dfbe7fb94-26 differ diff --git a/testdata/corpus/b8064c73a17105178426ee811fd7e8ddbd3c8a6e-22 b/testdata/corpus/b8064c73a17105178426ee811fd7e8ddbd3c8a6e-22 new file mode 100644 index 0000000..ce979d2 Binary files /dev/null and b/testdata/corpus/b8064c73a17105178426ee811fd7e8ddbd3c8a6e-22 differ diff --git a/testdata/corpus/b92c421ae18794c90bb78245ffefc69891a1b212-29 b/testdata/corpus/b92c421ae18794c90bb78245ffefc69891a1b212-29 new file mode 100644 index 0000000..012abf7 Binary files /dev/null and b/testdata/corpus/b92c421ae18794c90bb78245ffefc69891a1b212-29 differ diff --git a/testdata/corpus/ba1fe7e80d257cf0f97e3cf5056a065dd182c612-27 b/testdata/corpus/ba1fe7e80d257cf0f97e3cf5056a065dd182c612-27 new file mode 100644 index 0000000..8562fe9 Binary files /dev/null and b/testdata/corpus/ba1fe7e80d257cf0f97e3cf5056a065dd182c612-27 differ diff --git a/testdata/corpus/bb950a0e94c4e5852f78b9745f56a1fcfc6d3793-24 b/testdata/corpus/bb950a0e94c4e5852f78b9745f56a1fcfc6d3793-24 new file mode 100644 index 0000000..2edee5d Binary files /dev/null and b/testdata/corpus/bb950a0e94c4e5852f78b9745f56a1fcfc6d3793-24 differ diff --git a/testdata/corpus/bc3012d99f051d8f6dd72f64bfe30c8825413774-15 b/testdata/corpus/bc3012d99f051d8f6dd72f64bfe30c8825413774-15 new file mode 100644 index 0000000..aa82186 Binary files /dev/null and b/testdata/corpus/bc3012d99f051d8f6dd72f64bfe30c8825413774-15 differ diff --git a/testdata/corpus/bf35de24da6b93b24b8203e34f2c91f85aa23358-25 b/testdata/corpus/bf35de24da6b93b24b8203e34f2c91f85aa23358-25 new file mode 100644 index 0000000..395aaf1 Binary files /dev/null and b/testdata/corpus/bf35de24da6b93b24b8203e34f2c91f85aa23358-25 differ diff --git a/testdata/corpus/bfdebdd9e5d0987fc0443b654ffc7a077928a394-15 b/testdata/corpus/bfdebdd9e5d0987fc0443b654ffc7a077928a394-15 new file mode 100644 index 0000000..2f2c51c Binary files /dev/null and b/testdata/corpus/bfdebdd9e5d0987fc0443b654ffc7a077928a394-15 differ diff --git a/testdata/corpus/cd5f295b6d021868a7ab632ec03eb316d6c6e010-22 b/testdata/corpus/cd5f295b6d021868a7ab632ec03eb316d6c6e010-22 new file mode 100644 index 0000000..945a741 Binary files /dev/null and b/testdata/corpus/cd5f295b6d021868a7ab632ec03eb316d6c6e010-22 differ diff --git a/testdata/corpus/cd74cca3dc346b8b47b61ac987f03db93703f1c7-25 b/testdata/corpus/cd74cca3dc346b8b47b61ac987f03db93703f1c7-25 new file mode 100644 index 0000000..236e39a Binary files /dev/null and b/testdata/corpus/cd74cca3dc346b8b47b61ac987f03db93703f1c7-25 differ diff --git a/testdata/corpus/ce1224c07048279cf433284b765ce88ad68aad5c-25 b/testdata/corpus/ce1224c07048279cf433284b765ce88ad68aad5c-25 new file mode 100644 index 0000000..3a0afb7 Binary files /dev/null and b/testdata/corpus/ce1224c07048279cf433284b765ce88ad68aad5c-25 differ diff --git a/testdata/corpus/d0c0c6beb6e374f7d86e18e54985cac4ed1fd051-21 b/testdata/corpus/d0c0c6beb6e374f7d86e18e54985cac4ed1fd051-21 new file mode 100644 index 0000000..5876a51 Binary files /dev/null and b/testdata/corpus/d0c0c6beb6e374f7d86e18e54985cac4ed1fd051-21 differ diff --git a/testdata/corpus/d2bc5b2014b313b9da75d8d25926f937b1d7d1e5-21 b/testdata/corpus/d2bc5b2014b313b9da75d8d25926f937b1d7d1e5-21 new file mode 100644 index 0000000..d37d9a0 Binary files /dev/null and b/testdata/corpus/d2bc5b2014b313b9da75d8d25926f937b1d7d1e5-21 differ diff --git a/testdata/corpus/d42027a23e1cb69b41589b40bff7a4f236cd1627-27 b/testdata/corpus/d42027a23e1cb69b41589b40bff7a4f236cd1627-27 new file mode 100644 index 0000000..881b553 Binary files /dev/null and b/testdata/corpus/d42027a23e1cb69b41589b40bff7a4f236cd1627-27 differ diff --git a/testdata/corpus/d46958bfff37ee5dfaa20c39b568919ff92ead31-17 b/testdata/corpus/d46958bfff37ee5dfaa20c39b568919ff92ead31-17 new file mode 100644 index 0000000..7e986e2 Binary files /dev/null and b/testdata/corpus/d46958bfff37ee5dfaa20c39b568919ff92ead31-17 differ diff --git a/testdata/corpus/d49629bbf737e162754b52f3e1263f1970d58510-27 b/testdata/corpus/d49629bbf737e162754b52f3e1263f1970d58510-27 new file mode 100644 index 0000000..3c40f31 Binary files /dev/null and b/testdata/corpus/d49629bbf737e162754b52f3e1263f1970d58510-27 differ diff --git a/testdata/corpus/d57646a730378c58a8d1fda915b72e8a48914bbd-21 b/testdata/corpus/d57646a730378c58a8d1fda915b72e8a48914bbd-21 new file mode 100644 index 0000000..b632155 Binary files /dev/null and b/testdata/corpus/d57646a730378c58a8d1fda915b72e8a48914bbd-21 differ diff --git a/testdata/corpus/d68b0c4a65d86db5b580bb1c646885557a3becbd-19 b/testdata/corpus/d68b0c4a65d86db5b580bb1c646885557a3becbd-19 new file mode 100644 index 0000000..74891e7 Binary files /dev/null and b/testdata/corpus/d68b0c4a65d86db5b580bb1c646885557a3becbd-19 differ diff --git a/testdata/corpus/d9e4fa2225f4b0a9106cbbcff0ee687c5c35233a-33 b/testdata/corpus/d9e4fa2225f4b0a9106cbbcff0ee687c5c35233a-33 new file mode 100644 index 0000000..4b5bb7a Binary files /dev/null and b/testdata/corpus/d9e4fa2225f4b0a9106cbbcff0ee687c5c35233a-33 differ diff --git a/testdata/corpus/df557b134cb1bda39a310cbbf71af8f6c2f0e216-28 b/testdata/corpus/df557b134cb1bda39a310cbbf71af8f6c2f0e216-28 new file mode 100644 index 0000000..df1c5e7 Binary files /dev/null and b/testdata/corpus/df557b134cb1bda39a310cbbf71af8f6c2f0e216-28 differ diff --git a/testdata/corpus/e13e887a20eda2c13f55f17b35012b1d8ba4b98d-20 b/testdata/corpus/e13e887a20eda2c13f55f17b35012b1d8ba4b98d-20 new file mode 100644 index 0000000..af6c0b6 Binary files /dev/null and b/testdata/corpus/e13e887a20eda2c13f55f17b35012b1d8ba4b98d-20 differ diff --git a/testdata/corpus/e166514671b2011e5aafacc02bceb53258e6661b-23 b/testdata/corpus/e166514671b2011e5aafacc02bceb53258e6661b-23 new file mode 100644 index 0000000..abe31b4 Binary files /dev/null and b/testdata/corpus/e166514671b2011e5aafacc02bceb53258e6661b-23 differ diff --git a/testdata/corpus/e1cca7ed8a9b496b4737d863060d1364934de5a8-21 b/testdata/corpus/e1cca7ed8a9b496b4737d863060d1364934de5a8-21 new file mode 100644 index 0000000..00bfca4 Binary files /dev/null and b/testdata/corpus/e1cca7ed8a9b496b4737d863060d1364934de5a8-21 differ diff --git a/testdata/corpus/e206695f09384b7e00bfb83f8420ae32b7c2468e-26 b/testdata/corpus/e206695f09384b7e00bfb83f8420ae32b7c2468e-26 new file mode 100644 index 0000000..49b6634 Binary files /dev/null and b/testdata/corpus/e206695f09384b7e00bfb83f8420ae32b7c2468e-26 differ diff --git a/testdata/corpus/e574d4af4c3638b3386727fabd64678186033c81-24 b/testdata/corpus/e574d4af4c3638b3386727fabd64678186033c81-24 new file mode 100644 index 0000000..74ddb71 Binary files /dev/null and b/testdata/corpus/e574d4af4c3638b3386727fabd64678186033c81-24 differ diff --git a/testdata/corpus/e5770d61def8b575787aae9457d1bc02261dbd84-27 b/testdata/corpus/e5770d61def8b575787aae9457d1bc02261dbd84-27 new file mode 100644 index 0000000..34f592f Binary files /dev/null and b/testdata/corpus/e5770d61def8b575787aae9457d1bc02261dbd84-27 differ diff --git a/testdata/corpus/e5acbead07330bf8c34eadaf884576e644b5b2e7-23 b/testdata/corpus/e5acbead07330bf8c34eadaf884576e644b5b2e7-23 new file mode 100644 index 0000000..8b39ddd Binary files /dev/null and b/testdata/corpus/e5acbead07330bf8c34eadaf884576e644b5b2e7-23 differ diff --git a/testdata/corpus/e72b2cb44601f2daf18194eb005807209d2774bf-20 b/testdata/corpus/e72b2cb44601f2daf18194eb005807209d2774bf-20 new file mode 100644 index 0000000..f0ef0af Binary files /dev/null and b/testdata/corpus/e72b2cb44601f2daf18194eb005807209d2774bf-20 differ diff --git a/testdata/corpus/e8834ab47f71c54992875b749345b701c715d779-24 b/testdata/corpus/e8834ab47f71c54992875b749345b701c715d779-24 new file mode 100644 index 0000000..9ed69fe Binary files /dev/null and b/testdata/corpus/e8834ab47f71c54992875b749345b701c715d779-24 differ diff --git a/testdata/corpus/e8a1f0be9b3443fa8adf9911c6e4c67429bc929f-21 b/testdata/corpus/e8a1f0be9b3443fa8adf9911c6e4c67429bc929f-21 new file mode 100644 index 0000000..e68fc3c Binary files /dev/null and b/testdata/corpus/e8a1f0be9b3443fa8adf9911c6e4c67429bc929f-21 differ diff --git a/testdata/corpus/ef42e68cd3f7ae0da8e88614feb40ccc7e4dd017-24 b/testdata/corpus/ef42e68cd3f7ae0da8e88614feb40ccc7e4dd017-24 new file mode 100644 index 0000000..3dfdb94 Binary files /dev/null and b/testdata/corpus/ef42e68cd3f7ae0da8e88614feb40ccc7e4dd017-24 differ diff --git a/testdata/corpus/efceaac6e39bceeee8337474c1e39118a8a097ce-25 b/testdata/corpus/efceaac6e39bceeee8337474c1e39118a8a097ce-25 new file mode 100644 index 0000000..ce9f6ea Binary files /dev/null and b/testdata/corpus/efceaac6e39bceeee8337474c1e39118a8a097ce-25 differ diff --git a/testdata/corpus/f1efa9fe4886b61179e874c621c887428bbf81a1-27 b/testdata/corpus/f1efa9fe4886b61179e874c621c887428bbf81a1-27 new file mode 100644 index 0000000..67c369f Binary files /dev/null and b/testdata/corpus/f1efa9fe4886b61179e874c621c887428bbf81a1-27 differ diff --git a/testdata/corpus/f3aca7864b1de000677b0d4bcc5d18d15be2aea1-23 b/testdata/corpus/f3aca7864b1de000677b0d4bcc5d18d15be2aea1-23 new file mode 100644 index 0000000..7e01405 Binary files /dev/null and b/testdata/corpus/f3aca7864b1de000677b0d4bcc5d18d15be2aea1-23 differ diff --git a/testdata/corpus/f62f967416a52b4f25c977c5c1487555ac8e043d-23 b/testdata/corpus/f62f967416a52b4f25c977c5c1487555ac8e043d-23 new file mode 100644 index 0000000..17e6122 Binary files /dev/null and b/testdata/corpus/f62f967416a52b4f25c977c5c1487555ac8e043d-23 differ diff --git a/testdata/corpus/f860e7d60c6f3ddf697c4eda7a528688021be855-25 b/testdata/corpus/f860e7d60c6f3ddf697c4eda7a528688021be855-25 new file mode 100644 index 0000000..e307d20 Binary files /dev/null and b/testdata/corpus/f860e7d60c6f3ddf697c4eda7a528688021be855-25 differ diff --git a/testdata/corpus/fcce47777757315234c70eb38fec6916aa8e998d-23 b/testdata/corpus/fcce47777757315234c70eb38fec6916aa8e998d-23 new file mode 100644 index 0000000..852c278 Binary files /dev/null and b/testdata/corpus/fcce47777757315234c70eb38fec6916aa8e998d-23 differ diff --git a/testdata/corpus/ff93f3b0f00620af4bddf6d7003216bc6813c214-21 b/testdata/corpus/ff93f3b0f00620af4bddf6d7003216bc6813c214-21 new file mode 100644 index 0000000..67aa0a0 Binary files /dev/null and b/testdata/corpus/ff93f3b0f00620af4bddf6d7003216bc6813c214-21 differ diff --git a/testdata/corpus/ffb32ecf19c83fa1e7810c60d343c4cdc06423e0-25 b/testdata/corpus/ffb32ecf19c83fa1e7810c60d343c4cdc06423e0-25 new file mode 100644 index 0000000..8120dbf Binary files /dev/null and b/testdata/corpus/ffb32ecf19c83fa1e7810c60d343c4cdc06423e0-25 differ