diff options
Diffstat (limited to 'pkg/tcpip/header')
-rw-r--r-- | pkg/tcpip/header/ipv4.go | 58 | ||||
-rw-r--r-- | pkg/tcpip/header/ipv6.go | 4 | ||||
-rw-r--r-- | pkg/tcpip/header/ipv6_test.go | 8 |
3 files changed, 36 insertions, 34 deletions
diff --git a/pkg/tcpip/header/ipv4.go b/pkg/tcpip/header/ipv4.go index e6103f4bc..48ca60319 100644 --- a/pkg/tcpip/header/ipv4.go +++ b/pkg/tcpip/header/ipv4.go @@ -1,4 +1,4 @@ -// Copyright 2018 The gVisor Authors. +// Copyright 2021 The gVisor Authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -16,7 +16,6 @@ package header import ( "encoding/binary" - "errors" "fmt" "gvisor.dev/gvisor/pkg/tcpip" @@ -481,15 +480,13 @@ const ( IPv4OptionLengthOffset = 1 ) -// Potential errors when parsing generic IP options. -var ( - ErrIPv4OptZeroLength = errors.New("zero length IP option") - ErrIPv4OptDuplicate = errors.New("duplicate IP option") - ErrIPv4OptInvalid = errors.New("invalid IP option") - ErrIPv4OptMalformed = errors.New("malformed IP option") - ErrIPv4OptionTruncated = errors.New("truncated IP option") - ErrIPv4OptionAddress = errors.New("bad IP option address") -) +// IPv4OptParameterProblem indicates that a Parameter Problem message +// should be generated, and gives the offset in the current entity +// that should be used in that packet. +type IPv4OptParameterProblem struct { + Pointer uint8 + NeedICMP bool +} // IPv4Option is an interface representing various option types. type IPv4Option interface { @@ -583,8 +580,9 @@ func (i *IPv4OptionIterator) Finalize() IPv4Options { // It returns // - A slice of bytes holding the next option or nil if there is error. // - A boolean which is true if parsing of all the options is complete. -// - An error which is non-nil if an error condition was encountered. -func (i *IPv4OptionIterator) Next() (IPv4Option, bool, error) { +// Undefined in the case of error. +// - An error indication which is non-nil if an error condition was found. +func (i *IPv4OptionIterator) Next() (IPv4Option, bool, *IPv4OptParameterProblem) { // The opts slice gets shorter as we process the options. When we have no // bytes left we are done. if len(i.options) == 0 { @@ -606,24 +604,22 @@ func (i *IPv4OptionIterator) Next() (IPv4Option, bool, error) { // There are no more single byte options defined. All the rest have a length // field so we need to sanity check it. if len(i.options) == 1 { - return nil, true, ErrIPv4OptMalformed + return nil, false, &IPv4OptParameterProblem{ + Pointer: i.ErrCursor, + NeedICMP: true, + } } optLen := i.options[IPv4OptionLengthOffset] - if optLen == 0 { - i.ErrCursor++ - return nil, true, ErrIPv4OptZeroLength - } + if optLen <= IPv4OptionLengthOffset || optLen > uint8(len(i.options)) { + // The actual error is in the length (2nd byte of the option) but we + // return the start of the option for compatibility with Linux. - if optLen == 1 { - i.ErrCursor++ - return nil, true, ErrIPv4OptMalformed - } - - if optLen > uint8(len(i.options)) { - i.ErrCursor++ - return nil, true, ErrIPv4OptionTruncated + return nil, false, &IPv4OptParameterProblem{ + Pointer: i.ErrCursor, + NeedICMP: true, + } } optionBody := i.options[:optLen] @@ -635,7 +631,10 @@ func (i *IPv4OptionIterator) Next() (IPv4Option, bool, error) { case IPv4OptionTimestampType: if optLen < IPv4OptionTimestampHdrLength { i.ErrCursor++ - return nil, true, ErrIPv4OptMalformed + return nil, false, &IPv4OptParameterProblem{ + Pointer: i.ErrCursor, + NeedICMP: true, + } } retval := IPv4OptionTimestamp(optionBody) return &retval, false, nil @@ -643,7 +642,10 @@ func (i *IPv4OptionIterator) Next() (IPv4Option, bool, error) { case IPv4OptionRecordRouteType: if optLen < IPv4OptionRecordRouteHdrLength { i.ErrCursor++ - return nil, true, ErrIPv4OptMalformed + return nil, false, &IPv4OptParameterProblem{ + Pointer: i.ErrCursor, + NeedICMP: true, + } } retval := IPv4OptionRecordRoute(optionBody) return &retval, false, nil diff --git a/pkg/tcpip/header/ipv6.go b/pkg/tcpip/header/ipv6.go index 5580d6a78..f2403978c 100644 --- a/pkg/tcpip/header/ipv6.go +++ b/pkg/tcpip/header/ipv6.go @@ -453,9 +453,9 @@ const ( ) // ScopeForIPv6Address returns the scope for an IPv6 address. -func ScopeForIPv6Address(addr tcpip.Address) (IPv6AddressScope, *tcpip.Error) { +func ScopeForIPv6Address(addr tcpip.Address) (IPv6AddressScope, tcpip.Error) { if len(addr) != IPv6AddressSize { - return GlobalScope, tcpip.ErrBadAddress + return GlobalScope, &tcpip.ErrBadAddress{} } switch { diff --git a/pkg/tcpip/header/ipv6_test.go b/pkg/tcpip/header/ipv6_test.go index e3fbd64f3..f10f446a6 100644 --- a/pkg/tcpip/header/ipv6_test.go +++ b/pkg/tcpip/header/ipv6_test.go @@ -299,7 +299,7 @@ func TestScopeForIPv6Address(t *testing.T) { name string addr tcpip.Address scope header.IPv6AddressScope - err *tcpip.Error + err tcpip.Error }{ { name: "Unique Local", @@ -329,15 +329,15 @@ func TestScopeForIPv6Address(t *testing.T) { name: "IPv4", addr: "\x01\x02\x03\x04", scope: header.GlobalScope, - err: tcpip.ErrBadAddress, + err: &tcpip.ErrBadAddress{}, }, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { got, err := header.ScopeForIPv6Address(test.addr) - if err != test.err { - t.Errorf("got header.IsV6UniqueLocalAddress(%s) = (_, %v), want = (_, %v)", test.addr, err, test.err) + if diff := cmp.Diff(test.err, err); diff != "" { + t.Errorf("unexpected error from header.IsV6UniqueLocalAddress(%s), (-want, +got):\n%s", test.addr, diff) } if got != test.scope { t.Errorf("got header.IsV6UniqueLocalAddress(%s) = (%d, _), want = (%d, _)", test.addr, got, test.scope) |