From 9c4102896d8ffbe6a90b57e7aca85f912dcadd9c Mon Sep 17 00:00:00 2001 From: Julian Elischer Date: Wed, 11 Nov 2020 10:57:32 -0800 Subject: Teach netstack how to add options to IPv4 packets Most packets don't have options but they are an integral part of the standard. Teaching the ipv4 code how to handle them will simplify future testing and use. Because Options are so rare it is worth making sure that the extra work is kept out of the fast path as much as possible. Prior to this change, all usages of the IHL field of the IPv4Fields/Encode system set it to the same constant value except in a couple of tests for bad values. From this change IHL will not be a constant as it will depend on the size of any Options. Since ipv4.Encode() now handles the options it becomes a possible source of errors to let the callers set this value, so remove it entirely and calculate the value from the size of the Options if present (or not) therefore guaranteeing a correct value. Fixes #4709 RELNOTES: n/a PiperOrigin-RevId: 341864765 --- pkg/tcpip/network/ip_test.go | 29 ++------ pkg/tcpip/network/ipv4/ipv4.go | 19 +++++- pkg/tcpip/network/ipv4/ipv4_test.go | 130 ++++++++++++++++-------------------- 3 files changed, 80 insertions(+), 98 deletions(-) (limited to 'pkg/tcpip/network') diff --git a/pkg/tcpip/network/ip_test.go b/pkg/tcpip/network/ip_test.go index 8873bd91f..c7d26e14f 100644 --- a/pkg/tcpip/network/ip_test.go +++ b/pkg/tcpip/network/ip_test.go @@ -320,7 +320,6 @@ func TestSourceAddressValidation(t *testing.T) { pkt.SetChecksum(^header.Checksum(pkt, 0)) ip := header.IPv4(hdr.Prepend(header.IPv4MinimumSize)) ip.Encode(&header.IPv4Fields{ - IHL: header.IPv4MinimumSize, TotalLength: uint16(totalLen), Protocol: uint8(icmp.ProtocolNumber4), TTL: ipv4.DefaultTTL, @@ -579,7 +578,6 @@ func TestIPv4Receive(t *testing.T) { view := buffer.NewView(totalLen) ip := header.IPv4(view) ip.Encode(&header.IPv4Fields{ - IHL: header.IPv4MinimumSize, TotalLength: uint16(totalLen), TTL: 20, Protocol: 10, @@ -662,7 +660,6 @@ func TestIPv4ReceiveControl(t *testing.T) { // Create the outer IPv4 header. ip := header.IPv4(view) ip.Encode(&header.IPv4Fields{ - IHL: header.IPv4MinimumSize, TotalLength: uint16(len(view) - c.trunc), TTL: 20, Protocol: uint8(header.ICMPv4ProtocolNumber), @@ -681,7 +678,6 @@ func TestIPv4ReceiveControl(t *testing.T) { // Create the inner IPv4 header. ip = header.IPv4(view[header.IPv4MinimumSize+header.ICMPv4MinimumSize:]) ip.Encode(&header.IPv4Fields{ - IHL: header.IPv4MinimumSize, TotalLength: 100, TTL: 20, Protocol: 10, @@ -740,7 +736,6 @@ func TestIPv4FragmentationReceive(t *testing.T) { frag1 := buffer.NewView(totalLen) ip1 := header.IPv4(frag1) ip1.Encode(&header.IPv4Fields{ - IHL: header.IPv4MinimumSize, TotalLength: uint16(totalLen), TTL: 20, Protocol: 10, @@ -759,7 +754,6 @@ func TestIPv4FragmentationReceive(t *testing.T) { frag2 := buffer.NewView(totalLen) ip2 := header.IPv4(frag2) ip2.Encode(&header.IPv4Fields{ - IHL: header.IPv4MinimumSize, TotalLength: uint16(totalLen), TTL: 20, Protocol: 10, @@ -1052,15 +1046,13 @@ func TestWriteHeaderIncludedPacket(t *testing.T) { nicID = 1 transportProto = 5 - dataLen = 4 - optionsLen = 4 + dataLen = 4 ) dataBuf := [dataLen]byte{1, 2, 3, 4} data := dataBuf[:] - ipv4OptionsBuf := [optionsLen]byte{0, 1, 0, 1} - ipv4Options := ipv4OptionsBuf[:] + ipv4Options := header.IPv4Options{0, 1, 0, 1} ipv6FragmentExtHdrBuf := [header.IPv6FragmentExtHdrLength]byte{transportProto, 0, 62, 4, 1, 2, 3, 4} ipv6FragmentExtHdr := ipv6FragmentExtHdrBuf[:] @@ -1098,7 +1090,6 @@ func TestWriteHeaderIncludedPacket(t *testing.T) { } ip := header.IPv4(hdr.Prepend(header.IPv4MinimumSize)) ip.Encode(&header.IPv4Fields{ - IHL: header.IPv4MinimumSize, Protocol: transportProto, TTL: ipv4.DefaultTTL, SrcAddr: src, @@ -1140,12 +1131,12 @@ func TestWriteHeaderIncludedPacket(t *testing.T) { } ip := header.IPv4(hdr.Prepend(header.IPv4MinimumSize)) ip.Encode(&header.IPv4Fields{ - IHL: header.IPv4MinimumSize - 1, Protocol: transportProto, TTL: ipv4.DefaultTTL, SrcAddr: src, DstAddr: header.IPv4Any, }) + ip.SetHeaderLength(header.IPv4MinimumSize - 1) return hdr.View().ToVectorisedView() }, expectedErr: tcpip.ErrMalformedHeader, @@ -1159,7 +1150,6 @@ func TestWriteHeaderIncludedPacket(t *testing.T) { pktGen: func(t *testing.T, src tcpip.Address) buffer.VectorisedView { ip := header.IPv4(make([]byte, header.IPv4MinimumSize)) ip.Encode(&header.IPv4Fields{ - IHL: header.IPv4MinimumSize, Protocol: transportProto, TTL: ipv4.DefaultTTL, SrcAddr: src, @@ -1178,7 +1168,6 @@ func TestWriteHeaderIncludedPacket(t *testing.T) { pktGen: func(t *testing.T, src tcpip.Address) buffer.VectorisedView { ip := header.IPv4(make([]byte, header.IPv4MinimumSize)) ip.Encode(&header.IPv4Fields{ - IHL: header.IPv4MinimumSize, Protocol: transportProto, TTL: ipv4.DefaultTTL, SrcAddr: src, @@ -1213,7 +1202,7 @@ func TestWriteHeaderIncludedPacket(t *testing.T) { nicAddr: localIPv4Addr, remoteAddr: remoteIPv4Addr, pktGen: func(t *testing.T, src tcpip.Address) buffer.VectorisedView { - ipHdrLen := header.IPv4MinimumSize + len(ipv4Options) + ipHdrLen := header.IPv4MinimumSize + ipv4Options.AllocationSize() totalLen := ipHdrLen + len(data) hdr := buffer.NewPrependable(totalLen) if n := copy(hdr.Prepend(len(data)), data); n != len(data) { @@ -1221,15 +1210,12 @@ func TestWriteHeaderIncludedPacket(t *testing.T) { } ip := header.IPv4(hdr.Prepend(ipHdrLen)) ip.Encode(&header.IPv4Fields{ - IHL: uint8(ipHdrLen), Protocol: transportProto, TTL: ipv4.DefaultTTL, SrcAddr: src, DstAddr: header.IPv4Any, + Options: ipv4Options, }) - if n := copy(ip.Options(), ipv4Options); n != len(ipv4Options) { - t.Fatalf("copied %d bytes, expected %d bytes", n, len(ipv4Options)) - } return hdr.View().ToVectorisedView() }, checker: func(t *testing.T, pkt *stack.PacketBuffer, src tcpip.Address) { @@ -1261,16 +1247,15 @@ func TestWriteHeaderIncludedPacket(t *testing.T) { nicAddr: localIPv4Addr, remoteAddr: remoteIPv4Addr, pktGen: func(t *testing.T, src tcpip.Address) buffer.VectorisedView { - ip := header.IPv4(make([]byte, header.IPv4MinimumSize)) + ip := header.IPv4(make([]byte, header.IPv4MinimumSize+ipv4Options.AllocationSize())) ip.Encode(&header.IPv4Fields{ - IHL: uint8(header.IPv4MinimumSize + len(ipv4Options)), Protocol: transportProto, TTL: ipv4.DefaultTTL, SrcAddr: src, DstAddr: header.IPv4Any, + Options: ipv4Options, }) vv := buffer.View(ip).ToVectorisedView() - vv.AppendView(ipv4Options) vv.AppendView(data) return vv }, diff --git a/pkg/tcpip/network/ipv4/ipv4.go b/pkg/tcpip/network/ipv4/ipv4.go index cfd0c505a..a376cb8ec 100644 --- a/pkg/tcpip/network/ipv4/ipv4.go +++ b/pkg/tcpip/network/ipv4/ipv4.go @@ -199,14 +199,28 @@ func (e *endpoint) NetworkProtocolNumber() tcpip.NetworkProtocolNumber { } func (e *endpoint) addIPHeader(r *stack.Route, pkt *stack.PacketBuffer, params stack.NetworkHeaderParams) { - ip := header.IPv4(pkt.NetworkHeader().Push(header.IPv4MinimumSize)) + hdrLen := header.IPv4MinimumSize + var opts header.IPv4Options + if params.Options != nil { + var ok bool + if opts, ok = params.Options.(header.IPv4Options); !ok { + panic(fmt.Sprintf("want IPv4Options, got %T", params.Options)) + } + hdrLen += opts.AllocationSize() + if hdrLen > header.IPv4MaximumHeaderSize { + // Since we have no way to report an error we must either panic or create + // a packet which is different to what was requested. Choose panic as this + // would be a programming error that should be caught in testing. + panic(fmt.Sprintf("IPv4 Options %d bytes, Max %d", params.Options.AllocationSize(), header.IPv4MaximumOptionsSize)) + } + } + ip := header.IPv4(pkt.NetworkHeader().Push(hdrLen)) length := uint16(pkt.Size()) // RFC 6864 section 4.3 mandates uniqueness of ID values for non-atomic // datagrams. Since the DF bit is never being set here, all datagrams // are non-atomic and need an ID. id := atomic.AddUint32(&e.protocol.ids[hashRoute(r, params.Protocol, e.protocol.hashIV)%buckets], 1) ip.Encode(&header.IPv4Fields{ - IHL: header.IPv4MinimumSize, TotalLength: length, ID: uint16(id), TTL: params.TTL, @@ -214,6 +228,7 @@ func (e *endpoint) addIPHeader(r *stack.Route, pkt *stack.PacketBuffer, params s Protocol: uint8(params.Protocol), SrcAddr: r.LocalAddress, DstAddr: r.RemoteAddress, + Options: opts, }) ip.SetChecksum(^ip.CalculateChecksum()) pkt.NetworkProtocolNumber = ProtocolNumber diff --git a/pkg/tcpip/network/ipv4/ipv4_test.go b/pkg/tcpip/network/ipv4/ipv4_test.go index c7f434591..c6e565455 100644 --- a/pkg/tcpip/network/ipv4/ipv4_test.go +++ b/pkg/tcpip/network/ipv4/ipv4_test.go @@ -127,8 +127,8 @@ func TestIPv4Sanity(t *testing.T) { maxTotalLength uint16 transportProtocol uint8 TTL uint8 - options []byte - replyOptions []byte // if succeeds, reply should look like this + options header.IPv4Options + replyOptions header.IPv4Options // reply should look like this shouldFail bool expectErrorICMP bool ICMPType header.ICMPv4Type @@ -177,24 +177,24 @@ func TestIPv4Sanity(t *testing.T) { maxTotalLength: ipv4.MaxTotalSize, transportProtocol: uint8(header.ICMPv4ProtocolNumber), TTL: ttl, - options: []byte{0, 0, 0, 0}, - replyOptions: []byte{0, 0, 0, 0}, + options: header.IPv4Options{0, 0, 0, 0}, + replyOptions: header.IPv4Options{0, 0, 0, 0}, }, { name: "NOP options", maxTotalLength: ipv4.MaxTotalSize, transportProtocol: uint8(header.ICMPv4ProtocolNumber), TTL: ttl, - options: []byte{1, 1, 1, 1}, - replyOptions: []byte{1, 1, 1, 1}, + options: header.IPv4Options{1, 1, 1, 1}, + replyOptions: header.IPv4Options{1, 1, 1, 1}, }, { name: "NOP and End options", maxTotalLength: ipv4.MaxTotalSize, transportProtocol: uint8(header.ICMPv4ProtocolNumber), TTL: ttl, - options: []byte{1, 1, 0, 0}, - replyOptions: []byte{1, 1, 0, 0}, + options: header.IPv4Options{1, 1, 0, 0}, + replyOptions: header.IPv4Options{1, 1, 0, 0}, }, { name: "bad header length", @@ -240,12 +240,12 @@ func TestIPv4Sanity(t *testing.T) { maxTotalLength: ipv4.MaxTotalSize, transportProtocol: uint8(header.ICMPv4ProtocolNumber), TTL: ttl, - options: []byte{ + options: header.IPv4Options{ 68, 12, 13, 0x11, 192, 168, 1, 12, 1, 2, 3, 4, }, - replyOptions: []byte{ + replyOptions: header.IPv4Options{ 68, 12, 13, 0x21, 192, 168, 1, 12, 1, 2, 3, 4, @@ -256,7 +256,7 @@ func TestIPv4Sanity(t *testing.T) { maxTotalLength: ipv4.MaxTotalSize, transportProtocol: uint8(header.ICMPv4ProtocolNumber), TTL: ttl, - options: []byte{ + options: header.IPv4Options{ 68, 12, 13, 0xF1, // ^ Counter full (15/0xF) 192, 168, 1, 12, @@ -267,24 +267,24 @@ func TestIPv4Sanity(t *testing.T) { ICMPType: header.ICMPv4ParamProblem, ICMPCode: header.ICMPv4UnusedCode, paramProblemPointer: header.IPv4MinimumSize + 3, - replyOptions: []byte{}, + replyOptions: header.IPv4Options{}, }, { name: "unknown option", maxTotalLength: ipv4.MaxTotalSize, transportProtocol: uint8(header.ICMPv4ProtocolNumber), TTL: ttl, - options: []byte{10, 4, 9, 0}, + options: header.IPv4Options{10, 4, 9, 0}, // ^^ // The unknown option should be stripped out of the reply. - replyOptions: []byte{}, + replyOptions: header.IPv4Options{}, }, { name: "bad option - length 0", maxTotalLength: ipv4.MaxTotalSize, transportProtocol: uint8(header.ICMPv4ProtocolNumber), TTL: ttl, - options: []byte{ + options: header.IPv4Options{ 68, 0, 9, 0, // ^ 1, 2, 3, 4, @@ -296,7 +296,7 @@ func TestIPv4Sanity(t *testing.T) { maxTotalLength: ipv4.MaxTotalSize, transportProtocol: uint8(header.ICMPv4ProtocolNumber), TTL: ttl, - options: []byte{ + options: header.IPv4Options{ 68, 9, 9, 0, // ^ // There are only 8 bytes allocated to options so 9 bytes of timestamp @@ -315,7 +315,7 @@ func TestIPv4Sanity(t *testing.T) { TTL: ttl, // Timestamps are in multiples of 4 or 8 but never 7. // The option space should be padded out. - options: []byte{ + options: header.IPv4Options{ 68, 7, 5, 0, // ^ ^ Linux points here which is wrong. // | Not a multiple of 4 @@ -332,7 +332,7 @@ func TestIPv4Sanity(t *testing.T) { maxTotalLength: ipv4.MaxTotalSize, transportProtocol: uint8(header.ICMPv4ProtocolNumber), TTL: ttl, - options: []byte{ + options: header.IPv4Options{ 68, 24, 21, 0x00, 1, 2, 3, 4, 5, 6, 7, 8, @@ -340,7 +340,7 @@ func TestIPv4Sanity(t *testing.T) { 13, 14, 15, 16, 0, 0, 0, 0, }, - replyOptions: []byte{ + replyOptions: header.IPv4Options{ 68, 24, 25, 0x00, 1, 2, 3, 4, 5, 6, 7, 8, @@ -355,7 +355,7 @@ func TestIPv4Sanity(t *testing.T) { maxTotalLength: ipv4.MaxTotalSize, transportProtocol: uint8(header.ICMPv4ProtocolNumber), TTL: ttl, - options: []byte{ + options: header.IPv4Options{ 68, 20, 21, 0x11, // ^ 192, 168, 1, 12, @@ -364,7 +364,7 @@ func TestIPv4Sanity(t *testing.T) { 5, 6, 7, 8, }, // Overflow count is the top nibble of the 4th byte. - replyOptions: []byte{ + replyOptions: header.IPv4Options{ 68, 20, 21, 0x21, // ^ 192, 168, 1, 12, @@ -378,7 +378,7 @@ func TestIPv4Sanity(t *testing.T) { maxTotalLength: ipv4.MaxTotalSize, transportProtocol: uint8(header.ICMPv4ProtocolNumber), TTL: ttl, - options: []byte{ + options: header.IPv4Options{ 68, 28, 21, 0x01, 192, 168, 1, 12, 1, 2, 3, 4, @@ -387,7 +387,7 @@ func TestIPv4Sanity(t *testing.T) { 0, 0, 0, 0, 0, 0, 0, 0, }, - replyOptions: []byte{ + replyOptions: header.IPv4Options{ 68, 28, 29, 0x01, 192, 168, 1, 12, 1, 2, 3, 4, @@ -403,7 +403,7 @@ func TestIPv4Sanity(t *testing.T) { maxTotalLength: ipv4.MaxTotalSize, transportProtocol: uint8(header.ICMPv4ProtocolNumber), TTL: ttl, - options: []byte{ + options: header.IPv4Options{ 68, 20, 17, 0x01, // ^^ ^^ 20 byte area, next free spot at 17. 192, 168, 1, 12, @@ -423,13 +423,13 @@ func TestIPv4Sanity(t *testing.T) { maxTotalLength: ipv4.MaxTotalSize, transportProtocol: uint8(header.ICMPv4ProtocolNumber), TTL: ttl, - options: []byte{ + options: header.IPv4Options{ 68, 12, 13, 0x11, 192, 168, 1, 12, 1, 2, 3, 4, 0, 10, 3, 99, }, - replyOptions: []byte{ + replyOptions: header.IPv4Options{ 68, 12, 13, 0x21, 192, 168, 1, 12, 1, 2, 3, 4, @@ -442,7 +442,7 @@ func TestIPv4Sanity(t *testing.T) { maxTotalLength: ipv4.MaxTotalSize, transportProtocol: uint8(header.ICMPv4ProtocolNumber), TTL: ttl, - options: []byte{68, 1, 0, 0}, + options: header.IPv4Options{68, 1, 0, 0}, // ^ Smallest possible is 8. shouldFail: true, }, @@ -451,12 +451,12 @@ func TestIPv4Sanity(t *testing.T) { maxTotalLength: ipv4.MaxTotalSize, transportProtocol: uint8(header.ICMPv4ProtocolNumber), TTL: ttl, - options: []byte{ + options: header.IPv4Options{ 7, 7, 4, // 3 byte header 0, 0, 0, 0, 0, }, - replyOptions: []byte{ + replyOptions: header.IPv4Options{ 7, 7, 8, // 3 byte header 192, 168, 1, 58, // New IP Address. 0, // padding to multiple of 4 bytes. @@ -467,7 +467,7 @@ func TestIPv4Sanity(t *testing.T) { maxTotalLength: ipv4.MaxTotalSize, transportProtocol: uint8(header.ICMPv4ProtocolNumber), TTL: ttl, - options: []byte{ + options: header.IPv4Options{ 7, 23, 20, // 3 byte header 1, 2, 3, 4, 5, 6, 7, 8, @@ -476,7 +476,7 @@ func TestIPv4Sanity(t *testing.T) { 0, 0, 0, 0, 0, }, - replyOptions: []byte{ + replyOptions: header.IPv4Options{ 7, 23, 24, 1, 2, 3, 4, 5, 6, 7, 8, @@ -491,12 +491,12 @@ func TestIPv4Sanity(t *testing.T) { maxTotalLength: ipv4.MaxTotalSize, transportProtocol: uint8(header.ICMPv4ProtocolNumber), TTL: ttl, - options: []byte{ + options: header.IPv4Options{ 7, 7, 8, // 3 byte header 1, 2, 3, 4, 0, }, - replyOptions: []byte{ + replyOptions: header.IPv4Options{ 7, 7, 8, // 3 byte header 1, 2, 3, 4, 0, // padding to multiple of 4 bytes. @@ -508,7 +508,7 @@ func TestIPv4Sanity(t *testing.T) { maxTotalLength: ipv4.MaxTotalSize, transportProtocol: uint8(header.ICMPv4ProtocolNumber), TTL: ttl, - options: []byte{ + options: header.IPv4Options{ 7, 23, 24, // 3 byte header 1, 2, 3, 4, 5, 6, 7, 8, @@ -517,7 +517,7 @@ func TestIPv4Sanity(t *testing.T) { 17, 18, 19, 20, 0, }, - replyOptions: []byte{ + replyOptions: header.IPv4Options{ 7, 23, 24, 1, 2, 3, 4, 5, 6, 7, 8, @@ -534,7 +534,7 @@ func TestIPv4Sanity(t *testing.T) { maxTotalLength: ipv4.MaxTotalSize, transportProtocol: uint8(header.ICMPv4ProtocolNumber), TTL: ttl, - options: []byte{ + options: header.IPv4Options{ 7, 8, 8, // 3 byte header // ^ ^ Linux points here. We must too. // | Not enough room. 1 byte free, need 4. @@ -546,14 +546,14 @@ func TestIPv4Sanity(t *testing.T) { ICMPType: header.ICMPv4ParamProblem, ICMPCode: header.ICMPv4UnusedCode, paramProblemPointer: header.IPv4MinimumSize + 2, - replyOptions: []byte{}, + replyOptions: header.IPv4Options{}, }, { name: "duplicate record route", maxTotalLength: ipv4.MaxTotalSize, transportProtocol: uint8(header.ICMPv4ProtocolNumber), TTL: ttl, - options: []byte{ + options: header.IPv4Options{ 7, 7, 8, // 3 byte header 1, 2, 3, 4, 7, 7, 8, // 3 byte header @@ -565,7 +565,7 @@ func TestIPv4Sanity(t *testing.T) { ICMPType: header.ICMPv4ParamProblem, ICMPCode: header.ICMPv4UnusedCode, paramProblemPointer: header.IPv4MinimumSize + 7, - replyOptions: []byte{}, + replyOptions: header.IPv4Options{}, }, } @@ -599,12 +599,7 @@ func TestIPv4Sanity(t *testing.T) { }, }) - // Round up the header size to the next multiple of 4 as RFC 791, page 11 - // says: "Internet Header Length is the length of the internet header - // in 32 bit words..." and on page 23: "The internet header padding is - // used to ensure that the internet header ends on a 32 bit boundary." - ipHeaderLength := ((header.IPv4MinimumSize + len(test.options)) + header.IPv4IHLStride - 1) & ^(header.IPv4IHLStride - 1) - + ipHeaderLength := header.IPv4MinimumSize + test.options.AllocationSize() if ipHeaderLength > header.IPv4MaximumHeaderSize { t.Fatalf("too many bytes in options: got = %d, want <= %d ", ipHeaderLength, header.IPv4MaximumHeaderSize) } @@ -624,17 +619,13 @@ func TestIPv4Sanity(t *testing.T) { totalLen = test.maxTotalLength } ip.Encode(&header.IPv4Fields{ - IHL: uint8(ipHeaderLength), TotalLength: totalLen, Protocol: test.transportProtocol, TTL: test.TTL, SrcAddr: remoteIPv4Addr, DstAddr: ipv4Addr.Address, + Options: test.options, }) - if n := copy(ip.Options(), test.options); n != len(test.options) { - t.Fatalf("options larger than available space: copied %d/%d bytes", n, len(test.options)) - } - // Override the correct value if the test case specified one. if test.headerLength != 0 { ip.SetHeaderLength(test.headerLength) } @@ -1160,9 +1151,11 @@ func TestInvalidFragments(t *testing.T) { } type fragmentData struct { - ipv4fields header.IPv4Fields + ipv4fields header.IPv4Fields + // 0 means insert the correct IHL. Non 0 means override the correct IHL. + overrideIHL int // For 0 use 1 as it is an int and will be divided by 4. payload []byte - autoChecksum bool // if true, the Checksum field will be overwritten. + autoChecksum bool // If true, the Checksum field will be overwritten. } tests := []struct { @@ -1176,7 +1169,6 @@ func TestInvalidFragments(t *testing.T) { fragments: []fragmentData{ { ipv4fields: header.IPv4Fields{ - IHL: 0, TOS: tos, TotalLength: 0, ID: ident, @@ -1187,6 +1179,7 @@ func TestInvalidFragments(t *testing.T) { SrcAddr: addr1, DstAddr: addr2, }, + overrideIHL: 1, // See note above. payload: payloadGen(12), autoChecksum: true, }, @@ -1199,7 +1192,6 @@ func TestInvalidFragments(t *testing.T) { fragments: []fragmentData{ { ipv4fields: header.IPv4Fields{ - IHL: 0, TOS: tos, TotalLength: 0, ID: ident, @@ -1210,6 +1202,7 @@ func TestInvalidFragments(t *testing.T) { SrcAddr: addr1, DstAddr: addr2, }, + overrideIHL: 1, // See note above. payload: payloadGen(12), autoChecksum: true, }, @@ -1224,7 +1217,6 @@ func TestInvalidFragments(t *testing.T) { fragments: []fragmentData{ { ipv4fields: header.IPv4Fields{ - IHL: header.IPv4MinimumSize, TOS: tos, TotalLength: header.IPv4MinimumSize + 17, ID: ident, @@ -1249,7 +1241,6 @@ func TestInvalidFragments(t *testing.T) { fragments: []fragmentData{ { ipv4fields: header.IPv4Fields{ - IHL: header.IPv4MinimumSize, TOS: tos, TotalLength: header.IPv4MinimumSize + 16, ID: ident, @@ -1272,7 +1263,6 @@ func TestInvalidFragments(t *testing.T) { fragments: []fragmentData{ { ipv4fields: header.IPv4Fields{ - IHL: header.IPv4MinimumSize - 12, TOS: tos, TotalLength: header.IPv4MinimumSize + 28, ID: ident, @@ -1284,11 +1274,11 @@ func TestInvalidFragments(t *testing.T) { DstAddr: addr2, }, payload: payloadGen(28), + overrideIHL: header.IPv4MinimumSize - 12, autoChecksum: true, }, { ipv4fields: header.IPv4Fields{ - IHL: header.IPv4MinimumSize - 12, TOS: tos, TotalLength: header.IPv4MinimumSize - 12, ID: ident, @@ -1300,6 +1290,7 @@ func TestInvalidFragments(t *testing.T) { DstAddr: addr2, }, payload: payloadGen(28), + overrideIHL: header.IPv4MinimumSize - 12, autoChecksum: true, }, }, @@ -1311,7 +1302,6 @@ func TestInvalidFragments(t *testing.T) { fragments: []fragmentData{ { ipv4fields: header.IPv4Fields{ - IHL: header.IPv4MinimumSize + 4, TOS: tos, TotalLength: header.IPv4MinimumSize + 28, ID: ident, @@ -1323,11 +1313,11 @@ func TestInvalidFragments(t *testing.T) { DstAddr: addr2, }, payload: payloadGen(28), + overrideIHL: header.IPv4MinimumSize + 4, autoChecksum: true, }, { ipv4fields: header.IPv4Fields{ - IHL: header.IPv4MinimumSize + 4, TOS: tos, TotalLength: header.IPv4MinimumSize + 4, ID: ident, @@ -1339,6 +1329,7 @@ func TestInvalidFragments(t *testing.T) { DstAddr: addr2, }, payload: payloadGen(28), + overrideIHL: header.IPv4MinimumSize + 4, autoChecksum: true, }, }, @@ -1350,7 +1341,6 @@ func TestInvalidFragments(t *testing.T) { fragments: []fragmentData{ { ipv4fields: header.IPv4Fields{ - IHL: header.IPv4MinimumSize, TOS: tos, TotalLength: header.IPv4MinimumSize + 8, ID: ident, @@ -1366,7 +1356,6 @@ func TestInvalidFragments(t *testing.T) { }, { ipv4fields: header.IPv4Fields{ - IHL: header.IPv4MinimumSize, TOS: tos, TotalLength: header.IPv4MinimumSize + 8, ID: ident, @@ -1382,7 +1371,6 @@ func TestInvalidFragments(t *testing.T) { }, { ipv4fields: header.IPv4Fields{ - IHL: header.IPv4MinimumSize, TOS: tos, TotalLength: header.IPv4MinimumSize + 8, ID: ident, @@ -1423,6 +1411,11 @@ func TestInvalidFragments(t *testing.T) { ip := header.IPv4(hdr.Prepend(pktSize)) ip.Encode(&f.ipv4fields) + // Encode sets this up correctly. If we want a different value for + // testing then we need to overwrite the good value. + if f.overrideIHL != 0 { + ip.SetHeaderLength(uint8(f.overrideIHL)) + } copy(ip[header.IPv4MinimumSize:], f.payload) if f.autoChecksum { @@ -1474,7 +1467,6 @@ func TestFragmentReassemblyTimeout(t *testing.T) { fragments: []fragmentData{ { ipv4fields: header.IPv4Fields{ - IHL: header.IPv4MinimumSize, TOS: tos, TotalLength: header.IPv4MinimumSize + 16, ID: ident, @@ -1495,7 +1487,6 @@ func TestFragmentReassemblyTimeout(t *testing.T) { fragments: []fragmentData{ { ipv4fields: header.IPv4Fields{ - IHL: header.IPv4MinimumSize, TOS: tos, TotalLength: header.IPv4MinimumSize + 16, ID: ident, @@ -1510,7 +1501,6 @@ func TestFragmentReassemblyTimeout(t *testing.T) { }, { ipv4fields: header.IPv4Fields{ - IHL: header.IPv4MinimumSize, TOS: tos, TotalLength: header.IPv4MinimumSize + 16, ID: ident, @@ -1531,7 +1521,6 @@ func TestFragmentReassemblyTimeout(t *testing.T) { fragments: []fragmentData{ { ipv4fields: header.IPv4Fields{ - IHL: header.IPv4MinimumSize, TOS: tos, TotalLength: uint16(header.IPv4MinimumSize + len(data) - 16), ID: ident, @@ -1552,7 +1541,6 @@ func TestFragmentReassemblyTimeout(t *testing.T) { fragments: []fragmentData{ { ipv4fields: header.IPv4Fields{ - IHL: header.IPv4MinimumSize, TOS: tos, TotalLength: header.IPv4MinimumSize + 8, ID: ident, @@ -1567,7 +1555,6 @@ func TestFragmentReassemblyTimeout(t *testing.T) { }, { ipv4fields: header.IPv4Fields{ - IHL: header.IPv4MinimumSize, TOS: tos, TotalLength: uint16(header.IPv4MinimumSize + len(data) - 16), ID: ident, @@ -1588,7 +1575,6 @@ func TestFragmentReassemblyTimeout(t *testing.T) { fragments: []fragmentData{ { ipv4fields: header.IPv4Fields{ - IHL: header.IPv4MinimumSize, TOS: tos, TotalLength: uint16(header.IPv4MinimumSize + len(data) - 16), ID: ident, @@ -1603,7 +1589,6 @@ func TestFragmentReassemblyTimeout(t *testing.T) { }, { ipv4fields: header.IPv4Fields{ - IHL: header.IPv4MinimumSize, TOS: tos, TotalLength: header.IPv4MinimumSize + 8, ID: ident, @@ -2104,7 +2089,6 @@ func TestReceiveFragments(t *testing.T) { // Serialize IPv4 fixed header. ip := header.IPv4(hdr.Prepend(header.IPv4MinimumSize)) ip.Encode(&header.IPv4Fields{ - IHL: header.IPv4MinimumSize, TotalLength: header.IPv4MinimumSize + uint16(len(frag.payload)), ID: frag.id, Flags: frag.flags, @@ -2370,7 +2354,6 @@ func TestPacketQueing(t *testing.T) { u.SetChecksum(^u.CalculateChecksum(sum)) ip := header.IPv4(hdr.Prepend(header.IPv4MinimumSize)) ip.Encode(&header.IPv4Fields{ - IHL: header.IPv4MinimumSize, TotalLength: header.IPv4MinimumSize + header.UDPMinimumSize, TTL: ipv4.DefaultTTL, Protocol: uint8(udp.ProtocolNumber), @@ -2414,7 +2397,6 @@ func TestPacketQueing(t *testing.T) { pkt.SetChecksum(^header.Checksum(pkt, 0)) ip := header.IPv4(hdr.Prepend(header.IPv4MinimumSize)) ip.Encode(&header.IPv4Fields{ - IHL: header.IPv4MinimumSize, TotalLength: uint16(totalLen), Protocol: uint8(icmp.ProtocolNumber4), TTL: ipv4.DefaultTTL, -- cgit v1.2.3