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 }