github.com/graybobo/golang.org-package-offline-cache@v0.0.0-20200626051047-6608995c132f/x/net/icmp/ipv4.go (about)

     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  	"net"
     9  	"runtime"
    10  	"unsafe"
    11  
    12  	"golang.org/x/net/ipv4"
    13  )
    14  
    15  // See http://www.freebsd.org/doc/en/books/porters-handbook/freebsd-versions.html.
    16  var freebsdVersion uint32
    17  
    18  // ParseIPv4Header parses b as an IPv4 header of ICMP error message
    19  // invoking packet, which is contained in ICMP error message.
    20  func ParseIPv4Header(b []byte) (*ipv4.Header, error) {
    21  	if len(b) < ipv4.HeaderLen {
    22  		return nil, errHeaderTooShort
    23  	}
    24  	hdrlen := int(b[0]&0x0f) << 2
    25  	if hdrlen > len(b) {
    26  		return nil, errBufferTooShort
    27  	}
    28  	h := &ipv4.Header{
    29  		Version:  int(b[0] >> 4),
    30  		Len:      hdrlen,
    31  		TOS:      int(b[1]),
    32  		ID:       int(b[4])<<8 | int(b[5]),
    33  		FragOff:  int(b[6])<<8 | int(b[7]),
    34  		TTL:      int(b[8]),
    35  		Protocol: int(b[9]),
    36  		Checksum: int(b[10])<<8 | int(b[11]),
    37  		Src:      net.IPv4(b[12], b[13], b[14], b[15]),
    38  		Dst:      net.IPv4(b[16], b[17], b[18], b[19]),
    39  	}
    40  	switch runtime.GOOS {
    41  	case "darwin":
    42  		// TODO(mikio): fix potential misaligned memory access
    43  		h.TotalLen = int(*(*uint16)(unsafe.Pointer(&b[2:3][0])))
    44  	case "freebsd":
    45  		if freebsdVersion >= 1000000 {
    46  			h.TotalLen = int(b[2])<<8 | int(b[3])
    47  		} else {
    48  			// TODO(mikio): fix potential misaligned memory access
    49  			h.TotalLen = int(*(*uint16)(unsafe.Pointer(&b[2:3][0])))
    50  		}
    51  	default:
    52  		h.TotalLen = int(b[2])<<8 | int(b[3])
    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  }