ipv4: fix potential misaligned memory access
Also makes use of encoding/binary package.
Change-Id: Id41ea874487f88a3de9fa28b613a77eb66643cc8
Reviewed-on: https://go-review.googlesource.com/19534
Run-TryBot: Mikio Hara <mikioh.mikioh@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
diff --git a/ipv4/header.go b/ipv4/header.go
index d108176..363d9c2 100644
--- a/ipv4/header.go
+++ b/ipv4/header.go
@@ -5,11 +5,11 @@
package ipv4
import (
+ "encoding/binary"
"fmt"
"net"
"runtime"
"syscall"
- "unsafe"
)
const (
@@ -64,17 +64,16 @@
flagsAndFragOff := (h.FragOff & 0x1fff) | int(h.Flags<<13)
switch runtime.GOOS {
case "darwin", "dragonfly", "freebsd", "netbsd":
- // TODO(mikio): fix potential misaligned memory access
- *(*uint16)(unsafe.Pointer(&b[2:3][0])) = uint16(h.TotalLen)
- *(*uint16)(unsafe.Pointer(&b[6:7][0])) = uint16(flagsAndFragOff)
+ nativeEndian.PutUint16(b[2:4], uint16(h.TotalLen))
+ nativeEndian.PutUint16(b[6:8], uint16(flagsAndFragOff))
default:
- b[2], b[3] = byte(h.TotalLen>>8), byte(h.TotalLen)
- b[6], b[7] = byte(flagsAndFragOff>>8), byte(flagsAndFragOff)
+ binary.BigEndian.PutUint16(b[2:4], uint16(h.TotalLen))
+ binary.BigEndian.PutUint16(b[6:8], uint16(flagsAndFragOff))
}
- b[4], b[5] = byte(h.ID>>8), byte(h.ID)
+ binary.BigEndian.PutUint16(b[4:6], uint16(h.ID))
b[8] = byte(h.TTL)
b[9] = byte(h.Protocol)
- b[10], b[11] = byte(h.Checksum>>8), byte(h.Checksum)
+ binary.BigEndian.PutUint16(b[10:12], uint16(h.Checksum))
if ip := h.Src.To4(); ip != nil {
copy(b[12:16], ip[:net.IPv4len])
}
@@ -89,9 +88,6 @@
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 {
@@ -105,30 +101,26 @@
Version: int(b[0] >> 4),
Len: hdrlen,
TOS: int(b[1]),
- ID: int(b[4])<<8 | int(b[5]),
+ ID: int(binary.BigEndian.Uint16(b[4:6])),
TTL: int(b[8]),
Protocol: int(b[9]),
- Checksum: int(b[10])<<8 | int(b[11]),
+ Checksum: int(binary.BigEndian.Uint16(b[10:12])),
Src: net.IPv4(b[12], b[13], b[14], b[15]),
Dst: net.IPv4(b[16], b[17], b[18], b[19]),
}
switch runtime.GOOS {
case "darwin", "dragonfly", "netbsd":
- // TODO(mikio): fix potential misaligned memory access
- h.TotalLen = int(*(*uint16)(unsafe.Pointer(&b[2:3][0]))) + hdrlen
- // TODO(mikio): fix potential misaligned memory access
- h.FragOff = int(*(*uint16)(unsafe.Pointer(&b[6:7][0])))
+ h.TotalLen = int(nativeEndian.Uint16(b[2:4])) + hdrlen
+ h.FragOff = int(nativeEndian.Uint16(b[6:8]))
case "freebsd":
- // TODO(mikio): fix potential misaligned memory access
- h.TotalLen = int(*(*uint16)(unsafe.Pointer(&b[2:3][0])))
+ h.TotalLen = int(nativeEndian.Uint16(b[2:4]))
if freebsdVersion < 1000000 {
h.TotalLen += hdrlen
}
- // TODO(mikio): fix potential misaligned memory access
- h.FragOff = int(*(*uint16)(unsafe.Pointer(&b[6:7][0])))
+ h.FragOff = int(nativeEndian.Uint16(b[6:8]))
default:
- h.TotalLen = int(b[2])<<8 | int(b[3])
- h.FragOff = int(b[6])<<8 | int(b[7])
+ h.TotalLen = int(binary.BigEndian.Uint16(b[2:4]))
+ h.FragOff = int(binary.BigEndian.Uint16(b[6:8]))
}
h.Flags = HeaderFlags(h.FragOff&0xe000) >> 13
h.FragOff = h.FragOff & 0x1fff
diff --git a/ipv4/helper.go b/ipv4/helper.go
index 8a7ee90..acecfd0 100644
--- a/ipv4/helper.go
+++ b/ipv4/helper.go
@@ -5,8 +5,10 @@
package ipv4
import (
+ "encoding/binary"
"errors"
"net"
+ "unsafe"
)
var (
@@ -18,8 +20,23 @@
errOpNoSupport = errors.New("operation not supported")
errNoSuchInterface = errors.New("no such interface")
errNoSuchMulticastInterface = errors.New("no such multicast interface")
+
+ // See http://www.freebsd.org/doc/en/books/porters-handbook/freebsd-versions.html.
+ freebsdVersion uint32
+
+ nativeEndian binary.ByteOrder
)
+func init() {
+ i := uint32(1)
+ b := (*[4]byte)(unsafe.Pointer(&i))
+ if b[0] == 1 {
+ nativeEndian = binary.LittleEndian
+ } else {
+ nativeEndian = binary.BigEndian
+ }
+}
+
func boolint(b bool) int {
if b {
return 1