blob: ffc66ed4d80d8bc7b0d044d998dcc3fee1ee84b4 [file] [log] [blame]
David K. Bainbridge215e0242017-09-05 23:18:24 -07001// 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.
4
5package icmp
6
7import (
8 "encoding/binary"
9 "net"
10 "runtime"
11
12 "golang.org/x/net/internal/socket"
13 "golang.org/x/net/ipv4"
14)
15
16// freebsdVersion is set in sys_freebsd.go.
17// See http://www.freebsd.org/doc/en/books/porters-handbook/freebsd-versions.html.
18var freebsdVersion uint32
19
20// ParseIPv4Header parses b as an IPv4 header of ICMP error message
21// invoking packet, which is contained in ICMP error message.
22func ParseIPv4Header(b []byte) (*ipv4.Header, error) {
23 if len(b) < ipv4.HeaderLen {
24 return nil, errHeaderTooShort
25 }
26 hdrlen := int(b[0]&0x0f) << 2
27 if hdrlen > len(b) {
28 return nil, errBufferTooShort
29 }
30 h := &ipv4.Header{
31 Version: int(b[0] >> 4),
32 Len: hdrlen,
33 TOS: int(b[1]),
34 ID: int(binary.BigEndian.Uint16(b[4:6])),
35 FragOff: int(binary.BigEndian.Uint16(b[6:8])),
36 TTL: int(b[8]),
37 Protocol: int(b[9]),
38 Checksum: int(binary.BigEndian.Uint16(b[10:12])),
39 Src: net.IPv4(b[12], b[13], b[14], b[15]),
40 Dst: net.IPv4(b[16], b[17], b[18], b[19]),
41 }
42 switch runtime.GOOS {
43 case "darwin":
44 h.TotalLen = int(socket.NativeEndian.Uint16(b[2:4]))
45 case "freebsd":
46 if freebsdVersion >= 1000000 {
47 h.TotalLen = int(binary.BigEndian.Uint16(b[2:4]))
48 } else {
49 h.TotalLen = int(socket.NativeEndian.Uint16(b[2:4]))
50 }
51 default:
52 h.TotalLen = int(binary.BigEndian.Uint16(b[2:4]))
53 }
54 h.Flags = ipv4.HeaderFlags(h.FragOff&0xe000) >> 13
55 h.FragOff = h.FragOff & 0x1fff
56 if hdrlen-ipv4.HeaderLen > 0 {
57 h.Options = make([]byte, hdrlen-ipv4.HeaderLen)
58 copy(h.Options, b[ipv4.HeaderLen:])
59 }
60 return h, nil
61}