...
1
2
3
4
5 package icmp
6
7 import (
8 "encoding/binary"
9 "net"
10 "runtime"
11
12 "golang.org/x/net/internal/socket"
13 "golang.org/x/net/ipv4"
14 )
15
16
17
18 var freebsdVersion uint32
19
20
21
22
23
24
25
26
27
28
29
30 func ParseIPv4Header(b []byte) (*ipv4.Header, error) {
31 if len(b) < ipv4.HeaderLen {
32 return nil, errHeaderTooShort
33 }
34 hdrlen := int(b[0]&0x0f) << 2
35 if hdrlen > len(b) {
36 return nil, errBufferTooShort
37 }
38 h := &ipv4.Header{
39 Version: int(b[0] >> 4),
40 Len: hdrlen,
41 TOS: int(b[1]),
42 ID: int(binary.BigEndian.Uint16(b[4:6])),
43 FragOff: int(binary.BigEndian.Uint16(b[6:8])),
44 TTL: int(b[8]),
45 Protocol: int(b[9]),
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]),
49 }
50 switch runtime.GOOS {
51 case "darwin", "ios":
52 h.TotalLen = int(socket.NativeEndian.Uint16(b[2:4]))
53 case "freebsd":
54 if freebsdVersion >= 1000000 {
55 h.TotalLen = int(binary.BigEndian.Uint16(b[2:4]))
56 } else {
57 h.TotalLen = int(socket.NativeEndian.Uint16(b[2:4]))
58 }
59 default:
60 h.TotalLen = int(binary.BigEndian.Uint16(b[2:4]))
61 }
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:])
67 }
68 return h, nil
69 }
70
View as plain text