1 // Copyright 2014 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
12 "golang.org/x/net/internal/socket"
13 "golang.org/x/net/ipv4"
16 // freebsdVersion is set in sys_freebsd.go.
17 // See http://www.freebsd.org/doc/en/books/porters-handbook/freebsd-versions.html.
18 var freebsdVersion uint32
20 // ParseIPv4Header returns the IPv4 header of the IPv4 packet that
21 // triggered an ICMP error message.
22 // This is found in the Data field of the ICMP error message body.
24 // The provided b must be in the format used by a raw ICMP socket on
26 // This may differ from the wire format, and the format used by a raw
27 // IP socket, depending on the system.
29 // To parse an IPv6 header, use ipv6.ParseHeader.
30 func ParseIPv4Header(b []byte) (*ipv4.Header, error) {
31 if len(b) < ipv4.HeaderLen {
32 return nil, errHeaderTooShort
34 hdrlen := int(b[0]&0x0f) << 2
36 return nil, errBufferTooShort
39 Version: int(b[0] >> 4),
42 ID: int(binary.BigEndian.Uint16(b[4:6])),
43 FragOff: int(binary.BigEndian.Uint16(b[6:8])),
46 Checksum: int(binary.BigEndian.Uint16(b[10:12])),
47 Src: net.IPv4(b[12], b[13], b[14], b[15]),
48 Dst: net.IPv4(b[16], b[17], b[18], b[19]),
52 h.TotalLen = int(socket.NativeEndian.Uint16(b[2:4]))
54 if freebsdVersion >= 1000000 {
55 h.TotalLen = int(binary.BigEndian.Uint16(b[2:4]))
57 h.TotalLen = int(socket.NativeEndian.Uint16(b[2:4]))
60 h.TotalLen = int(binary.BigEndian.Uint16(b[2:4]))
62 h.Flags = ipv4.HeaderFlags(h.FragOff&0xe000) >> 13
63 h.FragOff = h.FragOff & 0x1fff
64 if hdrlen-ipv4.HeaderLen > 0 {
65 h.Options = make([]byte, hdrlen-ipv4.HeaderLen)
66 copy(h.Options, b[ipv4.HeaderLen:])