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

     1  // Copyright 2015 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  // An Extension represents an ICMP extension.
     8  type Extension interface {
     9  	// Len returns the length of ICMP extension.
    10  	// Proto must be either the ICMPv4 or ICMPv6 protocol number.
    11  	Len(proto int) int
    12  
    13  	// Marshal returns the binary enconding of ICMP extension.
    14  	// Proto must be either the ICMPv4 or ICMPv6 protocol number.
    15  	Marshal(proto int) ([]byte, error)
    16  }
    17  
    18  const extensionVersion = 2
    19  
    20  func validExtensionHeader(b []byte) bool {
    21  	v := int(b[0]&0xf0) >> 4
    22  	s := uint16(b[2])<<8 | uint16(b[3])
    23  	if s != 0 {
    24  		s = checksum(b)
    25  	}
    26  	if v != extensionVersion || s != 0 {
    27  		return false
    28  	}
    29  	return true
    30  }
    31  
    32  // parseExtensions parses b as a list of ICMP extensions.
    33  // The length attribute l must be the length attribute field in
    34  // received icmp messages.
    35  //
    36  // It will return a list of ICMP extensions and an adjusted length
    37  // attribute that represents the length of the padded original
    38  // datagram field. Otherwise, it returns an error.
    39  func parseExtensions(b []byte, l int) ([]Extension, int, error) {
    40  	// Still a lot of non-RFC 4884 compliant implementations are
    41  	// out there. Set the length attribute l to 128 when it looks
    42  	// inappropriate for backwards compatibility.
    43  	//
    44  	// A minimal extension at least requires 8 octets; 4 octets
    45  	// for an extension header, and 4 octets for a single object
    46  	// header.
    47  	//
    48  	// See RFC 4884 for further information.
    49  	if 128 > l || l+8 > len(b) {
    50  		l = 128
    51  	}
    52  	if l+8 > len(b) {
    53  		return nil, -1, errNoExtension
    54  	}
    55  	if !validExtensionHeader(b[l:]) {
    56  		if l == 128 {
    57  			return nil, -1, errNoExtension
    58  		}
    59  		l = 128
    60  		if !validExtensionHeader(b[l:]) {
    61  			return nil, -1, errNoExtension
    62  		}
    63  	}
    64  	var exts []Extension
    65  	for b = b[l+4:]; len(b) >= 4; {
    66  		ol := int(b[0])<<8 | int(b[1])
    67  		if 4 > ol || ol > len(b) {
    68  			break
    69  		}
    70  		switch b[2] {
    71  		case classMPLSLabelStack:
    72  			ext, err := parseMPLSLabelStack(b[:ol])
    73  			if err != nil {
    74  				return nil, -1, err
    75  			}
    76  			exts = append(exts, ext)
    77  		case classInterfaceInfo:
    78  			ext, err := parseInterfaceInfo(b[:ol])
    79  			if err != nil {
    80  				return nil, -1, err
    81  			}
    82  			exts = append(exts, ext)
    83  		}
    84  		b = b[ol:]
    85  	}
    86  	return exts, l, nil
    87  }