go.net/ipv4: add Flags field to Header
Fixes golang/go#6453.
R=golang-dev, mikioh.mikioh
CC=golang-dev
https://golang.org/cl/13832043
diff --git a/ipv4/header.go b/ipv4/header.go
index 45bd27a..e15db01 100644
--- a/ipv4/header.go
+++ b/ipv4/header.go
@@ -36,41 +36,47 @@
maxHeaderLen = 60 // sensible default, revisit if later RFCs define new usage of version and header length fields
)
-type headerField int
+const (
+ posTOS = 1 // type-of-service
+ posTotalLen = 2 // packet total length
+ posID = 4 // identification
+ posFragOff = 6 // fragment offset
+ posTTL = 8 // time-to-live
+ posProtocol = 9 // next protocol
+ posChecksum = 10 // checksum
+ posSrc = 12 // source address
+ posDst = 16 // destination address
+)
+
+type HeaderFlags int
const (
- posTOS headerField = 1 // type-of-service
- posTotalLen = 2 // packet total length
- posID = 4 // identification
- posFragOff = 6 // fragment offset
- posTTL = 8 // time-to-live
- posProtocol = 9 // next protocol
- posChecksum = 10 // checksum
- posSrc = 12 // source address
- posDst = 16 // destination address
+ MoreFragments HeaderFlags = 1 << iota // more fragments flag
+ DontFragment // don't fragment flag
)
// A Header represents an IPv4 header.
type Header struct {
- Version int // protocol version
- Len int // header length
- TOS int // type-of-service
- TotalLen int // packet total length
- ID int // identification
- FragOff int // fragment offset
- TTL int // time-to-live
- Protocol int // next protocol
- Checksum int // checksum
- Src net.IP // source address
- Dst net.IP // destination address
- Options []byte // options, extension headers
+ Version int // protocol version
+ Len int // header length
+ TOS int // type-of-service
+ TotalLen int // packet total length
+ ID int // identification
+ Flags HeaderFlags // flags
+ FragOff int // fragment offset
+ TTL int // time-to-live
+ Protocol int // next protocol
+ Checksum int // checksum
+ Src net.IP // source address
+ Dst net.IP // destination address
+ Options []byte // options, extension headers
}
func (h *Header) String() string {
if h == nil {
return "<nil>"
}
- return fmt.Sprintf("ver: %v, hdrlen: %v, tos: %#x, totallen: %v, id: %#x, fragoff: %#x, ttl: %v, proto: %v, cksum: %#x, src: %v, dst: %v", h.Version, h.Len, h.TOS, h.TotalLen, h.ID, h.FragOff, h.TTL, h.Protocol, h.Checksum, h.Src, h.Dst)
+ return fmt.Sprintf("ver: %v, hdrlen: %v, tos: %#x, totallen: %v, id: %#x, flags: %#x, fragoff: %#x, ttl: %v, proto: %v, cksum: %#x, src: %v, dst: %v", h.Version, h.Len, h.TOS, h.TotalLen, h.ID, h.Flags, h.FragOff, h.TTL, h.Protocol, h.Checksum, h.Src, h.Dst)
}
// Please refer to the online manual; IP(4) on Darwin, FreeBSD and
@@ -89,12 +95,13 @@
b := make([]byte, hdrlen)
b[0] = byte(Version<<4 | (hdrlen >> 2 & 0x0f))
b[posTOS] = byte(h.TOS)
+ flagsAndFragOff := (h.FragOff & 0x1fff) | int(h.Flags<<13)
if supportsNewIPInput {
b[posTotalLen], b[posTotalLen+1] = byte(h.TotalLen>>8), byte(h.TotalLen)
- b[posFragOff], b[posFragOff+1] = byte(h.FragOff>>8), byte(h.FragOff)
+ b[posFragOff], b[posFragOff+1] = byte(flagsAndFragOff>>8), byte(flagsAndFragOff)
} else {
*(*uint16)(unsafe.Pointer(&b[posTotalLen : posTotalLen+1][0])) = uint16(h.TotalLen)
- *(*uint16)(unsafe.Pointer(&b[posFragOff : posFragOff+1][0])) = uint16(h.FragOff)
+ *(*uint16)(unsafe.Pointer(&b[posFragOff : posFragOff+1][0])) = uint16(flagsAndFragOff)
}
b[posID], b[posID+1] = byte(h.ID>>8), byte(h.ID)
b[posTTL] = byte(h.TTL)
@@ -135,6 +142,8 @@
h.TotalLen += hdrlen
h.FragOff = int(*(*uint16)(unsafe.Pointer(&b[posFragOff : posFragOff+1][0])))
}
+ h.Flags = HeaderFlags(h.FragOff&0xe000) >> 13
+ h.FragOff = h.FragOff & 0x1fff
h.ID = int(b[posID])<<8 | int(b[posID+1])
h.TTL = int(b[posTTL])
h.Protocol = int(b[posProtocol])
diff --git a/ipv4/header_test.go b/ipv4/header_test.go
index cc2fd8e..121d1f2 100644
--- a/ipv4/header_test.go
+++ b/ipv4/header_test.go
@@ -16,28 +16,28 @@
var (
wireHeaderFromKernel = [ipv4.HeaderLen]byte{
0x45, 0x01, 0xbe, 0xef,
- 0xca, 0xfe, 0x05, 0xdc,
+ 0xca, 0xfe, 0x45, 0xdc,
0xff, 0x01, 0xde, 0xad,
172, 16, 254, 254,
192, 168, 0, 1,
}
wireHeaderToKernel = [ipv4.HeaderLen]byte{
0x45, 0x01, 0xbe, 0xef,
- 0xca, 0xfe, 0x05, 0xdc,
+ 0xca, 0xfe, 0x45, 0xdc,
0xff, 0x01, 0xde, 0xad,
172, 16, 254, 254,
192, 168, 0, 1,
}
wireHeaderFromTradBSDKernel = [ipv4.HeaderLen]byte{
0x45, 0x01, 0xdb, 0xbe,
- 0xca, 0xfe, 0xdc, 0x05,
+ 0xca, 0xfe, 0xdc, 0x45,
0xff, 0x01, 0xde, 0xad,
172, 16, 254, 254,
192, 168, 0, 1,
}
wireHeaderToTradBSDKernel = [ipv4.HeaderLen]byte{
0x45, 0x01, 0xef, 0xbe,
- 0xca, 0xfe, 0xdc, 0x05,
+ 0xca, 0xfe, 0xdc, 0x45,
0xff, 0x01, 0xde, 0xad,
172, 16, 254, 254,
192, 168, 0, 1,
@@ -51,6 +51,7 @@
TOS: 1,
TotalLen: 0xbeef,
ID: 0xcafe,
+ Flags: ipv4.DontFragment,
FragOff: 1500,
TTL: 255,
Protocol: 1,