Commit 28a4bd90 authored by Mikio Hara's avatar Mikio Hara

go.net/ipv4: handle total length field correctly on FreeBSD 10

FreeBSD 10 kernel has changed its incoming IPv4 packet handling
to stop trimming some IPv4 header fields on raw socket IO. This CL
just adapts package's IPv4 header representation to look the same
even on FreeBSD 10 kernel.

For further information:
http://svnweb.freebsd.org/base/head/?view=log&pathrev=226105
http://svnweb.freebsd.org/base/head/?view=log&pathrev=241913
http://svnweb.freebsd.org/base/head/?view=log&pathrev=241923

LGTM=iant
R=golang-codereviews, gobot, dave, iant
CC=golang-codereviews
https://golang.org/cl/53030043
parent f3b815ba
......@@ -121,6 +121,9 @@ func (h *Header) Marshal() ([]byte, error) {
return b, nil
}
// See http://www.freebsd.org/doc/en/books/porters-handbook/freebsd-versions.html.
var freebsdVersion uint32
// ParseHeader parses b as an IPv4 header.
func ParseHeader(b []byte) (*Header, error) {
if len(b) < HeaderLen {
......@@ -139,7 +142,9 @@ func ParseHeader(b []byte) (*Header, error) {
h.FragOff = int(b[posFragOff])<<8 | int(b[posFragOff+1])
} else {
h.TotalLen = int(*(*uint16)(unsafe.Pointer(&b[posTotalLen : posTotalLen+1][0])))
h.TotalLen += hdrlen
if runtime.GOOS != "freebsd" || freebsdVersion < 1000000 {
h.TotalLen += hdrlen
}
h.FragOff = int(*(*uint16)(unsafe.Pointer(&b[posFragOff : posFragOff+1][0])))
}
h.Flags = HeaderFlags(h.FragOff&0xe000) >> 13
......
......@@ -2,11 +2,10 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package ipv4_test
package ipv4
import (
"bytes"
"code.google.com/p/go.net/ipv4"
"net"
"reflect"
"runtime"
......@@ -14,28 +13,35 @@ import (
)
var (
wireHeaderFromKernel = [ipv4.HeaderLen]byte{
wireHeaderFromKernel = [HeaderLen]byte{
0x45, 0x01, 0xbe, 0xef,
0xca, 0xfe, 0x45, 0xdc,
0xff, 0x01, 0xde, 0xad,
172, 16, 254, 254,
192, 168, 0, 1,
}
wireHeaderToKernel = [ipv4.HeaderLen]byte{
wireHeaderToKernel = [HeaderLen]byte{
0x45, 0x01, 0xbe, 0xef,
0xca, 0xfe, 0x45, 0xdc,
0xff, 0x01, 0xde, 0xad,
172, 16, 254, 254,
192, 168, 0, 1,
}
wireHeaderFromTradBSDKernel = [ipv4.HeaderLen]byte{
wireHeaderFromTradBSDKernel = [HeaderLen]byte{
0x45, 0x01, 0xdb, 0xbe,
0xca, 0xfe, 0xdc, 0x45,
0xff, 0x01, 0xde, 0xad,
172, 16, 254, 254,
192, 168, 0, 1,
}
wireHeaderToTradBSDKernel = [ipv4.HeaderLen]byte{
wireHeaderFromFreeBSD10Kernel = [HeaderLen]byte{
0x45, 0x01, 0xef, 0xbe,
0xca, 0xfe, 0xdc, 0x45,
0xff, 0x01, 0xde, 0xad,
172, 16, 254, 254,
192, 168, 0, 1,
}
wireHeaderToTradBSDKernel = [HeaderLen]byte{
0x45, 0x01, 0xef, 0xbe,
0xca, 0xfe, 0xdc, 0x45,
0xff, 0x01, 0xde, 0xad,
......@@ -45,13 +51,13 @@ var (
// TODO(mikio): Add platform dependent wire header formats when
// we support new platforms.
testHeader = &ipv4.Header{
Version: ipv4.Version,
Len: ipv4.HeaderLen,
testHeader = &Header{
Version: Version,
Len: HeaderLen,
TOS: 1,
TotalLen: 0xbeef,
ID: 0xcafe,
Flags: ipv4.DontFragment,
Flags: DontFragment,
FragOff: 1500,
TTL: 255,
Protocol: 1,
......@@ -67,10 +73,9 @@ func TestMarshalHeader(t *testing.T) {
t.Fatalf("ipv4.Header.Marshal failed: %v", err)
}
var wh []byte
switch runtime.GOOS {
case "linux", "openbsd":
if supportsNewIPInput {
wh = wireHeaderToKernel[:]
default:
} else {
wh = wireHeaderToTradBSDKernel[:]
}
if !bytes.Equal(b, wh) {
......@@ -80,13 +85,16 @@ func TestMarshalHeader(t *testing.T) {
func TestParseHeader(t *testing.T) {
var wh []byte
switch runtime.GOOS {
case "linux", "openbsd":
if supportsNewIPInput {
wh = wireHeaderFromKernel[:]
default:
wh = wireHeaderFromTradBSDKernel[:]
} else {
if runtime.GOOS == "freebsd" && freebsdVersion >= 1000000 {
wh = wireHeaderFromFreeBSD10Kernel[:]
} else {
wh = wireHeaderFromTradBSDKernel[:]
}
}
h, err := ipv4.ParseHeader(wh)
h, err := ParseHeader(wh)
if err != nil {
t.Fatalf("ipv4.ParseHeader failed: %v", err)
}
......
// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package ipv4
import "syscall"
func init() {
freebsdVersion, _ = syscall.SysctlUint32("kern.osreldate")
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment