OSDN Git Service

new repo
[bytom/vapor.git] / vendor / golang.org / x / net / icmp / ipv4.go
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.
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 // 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
19
20 // ParseIPv4Header parses b as an IPv4 header of ICMP error message
21 // invoking packet, which is contained in ICMP error message.
22 func 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 }