diff options
author | Arthur Sfez <asfez@google.com> | 2020-12-02 14:09:40 -0800 |
---|---|---|
committer | gVisor bot <gvisor-bot@google.com> | 2020-12-02 14:12:01 -0800 |
commit | 6a26930eeb717f758ea7ba555df06d9028b24ec8 (patch) | |
tree | 49f3a27f5fbbe02cfe0dfad95d3a32e3036e03dc /test | |
parent | 24d6eb58e51be706ae66db31d027e2400307152f (diff) |
Abandon reassembly of a packet if fragments overlap
However, receiving duplicated fragments will not cause reassembly to
fail. This is what Linux does too:
https://github.com/torvalds/linux/blob/38525c6/net/ipv4/inet_fragment.c#L355
PiperOrigin-RevId: 345309546
Diffstat (limited to 'test')
-rw-r--r-- | test/packetimpact/tests/ipv4_fragment_reassembly_test.go | 65 | ||||
-rw-r--r-- | test/packetimpact/tests/ipv6_fragment_reassembly_test.go | 52 |
2 files changed, 99 insertions, 18 deletions
diff --git a/test/packetimpact/tests/ipv4_fragment_reassembly_test.go b/test/packetimpact/tests/ipv4_fragment_reassembly_test.go index e00a7aba2..d2203082d 100644 --- a/test/packetimpact/tests/ipv4_fragment_reassembly_test.go +++ b/test/packetimpact/tests/ipv4_fragment_reassembly_test.go @@ -34,10 +34,10 @@ type fragmentInfo struct { offset uint16 size uint16 more uint8 + id uint16 } func TestIPv4FragmentReassembly(t *testing.T) { - const fragmentID = 42 icmpv4ProtoNum := uint8(header.ICMPv4ProtocolNumber) tests := []struct { @@ -45,28 +45,75 @@ func TestIPv4FragmentReassembly(t *testing.T) { ipPayloadLen int fragments []fragmentInfo expectReply bool + skip bool + skipReason string }{ { description: "basic reassembly", - ipPayloadLen: 2000, + ipPayloadLen: 3000, fragments: []fragmentInfo{ - {offset: 0, size: 1000, more: header.IPv4FlagMoreFragments}, - {offset: 1000, size: 1000, more: 0}, + {offset: 0, size: 1000, id: 5, more: header.IPv4FlagMoreFragments}, + {offset: 1000, size: 1000, id: 5, more: header.IPv4FlagMoreFragments}, + {offset: 2000, size: 1000, id: 5, more: 0}, }, expectReply: true, }, { description: "out of order fragments", - ipPayloadLen: 2000, + ipPayloadLen: 3000, fragments: []fragmentInfo{ - {offset: 1000, size: 1000, more: 0}, - {offset: 0, size: 1000, more: header.IPv4FlagMoreFragments}, + {offset: 2000, size: 1000, id: 6, more: 0}, + {offset: 0, size: 1000, id: 6, more: header.IPv4FlagMoreFragments}, + {offset: 1000, size: 1000, id: 6, more: header.IPv4FlagMoreFragments}, }, expectReply: true, }, + { + description: "duplicated fragments", + ipPayloadLen: 3000, + fragments: []fragmentInfo{ + {offset: 0, size: 1000, id: 7, more: header.IPv4FlagMoreFragments}, + {offset: 1000, size: 1000, id: 7, more: header.IPv4FlagMoreFragments}, + {offset: 1000, size: 1000, id: 7, more: header.IPv4FlagMoreFragments}, + {offset: 2000, size: 1000, id: 7, more: 0}, + }, + expectReply: true, + skip: true, + skipReason: "gvisor.dev/issues/4971", + }, + { + description: "fragment subset", + ipPayloadLen: 3000, + fragments: []fragmentInfo{ + {offset: 0, size: 1000, id: 8, more: header.IPv4FlagMoreFragments}, + {offset: 1000, size: 1000, id: 8, more: header.IPv4FlagMoreFragments}, + {offset: 512, size: 256, id: 8, more: header.IPv4FlagMoreFragments}, + {offset: 2000, size: 1000, id: 8, more: 0}, + }, + expectReply: true, + skip: true, + skipReason: "gvisor.dev/issues/4971", + }, + { + description: "fragment overlap", + ipPayloadLen: 3000, + fragments: []fragmentInfo{ + {offset: 0, size: 1000, id: 9, more: header.IPv4FlagMoreFragments}, + {offset: 1512, size: 1000, id: 9, more: header.IPv4FlagMoreFragments}, + {offset: 1000, size: 1000, id: 9, more: header.IPv4FlagMoreFragments}, + {offset: 2000, size: 1000, id: 9, more: 0}, + }, + expectReply: false, + skip: true, + skipReason: "gvisor.dev/issues/4971", + }, } for _, test := range tests { + if test.skip { + t.Skip("%s test skipped: %s", test.description, test.skipReason) + continue + } t.Run(test.description, func(t *testing.T) { dut := testbench.NewDUT(t) conn := dut.Net.NewIPv4Conn(t, testbench.IPv4{}, testbench.IPv4{}) @@ -95,7 +142,7 @@ func TestIPv4FragmentReassembly(t *testing.T) { Protocol: &icmpv4ProtoNum, FragmentOffset: testbench.Uint16(fragment.offset), Flags: testbench.Uint8(fragment.more), - ID: testbench.Uint16(fragmentID), + ID: testbench.Uint16(fragment.id), }, &testbench.Payload{ Bytes: data[fragment.offset:][:fragment.size], @@ -114,7 +161,7 @@ func TestIPv4FragmentReassembly(t *testing.T) { }, time.Second) if err != nil { // Either an unexpected frame was received, or none at all. - if bytesReceived < test.ipPayloadLen { + if test.expectReply && bytesReceived < test.ipPayloadLen { t.Fatalf("received %d bytes out of %d, then conn.ExpectFrame(_, _, time.Second) failed with %s", bytesReceived, test.ipPayloadLen, err) } break diff --git a/test/packetimpact/tests/ipv6_fragment_reassembly_test.go b/test/packetimpact/tests/ipv6_fragment_reassembly_test.go index 65f742f55..dd98ee7a1 100644 --- a/test/packetimpact/tests/ipv6_fragment_reassembly_test.go +++ b/test/packetimpact/tests/ipv6_fragment_reassembly_test.go @@ -35,10 +35,10 @@ type fragmentInfo struct { offset uint16 size uint16 more bool + id uint32 } func TestIPv6FragmentReassembly(t *testing.T) { - const fragmentID = 42 icmpv6ProtoNum := header.IPv6ExtensionHeaderIdentifier(header.ICMPv6ProtocolNumber) tests := []struct { @@ -49,10 +49,11 @@ func TestIPv6FragmentReassembly(t *testing.T) { }{ { description: "basic reassembly", - ipPayloadLen: 1500, + ipPayloadLen: 3000, fragments: []fragmentInfo{ - {offset: 0, size: 760, more: true}, - {offset: 760, size: 740, more: false}, + {offset: 0, size: 1000, id: 100, more: true}, + {offset: 1000, size: 1000, id: 100, more: true}, + {offset: 2000, size: 1000, id: 100, more: false}, }, expectReply: true, }, @@ -60,12 +61,45 @@ func TestIPv6FragmentReassembly(t *testing.T) { description: "out of order fragments", ipPayloadLen: 3000, fragments: []fragmentInfo{ - {offset: 0, size: 1024, more: true}, - {offset: 2048, size: 952, more: false}, - {offset: 1024, size: 1024, more: true}, + {offset: 0, size: 1000, id: 101, more: true}, + {offset: 2000, size: 1000, id: 101, more: false}, + {offset: 1000, size: 1000, id: 101, more: true}, + }, + expectReply: true, + }, + { + description: "duplicated fragments", + ipPayloadLen: 3000, + fragments: []fragmentInfo{ + {offset: 0, size: 1000, id: 102, more: true}, + {offset: 1000, size: 1000, id: 102, more: true}, + {offset: 1000, size: 1000, id: 102, more: true}, + {offset: 2000, size: 1000, id: 102, more: false}, + }, + expectReply: true, + }, + { + description: "fragment subset", + ipPayloadLen: 3000, + fragments: []fragmentInfo{ + {offset: 0, size: 1000, id: 103, more: true}, + {offset: 1000, size: 1000, id: 103, more: true}, + {offset: 512, size: 256, id: 103, more: true}, + {offset: 2000, size: 1000, id: 103, more: false}, }, expectReply: true, }, + { + description: "fragment overlap", + ipPayloadLen: 3000, + fragments: []fragmentInfo{ + {offset: 0, size: 1000, id: 104, more: true}, + {offset: 1512, size: 1000, id: 104, more: true}, + {offset: 1000, size: 1000, id: 104, more: true}, + {offset: 2000, size: 1000, id: 104, more: false}, + }, + expectReply: false, + }, } for _, test := range tests { @@ -101,7 +135,7 @@ func TestIPv6FragmentReassembly(t *testing.T) { NextHeader: &icmpv6ProtoNum, FragmentOffset: testbench.Uint16(fragment.offset / header.IPv6FragmentExtHdrFragmentOffsetBytesPerUnit), MoreFragments: testbench.Bool(fragment.more), - Identification: testbench.Uint32(fragmentID), + Identification: testbench.Uint32(fragment.id), }, &testbench.Payload{ Bytes: data[fragment.offset:][:fragment.size], @@ -118,7 +152,7 @@ func TestIPv6FragmentReassembly(t *testing.T) { }, time.Second) if err != nil { // Either an unexpected frame was received, or none at all. - if bytesReceived < test.ipPayloadLen { + if test.expectReply && bytesReceived < test.ipPayloadLen { t.Fatalf("received %d bytes out of %d, then conn.ExpectFrame(_, _, time.Second) failed with %s", bytesReceived, test.ipPayloadLen, err) } break |