ipv4: fix error values on header manipulation

This change makes header manipulation methods and functions return a nil
header error if the receiver or wire header is nil, a header too short
error if the header length field value of receiver or wire header is
short, and a extension header error if the wire extnsion header is
short.

Also replaces syscall.EWINDOWS or syscall.EPLAN9 with more descriptive,
platform independent error values.

Change-Id: I923fb60b1d68857cffc9df20f3f6cb2babbcdb1f
Reviewed-on: https://go-review.googlesource.com/c/net/+/129136
Reviewed-by: Matt Layher <mdlayher@gmail.com>
This commit is contained in:
Mikio Hara
2018-11-16 17:37:45 +09:00
parent 16b79f2e4e
commit b774fd8d5c
4 changed files with 46 additions and 13 deletions

View File

@@ -4,13 +4,9 @@
package ipv4
import (
"syscall"
"golang.org/x/net/internal/socket"
)
import "golang.org/x/net/internal/socket"
func setControlMessage(c *socket.Conn, opt *rawOpt, cf ControlFlags, on bool) error {
// TODO(mikio): implement this
return syscall.EWINDOWS
return errNotImplemented
}

View File

@@ -57,7 +57,7 @@ func (h *Header) String() string {
// This may differ from the wire format, depending on the system.
func (h *Header) Marshal() ([]byte, error) {
if h == nil {
return nil, errInvalidConn
return nil, errNilHeader
}
if h.Len < HeaderLen {
return nil, errHeaderTooShort
@@ -107,12 +107,15 @@ func (h *Header) Marshal() ([]byte, error) {
// local system.
// This may differ from the wire format, depending on the system.
func (h *Header) Parse(b []byte) error {
if h == nil || len(b) < HeaderLen {
if h == nil || b == nil {
return errNilHeader
}
if len(b) < HeaderLen {
return errHeaderTooShort
}
hdrlen := int(b[0]&0x0f) << 2
if hdrlen > len(b) {
return errBufferTooShort
if len(b) < hdrlen {
return errExtHeaderTooShort
}
h.Version = int(b[0] >> 4)
h.Len = hdrlen

View File

@@ -157,10 +157,21 @@ var headerLittleEndianTests = []headerTest{
}
func TestMarshalHeader(t *testing.T) {
for i, tt := range []struct {
h *Header
err error
}{
{nil, errNilHeader},
{&Header{Len: HeaderLen - 1}, errHeaderTooShort},
} {
if _, err := tt.h.Marshal(); err != tt.err {
t.Errorf("#%d: got %v; want %v", i, err, tt.err)
}
}
if socket.NativeEndian != binary.LittleEndian {
t.Skip("no test for non-little endian machine yet")
}
for _, tt := range headerLittleEndianTests {
b, err := tt.Header.Marshal()
if err != nil {
@@ -189,10 +200,30 @@ func TestMarshalHeader(t *testing.T) {
}
func TestParseHeader(t *testing.T) {
for i, tt := range []struct {
h *Header
wh []byte
err error
}{
{nil, nil, errNilHeader},
{&Header{}, nil, errNilHeader},
{&Header{}, make([]byte, HeaderLen-1), errHeaderTooShort},
{&Header{}, []byte{
0x46, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
}, errExtHeaderTooShort},
} {
if err := tt.h.Parse(tt.wh); err != tt.err {
t.Fatalf("#%d: got %v; want %v", i, err, tt.err)
}
}
if socket.NativeEndian != binary.LittleEndian {
t.Skip("no test for big endian machine yet")
}
for _, tt := range headerLittleEndianTests {
var wh []byte
switch runtime.GOOS {

View File

@@ -7,18 +7,21 @@ package ipv4
import (
"errors"
"net"
"runtime"
)
var (
errInvalidConn = errors.New("invalid connection")
errMissingAddress = errors.New("missing address")
errMissingHeader = errors.New("missing header")
errNilHeader = errors.New("nil header")
errHeaderTooShort = errors.New("header too short")
errBufferTooShort = errors.New("buffer too short")
errExtHeaderTooShort = errors.New("extension header too short")
errInvalidConnType = errors.New("invalid conn type")
errOpNoSupport = errors.New("operation not supported")
errNoSuchInterface = errors.New("no such interface")
errNoSuchMulticastInterface = errors.New("no such multicast interface")
errNotImplemented = errors.New("not implemented on " + runtime.GOOS + "/" + runtime.GOARCH)
// See http://www.freebsd.org/doc/en/books/porters-handbook/freebsd-versions.html.
freebsdVersion uint32